Post

RVI : AUIPC

RVI : AUIPC

Content

  上篇研究了A64指令中的ADR/ADRP,当时就在想,蓬勃发展的RISC-V中有没有相应的PC-relative addressing的指令?!还真有,它就是AUIPC(Add Upper Immediate to PC),它的功能是否如ADR/ADRP一样呢?下面来看它的encoding和usage。

Encoding of AUIPC

  RISC-V得益于后发优势,它的指令集编码是非常规整的。它定义了指令编码的基本语法和规则,以此生成一套基本指令集(如下图所示六种type的基本指令集,均为32bit),开发者还可以在规则范围内自己扩展自己的指令,包括指令的长度从16bit到更多,非常的友好。下面这张图应该也会在解读其他指令的时候反复用到。

Desktop View

  回到AUIPC,它是U-type类型的指令。整体组成和ADR/ADRP类似,但,是不是规整很多!!!把ADR/ADRP的编码图片放上来做个对比。
Desktop View

  至少不需在重新组合imm了吧。
  AUIPC的bit[6:0]也就是opcode为0b0010111,其实所有base instruction的bit[1:0]都为0b11,因为非0b11是给16位指令留的,而bit[4:2]不能为0b111,因为这是给更长的指令预留的编码格式。跑题了,继续AUIPC。

1
2
3
AUIPC (add upper immediate to pc) is used to build pc-relative addresses and uses the U-type format.
AUIPC forms a 32-bit offset from the U-immediate, filling in the lowest 12 bits with zeros, adds this
offset to the address of the AUIPC instruction, then places the result in register rd.

  同样rd是目标寄存器的index,imm是一个32位立即数的高20位(所以寻址范围在[$ -2^{31} - 2^{11},2^{31} - 2^{11}-1 $])。指令用法为:

1
auipc Xd, imm

  第二个操作数为imm!?这貌似和ADR/ADRP不一样啊。来看伪代码:

1
X[rd] = pc + sign_extended(immediate[31:12] << 12)

  看起来和ADRP有点像,但人家ADRP第二个操作数是label啊,这里imm难道要开发者自己去算offset?

Usage

  关于上诉疑问,查阅spec,发现了下面这张表:
Desktop View
  原来RISC-V还有pseudo instruction,开发的时候使用pseudo instruction,编译器会把它变成真正的指令,高级!!!
  我们来看其中一个:

1
2
3
4
5
lla rd, symbol
------>
auipc rd, delta[31 : 12] + delta[11]
addi rd, rd, delta[11:0]
// Load local address, where delta = symbol − pc

  这下合理了,编译器把lla rd, symbol中symobl的和PC的相对地址求出来变成delta,然后用了两条指令auipc和addi生成两条编码,X[rd]中的结果就是实际所在位置。这个不就是ADRP吗。

  找一个例子来看看:

1
2
3
4
5
000000000002f000 g       .rela.dyn      0000000000000000 __rel_dyn_start

  lla     t0, __rel_dyn_start
4a:       0002f297                auipc   t0,0x2f
4e:       fb628293                addi    t0,t0,-74 # 2f000 <__rel_dyn_start>

  上诉反汇编片段中,__rel_dyn_start的地址为0x2f000,auipc指令地址为0x4a,两者地址4K向下对齐后差值为0x2f000,所以auipc中imm值为0x2f。整个编码为U-type格式:

1
2
3
1. opcode [6:0]  : 0b0010111  //auipc的操作码编码
2. rd     [11:7] : 0b00101    //X5
3. imm    [31:12]: 0b00101111 //0x2f

  关于rd为啥是X5可以用下图对照:
Desktop View

  第二条指令用addi把低12位的offset补回来,这里正好是-74(-0x4a)。

  如前所诉,RISC-V里auipc和ARM里的ADRP很像,都是只算4K对齐地址差值,需要另外一个指令补齐低位。ADRP的imm为21位,寻址空间会更大一些。RISC-V没有类似ADR的指令在小范围内寻址,所有的PC-relative addressing都要两条指令完成。

Example in OpenSource

  由于auipc隐藏在la/lla等pseudo instruction之后,了解他们之间的关系对阅读RISC-V的boot code会有一定的帮助。

Reference

Unprivileged ISA of RISC-V

This post is licensed under CC BY 4.0 by the author.

© sfeng. Some rights reserved.

Using the Chirpy theme for Jekyll.