decode: Add second fixed operand size
This commit is contained in:
28
decode.c
28
decode.c
@@ -303,15 +303,8 @@ struct InstrDesc
|
|||||||
{
|
{
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
uint8_t operand_indices;
|
uint8_t operand_indices;
|
||||||
uint8_t operand_sizes;
|
|
||||||
uint8_t immediate;
|
uint8_t immediate;
|
||||||
|
uint16_t operand_sizes;
|
||||||
uint8_t gp_size_8 : 1;
|
|
||||||
uint8_t gp_size_def64 : 1;
|
|
||||||
uint8_t gp_instr_width : 1;
|
|
||||||
uint8_t gp_fixed_operand_size : 3;
|
|
||||||
uint8_t lock : 1;
|
|
||||||
uint8_t vsib : 1;
|
|
||||||
uint16_t reg_types;
|
uint16_t reg_types;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
@@ -326,6 +319,13 @@ struct InstrDesc
|
|||||||
#define DESC_IMM_CONTROL(desc) (((desc)->immediate >> 4) & 0x7)
|
#define DESC_IMM_CONTROL(desc) (((desc)->immediate >> 4) & 0x7)
|
||||||
#define DESC_IMM_IDX(desc) (((desc)->immediate & 3) ^ 3)
|
#define DESC_IMM_IDX(desc) (((desc)->immediate & 3) ^ 3)
|
||||||
#define DESC_IMPLICIT_VAL(desc) (((desc)->immediate >> 2) & 1)
|
#define DESC_IMPLICIT_VAL(desc) (((desc)->immediate >> 2) & 1)
|
||||||
|
#define DESC_LOCK(desc) (((desc)->immediate >> 3) & 1)
|
||||||
|
#define DESC_VSIB(desc) (((desc)->immediate >> 7) & 1)
|
||||||
|
#define DESC_SIZE8(desc) (((desc)->operand_sizes >> 8) & 1)
|
||||||
|
#define DESC_SIZED64(desc) (((desc)->operand_sizes >> 9) & 1)
|
||||||
|
#define DESC_SIZE_FIX1(desc) (((desc)->operand_sizes >> 10) & 7)
|
||||||
|
#define DESC_SIZE_FIX2(desc) (((desc)->operand_sizes >> 13) & 3)
|
||||||
|
#define DESC_INSTR_WIDTH(desc) (((desc)->operand_sizes >> 15) & 1)
|
||||||
|
|
||||||
int
|
int
|
||||||
fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address,
|
fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address,
|
||||||
@@ -445,13 +445,13 @@ fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address,
|
|||||||
instr->address = address;
|
instr->address = address;
|
||||||
|
|
||||||
uint8_t op_size = 0;
|
uint8_t op_size = 0;
|
||||||
if (desc->gp_size_8)
|
if (DESC_SIZE8(desc))
|
||||||
op_size = 1;
|
op_size = 1;
|
||||||
else if (mode == DECODE_64 && (prefixes & PREFIX_REXW))
|
else if (mode == DECODE_64 && (prefixes & PREFIX_REXW))
|
||||||
op_size = 8;
|
op_size = 8;
|
||||||
else if (prefixes & PREFIX_OPSZ)
|
else if (prefixes & PREFIX_OPSZ)
|
||||||
op_size = 2;
|
op_size = 2;
|
||||||
else if (mode == DECODE_64 && desc->gp_size_def64)
|
else if (mode == DECODE_64 && DESC_SIZED64(desc))
|
||||||
op_size = 8;
|
op_size = 8;
|
||||||
else
|
else
|
||||||
op_size = 4;
|
op_size = 4;
|
||||||
@@ -492,7 +492,7 @@ fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address,
|
|||||||
operand2 = &instr->operands[DESC_MODREG_IDX(desc)];
|
operand2 = &instr->operands[DESC_MODREG_IDX(desc)];
|
||||||
|
|
||||||
retval = decode_modrm(buffer + off, len - off, mode, instr, prefixes,
|
retval = decode_modrm(buffer + off, len - off, mode, instr, prefixes,
|
||||||
desc->vsib, operand1, operand2);
|
DESC_VSIB(desc), operand1, operand2);
|
||||||
if (UNLIKELY(retval < 0))
|
if (UNLIKELY(retval < 0))
|
||||||
return retval;
|
return retval;
|
||||||
off += retval;
|
off += retval;
|
||||||
@@ -635,11 +635,11 @@ fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (UNLIKELY(prefixes & PREFIX_LOCK))
|
if (UNLIKELY(prefixes & PREFIX_LOCK))
|
||||||
if (!desc->lock || instr->operands[0].type != FD_OT_MEM)
|
if (!DESC_LOCK(desc) || instr->operands[0].type != FD_OT_MEM)
|
||||||
return FD_ERR_UD;
|
return FD_ERR_UD;
|
||||||
|
|
||||||
uint8_t operand_sizes[4] = {
|
uint8_t operand_sizes[4] = {
|
||||||
0, 1 << desc->gp_fixed_operand_size, op_size, vec_size
|
1 << DESC_SIZE_FIX1(desc) >> 1, 1 << DESC_SIZE_FIX2(desc), op_size, vec_size
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
@@ -657,7 +657,7 @@ fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address,
|
|||||||
}
|
}
|
||||||
|
|
||||||
instr->size = off;
|
instr->size = off;
|
||||||
instr->operandsz = desc->gp_instr_width ? op_size : 0;
|
instr->operandsz = DESC_INSTR_WIDTH(desc) ? op_size : 0;
|
||||||
|
|
||||||
return off;
|
return off;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,21 +30,20 @@ InstrFlags = bitstruct("InstrFlags", [
|
|||||||
"modreg_idx:2",
|
"modreg_idx:2",
|
||||||
"vexreg_idx:2",
|
"vexreg_idx:2",
|
||||||
"zeroreg_idx:2",
|
"zeroreg_idx:2",
|
||||||
|
"imm_idx:2",
|
||||||
|
"zeroreg_val:1",
|
||||||
|
"lock:1",
|
||||||
|
"imm_control:3",
|
||||||
|
"vsib:1",
|
||||||
"op0_size:2",
|
"op0_size:2",
|
||||||
"op1_size:2",
|
"op1_size:2",
|
||||||
"op2_size:2",
|
"op2_size:2",
|
||||||
"op3_size:2",
|
"op3_size:2",
|
||||||
"imm_idx:2",
|
"size8:1",
|
||||||
"zeroreg_val:1",
|
"sized64:1",
|
||||||
"_unused:1",
|
"size_fix1:3",
|
||||||
"imm_control:3",
|
"size_fix2:2",
|
||||||
"_unused:1",
|
"instr_width:1",
|
||||||
"gp_size_8:1",
|
|
||||||
"gp_size_def64:1",
|
|
||||||
"gp_instr_width:1",
|
|
||||||
"gp_fixed_operand_size:3",
|
|
||||||
"lock:1",
|
|
||||||
"vsib:1",
|
|
||||||
"op0_regty:3",
|
"op0_regty:3",
|
||||||
"op1_regty:3",
|
"op1_regty:3",
|
||||||
"op2_regty:3",
|
"op2_regty:3",
|
||||||
@@ -135,8 +134,8 @@ class InstrDesc(NamedTuple):
|
|||||||
|
|
||||||
OPKIND_REGTYS = {"GP": 0, "FPU": 1, "XMM": 2, "MASK": 3, "MMX": 4, "BND": 5}
|
OPKIND_REGTYS = {"GP": 0, "FPU": 1, "XMM": 2, "MASK": 3, "MMX": 4, "BND": 5}
|
||||||
OPKIND_SIZES = {
|
OPKIND_SIZES = {
|
||||||
0: (0,0), 1: (1,0), 2: (1,1), 4: (1,2), 8: (1,3), 16: (1,4), 32: (1,5),
|
0: 0, 1: 1, 2: 2, 4: 3, 8: 4, 16: 5, 32: 6, 10: 0,
|
||||||
OpKind.SZ_OP: (2,0), OpKind.SZ_VEC: (3,0),
|
OpKind.SZ_OP: -2, OpKind.SZ_VEC: -3,
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -148,23 +147,29 @@ class InstrDesc(NamedTuple):
|
|||||||
def encode(self):
|
def encode(self):
|
||||||
flags = copy(ENCODINGS[self.encoding])
|
flags = copy(ENCODINGS[self.encoding])
|
||||||
|
|
||||||
fixed_opsz = set()
|
opsz = set(self.OPKIND_SIZES[opkind.size] for opkind in self.operands)
|
||||||
|
|
||||||
|
# Sort fixed sizes encodable in size_fix2 as second element.
|
||||||
|
fixed = sorted((x for x in opsz if x >= 0), key=lambda x: 1 <= x <= 4)
|
||||||
|
if len(fixed) > 2 or (len(fixed) == 2 and not (1 <= fixed[1] <= 4)):
|
||||||
|
raise Exception("invalid fixed operand sizes: %r"%fixed)
|
||||||
|
sizes = (fixed + [1, 1])[:2] + [-2, -3] # See operand_sizes in decode.c.
|
||||||
|
flags.size_fix1 = sizes[0]
|
||||||
|
flags.size_fix2 = sizes[1] - 1
|
||||||
|
|
||||||
for i, opkind in enumerate(self.operands):
|
for i, opkind in enumerate(self.operands):
|
||||||
enc_size, fixed_size = self.OPKIND_SIZES.get(opkind.size, (0, 0))
|
sz = self.OPKIND_SIZES[opkind.size]
|
||||||
reg_type = self.OPKIND_REGTYS.get(opkind.kind, 7)
|
reg_type = self.OPKIND_REGTYS.get(opkind.kind, 7)
|
||||||
if enc_size == 1: fixed_opsz.add(fixed_size)
|
setattr(flags, "op%d_size"%i, sizes.index(sz))
|
||||||
setattr(flags, "op%d_size"%i, enc_size)
|
|
||||||
if i < 3:
|
if i < 3:
|
||||||
setattr(flags, "op%d_regty"%i, reg_type)
|
setattr(flags, "op%d_regty"%i, reg_type)
|
||||||
elif reg_type not in (7, 2):
|
elif reg_type not in (7, 2):
|
||||||
raise Exception("invalid regty for op 3, must be VEC")
|
raise Exception("invalid regty for op 3, must be VEC")
|
||||||
|
|
||||||
if fixed_opsz: flags.gp_fixed_operand_size = next(iter(fixed_opsz))
|
|
||||||
|
|
||||||
# Miscellaneous Flags
|
# Miscellaneous Flags
|
||||||
if "DEF64" in self.flags: flags.gp_size_def64 = 1
|
if "DEF64" in self.flags: flags.sized64 = 1
|
||||||
if "SIZE_8" in self.flags: flags.gp_size_8 = 1
|
if "SIZE_8" in self.flags: flags.size8 = 1
|
||||||
if "INSTR_WIDTH" in self.flags: flags.gp_instr_width = 1
|
if "INSTR_WIDTH" in self.flags: flags.instr_width = 1
|
||||||
if "IMM_8" in self.flags: flags.imm_control = {4: 5, 6: 7}[flags.imm_control]
|
if "IMM_8" in self.flags: flags.imm_control = {4: 5, 6: 7}[flags.imm_control]
|
||||||
if "LOCK" in self.flags: flags.lock = 1
|
if "LOCK" in self.flags: flags.lock = 1
|
||||||
if "VSIB" in self.flags: flags.vsib = 1
|
if "VSIB" in self.flags: flags.vsib = 1
|
||||||
|
|||||||
Reference in New Issue
Block a user