基础指令集
riscv指令码格式
加载与存储指令
加载指令
l {d|w|h|b} {u} rd, offset(rs1)
-
l: 表示加载(load)操作
-
{d|w|h|b}
:这是指定加载的数据大小的字段。它表示数据的字长,可以是字(d
)、半字(h
)、字节(b
)或者字宽(w
)。-
d
:加载一个64位的双字。 -
w
:加载一个32位的字。 -
h
:加载一个16位的半字。 -
b
:加载一个8位的字节。
-
-
{u}
:这是一个可选的字段,表示无符号加载。如果指定了u
,则执行无符号加载。否则,默认为有符号加载。 -
rd
:目标寄存器,用于存储加载的数据。 -
offset
:偏移量,表示相对于rs1
的内存偏移地址。 -
rs1
: 表示源寄存器1 -
(rs1)
: 基地址寄存器,表示以rs1寄存器里的值为地址进行寻址
lui rd, imm
将立即数imm左移12位,然后符号扩展,将结果写入rd寄存器中。
存储指令
s {d|w|h|b} {u} rs2, offset(rs1)
-
s
: 表示存储(store)操作。 -
{d|w|h|b}
: 这是指定存储的数据大小的字段。它表示数据的字长,可以是字(d
)、半字(h
)、字节(b
)或者字宽(w
)。-
d
:存储一个64位的双字。 -
w
:存储一个32位的字。 -
h
:存储一个16位的半字。 -
b
:存储一个8位的字节。
-
-
{u}
: 这是一个可选的字段,表示无符号存储。如果指定了u
,则执行无符号存储。否则,默认为有符号存储。 -
rs2
: 源寄存器,其中包含要存储到内存中的数据。 -
offset
: 偏移量,表示相对于rs1
的内存偏移地址。 -
(rs1)
: 基地址寄存器,表示以rs1寄存器里的值为地址进行寻址。
pc相对寻址
auipc rd, imm
auipc
用于将无符号的相对地址添加到程序计数器 (pc
) 中,auipc
是 “Add Upper Immediate to Program Counter” 的缩写。
-
rd
:目标寄存器,表示要存储结果的寄存器。 -
imm
:一个20位的立即数,表示无符号的相对地址,立即数带符号扩展到64位
auipc
指令的作用是将 imm
左移12位(因为RISC-V指令集中的立即数通常是左移12位的),然后将结果与程序计数器(pc
)的当前值相加,最后将结果存储到目标寄存器 rd
中。
这个指令通常用于构建全局地址,以便进行全局跳转或加载全局变量。例如,如果你执行 auipc x1, 0x1234
,那么 x1
将包含当前 pc
加上 0x12340000
的值。
伪指令
RISC-V架构中的伪指令(Pseudo Instructions)是一类在汇编层面上提供方便或语法糖的指令,它们不是硬件上的实际指令,而是在汇编阶段被翻译成真实的RISC-V指令序列。
这些伪指令的目的是为了简化编程、提高代码可读性和便于移植性。
- 加载立即数到寄存器伪指令
li rd, imm
li
是 RISC-V 汇编语言中的一条伪指令,用于将一个立即数(immediate)加载到目标寄存器中。
li rd, imm
: li
是 “Load Immediate” 的缩写。
-
rd
: 目标寄存器,表示要存储结果的寄存器。 -
imm
: 立即数,表示要加载到寄存器中的数值。
例如:
li x1, 42
这条指令将常数 42
加载到寄存器 x1
中。虽然 li
是一个伪指令,但编译器会将其转化为实际的RISC-V指令序列,通常是 lui
(Load Upper Immediate)和 addi
(Add Immediate)的组合。在这个例子中,li x1, 42
可能会被翻译成以下实际的指令:
lui x1, 0 // 将常数的高 20 位加载到 x1
addi x1, x1, 42 // 将常数的低 12 位添加到 x1
这样,li
指令提供了一种方便的方式来将一个常数加载到寄存器中,而不必手动分解成高位和低位两个部分。
- 加载符号地址伪指令
la rd, symbol (非PIC) // 加载符号的绝对地址
la rd, symbol (PIC) // 加载符号的绝对地址
la rd, symbol(Non PIC)
: la
是 “Load Address” 的缩写。它用于加载一个符号(如标签或变量)的绝对地址到目标寄存器 rd
。
在底层,它可能会被翻译为两条指令:
// note: delta = symbol - pc
auipc rd, delta[31:12] + delta[11] // delta[31:12]: 绝对地址的高位 => rd = pc + delta[31:12] + delta[11]
addi rd, rd, delta[11:0] // delta[11:0]: 绝对地址的低位 => rd = pc + delta[31:12] + delta[11] + delta[11:0]
-
auipc rd, delta[31:12]
: 这一部分使用auipc
指令,将符号的高位加载到目标寄存器rd
。auipc
操作是将符号左移12位(即delta[31:12]
)并加到程序计数器的当前值上,从而得到符号的高位。其中加上delta[11]是为了消除符号位的影响 -
addi rd, rd, delta[11:0]
:这一部分使用addi
指令,将符号的低位加载到目标寄存器rd
。addi
操作是将符号的低位(即delta[11:0]
)加到之前auipc
部分计算的结果上,完成加载。
la rd, symbol(PIC)
: 用于加载一个符号(如标签或变量)的相对地址到目标寄存器 rd
。
在底层,它可能会被翻译为两条指令:
// note: delta = GOT(symbol) - pc
auipc rd, delta[31:12] + delta[11] // delta[31:12]: 绝对地址的高位
l{w|d} rd, delta[11:0](rd) // delta[11:0]: 绝对地址的低位
移位指令
- sll: 逻辑左移(shift left logic),最高位丢弃,最低位补0
- srl: 逻辑右移(shift right logic),最低位丢弃,最高位补0
- sra: 算数右移(shift right arithmetic),最低位丢弃,最高位按符号扩展
##### 逻辑左移指令
将rs1寄存器,逻辑左移rs2位,结果写入rd寄存器中
sll rd, rs1, rs2