シフト/ローテイト命令

レジスタの内容を右または左方向にずらしたり(シフト)、ずらしてはみ出た分を 逆方向から挿入する(ローテイト) 命令です。 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」と指定します。

MBME
00000000011111111111100000000000

すべてのビットが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-1EXTract and Left justify Word Immediate
extrwi rA,rS,n,b (n > 0) rlwinm rA,rS,b + n,32-n,31EXTract and Right justify Word Immediate
inslwi rA,rS,n,b (n > 0) rlwimi rA,rS,32-b,b,(b + n)-1INSert from Left Word Immediate
insrwi rA,rS,n,b (n > 0) rlwimi rA,rS,32-(b + n),b,(b + n)-1INSert from Right Word Immediate
rotlwi rA,rS,n rlwinm rA,rS,n,0,31ROTate Left Word Immediate
rotrwi rA,rS,n rlwinm rA,rS,32-n,0,31ROTate Right Word Immediate
rotlw rA,rS,rB rlwnm rA,rS,rB,0,31ROTate Word Left
slwi rA,rS,n (n < 32) rlwinm rA,rS,n,0,31-nShift Left Word Immediate
srwi rA,rS,n (n < 32) rlwinm rA,rS,32-n,n,31Shift Right Word Immediate
clrlwi rA,rS,n (n < 32) rlwinm rA,rS,0,n,31CLeaR Left Word Immediate
clrrwi rA,rS,n (n < 32) rlwinm rA,rS,0,0,31-nCLeaR Right Word Immediate
clrlslwi rA,rS,b,n (n-b-31) rlwinm rA,rS,n,b-n,31-nCLeaR Left and Shift Left Word Immediate