文章目录

  • RISC-V 指令学习笔记(基于CH32V103)
    • 一、指令结构分类
    • 二、寄存器功能
    • 三、加载存储指令
    • 四、算数运算指令
    • 五、移位指令
    • 六、逻辑操作指令
    • 七、跳转指令
      • 7.1 条件跳转
      • 7.2 无条件跳转
    • 八、比较判断
    • 九、CSR 操作指令

RISC-V 指令学习笔记(基于CH32V103)

最近学习 RISC-V 指令,参考书籍、博客:

  • RISC-V Reader Chinese v2p1

  • RISC-V 指令格式和6种基本整数指令

学习过程中使用 CH32V103 RV32 架构的单片机进行一些指令的使用复现,加强记忆!

一、指令结构分类

以 32 位 RV 架构 CPU 为例子,从 CPU 级别看来,各种指令就是 32 位的一串数字,这 32 位的数字按照存储数据的位结构,具体可以分为 6 类:

关于 6 种指令的说明,参考博客内的总结:

  • R-typed

    R-typed 指令是最常用的运算指令,具有三个寄存器地址,每个都用 5bit 的数表示。指令的操作由 7 位的 opcode、7 位的 funct7 以及 3 位的 funct3 共同决定的。R-typed 是不包含立即数的所有整数计算指令,一般表示寄存器-寄存器操作的指令。

  • I-typed

    I-typed 具有两个寄存器地址和一个立即数,其中一个是源寄存器 rs1,一个是目的寄存器 rd,指令的高 12 位是立即数。指令的操作仅由 7 位的 opcode 和 3 位的funct3两者决定。值得注意的是,在执行运算时需要先把 12 位立即数扩展到 32 位之后再进行运算。I-typed 指令相当于将 R-typed 指令格式中的一个操作数改为立即数。一般表示短立即数和访存 load 操作的指令。

  • S-typed

    S-typed 的指令功能由 7 位 opcode 和 3 位 funct3 决定,指令中包含两个源寄存器和指令的imm[31:25]和 imm[11:7]构成的一个12位的立即数,在执行指令运算时需要把12 位立即数扩展到 32 位,然后再进行运算,S-typed 一般表示访存 store 操作指令,如存储字(sw)、半字(sh)、字节(sb)等指令。

  • B-typed

    B-typed 的指令操作由 7 位 opcode 和 3 位 funct3 决定,指令中具有两个源寄存器和一个 12 位的立即数,该立即数构成是指令的第32位是 imm[12]、第7位是imm[11]、25 到 30 是 imm[10:5]、8 到 11 位是 imm[4:1],同样的,在执行运算时需要把12 位立即数扩展到 32 位,然后再进行运算。B-typed 一般表示条件跳转操作指令,如相等(beq)、不相等(bne)、大于等于(bge)以及小于(blt)等跳转指令。

  • U-typed

    U-typed 的指令操作仅由 7 位 opcode 决定,指令中包括一个目的寄存器 rd 和高20 位表示的 20 位立即数。U-typed 一般表示长立即数操作指令,例如 lui 指令,将立即数左移 12 位,并将低 12 位置零,结果写回目的寄存器中。

  • J-typed

    J-typed 的指令操作由 7 位 opcode 决定,与 U-typed 一样只有一个目的寄存器 rd和一个 20 位的立即数,但是 20 位的立即数组成不同,即指令的 31 位是 imm[20]、 12 到 19 位是 imm[19:12]、20 位是 imm[11]、21 到 30 位是 imm[10:1],J-typed 一般表示无条件跳转指令,如 jal 指令。

二、寄存器功能

了解了 RV32 的指令结构分类后,我们来看一下 RV32 架构的寄存器分配情况,RV32 有 32 个寄存器,这 32 个寄存器的定义如下:其中 ABI 是寄存器的二进制接口的名称,可以在汇编中使用。

寄存器编号 寄存器 ABI 名称 寄存器功能
x0 zero 全0寄存器
x1 ra 跳转返回指针
x2 sp 栈指针
x3 gp 全局指针
x4 tp 线程指针
x5 t0 临时存储器
x6 t1 临时存储器
x7 t2 临时存储器
x8 s0/fp 存储寄存器,框架指针
x9 s1 存储寄存器
x10 a0 函数参数寄存器(可用于返回值)
x11 a1 函数参数寄存器(可用于返回值)
x12 a2 函数参数寄存器
x13 a3 函数参数寄存器
x14 a4 函数参数寄存器
x15 a5 函数参数寄存器
x16 a6 函数参数寄存器
x17 a7 函数参数寄存器
x18 s2 存储寄存器
x19 s3 存储寄存器
x20 s4 存储寄存器
x21 s5 存储寄存器
x22 s6 存储寄存器
x23 s7 存储寄存器
x24 s8 存储寄存器
x25 s9 存储寄存器
x26 s10 存储寄存器
x27 s11 存储寄存器
x28 t3 临时存储器
x29 t4 临时存储器
x30 t5 临时存储器
x31 t6 临时存储器

