本文将从两者最基本的寄存器和汇编讲述两者的不同(ARM本文重点介绍ARMv7,ARMv8/9后续通过连载的方式展开,以下ARM架构描述默认指的是ARMv7架构)
如下图所示,最直观的感觉,RISC-V的通用寄存器有32个,相比ARM16个寄存器多了一倍,通用寄存器越多,好处可太多了。最常见的一个收益是C语言中函数之间的调用传参,在ARM中,只能用R0~R3这4个通用寄存器传参,一旦函数的参数超过4个,则必须把多的参数保存在栈也就是内存里面,进一步导致性能下降,同样的程序放在RISC-V中,则不会存在这个问题,因为它可以用a0~a7这8个通用寄存器保存参数,避免了ARM一旦参数超过4个需要压栈。
与ARM寄存器相比,RISC-V还有一个用于提升性能的寄存器gp,全局指针寄存器。
如上面的C代码所示, 对全局变量test加1操作,ARM需要5条汇编指令搞定
step1:获取变量大概地址
step2:获取变量(大概地址地址+偏移地址)的内容
step3:对地址的内容+1
step4:获取变量大概地址
step5:将step3的结果回写进(大概地址地址+偏移地址)
为啥获取变量的地址无法通过一条汇编指令完成(ARM&RISC-V都如此)呢?这个涉及到ISA指令编码知识点。CPU最终识别到的是0101这种二进制机器码,而不是汇编 。对于一条32位指令集而言,32bit表示的信息比较有限, 至少需要7bit(0~6bit)表示该条指令是add还是sub等, 剩下的32-7=25bit不足以精准的表示一个32bit数,因此需要2条汇编指令。
再举例最常见的汇编指令mov,
mov r0, #0x56000000 /* 可以正确编译 */
mov r0, #0x56000014 /* 无法正确编译 */
本质上还是因为mov对应的机器码内容无法表达任意32bit数值,只能某些bit通过相关规则表达符合规则的数值(该规则请各位看官老爷自行度娘)。同样C语言逻辑,对于RISC-V来说, 只需要3行汇编指令就搞定,相比ARM来说,足足少了2条指令,它的最大功臣来源于gp寄存器,通过一条和gp相关的指令就能获取变量的地址,这个性能的提升对于实时性比较敏感,比如基带处理等等起着非常重要的作用。
但是gp寄存器也不是万能的,我们查询RISC-V汇编指令手册(上图lw/sw指令)可以看到,以gp位基地址最大偏移地址只能是offset[11:0],即最大4096地址范围内,+-2k。gp寄存器在程序编译链接完成后就确定了,中途不能有任何改变,因此在工程实现的连接脚本中,把对时间比较敏感的变量尽可能的和gp(globe point)靠近在一起。
|