我写了一个riscv 64模拟器,但是在分支指令的偏移量计算上有一个问题(尤其是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; // \<- I think here is the problem
}
当程序得到这个简单的程序代码:
// I have simplified the code :
00000000000100e8 \<init\>:
10130: fd843783 ld a5,-40(s0)
1018c: fae7d2e3 bge a5,a4,10130 \<init+0x48\> # note that the condition is always met on my code
我得到了:0x 7a 2。
PC地址为:0x1018c
当我添加0x 1018 c到0x 7a 2,我得到:0x 1092 E有一个问题,但我不知道在哪里。我认为imm变量的提取有一些问题。
我试过修改imm变量的位移位和掩码。但是我没有任何运气。
我已经试过了:
unsigned long imm = second | third << 4 | first << 5 | fourth << 6; // output wrong data
unsigned long imm = second | third << 6 | first << 11 | fourth << 12; // output the same data as imm
unsigned long imm = second | third << 5 | first << 7 | fourth << 9; // actual version
unsigned long imm = second | third << 6 | first << 7 | fourth <<8; // output the same data as imm
1条答案
按热度按时间scyqe7ek1#
你很接近了,但还有几点:
1.变量
second
的位数为4:1,但由于没有移位1位(或者做了额外的〉〉1操作,注意IMM1 & 0b11110
也可以),所以将它们应用于3:0。1.您的变量
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
。这样,您将拥有一个32位的SB类型立即数,它是从指令中损坏的12位扩展而来的,适合添加到PC中。
该
bge
指令0xfae 7d2 e3中编码的立即数是-92(0xFFFFFFA 4)。