こんにちは、めのんです!
命令セットシミュレータのブログはほとんどワンパターンになってしまいましたね。
でも、別にバラエティを狙っているわけではないので、とことん地味でワンパターンで進めていきます(笑)
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個が埋まりました!
それでは次回またお会いしましょう!