GCC如何在x86_64上编译80位宽的10字节float __float80?

时间:2018-04-18 22:24:55

标签: gcc floating-point x86 precision x87

根据What's A Creel video, "Modern x64 Assembly 4: Data Types" (link to the slide)视频中的一张幻灯片,

  

注意:real10仅与x87 FPU一起使用,现在在很大程度上被忽略但提供了惊人的精确度!

他说,

  

“Real10仅用于x87浮点单元。[...]有趣的是它为你提供了大量的精确度提升。你可以通过这种增益获得性能提升,因为你不能使用带有SSE,打包,SIMD样式指令的real10。但是,它有点有趣,因为如果你想要更高的精度,你可以使用x87风格的FPU。现在它几乎从未使用过。“

但是,我在谷歌上搜索GCC supports __float80 and __float128

GCC中的__float80是否计算在x87上?或者像其他浮动操作一样使用SIMD?那么__float128呢?

2 个答案:

答案 0 :(得分:1)

GCC docs for Additional Floating Types

  

ISO / IEC TS 18661-3:2015为其他浮动类型_Floatn_Floatnx

定义了C支持      

... GCC目前在任何系统上都不支持_Float128x。

我认为_Float128x是IEEE binary128,即具有巨大指数范围的真正128位浮点数。请参阅http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1691.pdf

__float80显然是x87 10字节类型。在x86-64 SysV ABI中,它与long double相同;在ABI中都有16字节对齐。

  

__ float80在i386,x86_64和IA-64目标上可用,并支持80位(XFmode)浮点类型。它是这些目标上类型名称_Float64x的别名。

我认为__float128是使用SSE2的扩展精度类型,可能是“双倍”格式,尾数宽度的两倍,但指数限制与64位double相同。 (即指数范围小于__float80

  

在i386,x86_64和...上,__ fllo128是_Float128的别名

这些可能与gcc为您提供的{double}加倍__float128。或者也许它是一个纯软件浮点128位

Godbolt compiler explorer对于gcc7.3 -O3(与gcc4.6相同,显然这些类型不是新的)

//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

因此gcc调用了一个用于__float128加法的libgcc函数,而不是内联指数的增量或类似的任何聪明的东西。

答案 1 :(得分:0)

我找到了answer here

  

__float80可用于i386,x86_64和IA-64目标,并支持80位(XFmode)浮点类型。它是这些目标上类型名称_Float64x的别名。

查看了XFmode

  

“扩展浮动”模式表示IEEE扩展浮点数。该模式只有80个有意义的位(10个字节)。一些处理器要求将这些数字填充到十二个字节,其他处理器填充到十六个字节;此模式用于。

仍然不完全相信,我编写了一些简单的

int main () {
    __float80 a = 1.445839898;
    return 1;
}

使用Radare我把它倾倒了,

0x00000652      db2dc8000000   fld xword [0x00000720]
0x00000658      db7df0         fstp xword [local_10h]

我相信fldfstpx87指令集的一部分。所以它被用于__float80 10字节浮点数,但是在__float128,我得到了

0x000005fe      660f6f05aa00.  movdqa xmm0, xmmword [0x000006b0]
0x00000606      0f2945f0       movaps xmmword [local_10h], xmm0

所以我们在这里可以看到我们正在使用SIMD xmmword