From 99a9802f501f4fdfce005a6809f0ddc4ec5dd9f5 Mon Sep 17 00:00:00 2001 From: Alexis Engelke Date: Sat, 3 Dec 2022 14:52:06 +0100 Subject: [PATCH] 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. --- decode.c | 26 +++++++++++++------------- parseinstrs.py | 39 +++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/decode.c b/decode.c index 276572a..5928242 100644 --- a/decode.c +++ b/decode.c @@ -312,12 +312,17 @@ prefix_end: 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)) { unsigned modreg = (op_byte >> 3) & 0x7; unsigned modrm = op_byte & 0x7; FdOp* op_modreg = &instr->operands[DESC_MODREG_IDX(desc)]; op_modreg->type = FD_OT_REG; + op_modreg->size = op_size; op_modreg->reg = modreg | (prefix_rex & PREFIX_REXR ? 8 : 0); 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) @@ -327,6 +332,7 @@ prefix_end: FdOp* op_modrm = &instr->operands[DESC_MODRM_IDX(desc)]; op_modrm->type = FD_OT_REG; + op_modrm->size = op_size; op_modrm->reg = modrm | (prefix_rex & PREFIX_REXB ? 8 : 0); op_modrm->misc = FD_RT_GPL; goto skip_modrm; @@ -341,12 +347,14 @@ prefix_end: if (LIKELY(!(reg_ty & 4))) reg_idx += prefix_rex & PREFIX_REXR ? 8 : 0; op_modreg->type = FD_OT_REG; + op_modreg->size = operand_sizes[(desc->operand_sizes >> 2) & 3]; op_modreg->reg = reg_idx; } if (DESC_HAS_MODRM(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 rm = op_byte & 0x07; @@ -424,6 +432,7 @@ skip_modrm: // Without VEX prefix, this encodes an implicit register FdOp* operand = &instr->operands[DESC_VEXREG_IDX(desc)]; operand->type = FD_OT_REG; + operand->size = operand_sizes[(desc->operand_sizes >> 4) & 3]; if (mode == DECODE_32) vex_operand &= 0x7; operand->reg = vex_operand | DESC_ZEROREG_VAL(desc); @@ -442,6 +451,7 @@ skip_modrm: // 1 = immediate constant 1, used for shifts FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)]; operand->type = FD_OT_IMM; + operand->size = 1; instr->imm = 1; } else if (UNLIKELY(imm_control == 2)) @@ -449,6 +459,7 @@ skip_modrm: // 2 = memory, address-sized, used for mov with moffs operand FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)]; operand->type = FD_OT_MEM; + operand->size = op_size; operand->reg = 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] FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)]; operand->type = FD_OT_REG; + operand->size = op_size; operand->misc = FD_RT_VEC; if (UNLIKELY(off + 1 > len)) @@ -484,6 +496,7 @@ skip_modrm: { FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)]; operand->type = FD_OT_IMM; + operand->size = operand_sizes[(desc->operand_sizes >> 6) & 3]; // 4/5 = immediate, operand-sized/8 bit // 6/7 = offset, operand-sized/8 bit (used for jumps/calls) @@ -563,19 +576,6 @@ skip_modrm: 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 (!(prefix_rex & PREFIX_REX)) { for (int i = 0; i < 2; i++) { diff --git a/parseinstrs.py b/parseinstrs.py index 8137bd8..2aa6e36 100644 --- a/parseinstrs.py +++ b/parseinstrs.py @@ -18,10 +18,10 @@ INSTR_FLAGS_FIELDS, INSTR_FLAGS_SIZES = zip(*[ ("lock", 1), ("imm_control", 3), ("vsib", 1), - ("op0_size", 2), - ("op1_size", 2), - ("op2_size", 2), - ("op3_size", 2), + ("modrm_size", 2), + ("modreg_size", 2), + ("vexreg_size", 2), + ("imm_size", 2), ("unused2", 2), ("size_fix1", 3), ("size_fix2", 2), @@ -29,6 +29,7 @@ INSTR_FLAGS_FIELDS, INSTR_FLAGS_SIZES = zip(*[ ("modrm_ty", 3), ("modreg_ty", 3), ("vexreg_ty", 2), + ("imm_ty", 0), ("unused", 3), ("opsize", 3), ("modrm", 1), @@ -171,10 +172,18 @@ class InstrDesc(NamedTuple): operands: Tuple[str, ...] flags: FrozenSet[str] - OPKIND_REGTYS_MODRM = { "GP": 0, "XMM": 1, "MMX": 4, "FPU": 5, "MASK": 6, } - OPKIND_REGTYS_MODREG = { "GP": 0, "XMM": 1, "MASK": 2, "MMX": 4, "SEG": 5, - "CR": 0, "DR": 0 } # CR/DR handled in code. - OPKIND_REGTYS_VEXREG = { "GP": 0, "XMM": 1, "MASK": 2, "FPU": 3 } # also zeroreg + OPKIND_REGTYS = { + ("modrm", "GP"): 0, ("modreg", "GP"): 0, ("vexreg", "GP"): 0, + ("modrm", "XMM"): 1, ("modreg", "XMM"): 1, ("vexreg", "XMM"): 1, + ("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, "CR": 9, "DR": 10} OPKIND_SIZES = { @@ -271,19 +280,9 @@ class InstrDesc(NamedTuple): for i, opkind in enumerate(self.operands): 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] - if opname == "modrm": - if opkind.kind == "MEM": - 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") + extraflags[f"{opname}_size"] = sizes.index(sz) + extraflags[f"{opname}_ty"] = self.OPKIND_REGTYS[opname, opkind.kind] # Miscellaneous Flags if "VSIB" in self.flags: extraflags["vsib"] = 1