簡體   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