シフト演算とは論理演算と同じようにビット列を操作する演算
単純な左右へのシフトの他に、複雑な動作をするビットフィールド移動命令がある
### シフト演算
.include "debug.s"
.text
.global _start
num: .quad 0x876543210fedcba9
_start:
ldr x2, num
mov x0, x2
bl PrintHex16
bl NewLine
mov x1, #22
bl PrintRight
bl NewLine
lsl x0, x2, #8
bl PrintHex16
bl NewLine
mov x1, #22
bl PrintRight
bl NewLine
bl Exit
$ ./test
876543210FEDCBA9
-8690466096661279831
6543210FEDCBA900
7296712173568108800
算術右シフトはASR x0, x2, #8
論理右シフトはLSR x0, x2, #8
右ローテートはROR x0, x2, #8
左ローテートは右ローテート(ROR)のシフト量を (64 – ビット数) とすることで左ローテートを実現
### アドレッシングモード
シフト演算命令には、シフト量を定数で指定するイミディエートとレジスタで指定するモードの2種類のアドレッシングモードがある
LSR Wd, Wn, #imm6
LSR Xd, Xn, #imm6
LSR Wd, Wn, Wm
LSR Xd, Xn, Xm
### ASR
ASR命令 (Arithmetic Shift Right) は算術右シフトを実行。算術右シフトはRn レジスタの内容を Rm レジスタで指定したビット数だけ右にシフト。
ASR Wd, Wn, Wm // ASRV Wd, Wn, Wm と同じ
ASR Xd, Xn, Xm // ASRV Xd, Xn, Xm と同じ
### LSR
LSR命令 (Logical Shift Right)は論理右シフトを実行。論理右シフトはレジスタ Rn の内容をレジスタ Rm で指定したビット数だけ右にシフトしてレジスタ Rd に返却。
LSR Wd, Wn, Wm // LSRV Wd, Wn, Wm と同じ
LSR Xd, Xn, Xm // LSRV Xd, Xn, Xm と同じ
LSR Wd, Wn, #shift // UBFM Wd, Wn, #shift, #31
LSR Xd, Xn, #shift // UBFM Xd, Xn, #shift, #63
### LSL
LSL命令 (Logical Shift Left)は論理左シフトを実行。論理左シフトはレジスタ Rn の内容をレジスタ Rm で指定したビット数だけ左にシフトしてレジスタ Rd に返却
LSL Wd, Wn, Wm // LSLV Wd, Wn, Wm と同じ
LSL Xd, Xn, Xm // LSLV Xd, Xn, Xm と同じ
LSL Wd, Wn, #shift // UBFM Wd, Wn, #(-shift MOD 32), #(31-shift)
LSL Xd, Xn, #shift // UBFM Xd, Xn, #(-shift MOD 64), #(63 - shift)
### ROR
レジスタ Rn の内容をレジスタ Rm で指定したビット数(レジスタのビット数で除算した剰余)でローテイトした値をレジスタ Rd に返却
ROR Wd, Wn, Wm // RORV Wd, Wn, Wm と同じ
ROR Xd, Xn, Xm // RORV Xd, Xn, Xm と同じ
ROR Wd, Ws, #shift // EXTR Wd, Ws, Ws, #shift
ROR Xd, Xs, #shift // EXTR Xd, Xs, Xs, #shift
### EXTR
レジスタ Wn とレジスタ Wm のペアを連結してデータのビット列を抽出。定数には抽出する最下位のビット位置を指定
EXTR Wd, Wn, Wm, #lsb
EXTR Xd, Xn, Xm, #lsb
実装例
num0: .quad 0xabcdefabcdefabcd
num1: .quad 0x1234567890123456
//
ldr x11, num0
ldr x12, num1
//
extr x0, X11, x12, #8 // CD12345678901234
extr x0, X11, x12, #16 // ABCD123456789012
extr x0, X11, x12, #24 // EFABCD1234567890
### ビットフィールドムーブ命令
レジスタ内の最下位のビットを含む連続したビット列(最も右側のビット列)を移動する命令。 移動先レジスタをゼロクリアして 移動するビット列の最上位を符号フラグとして移動先レジスタの 上位ビットに符号をコピーする SBFM 命令、 移動先のレジスタの内容の対応するビット列だけ上書きして元の内容を保持する BFM 命令、移動先レジスタをゼロクリアしてビット列だけ を書き込む UBFM 命令がある。
x2 : 923486789ABCDEF0
x3 : 0123456789ABCDEF (使われない)
SBFM X3, X2, #40, #23 --> x3 : FFFFBCDEF0000000
x2 : 923486789ABCDEF0
x3 : BBBBBBBBBBBBBBBB (保持される)
BFM X3, X2, #40, #23 --> x3 : BBBBBCDEF0BBBBBB
x2 : 923486789ABCDEF0
x3 : 0123456789ABCDEF (使われない)
UBFM X3, X2, #40, #23 --> x3 : 0000BCDEF0000000
### SBFM
Signed Bitfield Move の略で、ソースレジスタ(Wn、Xn)の 下位ビット側の任意の桁数 (imms+1) を、転送先レジスタの右シフト (immr)するビット位置にコピー
SBFM Wd, Wn, #immr, #imms SBFM Xd, Xn, #immr, #imms
x2 : 823456789ABCDEF0 x5 : 5555555555555555 SBFM X5, X2, #60, #23 --> FFFFFFFFFBCDEF00 SBFM X5, X2, #56, #23 --> FFFFFFFFBCDEF000 SBFM X5, X2, #60, #47 --> 00056789ABCDEF00 SBFM X5, X2, #56, #47 --> 0056789ABCDEF000 SBFM X5, X2, #24, #47 --> 000000000056789A SBFM X5, X2, #16, #23 --> FFFFFFFFFFFFFFBC SBFM X5, X2, #8, #23 --> FFFFFFFFFFFFBCDE
### ASR
ASR 命令 (Arithmetic Shift Right) は転送元レジスタの内容を定数で指定したビット数だけ右にシフトして転送先レジスタにコピー
ASR Wd, Wn, #shift // SBFM Wd, Wn, #shift, #31
ASR Xd, Xn, #shift // SBFM Xd, Xn, #shift, #63
### SBFIZ
SBFIZ (Signed Bitfield Insert in Zero) 命令は、転送元レジスタの最下位ビットのビット番号が lsb、幅 が width のビット列を転送先レジスタの下位にコピー
SBFIZ Xd, Xn, #lsb, #width // SBFM Wd, Wn, #(-lsb MOD 32), #(width-1)
SBFIZ Wd, Wn, #lsb, #width // SBFM Xd, Xn, #(-lsb MOD 64), #(width-1)
### SBFX
SBFX (Signed Bitfield Extract) 命令は、転送元レジスタの最下位ビットのビット番号が lsb、幅 が width のビット列を取り出して符号拡張して転送先レジスタにコピー
SBFX Wd, Wn, #lsb, #width // SBFM Wd, Wn, #lsb, #(lsb+width-1)
SBFX Xd, Xn, #lsb, #width // SBFM Xd, Xn, #lsb, #(lsb+width-1)
### SXTB
SXTB (Signed Extend Byte) 命令は転送元レジスタの下位8ビットを符号拡張して転送先レジスタにコピー
SXTB Wd, Wn // SBFM Wd, Wn, #0, #7
SXTB Xd, Wn // SBFM Xd, Xn, #0, #7
### SXTH
SXTH (Sign Extend Halfword) 命令は転送元レジスタの下位16ビットを符号拡張して転送先レジスタにコピー
SXTH Wd, Wn // SBFM Wd, Wn, #0, #15
SXTH Xd, Wn // SBFM Xd, Xn, #0, #15
### SXTW
SXTW (Sign Extend Word) 命令は転送元レジスタの下位32ビットを符号拡張して転送先レジスタにコピー
SXTW Xd, Wn // SBFM Xd, Xn, #0, #31
### BFM
この命令は Bitfield Move の略で、ソースレジスタ(Wn、Xn)の 下位ビット側の任意の桁数 (imms+1) を、転送先レジスタの 右シフト(immr)したビット位置にコピー
BFM Wd, Wn, #imm6r, #imm6s // sf = 0 && N = 0
BFM Xd, Xn, #imm6r, #imm6s // sf = 1 && N = 1
x2 : 823456789ABCDEF0 x5 : 5555555555555555 BFM X5, X2, #60, #23 --> 555555555BCDEF05 BFM X5, X2, #56, #23 --> 55555555BCDEF055 BFM X5, X2, #60, #47 --> 55556789ABCDEF05 BFM X5, X2, #56, #47 --> 5556789ABCDEF055 BFM X5, X2, #24, #47 --> 555555555556789A BFM X5, X2, #16, #23 --> 55555555555555BC BFM X5, X2, #8, #23 --> 555555555555BCDE
### BFI
<--- width --->
before -----------------bbbbbbbbbbbbbbb
<--- width --->
lsb
after ------------bbbbbbbbbbbbbbb-----
BFI Wd, Wn, #lsb, #width // BFM Wd, Wn, #(-lsb MOD 32), #(width-1)
BFI Xd, Xn, #lsb, #width // BFM Xd, Xn, #(-lsb MOD 64), #(width-1)
### BFXIL
BFXIL命令 (Bitfield eXtract and Insert at Low end) は、転送元レジスタの最下位ビットのビット番号が lsb 幅 が width のビット列を転送先レジスタの下位にコピー
<--- width --->
lsb
before ------------bbbbbbbbbbbbbbb-----
<--- width --->
after -----------------bbbbbbbbbbbbbbb
BFXIL Wd, Wn, #lsb, #width // BFM Wd, Wn, #lsb, #(lsb+width-1)
BFXIL Xd, Xn, #lsb, #width // BFM Xd, Xn, #lsb, #(lsb+width-1)
### UBFM
UBFM Wd, Wn, #imm6r, #imm6s // sf = 0 && N = 0
UBFM Xd, Xn, #imm6r, #imm6s // sf = 1 && N = 1
x2 : 823456789ABCDEF0
x5 : 5555555555555555
UBFM X5, X2, #60, #23 --> 000000000BCDEF00
UBFM X5, X2, #56, #23 --> 00000000BCDEF000
UBFM X5, X2, #60, #47 --> 00056789ABCDEF00
UBFM X5, X2, #56, #47 --> 0056789ABCDEF000
UBFM X5, X2, #24, #47 --> 000000000056789A
UBFM X5, X2, #16, #23 --> 00000000000000BC
UBFM X5, X2, #8, #23 --> 000000000000BCDE
### LSL
LSL Wd, Wn, #shift // UBFM Wd, Wn, #(-shift MOD 32), #(31-shift)
LSL Xd, Xn, #shift // UBFM Xd, Xn, #(-shift MOD 64), #(63-shift)
### LSR
LSR Wd, Wn, #shift // UBFM Wd, Wn, #shift, #31
LSR Xd, Xn, #shift // UBFM Xd, Xn, #shift, #63
### UBFIZ
UBFIZ (Unsigned Bitfield Insert in Zero) 命令は転送先レジスタを0にした後、転送元レジスタの最下位ビットのビット番号が lsb、幅 が width のビット列を転送先レジスタの下位にコピー
UBFIZ Wd, Wn, #lsb, #width // UBFM Wd, Wn, #(-lsb MOD 32), #(width-1)
UBFIZ Xd, Xn, #lsb, #width // UBFM Xd, Xn, #(-lsb MOD 64), #(width-1)
### UBFX
UBFX (Unsigned Bitfield Extract) 命令は転送先レジスタを0にした後、、転送元レジスタの最下位ビットのビット番号が lsb、幅 が width のビット列を転送先レジスタの下位にコピー。コピーするビット列をゼロ拡張して転送する動作となる
UBFX Wd, Wn, #lsb, #width // UBFM Wd, Wn, #lsb, #(lsb+width-1)
UBFX Xd, Xn, #lsb, #width // UBFM Xd, Xn, #lsb, #(lsb+width-1)
### UXTB
UXTB (Unsigned Extend Byte) 命令は転送元レジスタの下位8ビットをゼロ拡張して転送先レジスタにコピー
UXTB Wd, Wn // UBFM Wd, Wn, #0, #7
### UXTH
UXTH (Sign Extend Halfword) 命令は転送元レジスタの下位16ビットをゼロ拡張して転送先レジスタにコピー
UXTH Wd, Wn // UBFM Wd, Wn, #0, #15