Riscv 指令集
立即数:
不同的立即数提取的方式不同,需要通过位运算实现立即数的拼接。
static word_t immI(uint32_t i) { return SEXT(BITS(i, 31, 20), 12); }
static word_t immU(uint32_t i) { return SEXT(BITS(i, 31, 12), 20) << 12; }
static word_t immS(uint32_t i) { return (SEXT(BITS(i, 31, 25), 7) << 5) | BITS(i, 11, 7); }
/* add by leesum */
static word_t immB(uint32_t i) {
return (SEXT(
BITS(i, 31, 31), 1) << 12 |
BITS(i, 7, 7) << 11 |
BITS(i, 30, 25) << 5 |
BITS(i, 11, 8) << 1 |
0);
}
static word_t immJ(uint32_t i) {
return (SEXT(
BITS(i, 31, 31), 1) << 20 |
BITS(i, 19, 12) << 12 |
BITS(i, 20, 20) << 11 |
BITS(i, 30, 21) << 1 |
0);
}
SEXT函数的作用,能够进行符号拓展,所有的立即数都通过immI、immU、immS、immB、immJ进行了符号拓展。
SEXT的实现操作如下:
#define SEXT(x, len) ({ struct { int64_t n : len; } __x = { .n = x }; (uint64_t)__x.n; })
上述函数的意思就是通过定义结构体实现符号拓展
BITS的操作实现如下:
#define BITMASK(bits) ((1ull << (bits)) - 1)
#define BITS(x, hi, lo) (((x) >> (lo)) & BITMASK((hi) - (lo) + 1)) // similar to x[hi:lo] in verilog
BITS函数能够实现对指定位的提取
**如果不理解SEXT的宏如何实现可以学习这篇文章:**https://www.cnblogs.com/zhangsanlisi411/p/16757422.html
符号转化
由于在指令中通常出现符号拓展,需要进行转化。故声明如下的宏定义:
#define S32(i) ((int32_t)i)
#define S64(i) ((int64_t)i)
#define U32(i) ((uint32_t)i)
#define U64(i) ((uint64_t)i)
不同指令的具体生成以及注意细节
操作运算符指令:
add、sub、and、or、xor R型指令
我们可以通过其指令分布可知,指令均为R型立即数指令
p37
由上述可知,ADD指令位rs1 + rs2得到,同理SUB指令、AND指令、OR指令、XOR指令,不做过多赘述
sltu slt R型指令
p38
上述分析可知,SLT表示有符号比较,SLTU表示无符号比较,伪代码可以描述如下:
SLTU:R(rd) = U64(rs1) < U64(rs2) ? 1 : 0
SLT: R(rd) = S64(rs1) < S64(rs2) ? 1 :0
举例子:
十六进制:0xffff ffff ffff ffff 与 0x0000 0000 0000 0000 在两种比较下大小不相同
I型立即数操作运算
addi xori ori andi
p36
第一次出现,sign-extended,
What is sign-extended?
基础知识:原码 补码 反码
原码16位-1 : 1000 0000 0000 0001
反码16位: 1111 1111 1111 1110
补码 : 1111 1111 1111 1111
https://blog.csdn.net/qq_48052049/article/details/125994544
好好想想!前面有链接哦 这个很重要!
slti sltiu
p36
SLTI:
上述可分析出如果rs1小于符号拓展后的立即数则为1反之则为0,一定要注意都要被当作符号类型进行运算!!!
SLTIU:被当作无符号类型
SRAI SRLI SLLI
p37
SRAI:
注意:上述描述我们知道,逻辑移位以及算术移位实际上就是无符号类型与有符号类型的移位。
lb lh lw ld
P42
LOAD(lb、lh、lw、ld)
Loads are encoded in the I-type format and stores are S-type
The effective address is obtained by adding register rs1 to the sign-extended 12-bit offset
上句描述表明load的地址位:rs1 + imm
注意:当在内存里面读一个数据的时候如果读取的位数小于X_len(最高位),那么转化为有符号型或者无符号型是一个很重要的问题
提示:lb、lh、lw都需要进行符号拓展
lbu lhu lwu
通过上图自行分析
sb sh sw sd
The SD, SW, SH, and SB instructions store 64-bit, 32-bit, 16-bit, and 8-bit values from the low bits of register rs2 to memory respectively.
从低位load:
branch指令
beq bne blt bge
p40
beq bne
仔细阅读!
blt bge
注意红字,有符号比较以及无符号比较
w结尾的指令
W指令的定义:
将32位作为符号位进行符号拓展得到符号拓展的64位riscv指令
p56
mul/div系列指令
P64
比如:两个64位的数字相乘得到128位以内的数字,这个128位以内的数字可以向算术右移64位就可以得到相乘后的结果,溢出不做考虑
mulh mulhu mulhsu
MULH, MULHU, and MULHSU perform the same multiplication but re- turn the upper XLEN bits of the full 2×XLEN-bit product, for signed×signed, unsigned×unsigned, and signed rs1×unsigned rs2 multiplication, respectively.
div略