slli

slli

RISC-V アセンブリ 参考

lyszt.netはslliおよびその他のRISC-V命令をより詳しく扱っています。

エンコーディング形式

R
31–25funct7
24–20rs2
19–15rs1
14–12funct3
11–7rd
6–0opcode
I
31–20imm[11:0]
19–15rs1
14–12funct3
11–7rd
6–0opcode
S
31–25imm[11:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:0]
6–0opcode
B
31–25imm[12,10:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:1,11]
6–0opcode
U
31–12imm[31:12]
11–7rd
6–0opcode
J
31–12imm[20,10:1,11,19:12]
11–7rd
6–0opcode

説明

slli はビットを固定量だけ左にシフトします。この操作は sll と同じです。ビットは左に滑り、右側にはゼロが入り、左端を越えたビットは失われ、1 桁移動するごとに値が 2 倍になります(仕組みについては sll のページで説明しています)。この命令はシフト距離を定数として保持するため、レジスタから供給されることはありません。i は即値(immediate)を意味し、これは命令に書き込まれる定数を指す用語です。

slli の形式を以下に示します。ここで amount は 0 から 31 までの固定数です。

slli rd, rs1, amount

次の行は t0 を 3 桁左にシフトし、これは 8 倍することに相当します。

slli t1, t0, 3

配列を使うとこの命令はよく登場します。配列内の 32 ビット値は 4 バイトを占めるため、i 番目の要素は先頭から i × 4 バイトの位置にあり、2 だけ左シフトすると 4 倍になります。通常のパターンでは、インデックスをシフトしてバイトオフセットを生成し、配列の開始アドレスを加算してから値をロードします。このシフト、加算、ロードの並びを見抜けると、他人が書いたアセンブリを読むときに役立ちます。

RISC-V マニュアルでは、定数によるシフトは標準的な命令レイアウトの 1 つである I タイプ形式の特殊化としてエンコードされます。rs1 はシフトされるオペランドを保持し、即値フィールドの下位 5 ビットがシフト量を保持します。slli は論理左シフトを実行し、下位ビットにはゼロが入ります。

コードを書く時点でシフト距離がわかっている場合は slli を使います。プログラム実行中に量が計算される場合は sll を使います。例では 5 を 3 だけ左にシフトし、これは 5 × 8、つまり 40 になります。

例

li t0, 5
slli t1, t0, 3   # t1 = 5 << 3 = 40  (5 * 8)