我在 C 中实现一个 RISCV 风格的系统 不一样但相似
我的程序读取一个二进制文件,对指令进行一些操作。但这无关紧要,因为这不是我今天在这里要问你的。
所以我有一个 32 位的二进制让我们说这是我们的二进制
00000000110000000000000011101111
我想求即时值
现在这是我系统中的 JAL 指令,因为 OPCode 是 1101111 而我们存储的寄存器是 00001
所以既然我们已经解决了这个问题
让我们开始
与 RISCV 不同,我们的立即值被编码为
嗯[20 | 10:1 | 11 | 19:12]
简单来说
第 31 到 12 位(20 位)是我们的立即数
第 7 位到第 11 位(5 位)是我们的 rd
Bits 0 到 6 是我们的操作码(7 位)
总指令大小为 32 位。
使用我们的二进制编码 00000000110000000000000011101111
因此我们得到:
这给了我们 00000000000000000110 (6)
然后我们移动 1 得到 000000000000000001100 或在本例中为 12。 12 是我们的直接价值。
我有一个 C 函数,它将指令作为 char*pointer 接收
int get_immediate(unsigned char* instruction){
return 0;
}
这个指针包含十六进制的二进制,所以在我们的例子中它是 {00,C0,00,EF}
现在我需要做哪些轮班操作才能获得如上所示的即时价值?
你可以这样写:
int get_immediate(unsigned char * p)
{
// Note: This assumes that the opcode is stored in big endian
// format, which is unusual for RISC-V. If this is not correct,
// change the indices accordingly.
unsigned int opcode = ( (((unsigned int)p[0]) << 24)
| (((unsigned int)p[1]) << 16)
| (((unsigned int)p[2]) << 8)
| ((unsigned int)p[3]));
// | imm20 | imm10-1 | imm11 | imm19-12 | Rd | Opcode |
// Note: imm0 it always 0 and not part of the opcode.
unsigned int uimm = ( ((opcode >> (21 - 1)) & 0x7FE) // imm10-1
| ((opcode >> (20 - 11)) & 0x800) // imm11
| ((opcode & 0xFF000)) // imm19-12
| ((opcode >> (31 - 20)) & 0x100000)); // imm20
int imm = uimm;
// Sign-extend the result:
return (imm << (32 - 21)) >> (32 - 21);
}
预订:我只是把这个放在一起,我还没有时间仔细检查所有口罩和班次,但这足以让你明白。