[小知识]节约一条指令的启发

今天又受教了,在汇编中对于一条指令的计较,代表了更高的性能和更小的 code size,工程师不能仅仅满足于功能的实现,挖掘硬件和编译器的全部潜力才是目标。学无止境~

1,之前讲到SCR1的CPU Timer寄存器是MMIO的,定义为:

#define MEM_MTIME_CTRL  0x00490000
#define MEM_MTIME_DIV   0x00490004
#define MEM_MTIME       0x00490008
#define MEM_MTIMEH      0x0049000C
#define MEM_MTIMECMP    0x00490010
#define MEM_MTIMECMPH   0x00490014

汇编中如下操作:

li          t0, MEM_MTIMECMP
sw          a1, 4(t0)
sw          a2, 0(t0)

编译器转为:

4817e2:	004902b7          	lui	t0,0x490
4817e6:	01028293          	addi	t0,t0,16 # 490010 <__tcm_end_vma+0xe3cc>
4817ea:	00b2a223          	sw	a1,4(t0)
4817ee:	00c2a023          	sw	a2,0(t0)

而更好的办法是定义为:

#define MMIO_BASE		0x00490000
#define MMIO_MTIME_CTRL         0x00
#define MMIO_MTIME_DIV          0x04
#define MMIO_MTIME              0x08
#define MMIO_MTIMEH             0x0C
#define MMIO_MTIMECMP           0x10
#define MMIO_MTIMECMPH          0x14

代码这样写:

li          t0, MMIO_BASE
sw	    a2, MMIO_MTIMECMP(t0)
sw	    a1, MMIO_MTIMECMPH(t0)

编译后:

4817da:	004902b7          	lui	t0,0x490
4817de:	00c2a823          	sw	a2,16(t0) # 490010 <__tcm_end_vma+0xe3cc>
4817e2:	00b2aa23          	sw	a1,20(t0)

实现一样的操作,节约了一条指令。

2,gp(global pointer) 应该初始化。理论上官方和很多sample code都对gp register进行了初始化,应该加入。

理论上gp寄存器 赋值为数据段中间地址,编译器可以利用这个地址的正负2k的访问范围 来替换 lui和aupic指令,这样可以节约一条指令

https://gnu-mcu-eclipse.github.io/arch/riscv/programmer/

[小知识]节约一条指令的启发_第1张图片

[小知识]节约一条指令的启发_第2张图片

但实际测试下来,结果不一致,用最新版本编译器看到的结果也是不符合的,但还是建议这样做,一是没有坏处,二是你可以避开因gp无值而导致的硬件异常。

编译器明明知道a0可以用gp+0x420来获取,但它竟然使用两条指令先lui a0,0x2,再加1052来取,也没用gp寄存器。

有可能是设置问题或是编译器问题,如果大家谁知道原因还请赐教。

你可能感兴趣的:(SCR1,gnu)