[英]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+308
和FLT_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.