JF Linux Kernel 3.x/2.6 Documentation: /usr/src/linux/Documentation/arm/nwfpe/NOTES

arm/nwfpe/NOTES

ARM stfe 命令の副作用 (拡張精度への格上げ) について [プレインテキスト版]


我々のエミュレータで exp(double) を使うと問題が起こるようです。原因はまだ掴め
ていません。この現象は、Russell King の提供するエミュレータでは発生しません。

ただ、エミュレータ内に一つだけ奇妙な点を発見しました。これが重大な問題だとは
思わないのですが、指摘だけしておきます。ARM の関数呼出し規約に従うとすると、
関数を呼出す場合には浮動小数点レジスタ f4 〜 f7 を退避しておく必要があります。
大抵の場合、コンパイラは関数に入る前に stfe 命令を使って f4 をスタックに保存し、
関数から戻る前に ldfe 命令を使ってそれを復元します。

倍精度 (double) の結果を計算するコードを眺めていたのですが、そこでは、結果を
f4 に格納し、それから関数呼出しをおこなっていました。そして、エミュレータでは、
関数呼出しから戻ってきたときに f4 内の数値が拡張精度値へと変換されていました。

これは stfe 命令の副作用です。f4 内の倍精度値は、拡張精度値に変換してから格納
する必要があったのです。もしも lfm/sfm の組が使われていたならば、変換は発生し
なかったでしょう。これはパフォーマンスを考慮したものです。関数呼出しの結果と
f4 は掛算で利用されていました。倍精度値と拡張精度値で掛算がおこなわれる場合、
エミュレータは、倍精度値を拡張精度値へと格上げし、それから拡張精度で掛算を
おこなうようになっています。

次のコードは上記の問題を発生させます:

double x, y, z;
z = log(x)/log(y);

log(x) の計算結果 (倍精度値) が f0 に返され、その後 log(y) の呼出しに先立って、
その値を退避するために f4 にその値が移動させられます。log(y) 内で f4 を保存する
ために stfe 命令が使われるので、割算は拡張精度で実行されてしまいます。

Linux カーネル 3.x/2.6 付属文書一覧へ戻る