Linux Kernel 2.4 Documentation:
/usr/src/linux/Documentation/arm/nwfpe/NOTES
arm/nwfpe/NOTES
ARM stfe 命令の副作用 (拡張精度への格上げ) について
[プレインテキスト版]
- 原著作者: unknown
- 翻訳者: 川崎 貴彦 <takahiko@hakubi.co.jp>
- バージョン: 2.4.19
- 翻訳日時: 2002/09/10
我々のエミュレータで 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 カーネル 2.4 付属文書一覧へ戻る