1.31. WORKING WITH FLOATING POINT NUMBERS USING SIMD
1.31.2 Passing floating point number via arguments
#include <math.h>
#include <stdio.h>
int main ()
{
printf ("32.01 ^ 1.54 = %lf\n", pow (32.01,1.54));
return 0;
}
They are passed in the lower halves of theXMM0-XMM3registers.
Listing 1.398: Optimizing MSVC 2012 x64
$SG1354 DB '32.01 ^ 1.54 = %lf', 0aH, 00H
real@40400147ae147ae1 DQ 040400147ae147ae1r ; 32.01
real@3ff8a3d70a3d70a4 DQ 03ff8a3d70a3d70a4r ; 1.54
main PROC
sub rsp, 40 ; 00000028H
movsdx xmm1, QWORD PTR real@3ff8a3d70a3d70a4
movsdx xmm0, QWORD PTR real@40400147ae147ae1
call pow
lea rcx, OFFSET FLAT:$SG1354
movaps xmm1, xmm0
movd rdx, xmm1
call printf
xor eax, eax
add rsp, 40 ; 00000028H
ret 0
main ENDP
ThereisnoMOVSDXinstructioninIntelandAMDmanuals(12.1.4onpage1013),thereitiscalledjustMOVSD.
So there are two instructions sharing the same name in x86 (about the other see:.1.6 on page 1029).
Apparently, Microsoft developers wanted to get rid of the mess, so they renamed it toMOVSDX. It just loads
a value into the lower half of a XMM register.
pow()takes arguments fromXMM0andXMM1, and returns result inXMM0. It is then moved toRDXfor
printf(). Why? Maybe becauseprintf()—is a variable arguments function?
Listing 1.399: Optimizing GCC 4.4.6 x64
.LC2:
.string "32.01 ^ 1.54 = %lf\n"
main:
sub rsp, 8
movsd xmm1, QWORD PTR .LC0[rip]
movsd xmm0, QWORD PTR .LC1[rip]
call pow
; result is now in XMM0
mov edi, OFFSET FLAT:.LC2
mov eax, 1 ; number of vector registers passed
call printf
xor eax, eax
add rsp, 8
ret
.LC0:
.long 171798692
.long 1073259479
.LC1:
.long 2920577761
.long 1077936455
GCC generates clearer output. The value forprintf()is passed inXMM0. By the way, here is a case when
1 is written intoEAXforprintf()—this implies that one argument will be passed in vector registers, just