シフト/ローテイト命令
レジスタの内容を右または左方向にずらしたり(シフト)、ずらしてはみ出た分を 逆方向から挿入する(ローテイト) 命令です。 2のべき乗演算、ビットの抽出、挿入などのビット操作に使います。
シフト命令
命令 | ニーモニックの意味 |
slw[.] | Shift Left Word |
srw[.] | Shift Right Word |
sraw[.] | Shift Right Algebraic Word |
srawi[.] | Shift Right Algebraic Word Immediate |
右シフト
レジスタの内容を右に指定したビット数分だけずらす命令です。 ずらして空いたビットには 0 を埋めます (sraw命令の場合は符号ビットの内容)。
Shift Right Word
srw rA,rS,rB srw. rA,rS,rB
rS の内容を rB で指定されるビット数だけ右にシフトして、 結果をrA に格納します。 右端のビットは失われ、左端のビットには 0 が入ります。
Shift Right Algebraic Word Immediate
srawi rA,rS,SH srawi. rA,rS,SH
rS の内容をSH ビットで指定されるビット数だけ右にシフトして、 結果をrA に格納します。 右端のビットは失われ、左端のビットには 0 が入ります。 シフトした値を符号拡張し、その32ビットの結果をrA に格納します。 rS の内容が負数で、ビット31 から「1」ビットがシフトされれば、 XER[CA] をセットします。それ以外はXER [CA] をクリアします。 シフト量がゼロならXER[CA] をクリアします。
Shift Right Algebraic Word
sraw rA,rS,rB sraw. rA,rS,rB
rS の内容を rB で指定されるビット数だけ右にシフトして、結果を rA に格納します。 右端のビットは失われ、左端のビットには符号ビットが入ります。 rB が32を超えると、rS の符号ビットで rA が埋められます。
rS の内容が負数で、ビット31 から「1」ビットがシフトされる場合、 XER[CA] をセットします。それ以外はXER[CA] をクリアします。 シフト量がゼロならXER[CA] をクリアします。
左シフト
レジスタの内容を左に指定したビット数分だけずらします。ずらして空いたビットには 0 を埋めます。
Shift Left Word
slw rA,rS,rB slw. rA,rS,rB
rS の内容を rB で指定されるビット数だけ左にシフトして、結果をrA に格納します。 左端のビットは失われ、右端のビットには 0 が入ります。 rB が32を超えると、rA のすべてのビットは 0 になります。
ローテイト命令
PowerPC のローテイト命令は最も複雑な命令です。 数値指定(即値)によるシフト、任意のビットの抽出、挿入、クリアなどの操作もローテイト命令で実現できます。
命令 | ニーモニックの意味 |
rlwimi[.] | Rotate Left Word Immediate then Mask Insert |
rlwinm[.] | Rotate Left Word Immediate then aNd with Mask |
rlwnm[.] | Rotate Left Word then aNd with Mask |
マスク
マスクとは任意の一連のビットを1とした数値で、ローテイトしたレジスタの内容とAND演算するためのものです。 マスクはビットが最初に1となる(左端)ビット番号(MB : Mask Begin)と、1となっているビットの右端の ビット番号(ME : Mask End)で指定します。つまり、ビットMB からビットME までを「1」、それ以外は「0」 となるようなマスクパターンになります。ビット番号付け方が他のCPUと逆になっています。bit0が最上位になり、 MBは左側、MEは右側になることに注意してください。
マスクの例
第9ビット(左から10番目のビット)から12個の「1」が並ぶマスクパターンは 次のように「MB=9」、「ME=20」と指定します。
MB | ME | ||||||||||||||||||||||||||||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
すべてのビットが1の数値が r7 レジスタに格納されているとして、r7 を0ビットシフト(シフトしない)、 マスクを「MB=9、ME=20」で指定して rlwinm を実行するとマスクパターンがそのままターゲットレジスタ (r10 とする) に出力されます。 ここではマスクの形を理解することが重要ですから、命令自体は気にしないで下さい。
実際に実行してレジスタの値を表示してみました。
rlwinm r10, r7, 0, 9, 20 r7: 11111111111111111111111111111111 FFFFFFFF r10: 00000000011111111111100000000000 007FF800
r10 の結果を上の表と見比べてみてください。
MBにMEより大きいビット番号を指定すると右端から左に回りこんだパターンとなります。 「MB=20、ME=9」と指定して rlwinm を実行すると次のようなパターンが生成されます。
rlwinm r10, r7, 0, 20, 9 r7: 11111111111111111111111111111111 FFFFFFFF r10: 11111111110000000000111111111111 FFC00FFF
ビット10からビット19までが「0」で、それ以外が「1」のマスクとなっていることが分かります。
Rotate Left Word Immediate then Mask Insert
rlwimi rA,rS,SH,MB,ME
rS の内容を SH で指定されたビット数だけ左にローテイト(回転)します。 ローテイトされたデータと生成したマスクをANDした結果と、 マスクパターンを反転してANDしたrAの内容とORしたものを rA に代入します。
rS をローテイトしたビット列のマスクに対応する部分だけを、rAのほかのビットを変化させずに上書きします。
Rotate Left Word Immediate then aNd with Mask
rlwinm rA,rS,SH,MB,ME (Rc = 0) rlwinm. rA,rS,SH,MB,ME (Rc = 1)
rS[0-31] の内容をオペランドSH で指定されるビット数だけ左にローテイトします。 ビットMB からビットME までが「1」、それ以外は「0」のビットからなるマスクを生成します。
ローテイトしたデータと生成したマスクを AND 演算し、結果をrA に格納します。 rlwinm で以下の方法を使用すれば、任意の長さ(32以内)のビット列に関して抽出、ローテイト、シフト、クリアといった操作ができます。
使用例
上位8ビットを取り出す
rlwinm r3, r11, 8, 24, 31 # 標準ニーモニック extlwi r3, r11, 8, 24 # 拡張ニーモニック
Rotate Left Word then aNd with Mask
rlwnm rA,rS,rB,MB,ME (Rc = 0) rlwnm. rA,rS,rB,MB,ME (Rc = 1)
rS の内容をrB の下位5 ビットで指定されるビット数だけ左にローテイトします。 rlwinm (Rotate Left Word Immediate then aNd with Mask) と似ていますが、ローテイトビット数を レジスタで指定します。 ビットMB からビットME までが「1」、それ以外は「0」のビットからなるマスクを生成します。 ローテイトしたデータと生成したマスクをAND演算し、その結果をrA に格納します。
rlwnm で以下の方法を使用すれば、ビット列の抽出やローテイトができます。
使用例
上位8ビットを取り出す(r4の内容が8の場合)
rlwnm r3, r11, r4, 24, 31 # 標準ニーモニック
拡張ニーモニック
ローテイト命令は機能が複雑なだけに多くの拡張ニーモニックが使用できます。 拡張ニーモニックのオペコードとオペランドの形式を覚えることの方が、 3種類のローテイト命令を理解するより大変な気がします。
即値指定のシフト命令「slwi」、「srwi」だけで十分ではないでしょうか。
拡張ニーモニック | 標準ニーモニック | 動作 |
extlwi rA,rS,n,b (n > 0) | rlwinm rA,rS,b,0,n-1 | EXTract and Left justify Word Immediate |
extrwi rA,rS,n,b (n > 0) | rlwinm rA,rS,b + n,32-n,31 | EXTract and Right justify Word Immediate |
inslwi rA,rS,n,b (n > 0) | rlwimi rA,rS,32-b,b,(b + n)-1 | INSert from Left Word Immediate |
insrwi rA,rS,n,b (n > 0) | rlwimi rA,rS,32-(b + n),b,(b + n)-1 | INSert from Right Word Immediate |
rotlwi rA,rS,n | rlwinm rA,rS,n,0,31 | ROTate Left Word Immediate |
rotrwi rA,rS,n | rlwinm rA,rS,32-n,0,31 | ROTate Right Word Immediate |
rotlw rA,rS,rB | rlwnm rA,rS,rB,0,31 | ROTate Word Left |
slwi rA,rS,n (n < 32) | rlwinm rA,rS,n,0,31-n | Shift Left Word Immediate |
srwi rA,rS,n (n < 32) | rlwinm rA,rS,32-n,n,31 | Shift Right Word Immediate |
clrlwi rA,rS,n (n < 32) | rlwinm rA,rS,0,n,31 | CLeaR Left Word Immediate |
clrrwi rA,rS,n (n < 32) | rlwinm rA,rS,0,0,31-n | CLeaR Right Word Immediate |
clrlslwi rA,rS,b,n (n-b-31) | rlwinm rA,rS,n,b-n,31-n | CLeaR Left and Shift Left Word Immediate |