2

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?

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
bowl
  • 559
  • 6
  • 12
  • I'd love to compare precision and execution time of my code for single, double and double-extended precision mode. While I can run code in double-extended and count clocks, I would also like to print (via 'printf("%Ld,integral);' and validate result. – bowl May 04 '16 at 15:10
  • 3
    Which calling convention applies here? The rules for long double differ. For x64 linux, you return them in ST(0) – harold May 04 '16 at 15:14
  • Thx, harold. Answer me, so I can mark your answer. – bowl May 04 '16 at 15:28
  • 2
    You can't move an 80-bit floating point number to XMM0. The XMM registers only support 32-bit and 64-bit floating numbers. As harlod said you need to follow the calling convention for your operating system which should provide some other mechanism. – Ross Ridge May 04 '16 at 15:28
  • Thank you. Please, answer question, @harold, so i can mark your answer. – bowl May 04 '16 at 15:38
  • 1
    I don't really have anything useful to cite for a proper answer, also are you actually using x64 linux? (that was just a total guess on my part) – harold May 04 '16 at 15:46
  • Yes, @harold, I am using x64 Linux. Sorry, I did not specify it. – bowl May 04 '16 at 15:58

1 Answers1

4

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.

Jester
  • 56,577
  • 4
  • 81
  • 125