什么是x86-64的长双?

时间:2013-03-02 15:45:42

标签: c linux floating-point x86-64 ieee-754

有人告诉我:

  

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

但是在x86-64 ABI中它说:

    C type  | sizeof | alignment | AMD64 Architecture
long double |   16   |    16     | 80-bit extended (IEEE-754)

请参阅:amd64-abi.pdf

和gcc说sizeof(long double)是16,并且FLT_DBL = 1.79769e+308FLT_LDBL = 1.18973e+4932

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

3 个答案:

答案 0 :(得分:8)

  

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

这就是x86-64下的通常发生的(保证SSE指令的存在),但程序仍然可以自由使用x87,当你使用{时,编译器可以使用x87 {1}}。

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

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, xmm0double产品的mulss xmm0, xmm2(两个SSE说明),但float( x87指令)代表fmulp st(1), st产品。

所以,已经证实,编译器尽可能使用SSE,但仍允许通过旧的x87指令集进行80位精度计算。


请注意,这是特定于编译器的 - 某些编译器(例如VC ++)始终忽略80位精度类型,只是将long double视为long double的同义词。

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

答案 1 :(得分:4)

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位英特尔浮点对象。技术上,编译器,版本和开关的每个不同组合都是一个独特的C实现。)

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

答案 2 :(得分:0)

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

正如你所指出的,那不是long double。 64位值仅在计算后写入long double。