RISC-V分支偏移机器指令编码

时间:2018-05-23 21:25:15

标签: assembly machine-code riscv

解码的RISC-V汇编指令是什么:0001100 01010 11100 100 10001 1100011?从specification我知道,操作码是BLT指令,rs1 = x28,rs2 = x10。

但编码的偏移量是多少? imm[12|10:5]是0001100 = 12而imm[4:1|11]是10001 = -8,对吗?跳转到哪里去了?

2 个答案:

答案 0 :(得分:2)

The RISC-V Instruction Set Manual 列出了第 19 章中的完整指令集。 opcode(7 个最低有效位)告诉我们我们处理的是 B 类指令。 funct3 位 ([14:12]) 指定 BLT 指令。

BLT 指令的编码如下:

RISC-V instruction set BLT instruction

这给了我们:

<头>
imm[12|10:5] rs2 rs1 函数3 imm[4:1|11] 操作码
说明 0001100 01010 11100 100 10001 1100011
价值 0xc 0xa (x10) 0x1c (x28) 0x4 0x11 0x63

立即数是指令位[31|7|30:25|11:8]的串联:0|1|001100|1000 = 0x4c8。 请注意,立即数会遗漏索引 0 处的位。

The RISC-V Instruction Set Manual 状态在 2.3 Immediate Encoding Variants 中:

<块引用>

基于立即数的处理,指令格式(B/J)还有两种变体,如图 2.3 所示。 S 和 B 格式之间的唯一区别是 12 位立即数字段用于在 B 格式中以 2 的倍数对分支偏移进行编码。 不是像传统那样在硬件中将指令编码的立即数中的所有位左移一,而是中间位 (imm[10:1]) 和符号位保持在固定位置,而 S 格式中的最低位 (inst[ 7]) 以 B 格式编码高位。

这是因为 RISC-V 有 16 位指令对齐约束(1.2 指令长度编码):

<块引用>

基础 RISC-V ISA 具有固定长度的 32 位指令,必须在 32 位边界上自然对齐。但是,标准 RISC-V 编码方案旨在支持具有可变长度指令的 ISA 扩展,其中每条指令可以是任意数量的 16 位指令包长度,并且包在 16 位边界上自然对齐。第 12 章中描述的标准压缩 ISA 扩展通过提供压缩的 16 位指令来减少代码大小,并放宽对齐约束以允许所有指令(16 位和 32 位)在任何 16 位边界上对齐以提高代码密度。< /p>

因此,我们需要在偏移量中添加一个尾随 0,这给我们:0|1|001100|1000|0 = 0x990

解码后的指令为:blt x28, x10, 0x990

答案 1 :(得分:1)

.word 0x18ae48e3

blt x28,x19,hello
blt x28,x19,hello
blt x28,x19,hello
blt x28,x19,hello
blt x28,x19,hello
blt x28,x19,hello
blt x28,x19,hello
blt x28,x19,hello
blt x28,x19,hello
blt x28,x19,hello
blt x28,x19,hello
blt x28,x19,hello
blt x28,x19,hello
hello:
blt x28,x19,hello
blt x28,x19,hello
blt x28,x19,hello



00000000 <hello-0x38>:
   0:   18ae48e3            blt x28,x10,990 <hello+0x958>
   4:   033e4a63            blt x28,x19,38 <hello>
   8:   033e4863            blt x28,x19,38 <hello>
   c:   033e4663            blt x28,x19,38 <hello>
  10:   033e4463            blt x28,x19,38 <hello>
  14:   033e4263            blt x28,x19,38 <hello>
  18:   033e4063            blt x28,x19,38 <hello>
  1c:   013e4e63            blt x28,x19,38 <hello>
  20:   013e4c63            blt x28,x19,38 <hello>
  24:   013e4a63            blt x28,x19,38 <hello>
  28:   013e4863            blt x28,x19,38 <hello>
  2c:   013e4663            blt x28,x19,38 <hello>
  30:   013e4463            blt x28,x19,38 <hello>
  34:   013e4263            blt x28,x19,38 <hello>

00000038 <hello>:
  38:   013e4063            blt x28,x19,38 <hello>
  3c:   ff3e4ee3            blt x28,x19,38 <hello>
  40:   ff3e4ce3            blt x28,x19,38 <hello>

00000001001111100100001001100011
00000001001111100100000001100011
11111111001111100100111011100011


0 000000 1001111100100 0010 0 1100011
0 000000 1001111100100 0000 0 1100011
1 111111 1001111100100 1110 1 1100011 

你确实看到如何从指令中提取这些数字,如文件所示?

0 0 000000 0010 0
0 0 000000 0000 0
1 1 111111 1110 0

0 0000 0000 0100 = 0x0004 
0 0000 0000 0000 = 0x0000 (<-- hello label here)
1 1111 1111 1100 = 0x1FFC

好的,这里没有魔力,有时会有偏移,通常会有偏移。通常,下一条指令的地址是应用立即数的地方。以ARM为例,前面两条指令的地址是应用偏移量的地方。

from your instruction
0001100 01010 11100 100 10001 1100011
0 001100 01010 11100 100 1000 1 1100011
010011001000 (add implied zero for bit 0)
0 1001 1001 0000 = 0x990