RISC-V常用指令学习笔记

RISC-V是一个基于精简指令集原则的开源指令集架构

ISA 指令集架构

ABI 应用程序二进制接口

PC  程序计数器

B-type 条件跳转指令

J-type 无条件跳转指令

I-type 寄存器-立即数指令

R-type寄存器-寄存器指令

RISC-V常用指令学习笔记_第1张图片 

(risc-v传输的数据都是32位字长,所以要进行扩展,sign-extended符号位扩展,zero-extended零扩展)

//offset,imm等、操作时都需要进行符号扩展,sexd()/(sign-extend)

1 R-type 寄存器-寄存器指令

funct-7

rs2-5

rs1-5

funct-3

rd-5

opcode-7

R-type

0000000

rs2

rs1

000

rd

0110011

R add

0100000

rs2

rs1

000

rd

0110011

R sub

0000000

rs2

rs1

001

rd

0110011

R sll

0000000

rs2

rs1

010

rd

0110011

R slt小置位

0000000

rs2

rs1

011

rd

0110011

R sltu

0000000

rs2

rs1

100

rd

0110011

R xor

0000000

rs2

rs1

101

rd

0110011

R srl

0100000

rs2

rs1

101

rd

0110011

R sra

0000000

rs2

rs1

110

rd

0110011

R or

0000000

rs2

rs1

111

rd

0110011

R and

1. ADD rd, rs1, rs2

x[rd] = x[rs1] + x[rs2],忽略溢出,保留低32bit

2. SUB rd, rs1, rs2

x[rd]  = x[rs1] - x[rs2],忽略溢出,保留低32bit

3. AND rd, rs1, rs2

x[rd]  = x[rs1] & x[rs2],按位与 &   //&&逻辑与

4. OR rd, rs1, rs2

x[rd]  = x[rs1] | x[rs2],按位或 |

5. XOR rd, rs1, rs2

x[rd] = x[rs1] ^ x[rs2], 按位异或 ^

6. SLT  (set less than小于置1)

SLT rd, rs1, rs2     

if (x[rs1] < x[rs2])  x[rd] = 1 else x[rd] = 0

7. SLTU  (set less than unsigned)

SLTU rd, rs1, rs2

if((unsigned)x[rs1] < (unsigned)x[rs2])  x[rd] = 1 else x[rd] = 0

8. SLL  (shift left logical)

SLL rd, rs1, rs2

rd = x[rs1] << rs2 [4 : 0],逻辑左移,低位补零,rs2的lower 5 bits作为偏移量,将寄存器rs1的值左移寄存器rs2的值这么多位,并写入寄存器rd //算数左移也是低位补零

9. SRL  (shift right logical)

SRL rd, rs1, rs2    

rd = x[rs1] >> rs2 [4 : 0],逻辑右移,高位补零,rs2的lower 5 bits作为偏移量

10. SRA  (shift right arithmetic)

SRA rd, rs1, rs2

rd = x[rs1] >> rs2 [4 : 0],算数右移,高位补符号位,rs2的lower 5 bits作为偏移量

2 S-type用于内存存储操作

Imm-7

rs2-5

rs1-5

funct-3

Imm-5

opcode-7

S-type

imm[11:5]

rs2

rs1

000

imm[4:0]

0100011

S sb字节

imm[11:5]

rs2

rs1

001

imm[4:0]

0100011

S sh半字

imm[11:5]

rs2

rs1

010

imm[4:0]

0100011

S sw字

Load指令使用的是I-Type指令的格式

Store指令使用的是S-Type指令的格式

Load和Store指令的偏移量均由一个12位的立即数给出,但是它们在指令中的位置不同,这是由指令的功能决定的:

Load指令需要将内存中的数据转移到寄存器组,因此需要提供目标寄存器

Store指令需要将寄存器组中的数据转移到内存,因此需要rs1提供内存中将要写入数据的地址,rs2提供需要转移的数据。

