RISC V::RV32I 指令介绍

本文目标

  • 学习 RV32I

进入正题

RV32I 是 32-bit 的基本整数指令集,该指令集会使用到 32 个暂存器 (x0-x31),且一共有 47 道指令,RV32I 的指令一共可分成六大类:

  • I-Type
    包含了暂存器与立即数的运算。
  • R-Type
    此类型的指令会有 3 个暂存器作为 Input ,分别是: rd, rs1, rs2 。
  • S-Type
    包含存取记忆体的指令。
  • SB-Type
    分支指令 (条件跳转)。
  • U-Type
    将立即数放到高位,这些指令被设计来实现完整的 32 bits 运算。
  • UJ-Type
    跳转指令。

为了方便, RISC-V 将一个 WORD 的大小设成 4 Bytes (32 bits) ,同时, RISC-V 的指令长度也是 32 bits,这些空间会被分割成好几个 fields,不同类型的指令都会有不同的分配方式。

I-Format

这种类型的指令代表暂存器与常数之间的运算:

| 31                20 | 19   15 | 14      12 | 11  07 | 06      00 |
+----------------------+---------+------------+--------+------------+
|   immediate[11:0]    |   rs1   |   funct3   |   rd   |   opcode   |
+----------------------+---------+------------+--------+------------+

ADDI

addi rd, rs1, simm12

常数部分为 (simm12) 为 12 位元的有号数,运算时会将 12 位元扩展成 32 位元,与 rs1 暂存器做加法运算并将结果写进 rd 暂存器中。

关於 simm12 扩展的逻辑,我们可以参考 rv32emu-next 的实作:

// FI_IMM_11_0  = 0b11111111111100000000000000000000
static inline int32_t dec_itype_imm(uint32_t inst){
   return ((int32_t)(inst & FI_IMM_11_0)) >> 20;
}

SLTI[U]

slti rd, rs1, simm12

运算时会将 12 位元扩展成 32 位元,再与 rs1 暂存器当做 signed number 做比较(如果指令为 SLTIU 则视为无号数),若 rs 暂存器 1 小於常数,则将数值 1 写入 rd 暂存器,否则为 0 。

补充
本篇文章的 simm[number] 代表有号的 number 个位元,若是 uimm[number] 则代表无号的 number 个位元。
若出现在下方指令,就不再特别说明。

ANDI/ORI/XORI

andi/ori/xori rd, rs1, simm12

将 simm12 扩展後与 rs1暂存器做 AND / OR / XOR 运算,再将结果写入 rd 暂存器中。

SLLI/SRLI/SRAI

slli/srli/srai rd, rs1, uimm5

常数部分为 unsigned 5 bits,将 rs1 暂存器做 shift 运算,偏移量为 uimm5 的值 (0 - 31),偏移後的结果会写入 rd 暂存器。

  • SLLI 代表逻辑左移
  • SRLI 为逻辑右移
  • SRAI 为算数右移

LW/LH/LHU/LB/LBU

lw/lh/lhu/lb/lbu rd, rs1, simm12

将 rs1 暂存器的内容加上 simm12 视为地址,并将该地址存放的值放到 rd 中。

  • LW 为载入 32 bits (WORD) 资料写入 rd 中。
  • LH/LHU 为载入 16 bits (Half of WORD) 资料分别做有号与无号扩展成 32 bits 後写入 rd 中。
  • LB/LBU 为载入 8 bits (BYTE) 资料分别做有号与无号扩展成 32 bits 後写入 rd 中。

U-Format

包含 upper immediates 的指令

LUI (Load upper immediate)

lui rd, uimm20

将 uimm20 存放到 rd 暂存器的高位 20 bits 中,剩余的 12 bits 皆为 0 。

  • AUIPC (add upper immediate to pc)
auipc rd, uimm20

unsigned 20-bit放到最高 20位元,剩余 12位元补0,将此数值与 pc相加写入 rd暂存器。

R-Format

指令为暂存器与暂存器之间的运算

ADD/SUB

add/sub rd, rs1, rs2

将 rs1 与 rs2 做加法/减法运算後,再将结果写入 rd暂存器。

SLT/SLTU

slt/sltu rd, rs1, rs2

将 rs1 与 rs2 暂存器当做有号或是无号数做比较,若 rs1 小於 rs2 ,将数值 1 写入 rd ,反之写入 0 。

AND/OR/XOR

and/or/xor rd, rs1, rs2

