From 807d8a817b7471d36529cc7165172858adadca33 Mon Sep 17 00:00:00 2001 From: Alexis Engelke Date: Thu, 18 Jun 2020 17:42:54 +0200 Subject: [PATCH] decode: Change imm_control to get rid of imm_byte --- decode.c | 21 ++++++++++++++------- parseinstrs.py | 24 ++++++++++++------------ 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/decode.c b/decode.c index 417a0ab..6b4e711 100644 --- a/decode.c +++ b/decode.c @@ -307,7 +307,6 @@ struct InstrDesc #define DESC_IMPLICIT_IDX(desc) ((((desc)->operand_indices >> 6) & 3) ^ 3) #define DESC_IMM_CONTROL(desc) (((desc)->immediate >> 4) & 0x7) #define DESC_IMM_IDX(desc) (((desc)->immediate & 3) ^ 3) -#define DESC_IMM_BYTE(desc) (((desc)->immediate >> 7) & 1) #define DESC_IMPLICIT_VAL(desc) (((desc)->immediate >> 2) & 1) int @@ -500,14 +499,16 @@ fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address, } uint32_t imm_control = DESC_IMM_CONTROL(desc); - if (imm_control == 1) + if (UNLIKELY(imm_control == 1)) { + // 1 = immediate constant 1, used for shifts FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)]; operand->type = FD_OT_IMM; instr->imm = 1; } - else if (imm_control == 2) + else if (UNLIKELY(imm_control == 2)) { + // 2 = memory, address-sized, used for mov with moffs operand FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)]; operand->type = FD_OT_MEM; operand->reg = FD_REG_NONE; @@ -527,8 +528,9 @@ fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address, #endif off += addr_size; } - else if (UNLIKELY(imm_control == 5)) + else if (UNLIKELY(imm_control == 3)) { + // 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; @@ -546,15 +548,20 @@ fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address, FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)]; operand->type = FD_OT_IMM; + // 4/5 = immediate, operand-sized/8 bit + // 6/7 = offset, operand-sized/8 bit (used for jumps/calls) + int imm_byte = imm_control & 1; + int imm_offset = imm_control & 2; + uint8_t imm_size; - if (DESC_IMM_BYTE(desc)) + if (imm_byte) imm_size = 1; else if (UNLIKELY(instr->type == FDI_RET || instr->type == FDI_RETF)) imm_size = 2; else if (UNLIKELY(instr->type == FDI_ENTER)) imm_size = 3; #if defined(ARCH_X86_64) - else if (mode == DECODE_64 && UNLIKELY(imm_control == 4)) + else if (mode == DECODE_64 && UNLIKELY(imm_offset)) // Jumps are always 8 or 32 bit on x86-64. imm_size = 4; #endif @@ -585,7 +592,7 @@ fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address, #endif off += imm_size; - if (imm_control == 4) + if (imm_offset) { if (instr->address != 0) instr->imm += instr->address + off; diff --git a/parseinstrs.py b/parseinstrs.py index 2ef48ee..02e757f 100644 --- a/parseinstrs.py +++ b/parseinstrs.py @@ -38,7 +38,7 @@ InstrFlags = bitstruct("InstrFlags", [ "zeroreg_val:1", "_unused:1", "imm_control:3", - "imm_byte:1", + "_unused:1", "gp_size_8:1", "gp_size_def64:1", "gp_instr_width:1", @@ -55,30 +55,30 @@ ENCODINGS = { "NP": InstrFlags(), "M": InstrFlags(modrm_idx=0^3), "M1": InstrFlags(modrm_idx=0^3, imm_idx=1^3, imm_control=1), - "MI": InstrFlags(modrm_idx=0^3, imm_idx=1^3, imm_control=3), + "MI": InstrFlags(modrm_idx=0^3, imm_idx=1^3, imm_control=4), "MC": InstrFlags(modrm_idx=0^3, zeroreg_idx=1^3, zeroreg_val=1), "MR": InstrFlags(modrm_idx=0^3, modreg_idx=1^3), "RM": InstrFlags(modrm_idx=1^3, modreg_idx=0^3), "RMA": InstrFlags(modrm_idx=1^3, modreg_idx=0^3, zeroreg_idx=2^3), - "MRI": InstrFlags(modrm_idx=0^3, modreg_idx=1^3, imm_idx=2^3, imm_control=3), - "RMI": InstrFlags(modrm_idx=1^3, modreg_idx=0^3, imm_idx=2^3, imm_control=3), + "MRI": InstrFlags(modrm_idx=0^3, modreg_idx=1^3, imm_idx=2^3, imm_control=4), + "RMI": InstrFlags(modrm_idx=1^3, modreg_idx=0^3, imm_idx=2^3, imm_control=4), "MRC": InstrFlags(modrm_idx=0^3, modreg_idx=1^3, zeroreg_idx=2^3, zeroreg_val=1), - "I": InstrFlags(imm_idx=0^3, imm_control=3), - "IA": InstrFlags(zeroreg_idx=0^3, imm_idx=1^3, imm_control=3), + "I": InstrFlags(imm_idx=0^3, imm_control=4), + "IA": InstrFlags(zeroreg_idx=0^3, imm_idx=1^3, imm_control=4), "O": InstrFlags(modreg_idx=0^3), - "OI": InstrFlags(modreg_idx=0^3, imm_idx=1^3, imm_control=3), + "OI": InstrFlags(modreg_idx=0^3, imm_idx=1^3, imm_control=4), "OA": InstrFlags(modreg_idx=0^3, zeroreg_idx=1^3), "AO": InstrFlags(modreg_idx=1^3, zeroreg_idx=0^3), - "D": InstrFlags(imm_idx=0^3, imm_control=4), + "D": InstrFlags(imm_idx=0^3, imm_control=6), "FD": InstrFlags(zeroreg_idx=0^3, imm_idx=1^3, imm_control=2), "TD": InstrFlags(zeroreg_idx=1^3, imm_idx=0^3, imm_control=2), "RVM": InstrFlags(modrm_idx=2^3, modreg_idx=0^3, vexreg_idx=1^3), - "RVMI": InstrFlags(modrm_idx=2^3, modreg_idx=0^3, vexreg_idx=1^3, imm_idx=3^3, imm_control=3, imm_byte=1), - "RVMR": InstrFlags(modrm_idx=2^3, modreg_idx=0^3, vexreg_idx=1^3, imm_idx=3^3, imm_control=5, imm_byte=1), + "RVMI": InstrFlags(modrm_idx=2^3, modreg_idx=0^3, vexreg_idx=1^3, imm_idx=3^3, imm_control=4, imm_byte=1), + "RVMR": InstrFlags(modrm_idx=2^3, modreg_idx=0^3, vexreg_idx=1^3, imm_idx=3^3, imm_control=3, imm_byte=1), "RMV": InstrFlags(modrm_idx=1^3, modreg_idx=0^3, vexreg_idx=2^3), "VM": InstrFlags(modrm_idx=1^3, vexreg_idx=0^3), - "VMI": InstrFlags(modrm_idx=1^3, vexreg_idx=0^3, imm_idx=2^3, imm_control=3, imm_byte=1), + "VMI": InstrFlags(modrm_idx=1^3, vexreg_idx=0^3, imm_idx=2^3, imm_control=4, imm_byte=1), "MVR": InstrFlags(modrm_idx=0^3, modreg_idx=2^3, vexreg_idx=1^3), } @@ -138,7 +138,7 @@ class InstrDesc(NamedTuple): if "DEF64" in self.flags: flags.gp_size_def64 = 1 if "SIZE_8" in self.flags: flags.gp_size_8 = 1 if "INSTR_WIDTH" in self.flags: flags.gp_instr_width = 1 - if "IMM_8" in self.flags: flags.imm_byte = 1 + 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 "VSIB" in self.flags: flags.vsib = 1 if "MUSTMEM" in self.flags: setattr(flags, "op%d_regty"%(flags.modrm_idx^3), 0xf)