Refactor ModRM decoding
This commit is contained in:
75
decode.c
75
decode.c
@@ -241,15 +241,12 @@ decode_modrm(const uint8_t* buffer, int len, DecodeMode mode, FdInstr* instr,
|
|||||||
|
|
||||||
// SIB byte
|
// SIB byte
|
||||||
uint8_t scale = 0;
|
uint8_t scale = 0;
|
||||||
uint8_t idx = 0;
|
uint8_t idx = 4;
|
||||||
uint8_t base = 0;
|
uint8_t base = rm;
|
||||||
if (rm == 4)
|
if (rm == 4)
|
||||||
{
|
{
|
||||||
if (UNLIKELY(off >= len))
|
if (UNLIKELY(off >= len))
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t sib = buffer[off++];
|
uint8_t sib = buffer[off++];
|
||||||
scale = (sib & 0xc0) >> 6;
|
scale = (sib & 0xc0) >> 6;
|
||||||
idx = (sib & 0x38) >> 3;
|
idx = (sib & 0x38) >> 3;
|
||||||
@@ -259,23 +256,29 @@ decode_modrm(const uint8_t* buffer, int len, DecodeMode mode, FdInstr* instr,
|
|||||||
base = sib & 0x07;
|
base = sib & 0x07;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out_o1->type = FD_OT_MEM;
|
||||||
|
instr->idx_scale = scale;
|
||||||
|
instr->idx_reg = idx == 4 ? FD_REG_NONE : idx;
|
||||||
|
|
||||||
|
// RIP-relative addressing only if SIB-byte is absent
|
||||||
|
if (mod == 0 && rm == 5 && mode == DECODE_64)
|
||||||
|
out_o1->reg = FD_REG_IP;
|
||||||
|
else if (mod == 0 && base == 5)
|
||||||
|
out_o1->reg = FD_REG_NONE;
|
||||||
|
else
|
||||||
|
out_o1->reg = base + (prefixes & PREFIX_REXB ? 8 : 0);
|
||||||
|
|
||||||
if (mod == 1)
|
if (mod == 1)
|
||||||
{
|
{
|
||||||
if (UNLIKELY(off + 1 > len))
|
if (UNLIKELY(off + 1 > len))
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
instr->disp = (int8_t) LOAD_LE_1(&buffer[off]);
|
instr->disp = (int8_t) LOAD_LE_1(&buffer[off]);
|
||||||
off += 1;
|
off += 1;
|
||||||
}
|
}
|
||||||
else if (mod == 2 || (mod == 0 && (rm == 5 || base == 5)))
|
else if (mod == 2 || (mod == 0 && base == 5))
|
||||||
{
|
{
|
||||||
if (UNLIKELY(off + 4 > len))
|
if (UNLIKELY(off + 4 > len))
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
instr->disp = (int32_t) LOAD_LE_4(&buffer[off]);
|
instr->disp = (int32_t) LOAD_LE_4(&buffer[off]);
|
||||||
off += 4;
|
off += 4;
|
||||||
}
|
}
|
||||||
@@ -284,54 +287,6 @@ decode_modrm(const uint8_t* buffer, int len, DecodeMode mode, FdInstr* instr,
|
|||||||
instr->disp = 0;
|
instr->disp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_o1->type = FD_OT_MEM;
|
|
||||||
instr->idx_scale = scale;
|
|
||||||
|
|
||||||
// If there was no SIB byte.
|
|
||||||
if (rm != 4)
|
|
||||||
{
|
|
||||||
instr->idx_reg = FD_REG_NONE;
|
|
||||||
if (mod == 0 && rm == 5)
|
|
||||||
{
|
|
||||||
#if defined(ARCH_X86_64)
|
|
||||||
if (mode == DECODE_64)
|
|
||||||
out_o1->reg = FD_REG_IP;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
out_o1->reg = FD_REG_NONE;
|
|
||||||
return off;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t reg_idx = rm;
|
|
||||||
#if defined(ARCH_X86_64)
|
|
||||||
reg_idx += prefixes & PREFIX_REXB ? 8 : 0;
|
|
||||||
#endif
|
|
||||||
out_o1->reg = reg_idx;
|
|
||||||
return off;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx == 4)
|
|
||||||
{
|
|
||||||
instr->idx_reg = FD_REG_NONE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
instr->idx_reg = idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (base == 5 && mod == 0)
|
|
||||||
{
|
|
||||||
out_o1->reg = FD_REG_NONE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint8_t reg_idx = base;
|
|
||||||
#if defined(ARCH_X86_64)
|
|
||||||
reg_idx += prefixes & PREFIX_REXB ? 8 : 0;
|
|
||||||
#endif
|
|
||||||
out_o1->reg = reg_idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return off;
|
return off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user