将 rs1 与 rs2 做 AND/OR/XOR 运算,并将结果写入 rd 中。

SLL/SRL/SRA

sll/srl/sra rd, rs1,, rs2

将 rs1 做 shift 运算,再将结果写入 rd 暂存器,rs2 的最低 5 位为代表位移量。

NOP 指令

NOP 指令即为不改变任何暂存器状态,除了 pc 以外。
NOP 指令会被编码成 addi x0, x0, 0 替代。

UJ-Format

UJ-Format 包含了无条件跳跃 (Unconditional Jumps) 类型的指令。

JAL (jump and link)

jal rd, simm21

常数部分为 21 位元的有号数(此常数必须为 2 的倍数,代表 LSB 必为 0 ),因为此道指令编码的常数位元数只有 20位元,所以只会将 simm21 的最高 20 位元放入指令编码中,跳跃范围为 -+1MiB ,同时也会将下一道指令的位址 pc+4 写入 rd 暂存器中,在标准的 calling convention 中,rd 暂存器会使用 x1 。如果只是单纯的 jump,并非是呼叫函示需要储存其返回位址 pc+4,可用 jal x0, simm21 取代。

JALR (jump and link register)

jalr rd, rs1, simm12

跳跃的位址为 rs暂存器加上 simm12 ,并把下一道指令的位址 pc+4 写入 rd 暂存器中。

SB-Format

SB-Format 包含了条件跳跃 (Conditional Branches) 类型的指令。

BEQ/BNE/BLT/BLTU/BGE/BGEU

beq/bne/blt/bltu/bge/bgeu rs1, rs2, simm13

常数部分必须为 2的倍数,即最低位元为 0 ,因为此道指令编码的常数位元数只有 12 位元,所以只会将 simm13 的最高 12 位元放入指令编码中,跳跃范围为 -+4Kib 。

  • BEQ/BNE 将 rs1 与 rs2 做相同与不同的比较,若成立则跳跃。
  • BLT/BLTU 将 rs1与 rs2 分别做有号/无号的小於比较,若成立则跳跃。
  • BGE/BGEU 将 rs1 与 rs2 分别做有号/无号的大於等於比较,若成立则跳跃,跳跃的位址则为 pc 加上 simm13 。

S-Format

将内容存放到记忆体中的指令。

SW/SH/SB

sw/sh/sb rs2, rs1, simm12

将 rs1 暂存器的内容加上 simm12 视为地址,并将 rs2 的资料写到该地址中。

  • SW 将 rs2 暂存器完整 32 bits 资料写入地址。
  • SH 将 rs2 暂存器最低 16 bits 资料写入地址。
  • SB 将 rs2 暂存器最低 8 bits 资料写入地址。

Memory model

定义了一组 FENCE 指令,达到多个 thread 间的记忆体同步。

控制与状态暂存器指令 (Control and Status Register Instructions)

CSR Instructions

CSRRW / CSRRS / CSRRC / CSRRWI / CSRRSI / CSRRCI

定义了一组 CSR指令,可用来读取写入 CSR。

Timers and Counters

RDCYCLE[H]

rdcycle 用来读取最低 31-bit cycle CSR , rdcycleh 用来读取最高 31-bit cycle 数。

RDTIME[H]

用来读取 time CSR 。

RDINSTRET

用来读取 instret CSR 。

Environment Call and Breakpoints

ECALL

属於 I-Type。

使用来呼叫 system call。

EBREAK

Debugger 用来切换进 Debugging 环境。

Reference


<<:  [第05天]理财达人Mx. Ada-历史K棒资料

>>:  不只懂 Vue 语法:如何使用 v-model 实现父子元件传递资料?

Day08【Web】DNS 与 CDN

什麽是 DNS DNS 全称 Domain Name System 中文为「网域名称系统」, 可视为...

Day 23 K-平均演算法 K-Means

介绍: k-平均演算法(英文:k-means clustering,以下简称为 k-means )是...

如果一件事情够重要,那麽即便所有条件都与你作对,你仍应该要做。

如果一件事情够重要,那麽即便所有条件都与你作对,你仍应该要做。 If something is im...

【Day28】Figma篇 : 实作

今天试着全用Figma做一个UI设计,无论是插图或是icon都是在Figma内画出来,Figma的画...

Day29-终於要进去新手村了-HTML DOM 范例

一样要说明这是由彭彭影片撷取出来的例题 <!DOCTYPE html> <html...