除了上面的寄存器外,还有个 pc 指针指向程序运行地址!了解完指令结构和架构寄存器的分工后,我们了解一下指令的功能分类~

三、加载存储指令

加载存储指令用于对寄存器进行数据的加载和保存操作,主要有以下几个

  • lb rd,offset(rs1):从地址为寄存器rs1的值加offset的主存中读一个字节,符号扩展后存入rd
  • lh rd,offset(rs1):从地址为寄存器rs1的值加offset的主存中读半个字,符号扩展后存入rd
  • lw rd,offset(rs1):从地址为寄存器rs1的值加offset的主存中读一个字,符号扩展后存入rd
  • lbu rd,offset(rs1):从地址为寄存器rs1的值加offset的主存中读一个无符号的字节,零扩展后存入rd
  • lhu rd,offset(rs1):从地址为寄存器rs1的值加offset的主存中读半个无符号的字,零扩展后存入rd
  • lwu rd,offset(rs1):从地址为寄存器rs1的值加offset的主存中读一个无符号的字,零扩展后存入rd
  • sb rs1,offset(rs2):把寄存器rs1的值存入地址为寄存器rs2的值加offset的主存中,保留最右端的8位
  • sh rs1,offset(rs2):把寄存器rs1的值存入地址为寄存器rs2的值加offset的主存中,保留最右端的16位
  • sw rs1,offset(rs2):把寄存器rs1的值存入地址为寄存器rs2的值加offset的主存中,保留最右端的32位

编程示例:

my_test:li t0, 0x20000000li t4, 0x12345678sw t4, 0x0(t0)lb t1, 0x0(t0)lh t2, 0x0(t0)lw t3, 0(t0)sb t4, 4(t0)sh t4, 8(t0)sw t4, 12(t0)j .

读取立即数 0x20000000 地址 (SRAM 地址 )到 t0,把 0x12345678 赋值给 t4 ,把 t4 的值保存到以 t0 值位地址的位置上,依次调用 lb、lh、lw 来读取,然后在调用 sb sh sw 将数据存放到 SRAM 上。

li 是立即数操作伪指令,因为立即数的操作是一些指令的合成,因为立即数操作使用频次较高,所以编译器将其缩减为 li,关于伪指令我在末尾会提到。

实验结果如下:

寄存器值:

Name : t0Hex:0x20000000Decimal:536870912Octal:04000000000Binary:100000000000000000000000000000Default:536870912Name : t1Hex:0x78Decimal:120Octal:0170Binary:1111000Default:120Name : t2Hex:0x5678Decimal:22136Octal:053170Binary:101011001111000Default:22136Name : t3Hex:0x12345678Decimal:305419896Octal:02215053170Binary:10010001101000101011001111000Default:305419896

SRAM 存放值:

因为 CH32 是大端存储,高字节在低地址,所以每个 byte 存储的数据位置相反,关于大端小端可以参考我之前的文章:内存大小端

四、算数运算指令

首先是寄存运算功能:加减乘除

  • add rd,rs1,rs2:将寄存器rs1与rs2的值相加并写入寄存器rd

编写代码测试指令:

 li t1, 12addi t2, t1, 4

给 t1 寄存器赋值 12,加上立即数 4 到 t2,编译运行查看结果

  • addi rd,rs1,imm:将寄存器rs1的值与立即数imm相加并存入寄存器rd

在将 t2 寄存器的值和 t1 寄存器相加,结果保存到 t2:

 add t2, t2, t1

运行结果:

  • sub rd,rs1,rs2:将寄存器rs1与rs2的值相减并写入寄存器rd
 li t3, 4sub t2, t2, t3

然后给 t3 赋值 4,使用 t2 寄存器的值减去 t3,结果保存到 t2,运行结果:

  • mul rd,rs1,rs2:将寄存器rs1与rs2的值相乘并写入寄存器rd
 mul t1, t1, t3

将 t1 和 t3 的值相乘存储到 t1,运行现象:

  • div rd,rs1,rs2:将寄存器rs1除以寄存器rs2的值,向零舍入并写入寄存器rd
 div t4, t1, t3

