From 95a3ccdd8006044d8f2ba39a9d1034112764589e Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 1 Jan 2014 15:29:32 +0000 Subject: [PATCH] Remove need for MODIFIER_OPCODE in the disassembler tables. AddRegFrms are really more like OrRegFrm so we don't need a difference since we can just mask bits. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198278 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../X86/Disassembler/X86Disassembler.cpp | 16 ++------ .../X86/Disassembler/X86DisassemblerDecoder.c | 41 +++---------------- .../X86/Disassembler/X86DisassemblerDecoder.h | 2 - .../X86DisassemblerDecoderCommon.h | 3 +- test/MC/Disassembler/X86/simple-tests.txt | 12 ++++++ utils/TableGen/X86RecognizableInstr.cpp | 12 ++---- 6 files changed, 26 insertions(+), 60 deletions(-) diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp index f766150cc24..1bc4dc477e4 100644 --- a/lib/Target/X86/Disassembler/X86Disassembler.cpp +++ b/lib/Target/X86/Disassembler/X86Disassembler.cpp @@ -609,16 +609,9 @@ static bool translateRM(MCInst &mcInst, const OperandSpecifier &operand, /// @param mcInst - The MCInst to append to. /// @param stackPos - The stack position to translate. /// @return - false on success; true otherwise. -static bool translateFPRegister(MCInst &mcInst, - uint8_t stackPos) { - if (stackPos >= 8) { - debug("Invalid FP stack position"); - return true; - } - +static void translateFPRegister(MCInst &mcInst, + uint8_t stackPos) { mcInst.addOperand(MCOperand::CreateReg(X86::ST0 + stackPos)); - - return false; } /// translateMaskRegister - Translates a 3-bit mask register number to @@ -683,12 +676,11 @@ static bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand, case ENCODING_RW: case ENCODING_RD: case ENCODING_RO: + case ENCODING_Rv: translateRegister(mcInst, insn.opcodeRegister); return false; case ENCODING_FP: - return translateFPRegister(mcInst, insn.modRM & 7); - case ENCODING_Rv: - translateRegister(mcInst, insn.opcodeRegister); + translateFPRegister(mcInst, insn.modRM & 7); return false; case ENCODING_VVVV: translateRegister(mcInst, insn.vvvv); diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c index 0659e4f4a94..52631bcbf2d 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c @@ -1501,40 +1501,12 @@ static int fixupReg(struct InternalInstruction *insn, return 0; } -/* - * readOpcodeModifier - Reads an operand from the opcode field of an - * instruction. Handles AddRegFrm instructions. - * - * @param insn - The instruction whose opcode field is to be read. - * @return - 0 on success; nonzero otherwise. - */ -static int readOpcodeModifier(struct InternalInstruction* insn) { - dbgprintf(insn, "readOpcodeModifier()"); - - if (insn->consumedOpcodeModifier) - return 0; - - insn->consumedOpcodeModifier = TRUE; - - switch (insn->spec->modifierType) { - default: - debug("Unknown modifier type."); - return -1; - case MODIFIER_NONE: - debug("No modifier but an operand expects one."); - return -1; - case MODIFIER_OPCODE: - insn->opcodeModifier = insn->opcode - insn->spec->modifierBase; - return 0; - } -} - /* * readOpcodeRegister - Reads an operand from the opcode field of an * instruction and interprets it appropriately given the operand width. * Handles AddRegFrm instructions. * - * @param insn - See readOpcodeModifier(). + * @param insn - the instruction whose opcode field is to be read. * @param size - The width (in bytes) of the register being specified. * 1 means AL and friends, 2 means AX, 4 means EAX, and 8 means * RAX. @@ -1543,16 +1515,13 @@ static int readOpcodeModifier(struct InternalInstruction* insn) { static int readOpcodeRegister(struct InternalInstruction* insn, uint8_t size) { dbgprintf(insn, "readOpcodeRegister()"); - if (readOpcodeModifier(insn)) - return -1; - if (size == 0) size = insn->registerSize; switch (size) { case 1: insn->opcodeRegister = (Reg)(MODRM_REG_AL + ((bFromREX(insn->rexPrefix) << 3) - | insn->opcodeModifier)); + | (insn->opcode & 7))); if (insn->rexPrefix && insn->opcodeRegister >= MODRM_REG_AL + 0x4 && insn->opcodeRegister < MODRM_REG_AL + 0x8) { @@ -1564,17 +1533,17 @@ static int readOpcodeRegister(struct InternalInstruction* insn, uint8_t size) { case 2: insn->opcodeRegister = (Reg)(MODRM_REG_AX + ((bFromREX(insn->rexPrefix) << 3) - | insn->opcodeModifier)); + | (insn->opcode & 7))); break; case 4: insn->opcodeRegister = (Reg)(MODRM_REG_EAX + ((bFromREX(insn->rexPrefix) << 3) - | insn->opcodeModifier)); + | (insn->opcode & 7))); break; case 8: insn->opcodeRegister = (Reg)(MODRM_REG_RAX + ((bFromREX(insn->rexPrefix) << 3) - | insn->opcodeModifier)); + | (insn->opcode & 7))); break; } diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h index 294c47688ff..c4c86ada3fa 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h @@ -634,8 +634,6 @@ struct InternalInstruction { uint64_t immediates[2]; /* A register or immediate operand encoded into the opcode */ - BOOL consumedOpcodeModifier; - uint8_t opcodeModifier; Reg opcodeRegister; /* Portions of the ModR/M byte */ diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h index dc06819bf5a..8ecda65d989 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h @@ -525,8 +525,7 @@ struct OperandSpecifier { */ #define MODIFIER_TYPES \ - ENUM_ENTRY(MODIFIER_NONE) \ - ENUM_ENTRY(MODIFIER_OPCODE) + ENUM_ENTRY(MODIFIER_NONE) #define ENUM_ENTRY(n) n, typedef enum { diff --git a/test/MC/Disassembler/X86/simple-tests.txt b/test/MC/Disassembler/X86/simple-tests.txt index 7ca08743897..e6e9c7bc9cc 100644 --- a/test/MC/Disassembler/X86/simple-tests.txt +++ b/test/MC/Disassembler/X86/simple-tests.txt @@ -359,6 +359,18 @@ # CHECK: xchgq %r8, %rax 0x49 0x90 +# CHECK: xchgl %r9d, %eax +0x41 0x91 + +# CHECK: xchgq %r9, %rax +0x49 0x91 + +# CHECK: xchgl %ecx, %eax +0x91 + +# CHECK: xchgq %rcx, %rax +0x48 0x91 + # CHECK: addb $0, %al 0x04 0x00 diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 678e843e9c9..4016116de13 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -1162,8 +1162,8 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { assert(filter && "Filter not set"); if (Form == X86Local::AddRegFrm) { - assert(opcodeToSet < 0xf9 && - "Not enough room for all ADDREG_FRM operands"); + assert(((opcodeToSet & 7) == 0) && + "ADDREG_FRM opcode not aligned"); uint8_t currentOpcode; @@ -1175,19 +1175,15 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { currentOpcode, *filter, UID, Is32Bit, IgnoresVEX_L); - - Spec->modifierType = MODIFIER_OPCODE; - Spec->modifierBase = opcodeToSet; } else { tables.setTableFields(opcodeType, insnContext(), opcodeToSet, *filter, UID, Is32Bit, IgnoresVEX_L); - - Spec->modifierType = MODIFIER_NONE; - Spec->modifierBase = opcodeToSet; } + Spec->modifierType = MODIFIER_NONE; + Spec->modifierBase = opcodeToSet; delete filter;