89435


コンパイルオプションに `-mno-80387` を付け、`double` と `long double` の  
計算を行うソースコードをコンパイルするとエラーが発生します。

[code]

    int main()
    {
            double d = 3.0F;
            d /= 1.5L;
            return 0;
    }
    
[/code]

コンパイルエラー

[code]

    $ gcc -mno-80387 a.c
    a.c: In function ‘main’:
    a.c:4:4: error: x87 register return with x87 disabled
        4 |  d /= 1.5L;
    
[/code]

利用している `gcc` のバージョンは以下の通りです。

[code]

    $ gcc -v 2>&1 | grep 'gcc version'
    gcc version 10.2.1 20210110 (Debian 10.2.1-6)
    
[/code]

clang では同様の現象がでないのですが、何かオプションを付ければ  
回避できる類のものでしょうか ?


CC BY-SA 4.0
2022-06-16T07:19:29.230
89414
2022-06-17T00:47:46.380
53097
question
gcc
"x87 register return with x87 disabled" のエラーが出る


cygwin32 / cygwin64 の gcc で `-mno-80387` つきで提示コードをコンパイルすると除算に `__divxf3`
なるライブラリ関数の呼び出しが生成されました。そして `undefined reference to '__divxf3'`
なるリンクエラーになってしまいました。ということはコンパイラは `-mno-80387`
に対応していても、それが必要とするランタイムライブラリ関数が用意されていないということです。

いかにも gcc 依存なランタイムライブラリ関数名っぽいので `gcc-11.2.0` のソースコードを調査してみました。 `__divxf3` なる関数は
`gcc-11.2.0/libgcc/config/ia64/lib1func.S` だけにあります。ということは今はすたれてしまった IA64
(Itanium) にしかこのランタイムライブラリ関数は実装されていないようです（ IA64 は x86 / x86-64 とは違うアーキテクチャです）  
# 要するに x86 や x86-64 では FPU が必ずあるので `nofpu` でコンパイルする理由が一切ないってこと

ということで Debian ディストロでは実行環境が対応していない機能（ `-mno-80387`
でコンパイルしたバイナリを実行することができないということ）は、コンパイル時点でエラーになるよう親切心で配慮がなされているということだと思われます。

ちなみに `lib1func.S` 中のコメントを見ると 80bit 浮動小数点数の計算という記載があって、これは確かに 8087/80387
の仕様ではあるのですが x86 あるいは x86-64 では 80bit 浮動小数点数は扱わないわけで、質問者氏のいうところの `long double`
が何 bit であるかは案件と実行環境の仕様とを十分に検討しないとまずそうです。

# WinXP についてきていた Space Cadet が 80bit 浮動小数点数に依存していて 64bit
浮動小数点数でコンパイルすると動きが全く違ってゲームにならない・・・なんて記事をどこかで読んだような記憶が

* * *

同様 `cygwin64-clang-8.0.1-x86_64-unknown-windows-cygnus` で `clang -S -mno-80387
a.c` を試したところ、普通に `fdivrp` 命令が生成されており `-mno-80387` には効力がないことがわかりました（ `gcc`
との互換性のためだけに `-mno-80387` は受け付けるが無効ということ）。当然リンクエラーも発生しませんし実行できます。 Debian
でもコンパイルエラーが出ないはある意味当然かも。


CC BY-SA 4.0
2022-06-16T23:52:12.883
89435
2022-06-17T00:47:46.380
2022-06-17T00:47:46.380
8589
8589
89414
answer