ComProcに即値付きメモリアクセス命令のバイトバージョンを追加する
#ComProc にLD.1 X+simm10とST.1 X+simm10を追加する I/Oにはバイトアクセスする物があるし、charの配列を読み書きするようなときにもバイトアクセス命令が欲しい。
命令空間が余っているので、バイトアクセス命令を増やすことにした。
code:命令セットの変化.diff
JZ simm12 |0001 simm11 0| stack から値をポップし、0 なら pc+simm12 にジャンプ
JNZ simm12 |0001 simm11 1| stack から値をポップし、1 なら pc+simm12 にジャンプ
-LD X+simm10 |0010xx simm9 0| memX+simm10 から読んだ値を stack にプッシュ -ST X+simm10 |0010xx simm9 1| stack からポップした値を memX+simm10 に書く -PUSH X+simm10 |0011xx simm10 | X+simm10 を stack にプッシュ
+LD.1 X+simm10 |0010xx simm10 | バイトバージョン
+ST.1 X+simm10 |0011xx simm10 | バイトバージョン
+LD X+simm10 |0100xx simm9 0| memX+simm10 から読んだ値を stack にプッシュ +ST X+simm10 |0100xx simm9 1| stack からポップした値を memX+simm10 に書く +PUSH X+simm10 |0101xx simm10 | X+simm10 を stack にプッシュ
X の選択: 0=0, 1=fp, 2=ip, 3=cstack0 -ADD FP,simm10 |010000 simm10 | fp += simm10
- |010001xxxxxxxxxx| 予約
- |01001xxxxxxxxxxx| 予約
- |0101xxxxxxxxxxxx| 予約
- |0110xxxxxxxxxxxx| 予約
+ADD FP,simm10 |011000 simm10 | fp += simm10
+ |011001xxxxxxxxxx| 予約
+ |01101xxxxxxxxxxx| 予約
|0111xxxxxxxxxxxx| 即値なし命令(別表)
最適化対象のサンプルコード
code:char-variable.c
void delay_ms(int ms) {
int *t = 2;
*t = ms;
while (*t > 0) {}
}
int main() {
char *p = 0x80;
char c = 0x30;
while (c < 0x3a) {
*p = c;
c++;
delay_ms(333);
}
return 0;
}
code:命令追加前の出力コード.asm
add fp,256
call main
st 130
fin:
jmp fin
delay_ms:
cpush fp
st cstack+0
add fp,4
push 2
st cstack+2
ld cstack+0
ld cstack+2
std
L_1:
ld cstack+2
ldd
push 0
lt
push 0
neq
jz L_2
jmp L_1
L_2:
cpop fp
ret
main:
cpush fp
add fp,4
push 128
st cstack+0
push 48
push cstack+2 ; 最適化したい行
sta.1 ; 最適化したい行
L_3:
push 58
push cstack+2
ldd.1
lt
push 0
neq
jz L_4
push cstack+2 ; 最適化したい行
ldd.1 ; 最適化したい行
ld cstack+0
std.1
push cstack+2 ; 最適化したい行
ldd.1 ; 最適化したい行
push 1
dup 1
add
push cstack+2 ; 最適化したい行
sta.1 ; 最適化したい行
pop
push 333
call delay_ms
jmp L_3
L_4:
push 0
cpop fp
ret
code:命令追加後の出力コード.asm
add fp,256
call main
st 130
fin:
jmp fin
delay_ms:
cpush fp
st cstack+0
add fp,4
push 2
st cstack+2
ld cstack+0
ld cstack+2
std
L_1:
ld cstack+2
ldd
push 0
lt
push 0
neq
jz L_2
jmp L_1
L_2:
cpop fp
ret
main:
cpush fp
add fp,4
push 128
st cstack+0
push 48
st.1 cstack+2
L_3:
push 58
ld.1 cstack+2
lt
push 0
neq
jz L_4
ld.1 cstack+2
ld cstack+0
std.1
ld.1 cstack+2
push 1
dup 1
add
push cstack+2 ; 最適化されず残った
sta.1
pop
push 333
call delay_ms
jmp L_3
L_4:
push 0
cpop fp
ret
最適化されず残った行 push cstack+2 と sta.1 は、恐らく c++ のコンパイル結果
現在のコンパイラの動作では、 expr ++ に対して expr の左辺値を生成し、その結果に対しインクリメントを行う
この仕組みなら expr が単純な変数名か (&c + 1) のような式かに依存せず同じ仕組みでコード生成を行える
しかし、単純な変数名であれば st.1 命令に置き換えることができる
これは今後の課題とする