x86: Rework opcode parsing to support 3 byte opcodes properly.

Instead of counting the number of opcode bytes in an instruction and recording
each byte before the actual opcode, we can represent the path we took to get to
the actual opcode byte by using a type code. That has a couple of advantages.
First, we can disambiguate the properties of opcodes of the same length which
have different properties. Second, it reduces the amount of data stored in an
ExtMachInst, making them slightly easier/faster to create and process. This
also adds some flexibility as far as how different types of opcodes are
handled, which might come in handy if we decide to support VEX or XOP
instructions.

This change also adds tables to support properly decoding 3 byte opcodes.
Before we would fall off the end of some arrays, on top of the ambiguity
described above.

This change doesn't measureably affect performance on the twolf benchmark.

--HG--
rename : src/arch/x86/isa/decoder/three_byte_opcodes.isa => src/arch/x86/isa/decoder/three_byte_0f38_opcodes.isa
rename : src/arch/x86/isa/decoder/three_byte_opcodes.isa => src/arch/x86/isa/decoder/three_byte_0f3a_opcodes.isa
This commit is contained in:
Gabe Black
2014-12-04 15:53:54 -08:00
parent 3069c28a02
commit 22aaa5867f
14 changed files with 1577 additions and 1399 deletions

View File

@@ -48,9 +48,8 @@ Decoder::doResetState()
emi.rex = 0;
emi.legacy = 0;
emi.opcode.num = 0;
emi.opcode.type = BadOpcode;
emi.opcode.op = 0;
emi.opcode.prefixA = emi.opcode.prefixB = 0;
immediateCollected = 0;
emi.immediate = 0;
@@ -94,8 +93,17 @@ Decoder::process()
case PrefixState:
state = doPrefixState(nextByte);
break;
case OpcodeState:
state = doOpcodeState(nextByte);
case OneByteOpcodeState:
state = doOneByteOpcodeState(nextByte);
break;
case TwoByteOpcodeState:
state = doTwoByteOpcodeState(nextByte);
break;
case ThreeByte0F38OpcodeState:
state = doThreeByte0F38OpcodeState(nextByte);
break;
case ThreeByte0F3AOpcodeState:
state = doThreeByte0F3AOpcodeState(nextByte);
break;
case ModRMState:
state = doModRMState(nextByte);
@@ -199,7 +207,7 @@ Decoder::doPrefixState(uint8_t nextByte)
emi.rex = nextByte;
break;
case 0:
nextState = OpcodeState;
nextState = OneByteOpcodeState;
break;
default:
panic("Unrecognized prefix %#x\n", nextByte);
@@ -207,79 +215,132 @@ Decoder::doPrefixState(uint8_t nextByte)
return nextState;
}
//Load all the opcodes (currently up to 2) and then figure out
//what immediate and/or ModRM is needed.
// Load the first opcode byte. Determine if there are more opcode bytes, and
// if not, what immediate and/or ModRM is needed.
Decoder::State
Decoder::doOpcodeState(uint8_t nextByte)
Decoder::doOneByteOpcodeState(uint8_t nextByte)
{
State nextState = ErrorState;
emi.opcode.num++;
//We can't handle 3+ byte opcodes right now
assert(emi.opcode.num < 4);
consumeByte();
if(emi.opcode.num == 1 && nextByte == 0x0f)
{
nextState = OpcodeState;
DPRINTF(Decoder, "Found two byte opcode.\n");
emi.opcode.prefixA = nextByte;
}
else if(emi.opcode.num == 2 && (nextByte == 0x38 || nextByte == 0x3A))
{
nextState = OpcodeState;
DPRINTF(Decoder, "Found three byte opcode.\n");
emi.opcode.prefixB = nextByte;
}
else
{
DPRINTF(Decoder, "Found opcode %#x.\n", nextByte);
if (nextByte == 0x0f) {
nextState = TwoByteOpcodeState;
DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
} else {
DPRINTF(Decoder, "Found one byte opcode %#x.\n", nextByte);
emi.opcode.type = OneByteOpcode;
emi.opcode.op = nextByte;
//Figure out the effective operand size. This can be overriden to
//a fixed value at the decoder level.
int logOpSize;
if (emi.rex.w)
logOpSize = 3; // 64 bit operand size
else if (emi.legacy.op)
logOpSize = altOp;
else
logOpSize = defOp;
nextState = processOpcode(ImmediateTypeOneByte, UsesModRMOneByte,
nextByte >= 0xA0 && nextByte <= 0xA3);
}
return nextState;
}
//Set the actual op size
emi.opSize = 1 << logOpSize;
// Load the second opcode byte. Determine if there are more opcode bytes, and
// if not, what immediate and/or ModRM is needed.
Decoder::State
Decoder::doTwoByteOpcodeState(uint8_t nextByte)
{
State nextState = ErrorState;
consumeByte();
if (nextByte == 0x38) {
nextState = ThreeByte0F38OpcodeState;
DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
} else if (nextByte == 0x3a) {
nextState = ThreeByte0F3AOpcodeState;
DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
} else {
DPRINTF(Decoder, "Found two byte opcode %#x.\n", nextByte);
emi.opcode.type = TwoByteOpcode;
emi.opcode.op = nextByte;
//Figure out the effective address size. This can be overriden to
//a fixed value at the decoder level.
int logAddrSize;
if(emi.legacy.addr)
logAddrSize = altAddr;
else
logAddrSize = defAddr;
nextState = processOpcode(ImmediateTypeTwoByte, UsesModRMTwoByte);
}
return nextState;
}
//Set the actual address size
emi.addrSize = 1 << logAddrSize;
// Load the third opcode byte and determine what immediate and/or ModRM is
// needed.
Decoder::State
Decoder::doThreeByte0F38OpcodeState(uint8_t nextByte)
{
consumeByte();
//Figure out the effective stack width. This can be overriden to
//a fixed value at the decoder level.
emi.stackSize = 1 << stack;
DPRINTF(Decoder, "Found three byte 0F38 opcode %#x.\n", nextByte);
emi.opcode.type = ThreeByte0F38Opcode;
emi.opcode.op = nextByte;
//Figure out how big of an immediate we'll retreive based
//on the opcode.
int immType = ImmediateType[emi.opcode.num - 1][nextByte];
if (emi.opcode.num == 1 && nextByte >= 0xA0 && nextByte <= 0xA3)
immediateSize = SizeTypeToSize[logAddrSize - 1][immType];
else
immediateSize = SizeTypeToSize[logOpSize - 1][immType];
return processOpcode(ImmediateTypeThreeByte0F38, UsesModRMThreeByte0F38);
}
//Determine what to expect next
if (UsesModRM[emi.opcode.num - 1][nextByte]) {
nextState = ModRMState;
// Load the third opcode byte and determine what immediate and/or ModRM is
// needed.
Decoder::State
Decoder::doThreeByte0F3AOpcodeState(uint8_t nextByte)
{
consumeByte();
DPRINTF(Decoder, "Found three byte 0F3A opcode %#x.\n", nextByte);
emi.opcode.type = ThreeByte0F3AOpcode;
emi.opcode.op = nextByte;
return processOpcode(ImmediateTypeThreeByte0F3A, UsesModRMThreeByte0F3A);
}
// Generic opcode processing which determines the immediate size, and whether
// or not there's a modrm byte.
Decoder::State
Decoder::processOpcode(ByteTable &immTable, ByteTable &modrmTable,
bool addrSizedImm)
{
State nextState = ErrorState;
const uint8_t opcode = emi.opcode.op;
//Figure out the effective operand size. This can be overriden to
//a fixed value at the decoder level.
int logOpSize;
if (emi.rex.w)
logOpSize = 3; // 64 bit operand size
else if (emi.legacy.op)
logOpSize = altOp;
else
logOpSize = defOp;
//Set the actual op size
emi.opSize = 1 << logOpSize;
//Figure out the effective address size. This can be overriden to
//a fixed value at the decoder level.
int logAddrSize;
if(emi.legacy.addr)
logAddrSize = altAddr;
else
logAddrSize = defAddr;
//Set the actual address size
emi.addrSize = 1 << logAddrSize;
//Figure out the effective stack width. This can be overriden to
//a fixed value at the decoder level.
emi.stackSize = 1 << stack;
//Figure out how big of an immediate we'll retreive based
//on the opcode.
int immType = immTable[opcode];
if (addrSizedImm)
immediateSize = SizeTypeToSize[logAddrSize - 1][immType];
else
immediateSize = SizeTypeToSize[logOpSize - 1][immType];
//Determine what to expect next
if (modrmTable[opcode]) {
nextState = ModRMState;
} else {
if(immediateSize) {
nextState = ImmediateState;
} else {
if(immediateSize) {
nextState = ImmediateState;
} else {
instDone = true;
nextState = ResetState;
}
instDone = true;
nextState = ResetState;
}
}
return nextState;
@@ -315,7 +376,7 @@ Decoder::doModRMState(uint8_t nextByte)
// The "test" instruction in group 3 needs an immediate, even though
// the other instructions with the same actual opcode don't.
if (emi.opcode.num == 1 && (modRM.reg & 0x6) == 0) {
if (emi.opcode.type == OneByteOpcode && (modRM.reg & 0x6) == 0) {
if (emi.opcode.op == 0xF6)
immediateSize = 1;
else if (emi.opcode.op == 0xF7)

View File

@@ -51,10 +51,19 @@ class Decoder
{
private:
//These are defined and documented in decoder_tables.cc
static const uint8_t Prefixes[256];
static const uint8_t UsesModRM[2][256];
static const uint8_t ImmediateType[2][256];
static const uint8_t SizeTypeToSize[3][10];
typedef const uint8_t ByteTable[256];
static ByteTable Prefixes;
static ByteTable UsesModRMOneByte;
static ByteTable UsesModRMTwoByte;
static ByteTable UsesModRMThreeByte0F38;
static ByteTable UsesModRMThreeByte0F3A;
static ByteTable ImmediateTypeOneByte;
static ByteTable ImmediateTypeTwoByte;
static ByteTable ImmediateTypeThreeByte0F38;
static ByteTable ImmediateTypeThreeByte0F3A;
protected:
struct InstBytes
@@ -166,7 +175,10 @@ class Decoder
ResetState,
FromCacheState,
PrefixState,
OpcodeState,
OneByteOpcodeState,
TwoByteOpcodeState,
ThreeByte0F38OpcodeState,
ThreeByte0F3AOpcodeState,
ModRMState,
SIBState,
DisplacementState,
@@ -181,12 +193,19 @@ class Decoder
State doResetState();
State doFromCacheState();
State doPrefixState(uint8_t);
State doOpcodeState(uint8_t);
State doOneByteOpcodeState(uint8_t);
State doTwoByteOpcodeState(uint8_t);
State doThreeByte0F38OpcodeState(uint8_t);
State doThreeByte0F3AOpcodeState(uint8_t);
State doModRMState(uint8_t);
State doSIBState(uint8_t);
State doDisplacementState();
State doImmediateState();
//Process the actual opcode found earlier, using the supplied tables.
State processOpcode(ByteTable &immTable, ByteTable &modrmTable,
bool addrSizedImm = false);
protected:
/// Caching for decoded instruction objects.

View File

@@ -58,7 +58,7 @@ namespace X86ISA
//This table identifies whether a byte is a prefix, and if it is,
//which prefix it is.
const uint8_t Decoder::Prefixes[256] =
const Decoder::ByteTable Decoder::Prefixes =
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
@@ -79,48 +79,89 @@ namespace X86ISA
/* F*/ LO, 0 , RN, RE, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
};
//This table identifies whether a particular opcode uses the ModRM byte
const uint8_t Decoder::UsesModRM[2][256] =
{//For one byte instructions
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
/* 1 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
/* 2 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
/* 3 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 6 */ 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 0,
/* 7 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 8 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* A */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* C */ 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* D */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1
},
//For two byte instructions
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1,
/* 1 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 2 */ 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 4 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 5 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 6 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 7 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1,
/* 8 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 9 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* A */ 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1,
/* B */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1,
/* C */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* D */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* E */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* F */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0
}
// These tables identify whether a particular opcode uses the ModRM byte.
const Decoder::ByteTable Decoder::UsesModRMOneByte =
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
/* 1 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
/* 2 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
/* 3 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 6 */ 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 0,
/* 7 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 8 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* A */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* C */ 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* D */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1
};
const Decoder::ByteTable Decoder::UsesModRMTwoByte =
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1,
/* 1 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 2 */ 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 4 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 5 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 6 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 7 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1,
/* 8 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 9 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* A */ 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1,
/* B */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1,
/* C */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* D */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* E */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* F */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0
};
const Decoder::ByteTable Decoder::UsesModRMThreeByte0F38 =
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
/* 1 */ 1 , 0 , 0 , 0 , 1 , 1 , 0 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 0,
/* 2 */ 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0,
/* 3 */ 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 4 */ 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 6 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 7 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 8 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* A */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* C */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* D */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1,
/* E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* F */ 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
};
const Decoder::ByteTable Decoder::UsesModRMThreeByte0F3A =
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 1 */ 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 2 */ 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 4 */ 1 , 1 , 1 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 6 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 7 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 8 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* A */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* C */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* D */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1,
/* E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
};
enum SizeType {
@@ -140,7 +181,7 @@ namespace X86ISA
VW = VWordImm,
ZWordImm,
ZW = ZWordImm,
//The enter instruction takes -2- immediates for a total of 3 bytes
// The enter instruction takes -2- immediates for a total of 3 bytes
Enter,
EN = Enter,
Pointer,
@@ -155,50 +196,90 @@ namespace X86ISA
{0, 1, 2, 4, 8, 16, 8, 4, 3, 0 } //64 bit
};
//This table determines the immediate type. The first index is the
//number of bytes in the instruction, and the second is the meaningful
//byte of the opcode. I didn't use the NI constant here for the sake
//of clarity.
const uint8_t Decoder::ImmediateType[2][256] =
{//For one byte instructions
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
/* 1 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
/* 2 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
/* 3 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 6 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ZW, ZW, BY, BY, 0 , 0 , 0 , 0 ,
/* 7 */ BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY,
/* 8 */ BY, ZW, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* A */ VW, VW, VW, VW, 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 ,
/* B */ BY, BY, BY, BY, BY, BY, BY, BY, VW, VW, VW, VW, VW, VW, VW, VW,
/* C */ BY, BY, WO, 0 , 0 , 0 , BY, ZW, EN, 0 , WO, 0 , 0 , BY, 0 , 0 ,
/* D */ 0 , 0 , 0 , 0 , BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* E */ BY, BY, BY, BY, BY, BY, BY, BY, ZW, ZW, PO, BY, 0 , 0 , 0 , 0 ,
/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
},
//For two byte instructions
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0 */ 0 , 0 , 0 , 0 , WO, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY ,
/* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 2 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 6 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 7 */ BY, BY, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 8 */ ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW,
/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* A */ 0 , 0 , 0 , 0 , BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY, 0 , 0 , 0 ,
/* B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ZW, 0 , BY, 0 , 0 , 0 , 0 , 0 ,
/* C */ 0 , 0 , BY, 0 , BY, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* D */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
}
// These tables determines the immediate type. I didn't use the NI
// constant here for the sake
// of clarity.
const Decoder::ByteTable Decoder::ImmediateTypeOneByte =
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
/* 1 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
/* 2 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
/* 3 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 ,
/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 6 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ZW, ZW, BY, BY, 0 , 0 , 0 , 0 ,
/* 7 */ BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY,
/* 8 */ BY, ZW, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* A */ VW, VW, VW, VW, 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 ,
/* B */ BY, BY, BY, BY, BY, BY, BY, BY, VW, VW, VW, VW, VW, VW, VW, VW,
/* C */ BY, BY, WO, 0 , 0 , 0 , BY, ZW, EN, 0 , WO, 0 , 0 , BY, 0 , 0 ,
/* D */ 0 , 0 , 0 , 0 , BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* E */ BY, BY, BY, BY, BY, BY, BY, BY, ZW, ZW, PO, BY, 0 , 0 , 0 , 0 ,
/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
};
const Decoder::ByteTable Decoder::ImmediateTypeTwoByte =
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0 */ 0 , 0 , 0 , 0 , WO, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY,
/* 1 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 2 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 6 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 7 */ BY, BY, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 8 */ ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW,
/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* A */ 0 , 0 , 0 , 0 , BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY, 0 , 0 , 0 ,
/* B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ZW, 0 , BY, 0 , 0 , 0 , 0 , 0 ,
/* C */ 0 , 0 , BY, 0 , BY, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* D */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
};
const Decoder::ByteTable Decoder::ImmediateTypeThreeByte0F38 =
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 1 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 2 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 6 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 7 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 8 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* A */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* C */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* D */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
};
const Decoder::ByteTable Decoder::ImmediateTypeThreeByte0F3A =
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY, BY, BY, BY, BY, BY, BY, BY,
/* 1 */ 0 , 0 , 0 , 0 , BY, BY, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 2 */ BY, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 4 */ BY, BY, BY, 0 , BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 6 */ BY, BY, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 7 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 8 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* A */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* C */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* D */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY,
/* E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
};
}

View File

@@ -59,9 +59,7 @@ def bitfield LEGACY_ADDR legacy.addr;
def bitfield LEGACY_SEG legacy.seg;
// Pieces of the opcode
def bitfield OPCODE_NUM opcode.num;
def bitfield OPCODE_PREFIXA opcode.prefixA;
def bitfield OPCODE_PREFIXB opcode.prefixB;
def bitfield OPCODE_TYPE opcode.type;
def bitfield OPCODE_OP opcode.op;
//The top 5 bits of the opcode tend to split the instructions into groups
def bitfield OPCODE_OP_TOP5 opcode.op.top5;

View File

@@ -43,16 +43,12 @@
decode LEGACY_LOCK default Unknown::unknown()
{
//No lock prefix
0x0: decode OPCODE_NUM default Unknown::unknown()
0x0: decode OPCODE_TYPE default Unknown::unknown()
{
0x0: M5InternalError::error(
{{"Saw an ExtMachInst with zero opcode bytes!"}});
//1 byte opcodes
##include "one_byte_opcodes.isa"
//2 byte opcodes
##include "two_byte_opcodes.isa"
//3 byte opcodes
##include "three_byte_opcodes.isa"
##include "three_byte_0f38_opcodes.isa"
##include "three_byte_0f3a_opcodes.isa"
}
//Lock prefix
##include "locked_opcodes.isa"

View File

@@ -38,8 +38,8 @@
0x1: decode MODRM_MOD {
format Inst {
0x3: UD2();
default: decode OPCODE_NUM {
0x1: decode OPCODE_OP_TOP5 {
default: decode OPCODE_TYPE {
'X86ISA::OneByteOpcode': decode OPCODE_OP_TOP5 {
0x00: decode OPCODE_OP_BOTTOM3 {
default: MultiInst::ADD_LOCKED(OPCODE_OP_BOTTOM3,
[Mb,Gb], [Mv,Gv]);
@@ -137,40 +137,36 @@
}
}
}
0x2: decode OPCODE_PREFIXA {
0x0F: decode OPCODE_OP_TOP5 {
0x04: decode OPCODE_OP_BOTTOM3 {
0x0: WarnUnimpl::mov_Rd_CR8D();
0x2: WarnUnimpl::mov_CR8D_Rd();
'X86ISA::TwoByteOpcode': decode OPCODE_OP_TOP5 {
0x04: decode OPCODE_OP_BOTTOM3 {
0x0: WarnUnimpl::mov_Rd_CR8D();
0x2: WarnUnimpl::mov_CR8D_Rd();
}
0x15: decode OPCODE_OP_BOTTOM3 {
0x3: BTS_LOCKED(Mv,Gv);
}
0x16: decode OPCODE_OP_BOTTOM3 {
0x0: CMPXCHG_LOCKED(Mb,Gb);
0x1: CMPXCHG_LOCKED(Mv,Gv);
0x3: BTR_LOCKED(Mv,Gv);
}
0x17: decode OPCODE_OP_BOTTOM3 {
0x2: decode MODRM_REG {
0x5: BTS_LOCKED(Mv,Ib);
0x6: BTR_LOCKED(Mv,Ib);
0x7: BTC_LOCKED(Mv,Ib);
}
0x15: decode OPCODE_OP_BOTTOM3 {
0x3: BTS_LOCKED(Mv,Gv);
}
0x16: decode OPCODE_OP_BOTTOM3 {
0x0: CMPXCHG_LOCKED(Mb,Gb);
0x1: CMPXCHG_LOCKED(Mv,Gv);
0x3: BTR_LOCKED(Mv,Gv);
}
0x17: decode OPCODE_OP_BOTTOM3 {
0x2: decode MODRM_REG {
0x5: BTS_LOCKED(Mv,Ib);
0x6: BTR_LOCKED(Mv,Ib);
0x7: BTC_LOCKED(Mv,Ib);
}
0x3: BTC_LOCKED(Mv,Gv);
}
0x18: decode OPCODE_OP_BOTTOM3 {
0x0: XADD_LOCKED(Mb,Gb);
0x1: XADD_LOCKED(Mv,Gv);
//0x7: group9();
0x7: decode MODRM_REG {
//Also CMPXCHG16B
0x1: CMPXCHG8B_LOCKED(Mdp);
}
0x3: BTC_LOCKED(Mv,Gv);
}
0x18: decode OPCODE_OP_BOTTOM3 {
0x0: XADD_LOCKED(Mb,Gb);
0x1: XADD_LOCKED(Mv,Gv);
//0x7: group9();
0x7: decode MODRM_REG {
//Also CMPXCHG16B
0x1: CMPXCHG8B_LOCKED(Mdp);
}
}
default: M5InternalError::error(
{{"Unexpected first opcode byte in two byte opcode!"}});
}
}
}

View File

@@ -40,7 +40,7 @@
// Decode the one byte opcodes
//
0x1: decode OPCODE_OP_TOP5 {
'X86ISA::OneByteOpcode': decode OPCODE_OP_TOP5 {
format Inst {
0x00: decode OPCODE_OP_BOTTOM3 {
0x6: decode MODE_SUBMODE {

View File

@@ -0,0 +1,110 @@
// Copyright (c) 2008 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: Gabe Black
////////////////////////////////////////////////////////////////////
//
// Decode the three byte opcodes with the 0f38 prefix.
//
'X86ISA::ThreeByte0F38Opcode': decode LEGACY_OP {
format WarnUnimpl {
1: decode OPCODE_OP {
0x00: pshufb_Vdq_Wdq();
0x01: phaddw_Vdq_Wdq();
0x02: phaddd_Vdq_Wdq();
0x03: phaddsw_Vdq_Wdq();
0x04: pmaddubsw_Vdq_Wdq();
0x05: phsubw_Vdq_Wdq();
0x06: phsubd_Vdq_Wdq();
0x07: phsubsw_Vdq_Wdq();
0x08: psignb_Vdq_Wdq();
0x09: psignw_Vdq_Wdq();
0x0A: psignd_Vdq_Wdq();
0x0B: pmulhrsw_Vdq_Wdq();
0x10: pblendvb_Vdq_Wdq();
0x14: blendvps_Vdq_Wdq();
0x15: blendvpd_Vdq_Wdq();
0x17: ptest_Vdq_Wdq();
0x1C: pabsb_Vdq_Wdq();
0x1D: pabsw_Vdq_Wdq();
0x1E: pabsd_Vdq_Wdq();
0x20: pmovsxbw_Vdq_Udq_or_Mq();
0x21: pmovsxbd_Vdq_Udq_or_Md();
0x22: pmovsxbq_Vdq_Udq_or_Mw();
0x23: pmovsxwd_Vdq_Udq_or_Mq();
0x24: pmovsxwq_Vdq_Udq_or_Md();
0x25: pmovsxdq_Vdq_Udq_or_Mq();
0x28: pmuldq_Vdq_Wdq();
0x29: pcmpeqq_Vdq_Wdq();
0x2A: movntdqa_Vdq_Mdq();
0x2B: packusdw_Vdq_Wdq();
0x30: pmovzxbw_Vdq_Udq_or_Mq();
0x31: pmovzxbd_Vdq_Udq_or_Md();
0x32: pmovzxbq_Vdq_Udq_or_Mw();
0x33: pmovzxwd_Vdq_Udq_or_Mq();
0x34: pmovzxwq_Vdq_Udq_or_Md();
0x35: pmovzxdq_Vdq_Udq_or_Mq();
0x37: pcmpgtq_Vdq_Wdq();
0x38: pminsb_Vdq_Wdq();
0x39: pminsd_Vdq_Wdq();
0x3A: pminuw_Vdq_Wdq();
0x3B: pminud_Vdq_Wdq();
0x3C: pmaxsb_Vdq_Wdq();
0x3D: pmaxsd_Vdq_Wdq();
0x3E: pmaxuw_Vdq_Wdq();
0x3F: pmaxud_Vdq_Wdq();
0x40: pmulld_Vdq_Wdq();
0x41: phminposuw_Vdq_Wdq();
default: Inst::UD2();
}
default: decode LEGACY_REPNE {
1: decode OPCODE_OP {
0xF0: crc32_Gd_Eb();
0xF1: crc32_Gd_Ev();
default: Inst::UD2();
}
default: decode OPCODE_OP {
0x00: pshufb_Pq_Qq();
0x01: phaddw_Pq_Qq();
0x02: phaddd_Pq_Qq();
0x03: phaddsw_Pq_Qq();
0x04: pmaddubsw_Pq_Qq();
0x05: phsubw_Pq_Qq();
0x06: phsubd_Pq_Qq();
0x07: phsubsw_Pq_Qq();
0x08: psignb_Pq_Qq();
0x09: psignw_Pq_Qq();
0x0A: psignd_Pq_Qq();
0x0B: pmulhrsw_Pq_Qq();
0x1C: pabsb_Pq_Qq();
0x1D: pabsw_Pq_Qq();
0x1E: pabsd_Pq_Qq();
default: Inst::UD2();
}
}
}
}

View File

@@ -0,0 +1,65 @@
// Copyright (c) 2008 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: Gabe Black
////////////////////////////////////////////////////////////////////
//
// Decode the three byte opcodes with the 0f3a prefix.
//
format WarnUnimpl {
'X86ISA::ThreeByte0F3AOpcode': decode LEGACY_OP {
1: decode OPCODE_OP {
0x08: roundps_Vdq_Wdq_Ib();
0x09: roundpd_Vdq_Wdq_Ib();
0x0A: roundss_Vss_Wss_Ib();
0x0B: roundsd_Vsd_Wsd_Ib();
0x0C: blendps_Vdq_Wdq_Ib();
0x0D: blendpd_Vdq_Wdq_Ib();
0x0E: pblendw_Vdq_Wdq_Ib();
0x0F: palignr_Vdq_Wdq_Ib();
0x14: pextrb_Rd_or_Mb_Vdq_Ib();
0x15: decode MODRM_MOD {
0x3: Inst::PEXTRW(Rd,Vdq,Ib);
default: pextrw_Mw_Vdq_Ib();
}
0x16: pextrd_pextrq_Ed_or_Eq_Vdq_Ib();
0x17: extractps_Ed_Vdq_Ib();
0x20: pinsrb_Vdq_Rd_or_Rq_or_Mb_Ib();
0x21: insertps_Vdq_Udq_or_Md_Ib();
0x22: pinsrd_pinsrq_Vdq_Ed_or_Eq_Ib();
0x40: dpps_Vdq_Wdq_Ib();
0x41: dppd_Vdq_Wdq_Ib();
0x42: pcmpistrm_Vdq_Wdq_Ib();
0x43: pcmpistri_Vdq_Wdq_Ib();
default: Inst::UD2();
}
default: decode OPCODE_OP {
0x0F: palignr_Pq_Qq_Ib();
default: Inst::UD2();
}
}
}

View File

@@ -1,151 +0,0 @@
// Copyright (c) 2008 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: Gabe Black
////////////////////////////////////////////////////////////////////
//
// Decode the three byte opcodes
//
0x3: decode OPCODE_PREFIXA {
0x0F: decode OPCODE_PREFIXB {
0x38: decode LEGACY_OP {
format WarnUnimpl {
1: decode OPCODE_OP {
0x00: pshufb_Vdq_Wdq();
0x01: phaddw_Vdq_Wdq();
0x02: phaddd_Vdq_Wdq();
0x03: phaddsw_Vdq_Wdq();
0x04: pmaddubsw_Vdq_Wdq();
0x05: phsubw_Vdq_Wdq();
0x06: phsubd_Vdq_Wdq();
0x07: phsubsw_Vdq_Wdq();
0x08: psignb_Vdq_Wdq();
0x09: psignw_Vdq_Wdq();
0x0A: psignd_Vdq_Wdq();
0x0B: pmulhrsw_Vdq_Wdq();
0x10: pblendvb_Vdq_Wdq();
0x14: blendvps_Vdq_Wdq();
0x15: blendvpd_Vdq_Wdq();
0x17: ptest_Vdq_Wdq();
0x1C: pabsb_Vdq_Wdq();
0x1D: pabsw_Vdq_Wdq();
0x1E: pabsd_Vdq_Wdq();
0x20: pmovsxbw_Vdq_Udq_or_Mq();
0x21: pmovsxbd_Vdq_Udq_or_Md();
0x22: pmovsxbq_Vdq_Udq_or_Mw();
0x23: pmovsxwd_Vdq_Udq_or_Mq();
0x24: pmovsxwq_Vdq_Udq_or_Md();
0x25: pmovsxdq_Vdq_Udq_or_Mq();
0x28: pmuldq_Vdq_Wdq();
0x29: pcmpeqq_Vdq_Wdq();
0x2A: movntdqa_Vdq_Mdq();
0x2B: packusdw_Vdq_Wdq();
0x30: pmovzxbw_Vdq_Udq_or_Mq();
0x31: pmovzxbd_Vdq_Udq_or_Md();
0x32: pmovzxbq_Vdq_Udq_or_Mw();
0x33: pmovzxwd_Vdq_Udq_or_Mq();
0x34: pmovzxwq_Vdq_Udq_or_Md();
0x35: pmovzxdq_Vdq_Udq_or_Mq();
0x37: pcmpgtq_Vdq_Wdq();
0x38: pminsb_Vdq_Wdq();
0x39: pminsd_Vdq_Wdq();
0x3A: pminuw_Vdq_Wdq();
0x3B: pminud_Vdq_Wdq();
0x3C: pmaxsb_Vdq_Wdq();
0x3D: pmaxsd_Vdq_Wdq();
0x3E: pmaxuw_Vdq_Wdq();
0x3F: pmaxud_Vdq_Wdq();
0x40: pmulld_Vdq_Wdq();
0x41: phminposuw_Vdq_Wdq();
default: Inst::UD2();
}
default: decode LEGACY_REPNE {
1: decode OPCODE_OP {
0xF0: crc32_Gd_Eb();
0xF1: crc32_Gd_Ev();
default: Inst::UD2();
}
default: decode OPCODE_OP {
0x00: pshufb_Pq_Qq();
0x01: phaddw_Pq_Qq();
0x02: phaddd_Pq_Qq();
0x03: phaddsw_Pq_Qq();
0x04: pmaddubsw_Pq_Qq();
0x05: phsubw_Pq_Qq();
0x06: phsubd_Pq_Qq();
0x07: phsubsw_Pq_Qq();
0x08: psignb_Pq_Qq();
0x09: psignw_Pq_Qq();
0x0A: psignd_Pq_Qq();
0x0B: pmulhrsw_Pq_Qq();
0x1C: pabsb_Pq_Qq();
0x1D: pabsw_Pq_Qq();
0x1E: pabsd_Pq_Qq();
default: Inst::UD2();
}
}
}
}
0x3A: decode LEGACY_OP {
format WarnUnimpl {
1: decode OPCODE_OP {
0x08: roundps_Vdq_Wdq_Ib();
0x09: roundpd_Vdq_Wdq_Ib();
0x0A: roundss_Vss_Wss_Ib();
0x0B: roundsd_Vsd_Wsd_Ib();
0x0C: blendps_Vdq_Wdq_Ib();
0x0D: blendpd_Vdq_Wdq_Ib();
0x0E: pblendw_Vdq_Wdq_Ib();
0x0F: palignr_Vdq_Wdq_Ib();
0x14: pextrb_Rd_or_Mb_Vdq_Ib();
0x15: decode MODRM_MOD {
0x3: Inst::PEXTRW(Rd,Vdq,Ib);
default: pextrw_Mw_Vdq_Ib();
}
0x16: pextrd_pextrq_Ed_or_Eq_Vdq_Ib();
0x17: extractps_Ed_Vdq_Ib();
0x20: pinsrb_Vdq_Rd_or_Rq_or_Mb_Ib();
0x21: insertps_Vdq_Udq_or_Md_Ib();
0x22: pinsrd_pinsrq_Vdq_Ed_or_Eq_Ib();
0x40: dpps_Vdq_Wdq_Ib();
0x41: dppd_Vdq_Wdq_Ib();
0x42: pcmpistrm_Vdq_Wdq_Ib();
0x43: pcmpistri_Vdq_Wdq_Ib();
default: Inst::UD2();
}
default: decode OPCODE_OP {
0x0F: palignr_Pq_Qq_Ib();
default: Inst::UD2();
}
}
}
default: M5InternalError::error(
{{"Unexpected second opcode byte in three byte opcode!"}});
}
default: M5InternalError::error(
{{"Unexpected first opcode byte in three byte opcode!"}});
}

File diff suppressed because it is too large Load Diff

View File

@@ -71,7 +71,7 @@ namespace X86ISA
const ExtMachInst NoopMachInst = {
0x0, // No legacy prefixes.
0x0, // No rex prefix.
{ 1, 0x0, 0x0, 0x90 }, // One opcode byte, 0x90.
{ OneByteOpcode, 0x90 }, // One opcode byte, 0x90.
0x0, 0x0, // No modrm or sib.
0, 0, // No immediate or displacement.
8, 8, 8, // All sizes are 8.

View File

@@ -43,9 +43,7 @@ paramOut(ostream &os, const string &name, ExtMachInst const &machInst)
paramOut(os, name + ".rex", (uint8_t)machInst.rex);
// Opcode
paramOut(os, name + ".opcode.num", machInst.opcode.num);
paramOut(os, name + ".opcode.prefixA", machInst.opcode.prefixA);
paramOut(os, name + ".opcode.prefixB", machInst.opcode.prefixB);
paramOut(os, name + ".opcode.type", (uint8_t)machInst.opcode.type);
paramOut(os, name + ".opcode.op", (uint8_t)machInst.opcode.op);
// Modifier bytes
@@ -79,9 +77,8 @@ paramIn(Checkpoint *cp, const string &section,
machInst.rex = temp8;
// Opcode
paramIn(cp, section, name + ".opcode.num", machInst.opcode.num);
paramIn(cp, section, name + ".opcode.prefixA", machInst.opcode.prefixA);
paramIn(cp, section, name + ".opcode.prefixB", machInst.opcode.prefixB);
paramIn(cp, section, name + ".opcode.type", temp8);
machInst.opcode.type = (OpcodeType)temp8;
paramIn(cp, section, name + ".opcode.op", temp8);
machInst.opcode.op = temp8;

View File

@@ -104,6 +104,33 @@ namespace X86ISA
Bitfield<0> b;
EndBitUnion(Rex)
enum OpcodeType {
BadOpcode,
OneByteOpcode,
TwoByteOpcode,
ThreeByte0F38Opcode,
ThreeByte0F3AOpcode
};
static inline const char *
opcodeTypeToStr(OpcodeType type)
{
switch (type) {
case BadOpcode:
return "bad";
case OneByteOpcode:
return "one byte";
case TwoByteOpcode:
return "two byte";
case ThreeByte0F38Opcode:
return "three byte 0f38";
case ThreeByte0F3AOpcode:
return "three byte 0f3a";
default:
return "unrecognized!";
}
}
BitUnion8(Opcode)
Bitfield<7,3> top5;
Bitfield<2,0> bottom3;
@@ -136,16 +163,7 @@ namespace X86ISA
//This holds all of the bytes of the opcode
struct
{
//The number of bytes in this opcode. Right now, we ignore that
//this can be 3 in some cases
uint8_t num;
//The first byte detected in a 2+ byte opcode. Should be 0xF0.
uint8_t prefixA;
//The second byte detected in a 3+ byte opcode. Could be 0x38-0x3F
//for some SSE instructions. 3dNow! instructions are handled as
//two byte opcodes and then split out further by the immediate
//byte.
uint8_t prefixB;
OpcodeType type;
//The main opcode byte. The highest addressed byte in the opcode.
Opcode op;
} opcode;
@@ -173,14 +191,12 @@ namespace X86ISA
operator << (std::ostream & os, const ExtMachInst & emi)
{
ccprintf(os, "\n{\n\tleg = %#x,\n\trex = %#x,\n\t"
"op = {\n\t\tnum = %d,\n\t\top = %#x,\n\t\t"
"prefixA = %#x,\n\t\tprefixB = %#x\n\t},\n\t"
"op = {\n\t\ttype = %s,\n\t\top = %#x,\n\t\t},\n\t"
"modRM = %#x,\n\tsib = %#x,\n\t"
"immediate = %#x,\n\tdisplacement = %#x\n\t"
"dispSize = %d}\n",
(uint8_t)emi.legacy, (uint8_t)emi.rex,
emi.opcode.num, (uint8_t)emi.opcode.op,
emi.opcode.prefixA, emi.opcode.prefixB,
opcodeTypeToStr(emi.opcode.type), (uint8_t)emi.opcode.op,
(uint8_t)emi.modRM, (uint8_t)emi.sib,
emi.immediate, emi.displacement, emi.dispSize);
return os;
@@ -193,14 +209,10 @@ namespace X86ISA
return false;
if(emi1.rex != emi2.rex)
return false;
if(emi1.opcode.num != emi2.opcode.num)
if(emi1.opcode.type != emi2.opcode.type)
return false;
if(emi1.opcode.op != emi2.opcode.op)
return false;
if(emi1.opcode.prefixA != emi2.opcode.prefixA)
return false;
if(emi1.opcode.prefixB != emi2.opcode.prefixB)
return false;
if(emi1.modRM != emi2.modRM)
return false;
if(emi1.sib != emi2.sib)
@@ -284,13 +296,11 @@ __hash_namespace_begin
template<>
struct hash<X86ISA::ExtMachInst> {
size_t operator()(const X86ISA::ExtMachInst &emi) const {
return (((uint64_t)emi.legacy << 56) |
((uint64_t)emi.rex << 48) |
((uint64_t)emi.modRM << 40) |
((uint64_t)emi.sib << 32) |
((uint64_t)emi.opcode.num << 24) |
((uint64_t)emi.opcode.prefixA << 16) |
((uint64_t)emi.opcode.prefixB << 8) |
return (((uint64_t)emi.legacy << 40) |
((uint64_t)emi.rex << 32) |
((uint64_t)emi.modRM << 24) |
((uint64_t)emi.sib << 16) |
((uint64_t)emi.opcode.type << 8) |
((uint64_t)emi.opcode.op)) ^
emi.immediate ^ emi.displacement ^
emi.mode ^