decode: Store op size per operand type
This change doesn't really affect performance and is preparatory work for AVX-512, where the memory operand size is required to compute the compressed displacement.
This commit is contained in:
26
decode.c
26
decode.c
@@ -312,12 +312,17 @@ prefix_end:
|
|||||||
op_size_alt = op_size - (DESC_OPSIZE(desc) & 3);
|
op_size_alt = op_size - (DESC_OPSIZE(desc) & 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t operand_sizes[4] = {
|
||||||
|
DESC_SIZE_FIX1(desc), DESC_SIZE_FIX2(desc) + 1, op_size, op_size_alt
|
||||||
|
};
|
||||||
|
|
||||||
if (UNLIKELY(instr->type == FDI_MOV_CR || instr->type == FDI_MOV_DR)) {
|
if (UNLIKELY(instr->type == FDI_MOV_CR || instr->type == FDI_MOV_DR)) {
|
||||||
unsigned modreg = (op_byte >> 3) & 0x7;
|
unsigned modreg = (op_byte >> 3) & 0x7;
|
||||||
unsigned modrm = op_byte & 0x7;
|
unsigned modrm = op_byte & 0x7;
|
||||||
|
|
||||||
FdOp* op_modreg = &instr->operands[DESC_MODREG_IDX(desc)];
|
FdOp* op_modreg = &instr->operands[DESC_MODREG_IDX(desc)];
|
||||||
op_modreg->type = FD_OT_REG;
|
op_modreg->type = FD_OT_REG;
|
||||||
|
op_modreg->size = op_size;
|
||||||
op_modreg->reg = modreg | (prefix_rex & PREFIX_REXR ? 8 : 0);
|
op_modreg->reg = modreg | (prefix_rex & PREFIX_REXR ? 8 : 0);
|
||||||
op_modreg->misc = instr->type == FDI_MOV_CR ? FD_RT_CR : FD_RT_DR;
|
op_modreg->misc = instr->type == FDI_MOV_CR ? FD_RT_CR : FD_RT_DR;
|
||||||
if (instr->type == FDI_MOV_CR && (~0x011d >> op_modreg->reg) & 1)
|
if (instr->type == FDI_MOV_CR && (~0x011d >> op_modreg->reg) & 1)
|
||||||
@@ -327,6 +332,7 @@ prefix_end:
|
|||||||
|
|
||||||
FdOp* op_modrm = &instr->operands[DESC_MODRM_IDX(desc)];
|
FdOp* op_modrm = &instr->operands[DESC_MODRM_IDX(desc)];
|
||||||
op_modrm->type = FD_OT_REG;
|
op_modrm->type = FD_OT_REG;
|
||||||
|
op_modrm->size = op_size;
|
||||||
op_modrm->reg = modrm | (prefix_rex & PREFIX_REXB ? 8 : 0);
|
op_modrm->reg = modrm | (prefix_rex & PREFIX_REXB ? 8 : 0);
|
||||||
op_modrm->misc = FD_RT_GPL;
|
op_modrm->misc = FD_RT_GPL;
|
||||||
goto skip_modrm;
|
goto skip_modrm;
|
||||||
@@ -341,12 +347,14 @@ prefix_end:
|
|||||||
if (LIKELY(!(reg_ty & 4)))
|
if (LIKELY(!(reg_ty & 4)))
|
||||||
reg_idx += prefix_rex & PREFIX_REXR ? 8 : 0;
|
reg_idx += prefix_rex & PREFIX_REXR ? 8 : 0;
|
||||||
op_modreg->type = FD_OT_REG;
|
op_modreg->type = FD_OT_REG;
|
||||||
|
op_modreg->size = operand_sizes[(desc->operand_sizes >> 2) & 3];
|
||||||
op_modreg->reg = reg_idx;
|
op_modreg->reg = reg_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DESC_HAS_MODRM(desc))
|
if (DESC_HAS_MODRM(desc))
|
||||||
{
|
{
|
||||||
FdOp* op_modrm = &instr->operands[DESC_MODRM_IDX(desc)];
|
FdOp* op_modrm = &instr->operands[DESC_MODRM_IDX(desc)];
|
||||||
|
op_modrm->size = operand_sizes[(desc->operand_sizes >> 0) & 3];
|
||||||
|
|
||||||
unsigned mod = op_byte & 0xc0;
|
unsigned mod = op_byte & 0xc0;
|
||||||
unsigned rm = op_byte & 0x07;
|
unsigned rm = op_byte & 0x07;
|
||||||
@@ -424,6 +432,7 @@ skip_modrm:
|
|||||||
// Without VEX prefix, this encodes an implicit register
|
// Without VEX prefix, this encodes an implicit register
|
||||||
FdOp* operand = &instr->operands[DESC_VEXREG_IDX(desc)];
|
FdOp* operand = &instr->operands[DESC_VEXREG_IDX(desc)];
|
||||||
operand->type = FD_OT_REG;
|
operand->type = FD_OT_REG;
|
||||||
|
operand->size = operand_sizes[(desc->operand_sizes >> 4) & 3];
|
||||||
if (mode == DECODE_32)
|
if (mode == DECODE_32)
|
||||||
vex_operand &= 0x7;
|
vex_operand &= 0x7;
|
||||||
operand->reg = vex_operand | DESC_ZEROREG_VAL(desc);
|
operand->reg = vex_operand | DESC_ZEROREG_VAL(desc);
|
||||||
@@ -442,6 +451,7 @@ skip_modrm:
|
|||||||
// 1 = immediate constant 1, used for shifts
|
// 1 = immediate constant 1, used for shifts
|
||||||
FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)];
|
FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)];
|
||||||
operand->type = FD_OT_IMM;
|
operand->type = FD_OT_IMM;
|
||||||
|
operand->size = 1;
|
||||||
instr->imm = 1;
|
instr->imm = 1;
|
||||||
}
|
}
|
||||||
else if (UNLIKELY(imm_control == 2))
|
else if (UNLIKELY(imm_control == 2))
|
||||||
@@ -449,6 +459,7 @@ skip_modrm:
|
|||||||
// 2 = memory, address-sized, used for mov with moffs operand
|
// 2 = memory, address-sized, used for mov with moffs operand
|
||||||
FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)];
|
FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)];
|
||||||
operand->type = FD_OT_MEM;
|
operand->type = FD_OT_MEM;
|
||||||
|
operand->size = op_size;
|
||||||
operand->reg = FD_REG_NONE;
|
operand->reg = FD_REG_NONE;
|
||||||
operand->misc = FD_REG_NONE;
|
operand->misc = FD_REG_NONE;
|
||||||
|
|
||||||
@@ -468,6 +479,7 @@ skip_modrm:
|
|||||||
// 3 = register in imm8[7:4], used for RVMR encoding with VBLENDVP[SD]
|
// 3 = register in imm8[7:4], used for RVMR encoding with VBLENDVP[SD]
|
||||||
FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)];
|
FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)];
|
||||||
operand->type = FD_OT_REG;
|
operand->type = FD_OT_REG;
|
||||||
|
operand->size = op_size;
|
||||||
operand->misc = FD_RT_VEC;
|
operand->misc = FD_RT_VEC;
|
||||||
|
|
||||||
if (UNLIKELY(off + 1 > len))
|
if (UNLIKELY(off + 1 > len))
|
||||||
@@ -484,6 +496,7 @@ skip_modrm:
|
|||||||
{
|
{
|
||||||
FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)];
|
FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)];
|
||||||
operand->type = FD_OT_IMM;
|
operand->type = FD_OT_IMM;
|
||||||
|
operand->size = operand_sizes[(desc->operand_sizes >> 6) & 3];
|
||||||
|
|
||||||
// 4/5 = immediate, operand-sized/8 bit
|
// 4/5 = immediate, operand-sized/8 bit
|
||||||
// 6/7 = offset, operand-sized/8 bit (used for jumps/calls)
|
// 6/7 = offset, operand-sized/8 bit (used for jumps/calls)
|
||||||
@@ -563,19 +576,6 @@ skip_modrm:
|
|||||||
instr->flags |= FD_FLAG_LOCK;
|
instr->flags |= FD_FLAG_LOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t operand_sizes[4] = {
|
|
||||||
DESC_SIZE_FIX1(desc), DESC_SIZE_FIX2(desc) + 1, op_size, op_size_alt
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
FdOp* operand = &instr->operands[i];
|
|
||||||
if (operand->type == FD_OT_NONE)
|
|
||||||
break;
|
|
||||||
|
|
||||||
operand->size = operand_sizes[(desc->operand_sizes >> 2 * i) & 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UNLIKELY(op_size == 1 || instr->type == FDI_MOVSX || instr->type == FDI_MOVZX)) {
|
if (UNLIKELY(op_size == 1 || instr->type == FDI_MOVSX || instr->type == FDI_MOVZX)) {
|
||||||
if (!(prefix_rex & PREFIX_REX)) {
|
if (!(prefix_rex & PREFIX_REX)) {
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ INSTR_FLAGS_FIELDS, INSTR_FLAGS_SIZES = zip(*[
|
|||||||
("lock", 1),
|
("lock", 1),
|
||||||
("imm_control", 3),
|
("imm_control", 3),
|
||||||
("vsib", 1),
|
("vsib", 1),
|
||||||
("op0_size", 2),
|
("modrm_size", 2),
|
||||||
("op1_size", 2),
|
("modreg_size", 2),
|
||||||
("op2_size", 2),
|
("vexreg_size", 2),
|
||||||
("op3_size", 2),
|
("imm_size", 2),
|
||||||
("unused2", 2),
|
("unused2", 2),
|
||||||
("size_fix1", 3),
|
("size_fix1", 3),
|
||||||
("size_fix2", 2),
|
("size_fix2", 2),
|
||||||
@@ -29,6 +29,7 @@ INSTR_FLAGS_FIELDS, INSTR_FLAGS_SIZES = zip(*[
|
|||||||
("modrm_ty", 3),
|
("modrm_ty", 3),
|
||||||
("modreg_ty", 3),
|
("modreg_ty", 3),
|
||||||
("vexreg_ty", 2),
|
("vexreg_ty", 2),
|
||||||
|
("imm_ty", 0),
|
||||||
("unused", 3),
|
("unused", 3),
|
||||||
("opsize", 3),
|
("opsize", 3),
|
||||||
("modrm", 1),
|
("modrm", 1),
|
||||||
@@ -171,10 +172,18 @@ class InstrDesc(NamedTuple):
|
|||||||
operands: Tuple[str, ...]
|
operands: Tuple[str, ...]
|
||||||
flags: FrozenSet[str]
|
flags: FrozenSet[str]
|
||||||
|
|
||||||
OPKIND_REGTYS_MODRM = { "GP": 0, "XMM": 1, "MMX": 4, "FPU": 5, "MASK": 6, }
|
OPKIND_REGTYS = {
|
||||||
OPKIND_REGTYS_MODREG = { "GP": 0, "XMM": 1, "MASK": 2, "MMX": 4, "SEG": 5,
|
("modrm", "GP"): 0, ("modreg", "GP"): 0, ("vexreg", "GP"): 0,
|
||||||
"CR": 0, "DR": 0 } # CR/DR handled in code.
|
("modrm", "XMM"): 1, ("modreg", "XMM"): 1, ("vexreg", "XMM"): 1,
|
||||||
OPKIND_REGTYS_VEXREG = { "GP": 0, "XMM": 1, "MASK": 2, "FPU": 3 } # also zeroreg
|
("modrm", "MMX"): 4, ("modreg", "MMX"): 4,
|
||||||
|
("modrm", "FPU"): 5, ("vexreg", "FPU"): 3,
|
||||||
|
("modrm", "MASK"): 6, ("modreg", "MASK"): 2, ("vexreg", "MASK"): 2,
|
||||||
|
("modreg", "SEG"): 5,
|
||||||
|
("modreg", "DR"): 0, # handled in code
|
||||||
|
("modreg", "CR"): 0, # handled in code
|
||||||
|
("modrm", "MEM"): 0,
|
||||||
|
("imm", "MEM"): 0, ("imm", "IMM"): 0, ("imm", "XMM"): 0,
|
||||||
|
}
|
||||||
OPKIND_REGTYS_ENC = {"SEG": 3, "FPU": 4, "MMX": 5, "XMM": 6, "BND": 8,
|
OPKIND_REGTYS_ENC = {"SEG": 3, "FPU": 4, "MMX": 5, "XMM": 6, "BND": 8,
|
||||||
"CR": 9, "DR": 10}
|
"CR": 9, "DR": 10}
|
||||||
OPKIND_SIZES = {
|
OPKIND_SIZES = {
|
||||||
@@ -271,19 +280,9 @@ class InstrDesc(NamedTuple):
|
|||||||
|
|
||||||
for i, opkind in enumerate(self.operands):
|
for i, opkind in enumerate(self.operands):
|
||||||
sz = self.OPKIND_SIZES[opkind.size] if opkind.size >= 0 else opkind.size
|
sz = self.OPKIND_SIZES[opkind.size] if opkind.size >= 0 else opkind.size
|
||||||
extraflags["op%d_size"%i] = sizes.index(sz)
|
|
||||||
opname = ENCODING_OPORDER[self.encoding][i]
|
opname = ENCODING_OPORDER[self.encoding][i]
|
||||||
if opname == "modrm":
|
extraflags[f"{opname}_size"] = sizes.index(sz)
|
||||||
if opkind.kind == "MEM":
|
extraflags[f"{opname}_ty"] = self.OPKIND_REGTYS[opname, opkind.kind]
|
||||||
continue
|
|
||||||
extraflags["modrm_ty"] = self.OPKIND_REGTYS_MODRM[opkind.kind]
|
|
||||||
elif opname == "modreg":
|
|
||||||
extraflags["modreg_ty"] = self.OPKIND_REGTYS_MODREG[opkind.kind]
|
|
||||||
elif opname == "vexreg":
|
|
||||||
extraflags["vexreg_ty"] = self.OPKIND_REGTYS_VEXREG[opkind.kind]
|
|
||||||
else:
|
|
||||||
if opkind.kind not in ("IMM", "MEM", "XMM"):
|
|
||||||
raise Exception("invalid regty for op 3, must be VEC")
|
|
||||||
|
|
||||||
# Miscellaneous Flags
|
# Miscellaneous Flags
|
||||||
if "VSIB" in self.flags: extraflags["vsib"] = 1
|
if "VSIB" in self.flags: extraflags["vsib"] = 1
|
||||||
|
|||||||
Reference in New Issue
Block a user