再将 t1 除以 t3,结果保存到 t4,运行现象:

  • rem rd, rs1, rs2:寄存器 rs1 除以寄存器 rs2 的值,向 0 舍入,都视为 2 的补码,余数写入 rd 寄存器
 rem t4, t1, t3

将 t1 除以 t3 取余数,运行现象:

  • neg rd, rs2:把寄存器 rs2 的值的二进制补码写入 rd 寄存器
 li t1, 0xF1neg t2, t1

将 t1 的补码保存到 t2,运行结果:

五、移位指令

  • sll rd,rs1,rs2:将寄存器rs1的值左移寄存器rs2的值这么多位,并写入寄存器rd

    li t2, 0x000F0000
    li t3, 4
    sll t1, t2, t3

将 0x000F0000 逻辑左移四位:

  • slli rd,rs1,imm:将寄存器rs1的值左移立即数imm的值这么多位,并写入寄存器rd
slli t1, t2, 8

将 0x000F0000 逻辑左移8位:

  • srl rd,rs1,rs2:将寄存器rs1的值逻辑右移寄存器rs2的值这么多位,并写入寄存器rd
srl t1, t2, t3

将 0x000F0000 逻辑右移4位:

  • srli rd,rs1,imm:将寄存器rs1的值逻辑右移立即数imm的值这么多位,并写入寄存器rd
srli t1, t2, 8

将 0x000F0000 逻辑右移8位:

  • sra rd,rs1,rs2:将寄存器rs1的值算数右移寄存器rs2的值这么多位,并写入寄存器rd

算数偏移,往左相对于乘以 2,往右相对于除以 2,该方式下会将符号位带入计算

li t2, -128
sra t1, t2, t3

逻辑右移 4 位,相对于除以 16,符号位不变,得到 -8:

  • srai rd,rs1,imm:将寄存器rs1的值算数右移立即数imm的值这么多位,并写入寄存器rd
srai t1, t2, 8

逻辑右移 8 位,相对于除以 128,符号位不变,得到 -1:

六、逻辑操作指令

  • and rd,rs1,rs2:将寄存器rs1与rs2的值按位与并写入寄存器rd
 li t1, 0b0A # 0000 1010li t2, 0x06 # 0000 0110and t3, t1, t2

执行结果:

  • andi rd,rs1,imm:将寄存器rs1的值与立即数imm的值按位与并写入寄存器rd
 andi t3, t1, 0x0F

执行结果:

  • or rd,rs1,rs2:将寄存器rs1与rs2的值按位或并写入寄存器rd
 or t3, t1, t2

执行结果:

  • ori rd,rs1,imm:将寄存器rs1的值与立即数imm的值按位或并写入寄存器rd
 ori t3, t1, 0x0F

执行结果:

  • xor rd,rs1,rs2:将寄存器rs1与rs2的值按位异或(相异为1,相同为0)并写入寄存器rd
 xor t3, t1, t2

执行结果:

  • xori rd,rs1,imm:将寄存器rs1的值与立即数imm的值按位异或并写入寄存器rd
 xori t3, t1, 0x0F

执行结果:

七、跳转指令

7.1 条件跳转

条件跳转是满足设置条件的情况下进行跳转:

  • beq rs1,rs2,lable:若rs1的值等于rs2的值,程序跳转到lable处继续执行

  • bne rs1,rs2,lable:若rs1的值不等于rs2的值,程序跳转到lable处继续执行

  • blt rs1,rs2,lable:若rs1的值小于rs2的值,程序跳转到lable处继续执行

  • bge rs1,rs2,lable:若rs1的值大于等于rs2的值,程序跳转到lable处继续执行

  • bltu rs1,rs2,lable:blt 无符号版

  • bgeu rs1,rs2,lable:bge 无符号版

写一段 c 语言方便理解:

if (t1 == t2) {fun1();
} else if (t1 < t2) {fun2();
} else if (t1 >= t2) {fun3();
}

对应的汇编:

 beq t1, t2, fun1blt t1, t2, fun2bge t1, t2, fun3

另一个版本

if (t1 != t2) {fun1();
}

对应的:

 bne t1, t2, fun1

7.2 无条件跳转

无条件跳转没有设置条件,可直接进行跳转

  • j label:程序直接跳转到lable处继续执行
  • jal rd,label:把下一条指令的地址保存在rd中(通常用x1),然后跳转到label处继续执行
  • jalr rd,offset(rs):把下一条指令的地址存到rd中,然后跳转到rs+offset地址处的指令继续执行。若 rd 为全 0 寄存器,则相当于 j

jal 和 jalr 常用于函数跳转和返回

