5

I wrote a simple program, thinking I could find out from the disassembly:

int main() {
  double a, b, c;
  scanf("%lf %lf %lf", &a, &b, &c);
  __float128 foo = a;
  foo += b; foo += c;
  printf("%f\n", (double)foo);
}

main compiles (-O3) to the following:

  400630:       48 83 ec 38             sub    $0x38,%rsp
  400634:       bf 34 08 40 00          mov    $0x400834,%edi
  400639:       31 c0                   xor    %eax,%eax
  40063b:       48 8d 4c 24 28          lea    0x28(%rsp),%rcx
  400640:       48 8d 54 24 20          lea    0x20(%rsp),%rdx
  400645:       48 8d 74 24 18          lea    0x18(%rsp),%rsi
  40064a:       e8 c1 ff ff ff          callq  400610 <scanf@plt>
  40064f:       f2 0f 10 44 24 18       movsd  0x18(%rsp),%xmm0
  400655:       e8 a6 ff ff ff          callq  400600 <__extenddftf2@plt>
  40065a:       0f 29 04 24             movaps %xmm0,(%rsp)
  40065e:       f2 0f 10 44 24 20       movsd  0x20(%rsp),%xmm0
  400664:       e8 97 ff ff ff          callq  400600 <__extenddftf2@plt>
  400669:       66 0f 6f 0c 24          movdqa (%rsp),%xmm1
  40066e:       e8 5d ff ff ff          callq  4005d0 <__addtf3@plt>
  400673:       0f 29 04 24             movaps %xmm0,(%rsp)
  400677:       f2 0f 10 44 24 28       movsd  0x28(%rsp),%xmm0
  40067d:       e8 7e ff ff ff          callq  400600 <__extenddftf2@plt>
  400682:       66 0f 6f 0c 24          movdqa (%rsp),%xmm1
  400687:       e8 44 ff ff ff          callq  4005d0 <__addtf3@plt>
  40068c:       e8 8f ff ff ff          callq  400620 <__trunctfdf2@plt>
  400691:       bf 3a 08 40 00          mov    $0x40083a,%edi
  400696:       b8 01 00 00 00          mov    $0x1,%eax
  40069b:       e8 20 ff ff ff          callq  4005c0 <printf@plt>
  4006a0:       31 c0                   xor    %eax,%eax
  4006a2:       48 83 c4 38             add    $0x38,%rsp
  4006a6:       c3                      retq

When I look at the disassembly of __addtf3 by setting a breakpoint there and running the program under gdb, I see a morass of arithmetic and conditionals. I didn't bother trying to read it, but it sure didn't look like the code for double double addition.

Are these software quad-precision floating-point numbers? If so, what format?

tmyklebu
  • 13,915
  • 3
  • 28
  • 57
  • 1
    possible duplicate of [long double (GCC specific) and \_\_float128](http://stackoverflow.com/questions/13516476/long-double-gcc-specific-and-float128) – 500 - Internal Server Error Oct 29 '14 at 20:01
  • @500-InternalServerError: Where in the answer to that question is the format described? – tmyklebu Oct 29 '14 at 20:02
  • Something else you can do is look at the software floating point emulation code that GCC (via glibc) uses. This includes `addtf3`. https://github.com/gcc-mirror/gcc/tree/master/libgcc/soft-fp – Michael Petch Oct 29 '14 at 20:06
  • You might tune for your native processor (e.g. compile with `gcc -O3 -fverbose-asm -mtune=native` ...) – Basile Starynkevitch Oct 29 '14 at 20:10
  • @BasileStarynkevitch: No appreciable difference, other than the use of AVX, with `-O3 -march=native -fverbose-asm -mtune-native` on a Sandy Bridge machine. It still calls `__addtf3`. – tmyklebu Oct 29 '14 at 20:13

1 Answers1

7

GCC's __float128 coresponds to its internal "TFmode" format, which varies depending on the target and the ABI that GCC is using.

The documentation says:

  • TFmode
    “Tetra Floating” mode represents a sixteen byte floating point number all 128 of whose bits are meaningful. One common use is the IEEE quad-precision format.

Support for TFmode on x86_64 was added by this patch and the GCC 4.3 release notes confirm that for x86_64 it is IEEE quad format:

  • Support for __float128 (TFmode) IEEE quad type and corresponding TCmode IEEE complex quad type is available via the soft-fp library on x86_64 targets.
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521