Reputation: 559
I've written an AT&T assembly function to calculate an integral. I need to pass it as a return value as it's called by code written in C. I've successfully managed to return it as a single precision float
and a double precision double
. But I know I can calculate it in 80-bit double extended precision and I'd love to pass it to C.
Let's assume the value I want to pass is pointed to in an FPU register pointed by TOP. Here's how I call functions.
For float:
//C
double integ_fo=integ_asm_fpu_fl();
#asm
...
fstps max # Fpu STore and Pop Short <- short for 32-bit
movss max, %xmm0 # MOVe Scalar Single precision
For double:
//C
double integ_do=integ_asm_fpu_do();
#asm
...
fstpl max # Fpu STore and Pop Long <- long for 64-bit
movsd max, %xmm0 # MOVe Scalar Dingle precision
My question is now: how can I complete following code, so that C can read long double
from the %XMM0
register.
For long double:
//C
long double integ_lo=integ_asm_fpu_lo();
#asm
...
fstpt max # FPU Store and Pop exTended <- extended for 80-bit
What should I do after that? How would I move 80 bits from max
to %XMM0
?
Upvotes: 2
Views: 623
Reputation: 58792
Your premise is wrong:
how can I complete following code, so that C can read long double from the %XMM0 register.
The sysv abi does not return long double
in xmm0
register, but st0
.
The relevant part of the documentation:
The 64-bit mantissa of arguments of type long double belongs to class X87, the 16-bit exponent plus 6 bytes of padding belongs to class X87UP.
If the class is X87UP, the value is returned together with the previous X87 value in %st0.
Apparently you already have the value in st0
so you don't have to do anything just leave it there, meaning delete the fstpt
in your example.
Upvotes: 4