代码之家  ›  专栏  ›  技术社区  ›  Evan Carroll

GCC如何在x86\u 64上编译80位宽的10字节浮点\uu float80?

  •  0
  • Evan Carroll  · 技术社区  · 6 年前

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

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

    他说,

    “Real10仅用于x87浮点单元。[…]有趣的是,它为您提供了巨大的精度提升。由于无法将real10与SSE、打包、SIMD风格的指令一起使用,因此您的性能受到了一定程度的影响。但是,这有点有趣,因为如果需要更高的精度,可以使用x87风格的FPU。现在有一天,它几乎从未被使用过。“”

    然而,我在google上看到了 GCC supports __float80 and __float128

    __浮动80 在x87上计算的GCC中?还是像其他浮点操作一样使用SIMD?那么...怎么样 __浮动128 ?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Community Reversed Engineer    4 年前

    GCC docs for Additional Floating Types :

    ISO/IEC TS 18661-3:2015定义了额外浮动类型的C支持 _Floatn _Floatnx

    。。。GCC目前不支持任何系统上的\u 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\u 64和IA-64目标,并支持80位(XFmode)浮点类型。它是这些目标上类型名称\u Float64x的别名。


    我想 __float128 是使用SSE2的扩展精度类型,可能是尾数宽度为两倍但指数限制与64位相同的“double-double”格式 double (即指数范围小于 __浮动80 )

    在i386、x86\u 64和__float128是\u float128的别名

    这些可能与gcc提供的doubledouble相同 __浮动128 大概 这是一个纯软件浮点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调用libgcc函数 __浮动128 此外,不要将增量内联到指数或任何类似的聪明的东西。

        2
  •  0
  •   Evan Carroll    6 年前

    我找到了 answer here

    __float80 在i386、x86\u 64和IA-64目标上可用,并支持80位( XFmode )浮动类型。它是这些目标上类型名称\u Float64x的别名。

    查阅了 XFmode ,则,

    扩展浮点模式表示IEEE扩展浮点数。此模式只有80个有意义的位(10个字节)。一些处理器要求将这些数字填充到12个字节,其他处理器要求填充到16个字节;此模式用于其中一种。

    我还是不完全相信,我编译了一些简单的东西

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

    我用雷达甩了它,

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

    我相信 fld fstp x87 指令集。所以它确实被用于 __浮动80 但在 __float128 ,我正在

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

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

    推荐文章