こんにちは、めのんです!
今回から算術論理演算に関する命令を実装していきます。
まずはビット単位の排他的論理和を行うEOR命令からです。
EOR命令の実装
EOR命令はレジスタどうしでビット単位の排他的論理和を求めます。
それ自体は簡単なんですが、演算後のステータスレジスタの変化に十分注意しなければなりません。
それではいつものように「AVR®命令一式手引書」から命令の説明を引用します。
最初に書いたようにステータスレジスタの変化をしっかり抑えておく必要があります。
これでも論理演算は算術演算に比べるとまだ簡単なんですよね。
それではコードを見ていきます。
static void eor(atmega328_t *cpu, uint16_t op)
{
int d = (op >> 4) & 0x1f;
int r = (op & 0xf) | (op >> 5) & 0x10;
int value = cpu->r[d] ^ cpu->r[r];
cpu->r[d] = value;
int sr = cpu->sr & ~(flag_S | flag_V | flag_N | flag_Z);
if (value & 0x80)
sr |= flag_N | flag_S;
if (value == 0)
sr |= flag_Z;
cpu->sr = sr;
++cpu->clock;
}
前半は排他的論理和の演算ですのでとくに説明は必要ないでしょう。
後半がステータスレジスタの設定に関する部分です。
EOR命令で変化するビットはS, V, N, Zの4つです。
これらのビットをいったん0にした値を変数srに格納しています。
Vビットは必ず0になるので、このままでOKですよね。
Vが必ず0なので、SとNは同じになるはずです。
排他的論理和の演算結果のビット7が1であれば、SとNが1になります。
Zは演算結果がゼロであれば1にセットしています。
op_tableへの登録
次に、いつものようにop_tableに登録します。
opcode.phpに次のコードを追加して実行してあげればOKです。
for ($i = 0; $i < 1024; ++$i)
{
$opcode_table[0b0010_0100_0000_0000 | $i] = 'eor';
}
今回は65,536命令のうち 32 × 32 = 1,024 個が埋まりました。
それでは次回またお会いしましょう!