8086 [段地址*16(逻辑地址)+偏移地址=物理地址]  //数据线16位,地址线20位

1. SB (store byte)

sb rs2, offset(rs1)

mem(x[rs1]+(sign-extend)offset)=x[rs2] [7:0]

//把寄存器rs2的值存入地址为寄存器rs1的值加offset的主存中,保留最右端的8位

2. SH (store half)

sh rs2, offset(rs1)

mem(x[rs1]+(sign-extend)offset)=x[rs2] [15:0]

//把寄存器rs2的值存入地址为寄存器rs1的值加offset的主存中,保留最右端的16位

3. SW (store word)

sw rs2, offset(rs1)

mem(x[rs1]+(sign-extend)offset)=x[rs2] [31:0]

//把寄存器rs2的值存入地址为寄存器rs1的值加offset的主存中,保留最右端的32位

3 I-type寄存器-立即数指令

imm[11:0]立即数

rs1-5

funct-3

rd-5

opcode-7

I-type

imm[11:0]

rs1

000

rd

1100111

I jalr

1. JALR  (jump and link register)

jalr rd,offset(rs1)   //其他写法??jalr rd,rs1,offset

把下一条指令的地址存到rd中,然后跳转到rs1+offset地址处的指令继续执行。

//类似函数调用?

imm[11:0]立即数

rs1-5

funct-3

rd-5

opcode-7

I-type

imm[11:0]

rs1

000

rd

0000011

I lb

imm[11:0]

rs1

001

rd

0000011

I lh

imm[11:0]

rs1

010

rd

0000011

I lw

imm[11:0]

rs1

100

rd

0000011

I lbu

imm[11:0]

rs1

101

rd

0000011

I lhu

1. LW  (load word载入字=4字节)

LW rd, offset(rs1)

x[rd] = mem[x[rs1] + (sign-extended) offset] [31:0]

2. LH (load half载入半字=2字节)

LH rd, offset(rs1)

x[rd] = (sign-extended) mem[x[rs1] + (sign-extend) offset)] [15:0]

(从地址为寄存器rs1的值加offset的主存中读一个字节,符号扩展后存入rd)

3. LB (load byte载入字节)

LB rd, offset(rs1)

x[rd] = (sign-extended) mem[x[rs1] + (sign-extend) offset)] [7:0]

4. LBU (load byte unsigned载入8位无符号字节)

LBU rd, offset(rs1)

x[rd] = (zero-extended) mem[x[rs1] + (sign-extend) offset)] [7:0]

(从地址为寄存器rs1的值加offset的主存中读一个无符号的字节,零扩展后存入rd)

5. LHU (load half unsigned载入8位无符号字节)

imm[11:0]立即数

rs1-5

funct-3

rd-5

opcode-7

I-type

imm[11:0]

rs1

000

rd

0010011

I addi

imm[11:0]

rs1

010

rd

0010011

I slti

imm[11:0]

rs1

011

rd

0010011

I sltiu

imm[11:0]

rs1

100

rd

0010011

I xori

imm[11:0]

rs1

110

rd

0010011

I ori

imm[11:0]

rs1

111

rd

0010011

I andi

imm[11:0]

rs1

001

rd

0010011

I slli

imm[11:0]

rs1

101

rd

0010011

I srli

imm[11:0]

rs1

101

rd

0010011

I srai

(imm是一个12位的立即数,在与32位的寄存器进行逻辑运算时必须进行符号位扩展)

1. ADD rd, rs1, imm

x[rd] = x[rs1] + (sign-extended) imm,忽略溢出,保留低32bit

2. AND rd, rs1, imm

x[rd] = x[rs1] & (sign-extended) imm,按位与 &   // &&逻辑与

3. OR rd, rs1, imm

x[rd] = x[rs1] | (sign-extended) imm,按位或 |

4. XOR rd, rs1, imm

