LDI命令の実装

こんにちは、めのんです!

命令セットシミュレータのブログはほとんどワンパターンになってしまいましたね。
でも、別にバラエティを狙っているわけではないので、とことん地味でワンパターンで進めていきます(笑)

LDI命令の実装

LDI命令は汎用レジスタに即値を設定するための命令です。
すごく基本的な命令なので、これ無しにはプログラムは書けないと思います。

「LDI」の末尾の「I」はImmediateの意味で、これは即値のことです。
機械語やアセンブリ言語ではよく使う用語ですので、ぜひ覚えておいてください。

それで、いつものように「AVR®命令一式手引書」から命令の説明を引用します。

AVRは8ビットのマイコンですので、汎用レジスタは8ビットですし、そこに設定する即値も8ビットです。

この命令で注意しないといけないのは、対象になる汎用レジスタはR16~R31なので、R0~R15は指定できないということです。
AVRの命令は、命令の種類を特定するのに最低でも4ビットが必要ですので、残りは4ビットしかありません。
4ビットだと0~15までの16パターンしか表現できないんです。

それではコードを見ていきます。

static void ldi(atmega328_t *cpu, uint16_t op)
{
  int d = (op >> 4) & 0xf;
  int K = (op & 0xf) | (op >> 4) & 0xf0;
  cpu->r[16 + d] = K;
  ++cpu->clock;
}

dは0~15の値を取りますが、実際に対象にするのはR16~R31ですから、16 + dとしています。
あとは説明はいらないでしょう。

op_tableへの登録

次に、いつものようにop_tableに登録します。

opcode.phpに次のコードを追加して実行してあげればOKです。

for ($i = 0; $i < 0x1000; ++$i)
{
  $opcode_table[0b1110_0000_0000_0000 | $i] = 'ldi';
}

これまではオペランドでループを回していました。
今回であればdとKですね。

ですが、簡単にするために今回からはなるべく単純なループにすることにします。
16ビットのオペコードのうち、下位12ビットがオペランドですので0~0x3fffを埋め込むようにしています。

今回は65,536命令のうちの4,096個が埋まりました!

それでは次回またお会いしましょう!