以最高评论为序...
创建一个使用表定义位的函数(例如):
imm = bitmask(opcode,31,25,5) | bitmask(opcode,11,7,0);
这是我快速完成的一些示例代码(因为您的时间压力)。我把它运行在下面gdb
and I think我拿到mask
生成正确——但不保证:
#include <stdio.h>
typedef unsigned int u32;
u32
bitmask(u32 opc,u32 bhi,u32 blo,u32 shfl)
{
u32 val = opc >> blo;
u32 mask = 0xFFFFFFFF >> 31 - (bhi - blo);
val &= mask;
val <<= shfl;
return val;
}
int
main(void)
{
u32 opc = 0xF0FFFF0A;
u32 imm = 0;
imm |= bitmask(opc,31,25,5);
imm |= bitmask(opc,11,7,0);
printf("%8.8X/%u\n",imm,imm);
return 0;
}
请注意,如果您使该功能inline
并且仅传递常量位值和移位,编译器优化器将生成高效的代码。
UPDATE:
这会返回带有符号的立即值吗? –
超级编码器Superion
No, bitmask
is 故意地无符号,因此您可以在许多安装格式上使用它来获取位字段。
您可以应用已有的代码来应用签名。
我正在做这个too快速地。这是我的尝试,但很容易出错——调整以适应:
#include <stdio.h>
typedef unsigned int u32;
u32
bitmask(u32 opc,u32 bhi,u32 blo,u32 shfl)
{
u32 val = opc >> blo;
u32 mask = 0xFFFFFFFF >> 31 - (bhi - blo);
val &= mask;
val <<= shfl;
return val;
}
int
main(void)
{
u32 opc = 0xF0FFFF0A;
u32 uimm = 0;
uimm |= bitmask(opc,31,25,5);
uimm |= bitmask(opc,11,7,0);
printf("uimm=%8.8X/%u\n",uimm,uimm);
int imm;
if (uimm & 0x1000) {
imm = uimm & 0xFFF;
imm = -imm;
}
else
imm = uimm;
printf("imm=%8.8X/%d\n",imm,imm);
return 0;
}
更新#2:
我仍然不明白,如何传递包含指令本身的指令数组? –
超级编码器Superion
您已经在现有代码中获得了大部分内容。当你得到之后opcode
,只需用我输入的代码替换您的位移代码main
。也就是说,使用bitmask
而不是你正在做的轮班。
这是您的代码的快速修改。
Note:我用了一种不同的方式来获得imm
from uimm
在第二个例子中。您必须尝试哪种方式(您的或我的)实际上是正确的,因为我没有时间进行太多测试。
int
type_sb_imm(unsigned char *p)
{
// Extract the 32-bit instruction from the byte array
unsigned int opcode = (((unsigned int) p[0]) << 24) | (((unsigned int) p[1]) << 16) | (((unsigned int) p[2]) << 8) | ((unsigned int) p[3]);
// Extract the immediate value from the instruction (Type SB: branch)
u32 uimm = 0;
uimm |= bitmask(opcode,31,25,5);
uimm |= bitmask(opcode,11,7,0);
// Sign-extend the immediate value to 32 bits
int imm = uimm;
if (imm & 0x1000) {
imm |= 0xFFFFE000;
}
return imm;
}