x[rd] = x[rs1] ^ (sign-extended) imm, 按位异或 ^

5. SLTI  (set less than immediate)

SLT rd, rs1, imm

if (x[rs1] < (sign-extended) imm)  x[rd] = 1 else x[rd] = 0

6. SLTIU  (set less than unsigned immediate)

SLTU rd, rs1, imm

if((unsigned)x[rs1]< (unsigned)(sign-extended)imm)  x[rd] = 1 else x[rd] = 0

RISC-V常用指令学习笔记_第2张图片

//移动指令中imm低6位作为偏移量,且当第6位为0指令才有效

1. slli  (Shift Left Logical Immediate立即数)  

slli rd, rs1, imm   

rd = x[rs1] << imm,逻辑左移,空位补零,结果写入rd

2. srli  (Shift Right Logical Immediate立即数)

srli rd, rs1, imm   

rd = x[rs1] >> imm,逻辑右移,空位补零,结果写入rd

3. srai  (Shift Right Arithmetic Immediate立即数)

srai rd, rs1, imm   

rd = x[rs1] >> imm,算数右移,高位补符号位,结果写入rd

imm[11:0]立即数

rs1-5

funct-3

rd-5

opcode-7

I-type

0000

pred

succ

00000

000

00000

0001111

I fence

0000

0000

0000

00000

001

00000

0001111

I fence.i

0000 0000 0000

00000

000

00000

1110011

I ecall

0000 0000 0001

00000

000

00000

1110011

I ebreak

csr

(control statue register)

rs1

001

rd

1110011

I csrrw

csr控制状态寄存器

rs1

010

rd

1110011

I csrrs

csr

rs1

011

rd

1110011

I csrrc

csr

zimm

101

rd

1110011

I csrrwi

csr

zimm

110

rd

1110011

I cssrrsi

csr

zimm

111

rd

1110011

I csrrci

4 B-type条件跳转指令

Imm-7

rs2-5

rs1-5

funct-3

Imm-5

opcode-7

B-type

imm[12|10:5]

rs2

rs1

000

imm[4:1|11]

1100011

B beq等于

imm[12|10:5]

rs2

rs1

001

imm[4:1|11]

1100011

B bne不等

imm[12|10:5]

rs2

rs1

100

imm[4:1|11]

1100011

B blt小于

imm[12|10:5]

rs2

rs1

101

imm[4:1|11]

1100011

B bge大于等于

imm[12|10:5]

rs2

rs1

110

imm[4:1|11]

1100011

B bltu

imm[12|10:5]

rs2

rs1

111

imm[4:1|11]

1100011

B bgeu

1. BEQ  (branch equal)

BEQ rs1, rs2, offset  

if (x[rs1] == x[rs2])  pc += (sign-extended) offset 

如果x[rs1]=x[rs2],pc的值被设置为当前值加上符号扩展偏移量,程序跳转到此时pc所指的地址继续执行。

//其他指令类似

2. BLTU  (branch less than unsigned无符号)

BLTU rs1, rs2, offset

if((unsigned) x[rs1]  < (unsigned) x[rs2])  pc += (sign-extended) offset 

如果x[rs1]符号扩展偏移量,程序跳转到此时pc所指的地址继续执行。

//其他指令类似

blt    (Branch if less than)小于

bne   (Branch if not equal)不等于

bge   (Branch if greater or equal)大于等于

bltu   (Branch if Less Than, Unsigned)

bgeu  (Branch if greater or equal, Unsigned)

5 J-type无条件跳转指令

Imm-20

Rd-5

opcode-7

J-type

imm[20|10:1|11|19:12]

rd

1101111

J jal

JAL  (jump and link)  

jal rd, offset

x[rd]=pc+4  //rd内存入下一条指令的地址,一条指令占4个字节

pc+=(sign-extended)offset  //程序跳转,继续执行

//对比I-type的JASR(jump and link register)

imm[11:0]立即数

rs1-5

funct-3

