分支RISC-V指令偏移计算在我的模拟器上

huangapple go评论58阅读模式
英文:

Branch riscv instruction offset calculation on my emulator

问题

我写了一个riscv64模拟器,但在分支指令的偏移计算上遇到了问题(特别是bge指令)。

对我来说,计算满足条件时要添加到pc的偏移量的公式是:PC = PC + IMM;
立即数从指令中提取出来:
这是我的C代码:

void BNE(unsigned long instr) {

unsigned long IMM1 = instr >> 7 & 0b11111;
unsigned long IMM2 = instr >> 25 & 0b1111111;

unsigned long first = IMM1 & 0b1; // 11 eme bits IMM\[11\]    
unsigned long second = IMM1 >> 1 & 0b1111; // IMM\[4:1\]
unsigned long third = IMM2 & 0b111111;    //imm\[10:5\]    
unsigned long fourth = IMM2 >> 6 & 0b1; // IMM\[12\]

// after extract assemble :
unsigned long imm = second | third << 5 |  first << 7 | fourth << 9; // \&lt;- I think here is the problem

}

当程序获取这个简单的程序代码时:

// 我简化了代码:
00000000000100e8 \&lt;init\&gt;:

10130:	fd843783          	ld	a5,-40(s0)

1018c:	fae7d2e3          	bge	a5,a4,10130 \&lt;init+0x48\&gt; # 注意我的代码中条件总是满足的

我得到:0x7a2。

pc地址是:0x1018c

当我将0x1018c加到0x7a2时,我得到:0x1092E
有一个问题,但我不知道问题出在哪里。我认为在imm变量的提取中可能存在问题。

我尝试修改imm变量的位移和掩码,但没有运气。

我尝试过这些:

unsigned long imm = second | third << 4 |  first << 5 | fourth << 6; // 输出错误的数据
unsigned long imm = second | third << 6 |  first << 11 | fourth << 12; // 输出与imm相同的数据
unsigned long imm = second | third << 5 |  first << 7 | fourth << 9; // 实际版本
unsigned long imm = second | third <<  6 |  first << 7 | fourth << 8; // 输出与imm相同的数据
英文:

I have wrote a riscv64 emulator but I have an issue on offset calculation for branch instructions (especially for bge).

For me , the formula to calculate offset to add to pc when condition is meet is : PC = PC+IMM;
Immediate is extract from instruction :
there is my C code :



void BNE(unsigned long instr) {

unsigned long IMM1 = instr &gt;&gt;7 &amp; 0b11111;
unsigned long IMM2 = instr &gt;&gt; 25 &amp; 0b1111111;

unsigned long first = IMM1 &amp; 0b1; // 11 eme bits IMM\[11\]	
unsigned long second = IMM1 &gt;&gt; 1 &amp; 0b1111; // IMM\[4:1\]
unsigned long third = IMM2 &amp; 0b111111;	//imm\[10:5\]	
unsigned long fourth = IMM2 &gt;&gt; 6 &amp; 0b1; // IMM\[12\]

// after extract assemble :
unsigned long imm = second | third &lt;&lt; 5 |  first &lt;&lt;7 | fourth &lt;&lt; 9; // \&lt;- I think here is the problem

}



When the program get this simply program code :



// I have simplified the code :
00000000000100e8 \&lt;init\&gt;:

10130:	fd843783          	ld	a5,-40(s0)

1018c:	fae7d2e3          	bge	a5,a4,10130 \&lt;init+0x48\&gt; # note that the condition is always met on my code

I got : 0x7a2.

The pc adress is : 0x1018c

When I add 0x1018c to 0x7a2 , I got :0x1092E
There is an issue but I don't know where. I think the extract on imm variable have some issue.

I have tried to modify the imm variable bits shift and mask. But I don't have any luck.

I have try this :


unsigned long imm = second | third &lt;&lt; 4 |  first &lt;&lt; 5 | fourth &lt;&lt; 6; // output wrong data
unsigned long imm = second | third &lt;&lt; 6 |  first &lt;&lt; 11 | fourth &lt;&lt; 12; // output the same data as imm 
unsigned long imm = second | third &lt;&lt; 5 |  first &lt;&lt; 7 | fourth &lt;&lt; 9; // actual version
unsigned long   imm = second | third &lt;&lt;  6 |  first &lt;&lt; 7 | fourth &lt;&lt;8; // output the same data as imm 

答案1

得分: 0

你已经很接近了,但有几个要点:

  1. 你的变量 second 包含了位 4 到 1,但你却将它们应用到位 3 到 0,因为你没有将其左移 1 位(或者可以使用额外的 >> 1,注意 IMM1 & 0b11110 也可以工作)。
  2. 你的变量 fourth 包含了位 12,但那是符号位,必须进行符号扩展以用作立即数的 32 位使用。

除此之外,只需按照以下模式检查你的移位操作:[m:n] 必须左移 n 位。所以,假设每个字段都是右对齐的某个变量:

  • [4:1] << 1
  • [11] << 11
  • [10:5] << 5
  • [12] << 12 —— 但要进行符号扩展 —— 因此在 32 位机器上,[12] << 31,然后视为有符号数 >> 19,或者使用 [12] ? 0xFFFFF000 : 0[12] ? -4096 : 0

这样,你将获得一个 SB 类型的立即数,它从指令中的混淆的 12 位扩展到 32 位,适合加到 PC 上。


bge 指令中编码的立即数值为 0xfae7d2e3,这是 -92(0xFFFFFFA4)。

英文:

You're close, but a few points:

  1. Your variable, second, has bits 4:1 but you're applying them to 3:0 by failing to shift by 1 bit (or by doing that extra >> 1, note that IMM1 &amp; 0b11110 would work).
  2. Your variable, fourth, has bit 12, though that is the sign bit and must be sign extended out to 32 bits for use as the immediate.

Otherwise, just recheck your shifts by the following pattern: [m:n] must << n.&nbsp; So, assuming each field is right justified in some variable:

  • [4:1] << 1
  • [11] << 11
  • [10:5] << 5
  • [12] << 12 &#8212; but with sign extension &#8212; so on 32-bit machine, [12] << 31, then taken as signed >> 19, or else use [12] ? 0xFFFFF000 : 0 or [12] ? -4096 : 0.

With that you'll have an SB-Type immediate of 32 bits expanded from the mangled 12 bits in the instruction and suitable for adding to the PC.


The immediate value encoded in that bge instruction, 0xfae7d2e3, is -92 (0xFFFFFFA4).

huangapple
  • 本文由 发表于 2023年1月8日 22:35:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75048599.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定