试图了解跳转指令如何在存在不同程序计数器时计算地址

Trying to understand how jump instruction calculate the address when different Program counter present

目前我正在理解 RISC-V(ISA) 指令集架构,具有三个扩展 I、M 和 C 扩展。我几乎理解了 I、M 和 C 扩展 的所有指令,但我还没有发现 jumpsbranches 指令在 2 个不同的情况下如何工作counter 呈现,以及它们如何计算下一条指令的地址和我们给出的标签的立即值。

注意:C-extension中程序计数器递增+2,因为C意味着压缩并且它包含16-bit说明。在 I 和 M 扩展 中,程序计数器递增 +4 因为 I 和 M 包含 32-bit 指令。

我有两个例子,我想了解 jumpsbranches 如何计算下一条指令的地址和给定标签的立即值。谁能提供或解释一下发生跳转或分支时计算指令下一个地址的公式。我提供了两个 RISC-V 汇编的例子。请帮助我。提前致谢。

示例 1:

0x0  addi x5,x0,12  #x5 = x0 + 12
0x4  c.addi x6,0    #x6 = x6 + 0 
     l1:
0x6  c.addi x8,6    #x8 = x8 + 6 
0x8  c.jal end      # ?
0xA  c.li x7,2      #x7 = x7 + 2
     end:
0xC  c.mv x6,x8     #x6 = x8
0xE  bne x5,x6,l1   # ?
0x12 c.add x7,x6    # x7 = x7 + x6
0x14 add x8,x5,x7   # x8 = x5 + x7
0x18 c.jal end      # ?

示例 2:

0x0  addi x5,x0,12  #x5 = x0 + 12
0x4  c.addi x6,1    #x6 = x6 + 1
     l1:
0x6  c.li x7,1      #x7 = x7 + 1
0x8  beq x6,x7,end  # ?
0xC  c.add x7,x6    #x7 = x7 + x6
end:
0xE  add x8,x5,x7   #x8 = x5 + x7
0x12 c.jal l1       # ?
0x14 sub x9,x8,x6   #x9 = x8 + x6

不确定这是否是最好的方法

<p id="x"></p> // replace **{{c}}** blank element hence it will impact anything

调用成功后ajax

success: function(data){ // data will hold whatever is returned from the url
           $("#x").html(data['c']); // This will populate the p element with your value
           alert("Hello");
         },

你也可以隐藏ment

bnebeq 是 32 位指令,允许 13 位立即字节偏移,只需要 12 位存储,因为低位始终为零,因此不存储(所有指令都是 2 字节的倍数)。

13位立即数用于pc-relative寻址模式,所以当条件分支发生时,硬件计算:

pc' := pc + signExtend(immediate12 ## 0)

其中pc'是下一个pc,##表示按位串联。当不采用分支时,它会计算通常的 pc' := pc + 4 这是顺序流。

进行符号扩展以将立即数解释为带符号的,这意味着立即数可以是负数或正数,分别向后或向前跳转。

13 位分支目标立即数的12 位分布存储在整个指令的多个字段中。选择这些字段是为了与其他立即数有良好的重叠,并允许寄存器字段相对于其他指令格式保留在同一位置。


c.jal指令在16位指令中编码了12位立即数;立即数以 11 位编码(同样因为低位总是零,所以不需要在指令中表示它)。硬件采用 11 位编码的立即数,在末尾添加一个额外的 0 使其成为 12 位,然后符号扩展到全角(我们也可以说它首先符号扩展到全角,然后乘以 2 — 结果相同).操作是 pc' := pc + signExtend(imm11 ## 0) 其中 ## 是串联。

一旦我们知道了处理器如何计算分支目标 pc,pc',我们就可以在汇编指令时简单地逆向计算。减去目标标签(to)和当前pc(from)之间的差异,然后除以2并截断以适应字段宽度。

如果截断改变了数值,那么立即数对于指令的字段来说太大了,因此无法编码。


内联编码立即字段的值:

0x0  addi x5,x0,12  #x5 = x0 + 12
0x4  c.addi x6,0    #x6 = x6 + 0 
     l1:
0x6  c.addi x8,6    #x8 = x8 + 6 
0x8  c.jal end      # ?                  **(to-from)/2=(0xC-0x8)/2=2**
0xA  c.li x7,2      #x7 = x7 + 2
     end:
0xC  c.mv x6,x8     #x6 = x8
0xE  bne x5,x6,l1   # ?                  **(0x6-0xE)/2=-4**
0x12 c.add x7,x6    # x7 = x7 + x6
0x14 add x8,x5,x7   # x8 = x5 + x7
0x18 c.jal end      # ?                  **(0xC-0x18)/2=-6**

0x0  addi x5,x0,12  #x5 = x0 + 12
0x4  c.addi x6,1    #x6 = x6 + 1
     l1:
0x6  c.li x7,1      #x7 = x7 + 1
0x8  beq x6,x7,end  # ?                    **(0xE-0x8)/2=3**
0xC  c.add x7,x6    #x7 = x7 + x6
end:
0xE  add x8,x5,x7   #x8 = x5 + x7
0x12 c.jal l1       # ?                    **(0x6-0x12)/2=-6**
0x14 sub x9,x8,x6   #x9 = x8 + x6

符号扩展用于将短符号字段变成全宽值。

一个 11 位编码的立即数,如 c.jal,以 -6 和 +6 为例,在二进制中看起来像这样:

# Example using -6
                     * The bit under the * is the MSB
                     |
                     11111111010    # -6 in 11 bits

11111111111111111111111111111010    # -6 in 32 bits
********************* Copied from the MSB in 11 bits


# Example using +6
                     * The bit under the * is the MSB
                     |
                     00000000110    # 6 in 11 bits

00000000000000000000000000000110    # 6 in 32 bits
*********************  Copied from the MSB in 11 bits

The Most Significant Bit 是最高位,如果为 1 则表示数字为负数。为了在加宽(例如从 11 位到 32 位)时保留值,将较短字段中的 MSB 传播到所有额外宽度的位。