diff options
-rw-r--r-- | lib/Target/X86/Disassembler/X86DisassemblerDecoder.c | 4 | ||||
-rw-r--r-- | lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h | 3 | ||||
-rw-r--r-- | utils/TableGen/X86DisassemblerTables.cpp | 35 |
3 files changed, 35 insertions, 7 deletions
diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c index 9a628f2..a7becdb 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c @@ -136,6 +136,10 @@ static InstrUID decode(OpcodeType type, if (modFromModRM(modRM) == 0x3) return modRMTable[dec->instructionIDs+1]; return modRMTable[dec->instructionIDs]; + case MODRM_SPLITREG: + if (modFromModRM(modRM) == 0x3) + return modRMTable[dec->instructionIDs+((modRM & 0x38) >> 3)+8]; + return modRMTable[dec->instructionIDs+((modRM & 0x38) >> 3)]; case MODRM_FULL: return modRMTable[dec->instructionIDs+modRM]; } diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h index a7ef0cc..d6b23c0 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h @@ -156,6 +156,8 @@ typedef uint16_t InstrUID; * MODRM_SPLITRM - If the ModR/M byte is between 0x00 and 0xbf, the opcode * corresponds to one instruction; otherwise, it corresponds to * a different instruction. + * MODRM_SPLITREG - ModR/M byte divided by 8 is used to select instruction. This + corresponds to instructions that use reg field as opcode * MODRM_FULL - Potentially, each value of the ModR/M byte could correspond * to a different instruction. */ @@ -163,6 +165,7 @@ typedef uint16_t InstrUID; #define MODRMTYPES \ ENUM_ENTRY(MODRM_ONEENTRY) \ ENUM_ENTRY(MODRM_SPLITRM) \ + ENUM_ENTRY(MODRM_SPLITREG) \ ENUM_ENTRY(MODRM_FULL) #define ENUM_ENTRY(n) n, diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index 7db39b8..b5f970d 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -208,28 +208,40 @@ static ModRMDecisionType getDecisionType(ModRMDecision &decision) { bool satisfiesOneEntry = true; bool satisfiesSplitRM = true; - + bool satisfiesSplitReg = true; + uint16_t index; - + for (index = 0; index < 256; ++index) { if (decision.instructionIDs[index] != decision.instructionIDs[0]) satisfiesOneEntry = false; - + if (((index & 0xc0) == 0xc0) && (decision.instructionIDs[index] != decision.instructionIDs[0xc0])) satisfiesSplitRM = false; - + if (((index & 0xc0) != 0xc0) && (decision.instructionIDs[index] != decision.instructionIDs[0x00])) satisfiesSplitRM = false; + + if (((index & 0xc0) == 0xc0) && + (decision.instructionIDs[index] != decision.instructionIDs[index&0xf8])) + satisfiesSplitReg = false; + + if (((index & 0xc0) != 0xc0) && + (decision.instructionIDs[index] != decision.instructionIDs[index&0x38])) + satisfiesSplitReg = false; } - + if (satisfiesOneEntry) return MODRM_ONEENTRY; - + if (satisfiesSplitRM) return MODRM_SPLITRM; - + + if (satisfiesSplitReg) + return MODRM_SPLITREG; + return MODRM_FULL; } @@ -322,6 +334,12 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, emitOneID(o1, i1, decision.instructionIDs[0x00], true); // mod = 0b00 emitOneID(o1, i1, decision.instructionIDs[0xc0], true); // mod = 0b11 break; + case MODRM_SPLITREG: + for (index = 0; index < 64; index += 8) + emitOneID(o1, i1, decision.instructionIDs[index], true); + for (index = 0xc0; index < 256; index += 8) + emitOneID(o1, i1, decision.instructionIDs[index], true); + break; case MODRM_FULL: for (index = 0; index < 256; ++index) emitOneID(o1, i1, decision.instructionIDs[index], true); @@ -348,6 +366,9 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, case MODRM_SPLITRM: sEntryNumber += 2; break; + case MODRM_SPLITREG: + sEntryNumber += 16; + break; case MODRM_FULL: sEntryNumber += 256; break; |