From 76b29b518dad5e719077a1066e242fa91f777a7c Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 13 Sep 2012 05:45:42 +0000 Subject: [PATCH] Add a new compression type to ModRM table that detects when the memory modRM byte represent 8 instructions and the reg modRM byte represents up to 64 instructions. Reduces modRM table from 43k entreis to 25k entries. Based on a patch from Manman Ren. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163774 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../X86/Disassembler/X86DisassemblerDecoder.c | 4 ++++ .../Disassembler/X86DisassemblerDecoderCommon.h | 5 +++++ utils/TableGen/X86DisassemblerTables.cpp | 17 +++++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c index af444d196eb..b24f5172099 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c @@ -138,6 +138,10 @@ static InstrUID decode(OpcodeType type, if (modFromModRM(modRM) == 0x3) return modRMTable[dec->instructionIDs+((modRM & 0x38) >> 3)+8]; return modRMTable[dec->instructionIDs+((modRM & 0x38) >> 3)]; + case MODRM_SPLITMISC: + if (modFromModRM(modRM) == 0x3) + return modRMTable[dec->instructionIDs+(modRM & 0x3f)+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 b0a0e1e78ef..23dfe4b5b5f 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h @@ -160,6 +160,10 @@ 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_SPLITMISC- If the ModR/M byte is between 0x00 and 0xbf, ModR/M byte + * divided by 8 is used to select instruction; otherwise, each + * value of the ModR/M byte could correspond 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 @@ -169,6 +173,7 @@ typedef uint16_t InstrUID; #define MODRMTYPES \ ENUM_ENTRY(MODRM_ONEENTRY) \ ENUM_ENTRY(MODRM_SPLITRM) \ + ENUM_ENTRY(MODRM_SPLITMISC) \ ENUM_ENTRY(MODRM_SPLITREG) \ ENUM_ENTRY(MODRM_FULL) diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index 8526621599a..468a1f81c71 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -209,6 +209,7 @@ static ModRMDecisionType getDecisionType(ModRMDecision &decision) { bool satisfiesOneEntry = true; bool satisfiesSplitRM = true; bool satisfiesSplitReg = true; + bool satisfiesSplitMisc = true; for (unsigned index = 0; index < 256; ++index) { if (decision.instructionIDs[index] != decision.instructionIDs[0]) @@ -228,7 +229,7 @@ static ModRMDecisionType getDecisionType(ModRMDecision &decision) { if (((index & 0xc0) != 0xc0) && (decision.instructionIDs[index] != decision.instructionIDs[index&0x38])) - satisfiesSplitReg = false; + satisfiesSplitMisc = false; } if (satisfiesOneEntry) @@ -237,9 +238,12 @@ static ModRMDecisionType getDecisionType(ModRMDecision &decision) { if (satisfiesSplitRM) return MODRM_SPLITRM; - if (satisfiesSplitReg) + if (satisfiesSplitReg && satisfiesSplitMisc) return MODRM_SPLITREG; + if (satisfiesSplitMisc) + return MODRM_SPLITMISC; + return MODRM_FULL; } @@ -332,6 +336,12 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2, for (unsigned index = 0xc0; index < 256; index += 8) emitOneID(o1, i1, decision.instructionIDs[index], true); break; + case MODRM_SPLITMISC: + for (unsigned index = 0; index < 64; index += 8) + emitOneID(o1, i1, decision.instructionIDs[index], true); + for (unsigned index = 0xc0; index < 256; ++index) + emitOneID(o1, i1, decision.instructionIDs[index], true); + break; case MODRM_FULL: for (unsigned index = 0; index < 256; ++index) emitOneID(o1, i1, decision.instructionIDs[index], true); @@ -361,6 +371,9 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2, case MODRM_SPLITREG: sEntryNumber += 16; break; + case MODRM_SPLITMISC: + sEntryNumber += 8 + 64; + break; case MODRM_FULL: sEntryNumber += 256; break;