整数レジスタに付随するbitについて
はじめに
- osecpu-vm.hのOsecpuVmという構造体の中には、bit[]という見慣れぬメンバ変数があります。これについての説明です。
- 基本的に以下の話は、VMを改造しようという人だけが気にすればいい話です。アプリを作る人は気にする必要はありません。
(1)
- bit[]はRxxの有効ビット数を保持しています。これはそのRxxに最後に代入した命令のbitの値がそのまま入っています。
- つまり32bit演算をした結果が入っているのなら32が入っていますし、8bit演算をした結果が入っているのなら8が入っています。
- このbitで表される数字以上の上位のビットについては、どんなゴミデータが入っていようともそれは無視しなければいけません。
- OSECPU-VMではbitの値を超える演算を認めません。たとえばR02のbitが16だったら、R02の値を使ってADD32などはできないのです。なぜなら、そんなことを認めたらゴミデータを参照して誤動作するかもしれないからです。
- R02の値を変更せずにbitだけを上げる方法があって、それはSBX命令です。SBXはbitの値を上げるだけではなく、R02を指定されたビット数で適正な値になるように、ゴミデータを部分を符号拡張によってクリアします。
- ですからSBX命令を使ってbitを上げてやればADD32にも使えるようになります。
- このルールを守らずに演算してしまった場合は、EXEC_BAD_BITSというセキュリティエラーになります。
- このbitの値は0にすることもできます。そうすると該当の整数レジスタの全てのビットがゴミデータということになります。これは未初期化状態として扱われます。そのレジスタの値を参照しようとすれば直ちにエラーになるわけです。
- なお、アプリがbitの値を知る方法はありません。そういう命令は用意しません。これはプログラマの不注意を検出するためだけのもので、それ以外の用途には使わせないためです。
- bitはなんとメモリにもあります。ただしメモリのbitが1だとしても、LMEM32で値をロードできます。LMEMには符号拡張(もしくはゼロ拡張)機能がデフォルトで入っているからです。
- 特別なプリフィクスをつけると、メモリのbitの値がそのままレジスタのbitの値になります。これは一時的にレジスタの値をメモリに退避したり戻したりするときに役立ちます。
- メモリのbitが役に立つのはbitが0のときです。つまりそのメモリは未初期化なので、参照できないということになります。この場合はLMEM32はセキュリティエラーになります。これにより初期化のやり忘れを容易に発見できます。
- ちなみに浮動小数点レジスタFxxにもbitはありますので、これらに対しても不定値を表現できます。
(2)
- OSECPU-VMはセキュリティチェックが満載ですが、JITC版ではこれらのチェックを性能向上のためにオフにすることができます(もちろんインタプリタ版と同等のチェックをすることもできる)。その場合、bit[]やそれに類するものは用意されず、チェックもしません。つまりレジスタを不定値にする方法もなくなります(bit=0な命令はNOP扱いを受けてコード生成されません)。
(3)
- メモリやレジスタの値で「不定」を表現できるようになったのは進歩です。今まではこれができなかったために、オブジェクトを生成したらとにかく初期値を入れて、不定値が残らないようにしましょう、とされてきました。というのは不定値に由来するバグが実に厄介だったからです。
- しかしそれはムダになっていることも往々にしてありました。あとから値をセットすると分かっているのに、それでも必要のない初期化をしていたからです。
- OSECPU-VMでは初期化忘れを検出できるので、こんなムダになるかもしれないプログラミングスタイルを強要されません。
こめんと欄