繁体   English   中英

x86-64 上的 long double 是什么?

[英]What is long double on x86-64?

有人告诉我:

在 x86-64 下,FP 算法是用 SSE 完成的,因此 long double 是 64 位。

但是在 x86-64 ABI 中它说:

C型 大小 结盟 AMD64 架构
长双 16 16 80 位扩展 (IEEE-754)

参见: amd64-abi.pdf

gcc 说sizeof(long double)是 16 并给出FLT_DBL = 1.79769e+308FLT_LDBL = 1.18973e+4932

所以我很困惑, long double 64 位的long double是多少? 我认为这是一个 80 位的表示。

在 x86-64 下,FP 算法是用 SSE 完成的,因此 long double 是 64 位。

这是 x86-64 下通常会发生的情况(保证 SSE 指令的存在),但程序仍然可以自由使用 x87,当您使用long double时,编译器可以求助于它。

您可以通过在 Linux 上使用g++编译这样的程序来确认这一点:

#include <iostream>
#include <cstdlib>
#include <ctime>

int main()
{
    std::srand(std::time(NULL));
    float f1=rand(), f2=rand();
    double d1=rand(), d2=rand();
    long double l1=rand(), l2=rand();

    std::cout<<f1*f2<<" "<<d1*d2<<" "<<l1*l2<<std::endl;
    return 0;
}

在汇编输出中,我发现mulsd xmm1, xmm0表示double积, mulss xmm0, xmm2表示float积(两个 SSE 指令),但fmulp st(1), st (x87 指令)表示long double积。

因此,可以确认的是,编译器会尽可能使用 SSE,但仍允许通过旧的 x87 指令集进行 80 位精度计算。


请注意,这是编译器特定的-一些编译器(例如VC ++)总是被忽略80位精度的类型,只是处理long double作为一个代名词double

另一方面,由于 x86-64 System V ABI(在 Linux 上采用)要求long double为 80 位,编译器使用该类型的所有可用精度执行计算的唯一方法是使用 x87 指令。

AMD ABI 实际上不能强制 C long double类型是什么,因为它没有权限/权限这样做。 每个 C 实现都可以根据 C 标准(如果 C 实现符合标准)制定自己的类型规范,并且每个 C 实现可以选择是否符合 AMD ABI。

这意味着您不能简单地问“x86-64 上的long double是什么?” 您必须询问特定 C 实现中的long double是什么。 这意味着指定用于编译的特定 C 编译器、版本和开关。 (编译器可能有一个开关,其中一个设置使long double成为 64 位二进制 IEEE 754 浮点对象,另一个设置使long double成为 80 位 Intel 浮点对象。从技术上讲,编译器的每个不同组合,版本,而开关是一个独特的 C 实现。)

long double实现为 64 位二进制 IEEE-754 浮点对象的编译器只是将它们作为 AMD ABI 调用的double传递; 它永远不会将它们作为 ABI 所称的long double传递。 这样做时,编译器的这一方面将仅与其他类似处理long double软件兼容。

SSE 计算为双精度,中间表示为 64 位。

正如您所指出的那样,这不是long double 64 位值只是在计算后写入 long double。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM