Kernel Planet のDaveM's Linux Networking BLOGを見て。
2つのレジスタの状態によって、第3のレジスタに 0 か 1 を代入するということをしたい時。
つまり、
if(reg1==reg2)
reg3=1;
else
reg3=0;
ってことをしたい時。
下のようなコードだと分岐予測がきかないため効率が良くないらしく(いまいち理由がわからない…)、
cmp %reg1, %reg2
mov 0, %reg3
bCOND,a 1f
mov 1, %reg3
1:
次のようなコードを生成するらしい。
/* %reg3 = (%reg1 != %reg2) */
xor %reg1, %reg2, %reg3
subcc %g0, %reg3, %g0
addx %g0, 0, %reg3
/* %reg3 = (%reg1 < %reg2) */
cmp %reg1, %reg2
addx %g0, 0, %reg3
/* %reg3 = (%reg1 > %reg2) */
cmp %reg2, %reg1
addx %g0, 0, %reg3
これを読むために色々調べたことをメモ。
SPARC のアセンブラの演算は
hoge <レジスタ>,<レジスタもしくは数字>,<レジスタ>
と呼出し、第1引数と第2引数の演算結果を第3引数のレジスタに代入する。
g0 レジスタは、常に 0 がはいっていて代入は意味がない。
〜cc は with carry で演算結果によっては carry bit をセットする。
〜x は carry bit を考慮して演算する。
下2つはともかく、 %reg3 = (%reg1 != %reg2) の時が面白い。
xor して reg3 が 0 (reg1 == reg2) なら
subcc は 0- 0 で carry bit は 0 。
addx は 0+ 0 + <carry bit> で reg3 は 0。
xor して reg3 が 正 (reg1 != reg2) なら
subcc は 0- 正 で carry bit は 1 。
addx は 0+ 0 + <carry bit> で reg3 は 1。
引き算の carry bit を足し算で使うというアイデア。
386本で読んだはずなのに、 carry bit なんてすっかり忘れてた…。
0 コメント:
コメントを投稿 | |