在 C 中从二进制中找到立即数

问题描述 投票:0回答:1

我在 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}

现在我需要做哪些轮班操作才能获得如上所示的即时价值?

c bit-manipulation bit riscv
1个回答
0
投票

你可以这样写:

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);
}

预订:我只是把这个放在一起,我还没有时间仔细检查所有口罩和班次,但这足以让你明白。

© www.soinside.com 2019 - 2024. All rights reserved.