八、比较判断

  • slt rd,rs1,rs2:若rs1的值小于rs2,rd置为1,否则置为0
  • slti rd,rs1,imm:若rs1的值小于立即数imm,rd置为1,否则置为0
  • sltu rd,rs1,rs2:若rs1的值小于rs1的值,rd置为1,否则置为0
  • sltiu rd,rs1,imm:若rs1的值小于立即数imm,rd置为1,否则置为0

九、CSR 操作指令

RISC - V 中有 8 个重要的 CSR 寄存器,寄存器如下:

  1. mtvec(Machine Trap Vector)它保存发生异常时处理器需要跳转到的地址
  2. mepc(Machine Exception PC)它指向发生异常的指令
  3. mcause(Machine Exception Cause)它指示发生异常的种类
  4. mie(Machine Interrupt Enable)它指出处理器目前能处理和必须忽略的中断
  5. mip(Machine Interrupt Pending)它列出目前正准备处理的中断
  6. mtval(Machine Trap Value)它保存了陷入(trap)的附加信息:地址例外中出错
    的地址、发生非法指令例外的指令本身,对于其他异常,它的值为 0
  7. mscratch(Machine Scratch)它暂时存放一个字大小的数据
  8. mstatus(Machine Status)它保存全局中断使能,以及许多其他的状态,如图所示

这些寄存器控制着中断的使能,同时可以用于异常的捕获,当异常发生时:异常指令的 PC 被保存在 mepc 中,PC 被设置为 mtvec(对于同步异常,mepc 指向导致异常的指令;对于中断,它指向中断处理后应该恢复执行的位置。)根据异常来源设置 mcause,并将 mtval 设置为出错的地址或者其它适用于特定异常的信息字,在机器模式(M 模式,对硬件有 %100 的控制权限)下,异常信息字设置如下:

异常类型分为 5 种:

  • 访问错误异常 当物理内存的地址不支持访问类型时发生(例如尝试写入 ROM)
  • 断点异常 在执行 ebreak 指令,或者地址或数据与调试触发器匹配时发生
  • 环境调用异常 在执行 ecall 指令时发生
  • 非法指令异常 在译码阶段发现无效操作码时发生
  • 非对齐地址异常 在有效地址不能被访问大小整除时发生

异常发生时异常指令的 PC 被保存在 mepc 中,PC 被设置为 mtvec(对于同步异常,mepc
指向导致异常的指令;对于中断,它指向中断处理后应该恢复执行的位置。)根据异常来源设置 mcause,并将 mtval 设置为出错的地址或者其它适用于特定异常的信息字。把控制状态寄存器 mstatus 中的 MIE 位置零以禁用中断,并把先前的 MIE 值保留到 MPIE 中。发生异常之前的权限模式保留在 mstatus 的 MPP 域中,再把权限模式更改为 M。

相关的寄存器操作使用如下指令完成,csr 就是上面相关寄存器:

  • csrrw rd, csr, rs:是读后写控制状态寄存器,先将 csr 的值记为 t,把 rs 寄存器的值写入 csr,再将 t 写入 rd 中;
  • csrrwi rd, csr, zimm:是立即数读后写控制状态寄存器,将 csr 的值写入 rd 中,再将立即数写入 csr 中;
  • csrrs rd, csr, rs1:是读后 置位 控制状态寄存器,先将 csr 的值记为 t,让 t 和 rs1 取或并写入 csr,再将 t 写入 rd 中;
  • csrrsi rd, csr, zimm:是立即数读后 置位 控制状态寄存器,先将 csr 的值记为 t,把 t 和立即数 zimm 取或并写入 csr,再将 t 写入 rd 中;
  • csrrc rd, csr, rs1:是读后 清除位 控制状态寄存器,先将 csr 的值记 为 t,把 t 和 rs1 位与并写入 csr,再将 t 写入 rd 中;
  • csrrci rd, csr, zimm:是立即数读后 清除位 控制状态寄存器,csr 的值记为 t,把 t 和立即数 zimm 位与并写入 csr,再将 t 写入 rd 中。