rd-5

opcode-7

I-type

imm[11:0]

rs1

000

rd

1100111

I jalr

JALR  (jump and link register)

jalr rd,offset(rs1)   //其他写法??jalr rd,rs1,offset

把下一条指令的地址存到rd中,然后跳转到rs1+offset地址处的指令继续执行。

//类似函数调用?

6 U-type用于长立即数操作

Imm-20

Rd-5

opcode-7

U-type

imm[31:12]

rd

0110111

U lui

imm[31:12]

rd

0010111

U auipc

1. LUI  (load upper immediate载入长立即数)

lui rd, imm

x[rd] = sext(imm[31:12] << 12)

//将符号扩展的20位立即数左移12位,即低12位抹零后存入rd中

2. AUIPC  (add upper immediate to pc)

auipc rd, imm

x[rd] = pc + sext(imm[31:12] << 12)

//将符号扩展的20位立即数左移12位,即低12位抹零后加上pc,结果存入rd中

7 乘法和除法指令

RISC-V常用指令学习笔记_第3张图片

 

funct-7

rs2-5

rs1-5

funct-3

rd-5

opcode-7

R-type

0000001

rs2

rs1

000

rd

0110011

R mul

0000001

rs2

rs1

001

rd

0110011

R mulh

0000001

rs2

rs1

010

rd

0110011

R mulhsu

0000001

rs2

rs1

011

rd

0110011

R mulhu

0000001

rs2

rs1

100

rd

0110011

R div

0000001

rs2

rs1

101

rd

0110011

R divu

0000001

rs2

rs1

110

rd

0110011

R rem余数

0000001

rs2

rs1

111

rd

0110011

R remu

//负数以补码的形式存放,补码等于原码取反加一(符号位不变),补码取反加一是绝对值

1. MUL  (multiple乘法)

mul rd, rs1, rs2

x[rd] = x[rs1] * x[rs2]

把寄存器 x[rs2]与寄存器 x[rs1]相乘,乘积写入 x[rd]。忽略算术溢出

2. MULH  (Multiply High)

mulh rd, rs1, rs2

x[rd] = (x[rs1] * x[rs2]) ≫XLEN

把寄存器 x[rs2]与寄存器 x[rs1]相乘,x[rs1] x[rs2]都视为二进制补码(都为有符号数),将乘积的高位(左32位)写入x[rd]。

//二进制补码(2的补码):(计算机中负数的表示方式)

第一步,每一个二进制位都取反值,0变成1,1变成0。

第二步,将上一步的得到的值加1

3. MULHSU  (Multiply High Signed-Unsigned)

mulhsu rd, rs1, rs2

x[rd] = (x[rs1] * x[rs2]) ≫XLEN

把寄存器 x[rs2]与寄存器 x[rs1]相乘,x[rs1]为二进制的补码(有符号数),x[rs2]为无符号数,将乘积的高位写入x[rd]。

4. MULHU  (Multiply High Unsigned)

mulhu rd, rs1, rs2

x[rd] = (x[rs1] * x[rs2]) ≫XLEN

把寄存器 x[rs2]与寄存器 x[rs1]相乘,x[rs1] x[rs2]都为无符号数,将乘积的高位写入x[rd]。

5. DIV  (Divide除法)

div rd, rs1, rs2

x[rd] = x[rs1] / x[rs2 signed]

用寄存器 x[rs1]的值除以寄存器 x[rs2]的值,向零舍入(正数向下舍入,负数向上舍入,舍入的方向要朝向0),将这些数视为二进制补码,把商写入x[rd]。

6. DIVU  (Divide Unsigned无符号除法)

divu rd, rs1, rs2

x[rd] = x[rs1] / x[rs2 unsigned]

用寄存器 x[rs1]的值除以寄存器 x[rs2]的值,向零舍入,将这些数视为无符号数,把商写入x[rd]。

你可能感兴趣的:(risc-v)