aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Target/X86/Disassembler/X86DisassemblerDecoder.c4
-rw-r--r--lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h3
-rw-r--r--utils/TableGen/X86DisassemblerTables.cpp35
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;