RISC-V 指令学习笔记(基于CH32V103)相关推荐

  1. STM32学习笔记——基于正点原子例程编码器模式小结

    STM32学习笔记--基于正点原子例程编码器模式小结 最近一段时间学习了,STM32f4的编码器功能,经过自己探索和他人的热心帮助,对于编码器模式有了一定了解.STM32f4单片机提供编码器模式,以便 ...

  2. 激光slam学习笔记——基于图优化的激光slam方法

    激光slam学习笔记--基于图优化的激光slam方法 1.slam基础 整体来说,在激光slam中,滤波器的误差要小于图优化的误差. 图优化通俗点说就是里程计计算的位姿与观测到的位姿之间会形成一个误差 ...

  3. 嵌入式学习笔记——基于Cortex-M的单片机介绍

    基于Cortex-M的单片机介绍 前言 1生产厂商及其产品线 1.1ARM单片机的产品线 1.2命名规则 作业1 2习单片机的资料准备 2.1STM32开发所需手册 2.1.1芯片的数据手册 芯片基本 ...

  4. 学习笔记 —— 基于C加速的Python高效计算 (Cython pybind11)

    目录 引言 Cython 示例介绍 第一阶段优化 第二阶段优化 Cython Annotation tool 优化方法 第三阶段优化 比对下 JIT的Numba 总结 pybind11 Links I ...

  5. ROS学习笔记——基于Prometheus无人机开源项目仿真环境配置

    本笔记基于ubuntu18.04版本,配置基于Prometheus无人机开源项目仿真环境. 需要事先在电脑上安装了ROS,Mavros功能包,其余可参考Amov教程,                  ...

  6. HaaS学习笔记 | 基于HaaS Python轻应用的LED跑马灯明细教程

    [1]题目要求     [案例]:在HaaS框架下实现LED跑马灯.       蓝蜻蜓ESP32开发板的LED灯电路连接如下:       D3灯----GPIO14,高电平点亮,低电平熄灭.   ...

  7. 学习笔记 | 基于FPGA的伪随机数发生器(附代码)

    今天给大侠带来在基于FPGA的伪随机数发生器,话不多说,上货. 今天是画师本人第一次和各位大侠见面,执笔绘画FPGA江湖,本人写了篇关于FPGA的伪随机数发生器学习笔记,这里分享给大家,仅供参考. 1 ...

  8. TensorRT学习笔记--基于FCN-ResNet101推理引擎实现语义分割

    目录 前言 1--Pytorch模型转换为Onnx模型 2--Onnx模型可视化及测试 2-1--可视化Onnx模型 2-2--测试Onnx模型 3--Onnx模型转换为Tensor RT推理模型 4 ...

  9. 马科维茨模型 matlab,马科维茨投资组合理论(均方模型)学习笔记——基于Matlab(四)...

    这是本阶段最后一次学习马科维茨投资组合理论的软件实现. 一.创建投资组合 %模拟N种资产的收益率mu=[10 20 30 50 60 90 120];sigma=[0.06 0.01 0.2 0.8 ...

最新文章

  1. 张苗 清华大学 计算机,2011222229张苗组件局域网及搭建服务器技术分析.doc
  2. java使用POI jar包读写xls文件
  3. Gitee ssh 公钥配置好后,仍然 permission denied 的排查过程及解决方法
  4. Groovy里的setProperty和getProperty重载用法
  5. 前端学习(2185):tabberitem传入active图片
  6. php获取页面中的指定内容,php 获取页面中指定内容的实现类
  7. 苹果iOS13将推出 这些经典手机将会被“淘汰”
  8. 挑战安卓会死?华为鸿蒙正为国产操作系统杀出一条路 | 涛滔不绝
  9. C# 套接字编程:Scoket,我用Scoket做的C# Windows应用程序如下:
  10. 网管日志-06.08.16
  11. 第一次作业-四则运算
  12. vsto java,从Excel VSTO项目打开WPF应用程序
  13. Android开源项目库汇总
  14. Simple---强大的XOM工具
  15. SysML 第一讲:SysML简介
  16. 农学跨专业考研计算机,跨专业考研依然可以得高分
  17. css 延时几秒代码,CSS3 会聚展开文字动画实例及animation-delay属性规则
  18. 美国计算机专业大学排名前30,【最新】2015年美国大学计算机专业排名
  19. Keep It for Mac(专业笔记工具)
  20. 500是什么php,HTTP 500,该怎么解决

热门文章

  1. 9.9 个 CSS 小技巧,让你有更多时间摸鱼~
  2. android社交软件页面,基于android社交软件的开发.pdf
  3. 香港城大:首创3D打印磁控微型机器人技术推动人体送药研究发展
  4. 【徒手写机器学习算法】再谈数据源:从普通图片到Cifar-10(使用C++)
  5. Data Leakage
  6. IDEA社区版怎么配置Spring boot项目?
  7. 学习CentOS7下使用ceph-deploy搭建Ceph
  8. 北信源董事长林皓:“信源豆豆”要做AI+IOT的社交平台
  9. javascript——队列(击鼓传花)
  10. vue3+vite使用element-plus