andeyqi

  • 2025-01-16
  • 回复了主题帖: 【入围名单】《图解入门——功率半导体基础与工艺精讲》

    个人信息无误,确认可以完成评测计划。

  • 2025-01-15
  • 加入了学习《Amplifier Protection Series》,观看 Overview of diagnostics and protection in automotive audio applications

  • 加入了学习《Amplifier Protection Series》,观看 Clip detection in automotive audio applications

  • 2025-01-10
  • 回复了主题帖: 【回顾2024,展望2025】新年抢楼活动来啦!

    ⑸立一个新年Flag 减减肥 

  • 2024-12-17
  • 回复了主题帖: 【读书】《RISC-V 体系结构编程与实践(第2版)》-- RISC-V GCC 内嵌汇编

    Jacktang 发表于 2024-12-15 09:52 都是汇编代码,厉害 涉及的汇编指令也不多,基本就是常用的存储加载和加法运算,RISC- V指令编码比较简洁易懂

  • 2024-12-14
  • 发表了主题帖: 【读书】《RISC-V 体系结构编程与实践(第2版)》-- RISC-V GCC 内嵌汇编

    本帖最后由 andeyqi 于 2024-12-13 11:20 编辑 ## 简介 内嵌汇编代码是指在C语言中嵌入汇编代码(Inline Assembly Language in C Code),可以在对代码时间要求比较高,及在C语言中访问某些汇编指令来实现特殊功能,内嵌汇编代码主要有两种形式: - 基础内嵌汇编代码(basic asm):不带任何参数 - 扩展内嵌汇编代码(extended asm):可以带输入/输出参数。 扩展内嵌汇编的模板如下 ```c asm asm-qualifiers ( AssemblerTemplate : OutputOperands [ : InputOperands [ : Clobbers ] ]) ``` asm 修饰词 (                         指令部分                         :输出部分                         :输入部分                         :损害部分                         ) 常见的约束体条件如下: - = 被修饰的操作数具有只写属性 - “+” 被修饰的操作数具有可读可写属性 - & 用于输出限定符,这个操作数在输入参数指令执行完成后才能写入。 - r 通用寄存器 - p 内存地址 - m 内存变量 - i 立即数 ### 内嵌汇编代码验证1 学习内嵌汇编代码,我们将之前汇编实现的my_memcpy 代码按照函数调用规划a0 传递数据源地址,a1 传递目的地址,a2 传递拷贝长度,返回拷贝长度通过a0 返回,以下是 rars 验证通过的汇编代码。 ```c .global my_memcpy_test .text li t0, 0x10010000 li t1, 0x11111111 sw t1, (t0) li t1, 0x22222222 sw t1, 4(t0) li t1, 0x33333333 sw t1, 8(t0) li t1, 0x44444444 sw t1, 12(t0) li t1, 0x55555555 sw t1, 16(t0) li t1, 0x66666666 sw t1, 20(t0) li t1, 0x77777777 sw t1, 24(t0) li t1, 0x88888888 sw t1, 28(t0) li t1, 0x99999999 sw t1, 32(t0) li t1, 0xaaaaaaaa sw t1, 36(t0) li t1, 0xbbbbbbbb sw t1, 40(t0) li a0, 0x10010000 li a1, 0x100100c0 li a2, 32 my_memcpy_test:     mv t0, a0     mv t1, a1     add t2, t0, a2 .loop:     lw t3, (t0)     sw t3, 0(t1)     addi t0, t0, 4     addi t1, t1, 4     blt t0, t2, .loop     mv a0,a2     ret ``` 将上述代码按照转化以下内嵌汇编代码: ```c int my_memcpy(void * src,void *  dest ,int len) {     asm volatile (     "mv t0, a0 \n"     "mv t1, a1 \n"     "add t2, t0, a2 \n"     ".loop: \n"     "lw t3, (t0) \n"     "sw t3, 0(t1) \n"     "addi t0, t0, 4 \n"     "addi t1, t1, 4 \n"     "blt t0, t2, .loop\n"     "mv a0,a2 \n"     "ret \n"     :::     ); } ``` 在main函数内添加测试代码调用my_mempy 函数,验证函数工作状态。 ```c int main(void) {     int src[8] = {0x11111111,0x22222222,0x33333333,0x44444444,                    0x55555555,0x66666666,0x7777777,0x88888888};     int dest[8] = {0x00};     int ret = my_memcpy((void*) src,(void *)dest,32);     for(int i = 0;i < 8;i++)         printf("dest[%d] = %x,",i,dest);     printf("ret = %d\r\n",ret); } ``` 运行后数据已经按照预期的进行了拷贝,函数返回值也已经按照预期的打印输出32. ```c dest[0] = 11111111,dest[1] = 22222222,dest[2] = 33333333,dest[3] = 44444444,dest[4] = 55555555,dest[5] = 66666666,dest[6] = 7777777,dest[7] = 88888888,ret = 32 ``` 反汇编 产看编译器产生的汇编代码如下: ```c 30079462 : 30079462:        82aa                        mv        t0,a0 30079464:        832e                        mv        t1,a1 30079466:        00c283b3                  add        t2,t0,a2 3007946a : 3007946a:        0002ae03                  lw        t3,0(t0) 3007946e:        01c32023                  sw        t3,0(t1) 30079472:        0291                        addi        t0,t0,4 30079474:        0311                        addi        t1,t1,4 30079476:        fe72cae3                  blt        t0,t2,3007946a 3007947a:        8532                        mv        a0,a2 3007947c:        8082                        ret 3007947e:        8082                        ret 30079480 : 30079480:        1101                        addi        sp,sp,-32 30079482:        02000613                  li        a2,32 30079486:        0ff89597                  auipc        a1,0xff89 3007948a:        c3258593                  addi        a1,a1,-974 # 400020b8 3007948e:        00043517                  auipc        a0,0x43 30079492:        4aa50513                  addi        a0,a0,1194 # 300bc938 30079496:        cc22                        sw        s0,24(sp) 30079498:        ca26                        sw        s1,20(sp) 3007949a:        c84a                        sw        s2,16(sp) 3007949c:        c64e                        sw        s3,12(sp) 3007949e:        c452                        sw        s4,8(sp) 300794a0:        ce06                        sw        ra,28(sp) 300794a2:        fc1ff0ef                  jal        ra,30079462 300794a6:        8a2a                        mv        s4,a0 300794a8:        4401                        li        s0,0 ``` ### 内嵌汇编代码验证2 上面的内嵌汇编的代码直接使用的汇编代码实现的,并没有使用变量,我们再次基础上修改内嵌汇编的代码使用变量的方式实现上述功能,修改代码如下。 ```c static int my_memcpy1(void * src,void *  dst ,int len) {         unsigned long tmp = 0;         unsigned long end = (char *)src + len;         asm volatile (                         "1: lw %1, (%2)\n"   //tmp = *src                         "sw %1, (%0)\n"      //*dst  = tmp                         "addi %0, %0, 4\n"   //dst += 4                         "addi %2, %2, 4\n"   //src += 4                         "blt %2, %3, 1b"     //if(src < end) goto 1                         : "+r" (dst), "+r" (tmp), "+r" (src)                         : "r" (end)                         : "memory");         return len; } ``` 添加测试代码在main 函数中调用my_memcpy1 函数 ```asp int main(void) {   static int src[8] = {0x11111111,0x22222222,0x33333333,0x44444444,                 0x55555555,0x66666666,0x7777777,0x88888888};   static int dest[8] = {0x00};   int ret = my_memcpy1((void*) src,(void *)dest,32);   for(int i = 0;i < 8;i++)     printf("dest[%d] = %x,",i,dest);      printf("ret = %d\r\n",ret); } ``` 上述代码运行结果跟之前也是一致说明功能已经ok,查看反汇编代码如下 ```asp 40034284 : 40034284:        1101                        addi        sp,sp,-32 40034286:        ca26                        sw        s1,20(sp) 40034288:        0007c497                  auipc        s1,0x7c 4003428c:        98048493                  addi        s1,s1,-1664 # 400afc08 40034290:        ce06                        sw        ra,28(sp) 40034292:        cc22                        sw        s0,24(sp) 40034294:        c84a                        sw        s2,16(sp) 40034296:        c64e                        sw        s3,12(sp) 40034298:        87a6                        mv        a5,s1 4003429a:        4701                        li        a4,0 4003429c:        00078697                  auipc        a3,0x78 400342a0:        1c868693                  addi        a3,a3,456 # 400ac464 400342a4:        00078617                  auipc        a2,0x78 400342a8:        1e060613                  addi        a2,a2,480 # 400ac484 400342ac:        4298                        lw        a4,0(a3) 400342ae:        c398                        sw        a4,0(a5) 400342b0:        0791                        addi        a5,a5,4 400342b2:        0691                        addi        a3,a3,4 400342b4:        fec6cce3                  blt        a3,a2,400342ac ``` 发现编译器将 my_memcpy1 函数进行了编译优化,进行了inline 处理,修改my_memcpy1 函数的编译属性__attribute__((noinline))查看反汇编代码如下。 ```c 40034264 : 40034264:        00c506b3                  add        a3,a0,a2 //end = src + len 40034268:        4701                        li        a4,0 //tmp = 0 4003426a:        87aa                        mv        a5,a0 //a5 = src 4003426c:        4398                        lw        a4,0(a5) //tmp = *src 4003426e:        c198                        sw        a4,0(a1) //*dst = tmp 40034270:        0591                        addi        a1,a1,4 //dst += 4 40034272:        0791                        addi        a5,a5,4 //src += 4 40034274:        fed7cce3                  blt        a5,a3,4003426c if(src < end) goto 4003426c 40034278:        8532                        mv        a0,a2 4003427a:        8082                        ret ``` 从上述反汇编代码可以看出 src 通过 a0/a5 传递 dst 通过 a1 传递 len 通过 a2 传递 将end 变量分配了a3寄存器 tmp 变量分配了a4 寄存器 返回值通过 a0 返回

  • 2024-12-08
  • 回复了主题帖: 【读书】《RISC-V 体系结构编程与实践(第2版)》-- RISC-V 函数调用规范

    电子烂人 发表于 2024-12-8 18:01 这个函数调用规范是在RISC-V才新提出的吗? 这个是RISC-V架构 定义的ABI接口调用规范

  • 发表了主题帖: 【读书】《RISC-V 体系结构编程与实践(第2版)》-- RISC-V 函数调用规范

    本帖最后由 andeyqi 于 2024-12-8 16:02 编辑 ## 简介 函数调用规范(calling convention)是用来描述父/子函数是如何编译和链接的,特别是父函数和子函数之间的调用约定,如栈的布局,参数传递等。 RISC-V 整型通用寄存器在函数调用规范中使用情况如下: 从上述表格可以看出通用寄存器,只有**sp,s0-s11**在子函数中使用了需要保存到栈中,使用完之后再从栈中恢复到寄存器中,以下是riscv-abi.pdf 文档中的描述信息。 > In the standard ABI, procedures should not modify the integer registers tp and gp, because signal handlers may rely upon their values. The presence of a frame pointer is optional. If a frame pointer exists it must reside in x8 (s0), the register remains callee-saved. **函数的调用规范如下:** - 函数的前八个参数使用a0-a7寄存器来传递 - 如果函数参数大于8个,前面8个参数使用寄存器来传递,后面的传递使用栈来传递。 - 如果传递的参数小于寄存器宽度(64位),那么先按照符号扩展到32位,再按照符号扩展到64位,如果传递的数据是128位,则使用一对寄存器来传递该值,官方文规则说明如下。 > Scalars that are at most XLEN bits wide are passed in a single argument register, or on the stack by value if none is available. When passed in registers or on the stack, integer scalars narrower than XLEN bits are widened according to the sign of their type up to 32 bits, then sign-extended to XLEN bits. When passed in registers or on the stack, floating-point types narrower than XLEN bits are widened to XLEN bits, with the upper bits undefined. > Scalars that are 2×XLEN bits wide are passed in a pair of argument registers, with the low-order XLEN bits in the lower-numbered register and the high-order XLEN bits in the higher-numbered register. If no argument registers are available, the scalar is passed on the stack by value. If exactly one register is available, the loworder XLEN bits are passed in the register and the high-order XLEN bits are passed on the stack. - 函数的返回值保存在a0 a1 寄存器中 - 函数的返回值保存在ra 寄存器中 - 如果子函数中使用了s0-s11 寄存器,那么子函数在使用这些寄存器前需要先保存到栈中,函数退出时再将寄存器从栈中恢复 - 栈向下生长,sp 寄存器在进入子函数时sp 要对齐到16字节的边界上,传递的第一个参数位于sp 寄存器的0偏移量处,后续的参数则位于高地址处 - 如果GCC 使用-fno-omit-frame-pointer 编译选项,那么编译器将使用s0 寄存器作为栈帧指针(Frame Point,FP) ### 参数传递验证 在编写如下代码传递多个参数C代码。 ```c #include int main(void) {     int a = 1,b = 2,c = 3,d = 4,e = 5,f = 6,g = 7,h = 8,i = 9,j = -1;         printf("data %d %d  %d %d   %d %d   %d %d  %d %d \n",            a,b,c,d,e,f,g,h,i,j); } ``` 上述代码会被编译成如下的汇编代码: ```c 30078e2a : 30078e2a:        1101                        addi        sp,sp,-32 30078e2c:        557d                        li        a0,-1 30078e2e:        c42a                        sw        a0,8(sp) 30078e30:        4525                        li        a0,9 30078e32:        c22a                        sw        a0,4(sp) 30078e34:        4521                        li        a0,8 30078e36:        c02a                        sw        a0,0(sp) 30078e38:        489d                        li        a7,7 30078e3a:        4819                        li        a6,6 30078e3c:        4795                        li        a5,5 30078e3e:        4711                        li        a4,4 30078e40:        468d                        li        a3,3 30078e42:        4609                        li        a2,2 30078e44:        4585                        li        a1,1 30078e46:        00037517                  auipc        a0,0x37 30078e4a:        71250513                  addi        a0,a0,1810 # 300b0558 30078e4e:        ce06                        sw        ra,28(sp) 30078e50:        d53c80ef                  jal        ra,30041ba2 ``` 从以上汇编代码调用printf 函数时传递参数的过程可以看出,对应流程如下 1. sp = sp - 32 将SP对齐到32字节边界上,书中描述是16 字节,这个猜测是跟编译器的实现有关 2. sp + 8 处保存参数-1 3. sp + 4 处保存参数9 4. sp + 0 处保存参数8 5. a7 保存参数7 6. a6 保存参数6 7. a5 保存参数5 8. a4 保存参数4 9. a3 保存参数3 10. a2 保存参数2 11. a1 保存参数1 12. a0 保存格式化字符串 data %d %d  %d %d   %d %d   %d %d  %d %d  这里面的寻址方式正是之前文章说的PC相对寻址 调用printf 函数前栈帧及通用寄存器a0-a7的布局如下 从上述过程也可以看出,参数的保存顺序是从左至右先使用a0-a7 ,参数超过8个后使用栈空间,栈空间内靠右侧的参数分配在栈的高地址也就是先压栈的效果,上述参数8,9,-1 的压栈的顺序为 -1.9,8

  • 2024-12-07
  • 回复了主题帖: FREERTOS编译错误的问题

    chenbingjy 发表于 2024-12-6 11:59 查了,就是这样写的   是不是这里面的 --far 或者 --interrupt 没有被正常识别编译器不认识报错了

  • 发表了主题帖: 【读书】《RISC-V 体系结构编程与实践(第2版)》-- RISC-V memcpy 实验

    本帖最后由 andeyqi 于 2024-12-7 12:10 编辑 ## 简介 书中有很多上机试验的参考代码,书中使用的是QEMU的实验环境,本地使用RARS 模拟器环境来继续验证学习RISC-V 体系知识,实验代码可以从以下路径获取下载。 > 《RISC-V体系结构编程与实践》一书的实验参考代码由git来管理, 读者可以通过如下地址来下载。 Github站点: https://github.com/runninglinuxkernel/riscv_programming_practice 国内镜像站点: https://gitee.com/benshushu/riscv_programming_practice 书中有如下memcpy 的试验代码 ```c .global my_memcpy_test my_memcpy_test:         li t0, 0x80200000         li t1, 0x80210000         addi t2, t0, 32 .loop:         ld t3, (t0)         sd t3, (t1)         addi t0, t0, 8         addi t1, t1, 8         blt t0, t2, .loop         ret ``` 上述试验代码,跟memcpy 的参数分布类似,t0 存储数据源地址0x80200000,t1 存储目的地址 0x80210000 ,t2 代表拷贝结束地址 拷贝32字节的数据,参照上述代码在RARS 环境下运行该代码进行试验。 拷贝上述代码至RARS 模拟运行修改数据源地址和目标地址,发现运行结果跟预期的一致,从0x10010000 拷贝了 32字节至 0x100100c0地址 ```c .global my_memcpy_test .text my_memcpy_test:         li t0, 0x10010000         li t1, 0x100100c0         addi t2, t0, 32 .loop:         ld t3, (t0)         sd t3, 0(t1)         addi t0, t0, 8         addi t1, t1, 8         blt t0, t2, .loop         ret ```

  • 2024-12-03
  • 回复了主题帖: 【读书】《RISC-V 体系结构编程与实践(第2版)》-- RISC-V 存储加载指令集学习

    学学学学学学学 发表于 2024-12-3 15:08 rars 这个软件有下载链接吗大佬 https://github.com/TheThirdOne/rars  

  • 2024-11-29
  • 回复了主题帖: 【读书】《RISC-V 体系结构编程与实践(第2版)》-- RISC-V CSR 指令集学习

    Jacktang 发表于 2024-11-29 07:26 好书,RISC-V 体系结构该讲的都讲到了 嗯 很适合座位学习RISC-V 的入门书籍

  • 2024-11-28
  • 发表了主题帖: 【读书】《RISC-V 体系结构编程与实践(第2版)》-- RISC-V CSR 指令集学习

    本帖最后由 andeyqi 于 2024-11-28 23:47 编辑 ## 简介 RISC-V 除了通用寄存器外,还定义了CSR 系统控制与状态寄存器,来实现中断控制及系统状态获取等功能,这些特殊的寄存器的访问需要使用特定的 CSR 指令来读取,设置。对于CSR 指令的验证依然在 RARS 模拟器上进行验证,RARS 定义了 U Mode 下的CSR 寄存器,模拟器的寄存器定义如下。 以下书中对U mode 下的CSR 寄存器说明 以下是书中对CSR 指令的说明 ### CSRRW 指令测试验证 指令格式:csrrw rd,csr,rs1 指令描述:原子的交换CSR 和 rs1 寄存器的值,读取CSR旧值,写入到rd寄存器中,与此同时rs1 寄存器的旧值被写入到CSR中,对应伪代码如下 rd = csr,csr = rs1 以下是CSRW 指令说明。 上述当rd 为 x0 时,不进行读操作,编写如下代码验证csrrw 指令运行效果。 ```c li x2,0x55 csrrw x1,fcsr,x2 nop ``` 上述代码执行后会将fcsr 寄存器的值(0xaa)更新到x1,将x2 的值0x55 更新到fcsr 寄存器 **csrrw x1,fcsr,x2** 执行后x1 被更新为0xaa 同时fcsr 寄存器更新为x2 的值0x55 ### CSRRS 指令测试验证 指令格式:csrrs rd,csr,rs1 指令说明:原子的读取CSR 的值并且设置CSR中相应的位。对应伪代码如下 rd = csr,csr |= rs1 CSRRS 指令说明如下 > The CSRRS (Atomic Read and Set Bits in CSR) instruction reads the value of the CSR, zeroextends the value to XLEN bits, and writes it to integer register rd. The initial value in integer register rs1 is treated as a bit mask that specifies bit positions to be set in the CSR. Any bit that is high in rs1 will cause the corresponding bit to be set in the CSR, if that CSR bit is writable. Other bits in the CSR are unaffected (though CSRs might have side effects when written). 添加如下测试代码,fcsr 初始值为0xaa, 设置rs1 = 0x55 掩码跟新fcsr bit0-3 ,按照上述说明执行后fcsr 更新为0xff. ```c li x2,0x55 csrrs x1,fcsr,x2 nop ``` 另外的csrrc/csrrwi/csrrsi/csrrci 指令跟上述处理也是类似,再此就不额外赘述了。 CSR寄存器 指令还可以通过以下伪指令来访问,伪指令会被被转化成相应的CSR指令来更新寄存器

  • 2024-11-26
  • 回复了主题帖: 《RISC-V 体系结构编程与实践(第2版)》互动:接龙解答作者笨叔出的思考题

    本帖最后由 andeyqi 于 2024-11-26 17:55 编辑 第3章:问题回答 1.RISC-V指令集有什么特点? ==》 RISC-V 指令集采用了模块化的设计方法,设计了一个最小集合的基础指令集,这个最小指令集可以完整的是实现一个软件栈,其他功能可以在此基础上通过模块化的方式叠加扩展,用于支持浮点,乘法,除法,矢量运算等。 2.RISC-V指令编码格式分成几类? ==》 指令格式可以分为6种 R类型:寄存器与寄存器算术指令。 I类型:寄存器与立即数算术指令或者加载指令。 S类型:存储指令。 B类型:条件跳转指令。 U类型:长立即数操作指令。 J类型:无条件跳转指令。 3.什么是零扩展和符号扩展? ==》 符号扩展:对于一个需要扩展的立即数的最高位作为符号位进行扩展,最高位的符号位为1 前面的数据全部填充为1,0则填充为0 零扩展:扩展时不考虑符号位,直接在前面填充为0   4.什么是PC相对寻址? ==》 使用PC + offset 的形式进行寻址方式,RISC-V 提供了AUIPC 指令根据当前PC的值 算出 要寻址的偏移的大小,但是AUIPC 指令编码格式的限制只能寻址到4KB边界的位置,随影通常配合ADDI 指令联合使用来实现32位地址空间的PC 相对寻址。

  • 回复了主题帖: 《RISC-V 体系结构编程与实践(第2版)》互动:接龙解答作者笨叔出的思考题

    第1章:问题回答 1.RISC-V体系结构有什么特点? ==> 对学术界和工业界完全开放,开源的架构 属于一个通用指令集体系结构 真正适合硬件实现的指令集体系结构 实现最小的整数指令集作为基础指令集,在此基础上实现众多众多可选扩展 支持IEEE 754浮点标准 支持众多扩展指令集 支持多核异构体系结构 支持可选的压缩指令集 支持虚拟化扩展 支持可伸缩矢量指令扩展   2.RISC-V体系结构处理器包含多少个通用寄存器? ==> 包括32个整形通用寄存器x0-x31,32个浮点通用寄存器 f0~f31 3.RISC-V体系结构包含几种处理器模式?它们分别有什么作用 ==> U 模式用于运行应用程序 S模式用于运行操作系统,为应用程序提供服务 M模式用于运行SBI固件,为操作系统提供服务

  • 2024-11-24
  • 回复了主题帖: 【读书】《RISC-V 体系结构编程与实践(第2版)》-- RISC-V 架构寄存器学习

    lemonboard 发表于 2024-11-24 10:33 RISC-V在国内的份量越来越重了 嗯  国内市面上的RISC-V 的芯片也越来越多了

  • 发表了主题帖: 【读书】《RISC-V 体系结构编程与实践(第2版)》-- RISC-V 存储加载指令集学习

    本帖最后由 andeyqi 于 2024-11-24 22:35 编辑 ## 简介 RISC-V 指令按照类型分为6种,对应指令编码格式如下。 - R类型:寄存器与寄存器算术指令。 - I类型:寄存器与立即数算术指令或者加载指令。 - S类型:存储指令。 - B类型:条件跳转指令。 - U类型:长立即数操作指令。 - J类型:无条件跳转指令。 以下是 RV32I 基础指令集所包含的指令 RV64I 指令相对RV32I 增加了部分指令,这也体现了RISC-V 指令集模块化的设计方式 ### 存储与加载指令 RISC-V 架构是基于存储加载的设计方式,CPU 访问内存不可以直接从将数据写入内存,需要通过过寄存器将要写的数据先写入寄存器,让后将寄存器数据加载到内存,所以存储与加载指令只是最基本的指令。 #### 加载指令 以下是加载指令编码格式 对应ld 指令说明如下 以下是书中对ld 指令的测试代码 上述代码使用LD指令load 0x8000000 + offset 的memory 书籍至寄存器,书中使用的验证环境为QEMU ,本地使用 rars 软件验证上述ld 指令运行效果。 添加如下测试代码 ```c li t0,0x10010010 lb t1,(t0) lb t2,4(t0) lbu t3,4(t0) lb t4,-4(t0) ld t5,(t0) ld t6,16(t0) ``` 运行后结果如下,发现按照预期的方式将内存的数据加载到t1-t6 寄存器中。 #### 存储指令 以下是store 指令的编码说明 我们在之前的代码基础上添加代码将t1-t6 的寄存器内容写入到内存中 ```c li t0,0x10010010 lb t1,(t0) lb t2,4(t0) lbu t3,4(t0) lb t4,-4(t0) ld t5,(t0) ld t6,16(t0) li a0,0x10010040 sb t1,(a0) sb t2,4(a0) sw t3,8(a0) sw t4,12(a0) sd t5,16(a0) sd t6,24(a0) ``` 运行后发现t1-t6 寄存器的数值已经通过a0寄存器写入到内存中了。

  • 2024-11-23
  • 发表了主题帖: 【读书】《RISC-V 体系结构编程与实践(第2版)》-- RISC-V 架构寄存器学习

    本帖最后由 andeyqi 于 2024-11-24 16:42 编辑 ## 简介 很高兴能够与参加论坛的《RISC-V 体系结构编程与实践(第2版)》的读书活动,借此读书活动学习了解RISC-V架构的知识,收到了论坛邮寄的书籍,先来张书籍崭新的封面,查看目录发现内容还是很丰富的,熟悉RISC-V 先从架构的基本的寄存器开始学习。 ### RISC-V 寄存器 #### 通用寄存器 RISC-V 体系结构提供32个通用整型寄存器(X0-X31),寄存器的长度则根据处理器的位数相关,64位处理器寄存器长度位64位,32位处理器则是32位,长度位XLENG根据处理器的长度一致,浮点数运行RISC-V处理器也提供32个浮点数通用寄存器f0-f31。书中对寄存器也有详细描述,对应内容如下。 RISC-V 对寄存器划分了特定的功能用途对应如下。 - x0 寄存器别名为zer0,寄存器内容全是0,可以作为源寄存器,也可以作为目标寄存器 - x1 寄存器别名为ra 链接寄存器,用于保存函数返回地址 - x2 寄存器别名为sp 栈指针寄存器,指向栈地址 - x3 寄存器别名为gp 全局寄存器,用于链接器松弛优化 - x4 寄存器别名为tp 线程寄存器,通常在操作系统中保存指向进程控制块 task_struct 指针 - x5-x7 以及 x28-x31 寄存器为临时寄存器,它们别名分别是t0~t6 - x8-x9 以及 x18-x27 寄存器的别名分别为s0-s11,称为Callee-saved registers 寄存器用户在程序中使用需要保存到栈中 - x10-x17 寄存器别名为a0-a7,在函数调用时传递参数和返回值 以下是**通用寄存器**的number 和 别名的对应关系 以下是**浮点寄存器**的number 和 别名的对应关系 #### 系统寄存器 除了上述系统必须的通用寄存器外,RISC-V 还定义了其他的系统控制和状态寄存器(Control and Status Registers,CSRs),通过特定的CSR 指令去访问这些寄存器。CSR 指令编码中预留了12bit 的编码空间(csr[11:0])用来作为索引访问特定的系统寄存器,对应的CSR 指令编码格式如下。 其中12bit 的编码空间可以用来索引4096 个寄存器,其中12bit 编码管理方式如下: 1. CSR[11:10] 用来表示系统寄存器的读写属性,0b11 表示只读,其余表示可读可写 2. CSR[9:8] 表示允许访问该系统处理器的模式,0b00 表示U模式,0b11 S模式,0b11 M模式 ,0b10 HS/VS 模式 以下是RISC-V 规范(riscv-privileged-20211203.pdf)中对CSR 寄存器管理的说明 **U模式下的CSR寄存器定义说明** **S模式的CSR寄存器定义说明** **M模式下的CSR寄存器定义说明** ##### GD32VF103 MCU CSR 寄存器的定义说明 对于CSR 寄存器我们查看GD32VF103基于RISC-V 32bit 的 Bumblebee 内核的处理器芯片的手册查看其中定义了如下的CSR寄存器 从上述CSR 寄存器定义可以看出GD32VF103 的芯片只实现支持了M模式和U模式,支持了部分的RISC-V 标准的CSR寄存器外还自定义了部分的CSR 寄存器。 CSR 寄存器访问索引中定义了寄存器访问的模式及读写属性,该特性可以用于芯片的访问权限的管理,以下是GD32VF103基于RISC-V 32bit 的 Bumblebee 内核的 的管理方法说明。

  • 2024-11-21
  • 回复了主题帖: STM32全球线上峰会,STM32N6重磅发布啦!

     

  • 2024-11-20
  • 回复了主题帖: 读书入围名单:《RISC-V 体系结构编程与实践(第2版)》

    个人信息无误,确认可以完成阅读计划和打卡任务

最近访客

< 1/2 >

统计信息

已有27人来访过

  • 芯积分:110
  • 好友:--
  • 主题:11
  • 回复:16

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言