13

有人告诉我:

在 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 double64位如何?我认为这是一个 80 位的表示。

4

3 回答 3

11

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

通常在 x86-64 下发生(保证存在 SSE 指令),但程序仍然可以自由使用 x87,当您使用long double.

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

#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, xmm0double产品和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 double80 位,编译器使用该类型的所有可用精度执行计算的唯一方法是使用 x87 指令。

于 2013-03-02T16:00:11.007 回答
4

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

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

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

于 2013-03-03T11:27:31.820 回答
0

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

long double正如您所指出的,那不是。64 位值只是在计算后写入长双精度数。

于 2013-03-02T15:49:23.223 回答