2010年05月20日
QEMU MIPS Target の不具合
問題は、MIPS の整数積和演算系の、以下の命令を実行後のデスティネイションレジスタの値が仕様通りではないというものです。
MULS,MULSU,MACC,MACCHI,MACCU,MACCHIU,MSAC,MSACHI,MSACU,MSACHIU,MULHI,MULHIU,MULSHI,MULSHIU
QEMU の実装を見てみたところ、理由は一目瞭然。非常に初歩的なミスでした。以下に一部だけ抜粋します。(実際は、これと同様のミスが多くの箇所に存在します。)
qemu-0.12.4/target-mips/op_helper.c
static inline void set_HI_LOT0 (target_ulong arg1, uint64_t HILO) { arg1 = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); // ?????? env->active_tc.HI[0] = (int32_t)(HILO >> 32); } ... target_ulong helper_macc (target_ulong arg1, target_ulong arg2) { set_HI_LOT0(arg1, ((int64_t)get_HILO()) + ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2)); return arg1; // ?????? }
git レポジトリ: root/target-mips/op_helper.c
おそらく、以前はプロプロセッサマクロだったものを、inline 関数に書き換えた際に入ったミスなのではないかと推測されます。
helper_XXXX 関数は、JIT された機械語から単に呼び出されるだけの、普通の C 関数です。
(C 関数を gcc 3.x でコンパイルして、それをコピーするという、JIT が dyngen だった頃の QEMU のコードのような、わかりにくいトリックは無いと思います。)
当然上記コードは意図した通りには動かないでしょう。
(もしかして、たまたま素直に inline 展開されて、偶然動いてしまうコンパイラがあるのでしょうか ? 少なくとも gcc 4.4.0 では正しく動きませんでした。当然。)
QEMU はかなり成熟したプロジェクトというイメージがあったのですが、まだこういうわかりやすい不具合が存在するんだなと新鮮な気持ちになりました。
(もしかして私が何かとんでもない勘違いをしている可能性を疑ってしまうレベルの凡ミスなので、本家に報告する前に、一度ブログに書いてみました。何かお気づきの点がありましたら、コメントよろしくお願いします。)