XMM register move commands are created because, in System V AMD64 ABI , floating point arguments are stored in XMM0-XMM7.
Since we donβt know if floating points are used simply by looking at a variable function, the compiler must generate instructions to push the floating point values ββto va_list .
You can use the -mno-sse to disable SSE . For instance,
__attribute__((noinline)) void f(const char* x, ...) { va_list va; va_start(va, x); vprintf(x, va); va_end(va); }
Without the -mno-sse :
subq $0x000000d8,%rsp testb %al,%al movq %rsi,0x28(%rsp) movq %rdx,0x30(%rsp) movq %rcx,0x38(%rsp) movq %r8,0x40(%rsp) movq %r9,0x48(%rsp) je 0x100000f1b movaps %xmm0,0x50(%rsp) movaps %xmm1,0x60(%rsp) movaps %xmm2,0x70(%rsp) movaps %xmm3,0x00000080(%rsp) movaps %xmm4,0x00000090(%rsp) movaps %xmm5,0x000000a0(%rsp) movaps %xmm6,0x000000b0(%rsp) movaps %xmm7,0x000000c0(%rsp) 0x100000f1b: leaq 0x000000e0(%rsp),%rax movl $0x00000008,0x08(%rsp) movq %rax,0x10(%rsp) leaq 0x08(%rsp),%rsi leaq 0x20(%rsp),%rax movl $0x00000030,0x0c(%rsp) movq %rax,0x18(%rsp) callq 0x100000f6a ; symbol stub for: _vprintf addq $0x000000d8,%rsp ret
With the -mno-sse :
subq $0x58,%rsp leaq 0x60(%rsp),%rax movq %rsi,0x28(%rsp) movq %rax,0x10(%rsp) leaq 0x08(%rsp),%rsi leaq 0x20(%rsp),%rax movq %rdx,0x30(%rsp) movq %rcx,0x38(%rsp) movq %r8,0x40(%rsp) movq %r9,0x48(%rsp) movl $0x00000008,0x08(%rsp) movq %rax,0x18(%rsp) callq 0x100000f6a ; symbol stub for: _vprintf addq $0x58,%rsp ret
You can also use the target attribute to disable SSE only for this function, for example.
__attribute__((noinline, target("no-sse")))
But be careful that other functions with SSE support will not know that f does not use SSE , and therefore calling them with floating point numbers will lead to undefined behavior:
int main() { f("%g %g", 1.0, 2.0); // 1.0 and 2.0 are stored in XMM0β1 // So this will print garbage eg `0 6.95326e-310` }