[英]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.