According to one of the slides in the video by What's A Creel video, "Modern x64 Assembly 4: Data Types" (link to the slide),
Note: real10 is only used with the x87 FPU, it is largely ignored nowadays but offers amazing precision!
He says,
"Real10 is only used with the x87 Floating Point Unit. [...] It's interesting the massive gain in precision that it offers you. You kind of take a performance hit with that gain because you can't use real10 with SSE, packed, SIMD style instructions. But, it's kind of interesting because if you want extra precision you can go to the x87 style FPU. Now a days it's almost never used at all."
However, I was googling and saw that GCC supports __float80
and __float128
.
Is the __float80
in GCC calculated on the x87? Or it is using SIMD like the other float operations? What about __float128
?
GCC docs for Additional Floating Types:
ISO/IEC TS 18661-3:2015 defines C support for additional floating types
_Floatn
and_Floatnx
... GCC does not currently support _Float128x on any systems.
I think _Float128x
is IEEE binary128, i.e. a true 128-bit float with a huge exponent range. See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1691.pdf.
__float80
is obviously the x87 10-byte type. In the x86-64 SysV ABI, it's the same as long double
; both have 16-byte alignment in that ABI.
__float80 is available on the i386, x86_64, and IA-64 targets, and supports the 80-bit (XFmode) floating type. It is an alias for the type name _Float64x on these targets.
I think __float128
is an extended-precision type using SSE2, presumably a "double double" format with twice the mantissa width but the same exponent limits as 64-bit double
. (i.e. less exponent range than __float80
)
On i386, x86_64, and ..., __float128 is an alias for _Float128
Those are probably the same doubledouble that gcc gives you with __float128
. Or maybe it's a pure software floating point 128-bit
Godbolt compiler explorer for gcc7.3 -O3 (same as gcc4.6, apparently these types aren't new)
//long double add_ld(long double x) { return x+x; } // same as __float80
__float80 add80(__float80 x) { return x+x; }
fld TBYTE PTR [rsp+8] # arg on the stack
fadd st, st(0)
ret # and returned in st(0)
__float128 add128(__float128 x) { return x+x; }
# IDK why not movapd or better movaps, silly compiler
movdqa xmm1, xmm0 # x arg in xmm0
sub rsp, 8 # align the stack
call __addtf3 # args in xmm0, xmm1
add rsp, 8
ret # return value in xmm0, I assume
int size80 = sizeof(__float80); // 16
int sizeld = sizeof(long double); // 16
int size128 = sizeof(__float128); // 16
So gcc calls a libgcc function for __float128
addition, not inlining an increment to the exponent or anything clever like that.