diff options
author | Gabe Black <gabeblack@google.com> | 2014-12-04 15:53:54 -0800 |
---|---|---|
committer | Gabe Black <gabeblack@google.com> | 2014-12-04 15:53:54 -0800 |
commit | 22aaa5867f2449e2a73b7891fc34072c12c199b3 (patch) | |
tree | 6083ecfd34307076c8d9c55a450e6cc118025b95 /src/arch/x86 | |
parent | 3069c28a021d3f8c29221e537d48ee382c30646f (diff) | |
download | gem5-22aaa5867f2449e2a73b7891fc34072c12c199b3.tar.xz |
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
Diffstat (limited to 'src/arch/x86')
-rw-r--r-- | src/arch/x86/decoder.cc | 191 | ||||
-rw-r--r-- | src/arch/x86/decoder.hh | 29 | ||||
-rw-r--r-- | src/arch/x86/decoder_tables.cc | 259 | ||||
-rw-r--r-- | src/arch/x86/isa/bitfields.isa | 4 | ||||
-rw-r--r-- | src/arch/x86/isa/decoder/decoder.isa | 10 | ||||
-rw-r--r-- | src/arch/x86/isa/decoder/locked_opcodes.isa | 62 | ||||
-rw-r--r-- | src/arch/x86/isa/decoder/one_byte_opcodes.isa | 2 | ||||
-rw-r--r-- | src/arch/x86/isa/decoder/three_byte_0f38_opcodes.isa | 110 | ||||
-rw-r--r-- | src/arch/x86/isa/decoder/three_byte_0f3a_opcodes.isa | 65 | ||||
-rw-r--r-- | src/arch/x86/isa/decoder/three_byte_opcodes.isa | 151 | ||||
-rw-r--r-- | src/arch/x86/isa/decoder/two_byte_opcodes.isa | 1858 | ||||
-rw-r--r-- | src/arch/x86/isa_traits.hh | 2 | ||||
-rw-r--r-- | src/arch/x86/types.cc | 9 | ||||
-rw-r--r-- | src/arch/x86/types.hh | 62 |
14 files changed, 1496 insertions, 1318 deletions
diff --git a/src/arch/x86/decoder.cc b/src/arch/x86/decoder.cc index f42fb28bf..59f2e0f4f 100644 --- a/src/arch/x86/decoder.cc +++ b/src/arch/x86/decoder.cc @@ -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; + 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; + + nextState = processOpcode(ImmediateTypeOneByte, UsesModRMOneByte, + nextByte >= 0xA0 && nextByte <= 0xA3); } - else - { - DPRINTF(Decoder, "Found opcode %#x.\n", nextByte); + return nextState; +} + +// 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 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(ImmediateTypeTwoByte, UsesModRMTwoByte); + } + return nextState; +} - //Set the actual op size - emi.opSize = 1 << logOpSize; +// 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 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; + DPRINTF(Decoder, "Found three byte 0F38 opcode %#x.\n", nextByte); + emi.opcode.type = ThreeByte0F38Opcode; + emi.opcode.op = nextByte; - //Set the actual address size - emi.addrSize = 1 << logAddrSize; + return processOpcode(ImmediateTypeThreeByte0F38, UsesModRMThreeByte0F38); +} - //Figure out the effective stack width. This can be overriden to - //a fixed value at the decoder level. - emi.stackSize = 1 << stack; +// Load the third opcode byte and determine what immediate and/or ModRM is +// needed. +Decoder::State +Decoder::doThreeByte0F3AOpcodeState(uint8_t nextByte) +{ + consumeByte(); - //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]; + 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; - //Determine what to expect next - if (UsesModRM[emi.opcode.num - 1][nextByte]) { - nextState = ModRMState; + //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) diff --git a/src/arch/x86/decoder.hh b/src/arch/x86/decoder.hh index ca7ef96fe..a37fccfb1 100644 --- a/src/arch/x86/decoder.hh +++ b/src/arch/x86/decoder.hh @@ -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. diff --git a/src/arch/x86/decoder_tables.cc b/src/arch/x86/decoder_tables.cc index a132cb864..d5fcceef8 100644 --- a/src/arch/x86/decoder_tables.cc +++ b/src/arch/x86/decoder_tables.cc @@ -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 }; } diff --git a/src/arch/x86/isa/bitfields.isa b/src/arch/x86/isa/bitfields.isa index a7753ba3d..e2751a8ef 100644 --- a/src/arch/x86/isa/bitfields.isa +++ b/src/arch/x86/isa/bitfields.isa @@ -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; diff --git a/src/arch/x86/isa/decoder/decoder.isa b/src/arch/x86/isa/decoder/decoder.isa index 9b2ce0ba0..eaa579817 100644 --- a/src/arch/x86/isa/decoder/decoder.isa +++ b/src/arch/x86/isa/decoder/decoder.isa @@ -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" diff --git a/src/arch/x86/isa/decoder/locked_opcodes.isa b/src/arch/x86/isa/decoder/locked_opcodes.isa index e776d1320..d2bfac57e 100644 --- a/src/arch/x86/isa/decoder/locked_opcodes.isa +++ b/src/arch/x86/isa/decoder/locked_opcodes.isa @@ -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(); - } - 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); + '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); } - 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!"}}); } } } diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 92e5cd0a8..859d1f1b4 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -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 { diff --git a/src/arch/x86/isa/decoder/three_byte_0f38_opcodes.isa b/src/arch/x86/isa/decoder/three_byte_0f38_opcodes.isa new file mode 100644 index 000000000..d04f15ec3 --- /dev/null +++ b/src/arch/x86/isa/decoder/three_byte_0f38_opcodes.isa @@ -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(); + } + } + } +} diff --git a/src/arch/x86/isa/decoder/three_byte_0f3a_opcodes.isa b/src/arch/x86/isa/decoder/three_byte_0f3a_opcodes.isa new file mode 100644 index 000000000..5935fb6a5 --- /dev/null +++ b/src/arch/x86/isa/decoder/three_byte_0f3a_opcodes.isa @@ -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(); + } + } +} diff --git a/src/arch/x86/isa/decoder/three_byte_opcodes.isa b/src/arch/x86/isa/decoder/three_byte_opcodes.isa deleted file mode 100644 index 7587e3dad..000000000 --- a/src/arch/x86/isa/decoder/three_byte_opcodes.isa +++ /dev/null @@ -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!"}}); -} diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 081bad971..e1b20feb1 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -42,1029 +42,1025 @@ // // Decode the two byte opcodes // -0x2: decode OPCODE_PREFIXA { - 0x0F: decode OPCODE_OP_TOP5 { - format WarnUnimpl { - 0x00: decode OPCODE_OP_BOTTOM3 { - //0x00: group6(); - 0x00: decode MODRM_REG { - 0x0: sldt_Mw_or_Rv(); - 0x1: str_Mw_or_Rv(); - 0x2: Inst::LLDT(Ew); - 0x3: Inst::LTR(Ew); - 0x4: verr_Mw_or_Rv(); - 0x5: verw_Mw_or_Rv(); - //0x6: jmpe_Ev(); // IA-64 - default: Inst::UD2(); - } - //0x01: group7(); // Ugly, ugly, ugly... - 0x01: decode MODRM_REG { - 0x0: decode MODRM_MOD { - 0x3: decode MODRM_RM { - 0x1: vmcall(); - 0x2: vmlaunch(); - 0x3: vmresume(); - 0x4: vmxoff(); - default: Inst::UD2(); - } - default: sgdt_Ms(); - } - 0x1: decode MODRM_MOD { - 0x3: decode MODRM_RM { - 0x0: MonitorInst::monitor({{ - xc->armMonitor(Rax); - }}); - 0x1: MwaitInst::mwait({{ - uint64_t m = 0; //mem - unsigned s = 0x8; //size - unsigned f = 0; //flags - readMemAtomic(xc, traceData, - xc->getAddrMonitor()->vAddr, - m, s, f); - xc->mwaitAtomic(xc->tcBase()); - MicroHalt hltObj(machInst, mnemonic, 0x0); - hltObj.execute(xc, traceData); - }}); - default: Inst::UD2(); - } - default: sidt_Ms(); +'X86ISA::TwoByteOpcode': decode OPCODE_OP_TOP5 { + format WarnUnimpl { + 0x00: decode OPCODE_OP_BOTTOM3 { + //0x00: group6(); + 0x00: decode MODRM_REG { + 0x0: sldt_Mw_or_Rv(); + 0x1: str_Mw_or_Rv(); + 0x2: Inst::LLDT(Ew); + 0x3: Inst::LTR(Ew); + 0x4: verr_Mw_or_Rv(); + 0x5: verw_Mw_or_Rv(); + //0x6: jmpe_Ev(); // IA-64 + default: Inst::UD2(); + } + //0x01: group7(); // Ugly, ugly, ugly... + 0x01: decode MODRM_REG { + 0x0: decode MODRM_MOD { + 0x3: decode MODRM_RM { + 0x1: vmcall(); + 0x2: vmlaunch(); + 0x3: vmresume(); + 0x4: vmxoff(); + default: Inst::UD2(); } - 0x2: decode MODRM_MOD { - 0x3: decode MODRM_RM { - 0x0: xgetbv(); - 0x1: xsetbv(); - } - default: decode MODE_SUBMODE { - 0x0: Inst::LGDT(M); - default: decode OPSIZE { - // 16 bit operand sizes are special, but only - // in legacy and compatability modes. - 0x2: Inst::LGDT_16(M); - default: Inst::LGDT(M); - } - } + default: sgdt_Ms(); + } + 0x1: decode MODRM_MOD { + 0x3: decode MODRM_RM { + 0x0: MonitorInst::monitor({{ + xc->armMonitor(Rax); + }}); + 0x1: MwaitInst::mwait({{ + uint64_t m = 0; //mem + unsigned s = 0x8; //size + unsigned f = 0; //flags + readMemAtomic(xc, traceData, + xc->getAddrMonitor()->vAddr, + m, s, f); + xc->mwaitAtomic(xc->tcBase()); + MicroHalt hltObj(machInst, mnemonic, 0x0); + hltObj.execute(xc, traceData); + }}); + default: Inst::UD2(); } - 0x3: decode MODRM_MOD { - 0x3: decode MODRM_RM { - 0x0: vmrun(); - 0x1: vmmcall(); - 0x2: vmload(); - 0x3: vmsave(); - 0x4: stgi(); - 0x5: clgi(); - 0x6: skinit(); - 0x7: invlpga(); - } - default: decode MODE_SUBMODE { - 0x0: Inst::LIDT(M); - default: decode OPSIZE { - // 16 bit operand sizes are special, but only - // in legacy and compatability modes. - 0x2: Inst::LIDT_16(M); - default: Inst::LIDT(M); - } + default: sidt_Ms(); + } + 0x2: decode MODRM_MOD { + 0x3: decode MODRM_RM { + 0x0: xgetbv(); + 0x1: xsetbv(); + } + default: decode MODE_SUBMODE { + 0x0: Inst::LGDT(M); + default: decode OPSIZE { + // 16 bit operand sizes are special, but only + // in legacy and compatability modes. + 0x2: Inst::LGDT_16(M); + default: Inst::LGDT(M); } } - 0x4: decode MODRM_MOD { - 0x3: Inst::SMSW(Rv); - default: Inst::SMSW(Mw); - } - 0x6: Inst::LMSW(Ew); - 0x7: decode MODRM_MOD { - 0x3: decode MODRM_RM { - 0x0: Inst::SWAPGS(); - 0x1: rdtscp(); - default: Inst::UD2(); + } + 0x3: decode MODRM_MOD { + 0x3: decode MODRM_RM { + 0x0: vmrun(); + 0x1: vmmcall(); + 0x2: vmload(); + 0x3: vmsave(); + 0x4: stgi(); + 0x5: clgi(); + 0x6: skinit(); + 0x7: invlpga(); + } + default: decode MODE_SUBMODE { + 0x0: Inst::LIDT(M); + default: decode OPSIZE { + // 16 bit operand sizes are special, but only + // in legacy and compatability modes. + 0x2: Inst::LIDT_16(M); + default: Inst::LIDT(M); } - default: Inst::INVLPG(M); } } - 0x02: lar_Gv_Ew(); - 0x03: lsl_Gv_Ew(); - // sandpile.org doesn't seem to know what this is...? We'll - // use it for pseudo instructions. We've got 16 bits of space - // to play with so there can be quite a few pseudo - // instructions. - //0x04: loadall_or_reset_or_hang(); - 0x4: decode IMMEDIATE { - format BasicOperate { - 0x00: m5arm({{ - PseudoInst::arm(xc->tcBase()); - }}, IsNonSpeculative); - 0x01: m5quiesce({{ - PseudoInst::quiesce(xc->tcBase()); - }}, IsNonSpeculative, IsQuiesce); - 0x02: m5quiesceNs({{ - PseudoInst::quiesceNs(xc->tcBase(), Rdi); - }}, IsNonSpeculative, IsQuiesce); - 0x03: m5quiesceCycle({{ - PseudoInst::quiesceCycles(xc->tcBase(), Rdi); - }}, IsNonSpeculative, IsQuiesce); - 0x04: m5quiesceTime({{ - Rax = PseudoInst::quiesceTime(xc->tcBase()); - }}, IsNonSpeculative); - 0x07: m5rpns({{ - Rax = PseudoInst::rpns(xc->tcBase()); - }}, IsNonSpeculative); - 0x21: m5exit({{ - PseudoInst::m5exit(xc->tcBase(), Rdi); - }}, IsNonSpeculative); - 0x22: m5fail({{ - PseudoInst::m5fail(xc->tcBase(), Rdi, Rsi); - }}, IsNonSpeculative); - 0x30: m5initparam({{ - Rax = PseudoInst::initParam(xc->tcBase()); - }}, IsNonSpeculative); - 0x31: m5loadsymbol({{ - PseudoInst::loadsymbol(xc->tcBase()); - }}, IsNonSpeculative); - 0x40: m5resetstats({{ - PseudoInst::resetstats(xc->tcBase(), Rdi, Rsi); - }}, IsNonSpeculative); - 0x41: m5dumpstats({{ - PseudoInst::dumpstats(xc->tcBase(), Rdi, Rsi); - }}, IsNonSpeculative); - 0x42: m5dumpresetstats({{ - PseudoInst::dumpresetstats(xc->tcBase(), Rdi, Rsi); - }}, IsNonSpeculative); - 0x43: m5checkpoint({{ - PseudoInst::m5checkpoint(xc->tcBase(), Rdi, Rsi); - }}, IsNonSpeculative); - 0x50: m5readfile({{ - Rax = PseudoInst::readfile( - xc->tcBase(), Rdi, Rsi, Rdx); - }}, IsNonSpeculative); - 0x51: m5debugbreak({{ - PseudoInst::debugbreak(xc->tcBase()); - }}, IsNonSpeculative); - 0x52: m5switchcpu({{ - PseudoInst::switchcpu(xc->tcBase()); - }}, IsNonSpeculative); - 0x53: m5addsymbol({{ - PseudoInst::addsymbol(xc->tcBase(), Rdi, Rsi); - }}, IsNonSpeculative); - 0x54: m5panic({{ - panic("M5 panic instruction called at pc = %#x.\n", - RIP); - }}, IsNonSpeculative); - 0x55: m5reserved1({{ - warn("M5 reserved opcode 1 ignored.\n"); - }}, IsNonSpeculative); - 0x56: m5reserved2({{ - warn("M5 reserved opcode 2 ignored.\n"); - }}, IsNonSpeculative); - 0x57: m5reserved3({{ - warn("M5 reserved opcode 3 ignored.\n"); - }}, IsNonSpeculative); - 0x58: m5reserved4({{ - warn("M5 reserved opcode 4 ignored.\n"); - }}, IsNonSpeculative); - 0x59: m5reserved5({{ - warn("M5 reserved opcode 5 ignored.\n"); - }}, IsNonSpeculative); - 0x5a: m5_work_begin({{ - PseudoInst::workbegin(xc->tcBase(), Rdi, Rsi); - }}, IsNonSpeculative); - 0x5b: m5_work_end({{ - PseudoInst::workend(xc->tcBase(), Rdi, Rsi); - }}, IsNonSpeculative); + 0x4: decode MODRM_MOD { + 0x3: Inst::SMSW(Rv); + default: Inst::SMSW(Mw); + } + 0x6: Inst::LMSW(Ew); + 0x7: decode MODRM_MOD { + 0x3: decode MODRM_RM { + 0x0: Inst::SWAPGS(); + 0x1: rdtscp(); default: Inst::UD2(); } + default: Inst::INVLPG(M); } - 0x05: decode FullSystemInt { - 0: SyscallInst::syscall('xc->syscall(Rax)', - IsSyscall, IsNonSpeculative, IsSerializeAfter); - default: decode MODE_MODE { - 0x0: decode MODE_SUBMODE { - 0x0: Inst::SYSCALL_64(); - 0x1: Inst::SYSCALL_COMPAT(); - } - 0x1: Inst::SYSCALL_LEGACY(); - } + } + 0x02: lar_Gv_Ew(); + 0x03: lsl_Gv_Ew(); + // sandpile.org doesn't seem to know what this is...? We'll + // use it for pseudo instructions. We've got 16 bits of space + // to play with so there can be quite a few pseudo + // instructions. + //0x04: loadall_or_reset_or_hang(); + 0x4: decode IMMEDIATE { + format BasicOperate { + 0x00: m5arm({{ + PseudoInst::arm(xc->tcBase()); + }}, IsNonSpeculative); + 0x01: m5quiesce({{ + PseudoInst::quiesce(xc->tcBase()); + }}, IsNonSpeculative, IsQuiesce); + 0x02: m5quiesceNs({{ + PseudoInst::quiesceNs(xc->tcBase(), Rdi); + }}, IsNonSpeculative, IsQuiesce); + 0x03: m5quiesceCycle({{ + PseudoInst::quiesceCycles(xc->tcBase(), Rdi); + }}, IsNonSpeculative, IsQuiesce); + 0x04: m5quiesceTime({{ + Rax = PseudoInst::quiesceTime(xc->tcBase()); + }}, IsNonSpeculative); + 0x07: m5rpns({{ + Rax = PseudoInst::rpns(xc->tcBase()); + }}, IsNonSpeculative); + 0x21: m5exit({{ + PseudoInst::m5exit(xc->tcBase(), Rdi); + }}, IsNonSpeculative); + 0x22: m5fail({{ + PseudoInst::m5fail(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + 0x30: m5initparam({{ + Rax = PseudoInst::initParam(xc->tcBase()); + }}, IsNonSpeculative); + 0x31: m5loadsymbol({{ + PseudoInst::loadsymbol(xc->tcBase()); + }}, IsNonSpeculative); + 0x40: m5resetstats({{ + PseudoInst::resetstats(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + 0x41: m5dumpstats({{ + PseudoInst::dumpstats(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + 0x42: m5dumpresetstats({{ + PseudoInst::dumpresetstats(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + 0x43: m5checkpoint({{ + PseudoInst::m5checkpoint(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + 0x50: m5readfile({{ + Rax = PseudoInst::readfile( + xc->tcBase(), Rdi, Rsi, Rdx); + }}, IsNonSpeculative); + 0x51: m5debugbreak({{ + PseudoInst::debugbreak(xc->tcBase()); + }}, IsNonSpeculative); + 0x52: m5switchcpu({{ + PseudoInst::switchcpu(xc->tcBase()); + }}, IsNonSpeculative); + 0x53: m5addsymbol({{ + PseudoInst::addsymbol(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + 0x54: m5panic({{ + panic("M5 panic instruction called at pc = %#x.\n", + RIP); + }}, IsNonSpeculative); + 0x55: m5reserved1({{ + warn("M5 reserved opcode 1 ignored.\n"); + }}, IsNonSpeculative); + 0x56: m5reserved2({{ + warn("M5 reserved opcode 2 ignored.\n"); + }}, IsNonSpeculative); + 0x57: m5reserved3({{ + warn("M5 reserved opcode 3 ignored.\n"); + }}, IsNonSpeculative); + 0x58: m5reserved4({{ + warn("M5 reserved opcode 4 ignored.\n"); + }}, IsNonSpeculative); + 0x59: m5reserved5({{ + warn("M5 reserved opcode 5 ignored.\n"); + }}, IsNonSpeculative); + 0x5a: m5_work_begin({{ + PseudoInst::workbegin(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + 0x5b: m5_work_end({{ + PseudoInst::workend(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + default: Inst::UD2(); } - 0x06: Inst::CLTS(); - 0x07: decode MODE_SUBMODE { - 0x0: decode OPSIZE { - // Return to 64 bit mode. - 0x8: Inst::SYSRET_TO_64(); - // Return to compatibility mode. - default: Inst::SYSRET_TO_COMPAT(); - } - default: Inst::SYSRET_NON_64(); + } + 0x05: decode FullSystemInt { + 0: SyscallInst::syscall('xc->syscall(Rax)', + IsSyscall, IsNonSpeculative, IsSerializeAfter); + default: decode MODE_MODE { + 0x0: decode MODE_SUBMODE { + 0x0: Inst::SYSCALL_64(); + 0x1: Inst::SYSCALL_COMPAT(); + } + 0x1: Inst::SYSCALL_LEGACY(); } } - 0x01: decode OPCODE_OP_BOTTOM3 { - 0x0: invd(); - 0x1: wbinvd(); - 0x2: Inst::UD2(); - 0x3: Inst::UD2(); - 0x4: Inst::UD2(); - 0x5: Inst::PREFETCH(Mb); - 0x6: FailUnimpl::femms(); - 0x7: decode IMMEDIATE { - 0x0C: pi2fw_Pq_Qq(); - 0x0D: pi2fd_Pq_Qq(); - 0x1C: pf2iw_Pq_Qq(); - 0x1D: pf2id_Pq_Qq(); - 0x8A: pfnacc_Pq_Qq(); - 0x8E: pfpnacc_Pq_Qq(); - 0x90: pfcmpge_Pq_Qq(); - 0x94: pfmin_Pq_Qq(); - 0x96: pfrcp_Pq_Qq(); - 0x97: pfrsqrt_Pq_Qq(); - 0x9A: Inst::PFSUB(Pq,Qq); - 0x9E: pfadd_Pq_Qq(); - 0xA0: pfcmpgt_Pq_Qq(); - 0xA4: pfmax_Pq_Qq(); - 0xA6: pfrcpit1_Pq_Qq(); - 0xA7: pfrsqit1_Pq_Qq(); - 0xAA: Inst::PFSUBR(Pq,Qq); - 0xAE: pfacc_Pq_Qq(); - 0xB0: pfcmpeq_Pq_Qq(); - 0xB4: Inst::PFMUL(Pq,Qq); - 0xB6: pfrcpit2_Pq_Qq(); - 0xB7: Inst::PMULHRW(Pq,Qq); - 0xBB: pswapd_Pq_Qq(); - 0xBF: pavgusb_Pq_Qq(); - default: Inst::UD2(); + 0x06: Inst::CLTS(); + 0x07: decode MODE_SUBMODE { + 0x0: decode OPSIZE { + // Return to 64 bit mode. + 0x8: Inst::SYSRET_TO_64(); + // Return to compatibility mode. + default: Inst::SYSRET_TO_COMPAT(); } + default: Inst::SYSRET_NON_64(); } - format Inst{ - 0x02: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x0: MOVUPS(Vo,Wo); - 0x1: MOVUPS(Wo,Vo); - 0x2: decode MODRM_MOD { - 0x3: MOVHLPS(Vps,VRq); - default: MOVLPS(Vps,Mq); - } - 0x3: MOVLPS(Mq,Vps); - 0x4: UNPCKLPS(Vps,Wq); - 0x5: UNPCKHPS(Vps,Wq); - 0x6: decode MODRM_MOD { - 0x3: MOVLHPS(Vps,VRq); - default: MOVHPS(Vps,Mq); - } - 0x7: MOVHPS(Mq,Vq); - } - // repe (0xF3) - 0x4: decode OPCODE_OP_BOTTOM3 { - 0x0: MOVSS(Vd,Wd); - 0x1: MOVSS(Wd,Vd); - 0x2: WarnUnimpl::movsldup_Vo_Wo(); - 0x6: WarnUnimpl::movshdup_Vo_Wo(); - default: UD2(); - } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x0: MOVUPD(Vo,Wo); - 0x1: MOVUPD(Wo,Vo); - 0x2: MOVLPD(Vq,Mq); - 0x3: MOVLPD(Mq,Vq); - 0x4: UNPCKLPD(Vo,Wq); - 0x5: UNPCKHPD(Vo,Wo); - 0x6: MOVHPD(Vq,Mq); - 0x7: MOVHPD(Mq,Vq); + } + 0x01: decode OPCODE_OP_BOTTOM3 { + 0x0: invd(); + 0x1: wbinvd(); + 0x2: Inst::UD2(); + 0x3: Inst::UD2(); + 0x4: Inst::UD2(); + 0x5: Inst::PREFETCH(Mb); + 0x6: FailUnimpl::femms(); + 0x7: decode IMMEDIATE { + 0x0C: pi2fw_Pq_Qq(); + 0x0D: pi2fd_Pq_Qq(); + 0x1C: pf2iw_Pq_Qq(); + 0x1D: pf2id_Pq_Qq(); + 0x8A: pfnacc_Pq_Qq(); + 0x8E: pfpnacc_Pq_Qq(); + 0x90: pfcmpge_Pq_Qq(); + 0x94: pfmin_Pq_Qq(); + 0x96: pfrcp_Pq_Qq(); + 0x97: pfrsqrt_Pq_Qq(); + 0x9A: Inst::PFSUB(Pq,Qq); + 0x9E: pfadd_Pq_Qq(); + 0xA0: pfcmpgt_Pq_Qq(); + 0xA4: pfmax_Pq_Qq(); + 0xA6: pfrcpit1_Pq_Qq(); + 0xA7: pfrsqit1_Pq_Qq(); + 0xAA: Inst::PFSUBR(Pq,Qq); + 0xAE: pfacc_Pq_Qq(); + 0xB0: pfcmpeq_Pq_Qq(); + 0xB4: Inst::PFMUL(Pq,Qq); + 0xB6: pfrcpit2_Pq_Qq(); + 0xB7: Inst::PMULHRW(Pq,Qq); + 0xBB: pswapd_Pq_Qq(); + 0xBF: pavgusb_Pq_Qq(); + default: Inst::UD2(); + } + } + format Inst{ + 0x02: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x0: MOVUPS(Vo,Wo); + 0x1: MOVUPS(Wo,Vo); + 0x2: decode MODRM_MOD { + 0x3: MOVHLPS(Vps,VRq); + default: MOVLPS(Vps,Mq); } - // repne (0xF2) - 0x8: decode OPCODE_OP_BOTTOM3 { - 0x0: MOVSD(Vq,Wq); - 0x1: MOVSD(Wq,Vq); - 0x2: MOVDDUP(Vo,Wq); - default: UD2(); + 0x3: MOVLPS(Mq,Vps); + 0x4: UNPCKLPS(Vps,Wq); + 0x5: UNPCKHPS(Vps,Wq); + 0x6: decode MODRM_MOD { + 0x3: MOVLHPS(Vps,VRq); + default: MOVHPS(Vps,Mq); } - default: UD2(); + 0x7: MOVHPS(Mq,Vq); } - 0x03: decode OPCODE_OP_BOTTOM3 { - //group16(); - 0x0: decode MODRM_REG { - 0x0: WarnUnimpl::prefetch_nta(); - 0x1: PREFETCH_T0(Mb); - 0x2: WarnUnimpl::prefetch_t1(); - 0x3: WarnUnimpl::prefetch_t2(); - default: HINT_NOP(); - } - 0x1: HINT_NOP(); - 0x2: HINT_NOP(); - 0x3: HINT_NOP(); - 0x4: HINT_NOP(); - 0x5: HINT_NOP(); - 0x6: HINT_NOP(); - 0x7: HINT_NOP(); + // repe (0xF3) + 0x4: decode OPCODE_OP_BOTTOM3 { + 0x0: MOVSS(Vd,Wd); + 0x1: MOVSS(Wd,Vd); + 0x2: WarnUnimpl::movsldup_Vo_Wo(); + 0x6: WarnUnimpl::movshdup_Vo_Wo(); + default: UD2(); } - 0x04: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x0: MOV(Rd,Cd); - 0x1: MOV(Rd,Dd); - 0x2: MOV(Cd,Rd); - 0x3: MOV(Dd,Rd); - default: UD2(); - } + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x0: MOVUPD(Vo,Wo); + 0x1: MOVUPD(Wo,Vo); + 0x2: MOVLPD(Vq,Mq); + 0x3: MOVLPD(Mq,Vq); + 0x4: UNPCKLPD(Vo,Wq); + 0x5: UNPCKHPD(Vo,Wo); + 0x6: MOVHPD(Vq,Mq); + 0x7: MOVHPD(Mq,Vq); + } + // repne (0xF2) + 0x8: decode OPCODE_OP_BOTTOM3 { + 0x0: MOVSD(Vq,Wq); + 0x1: MOVSD(Wq,Vq); + 0x2: MOVDDUP(Vo,Wq); default: UD2(); } - 0x05: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - //These moves should really use size o (octword), but - //because they are split in two, they use q (quadword). - 0x0: MOVAPS(Vq,Wq); - 0x1: MOVAPS(Wq,Vq); - 0x2: CVTPI2PS(Vq,Qq); - 0x3: WarnUnimpl::movntps_Mo_Vo(); - 0x4: CVTTPS2PI(Pq,Wq); - 0x5: CVTPS2PI(Pq,Wq); - 0x6: UCOMISS(Vd,Wd); - 0x7: COMISS(Vd,Wd); - } - // repe (0xF3) - 0x4: decode OPCODE_OP_BOTTOM3 { - 0x2: CVTSI2SS(Vd,Ed); - 0x4: CVTTSS2SI(Gd,Wd); - 0x5: CVTSS2SI(Gd,Wd); - default: UD2(); - } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x0: MOVAPD(Vo,Wo); - 0x1: MOVAPD(Wo,Vo); - 0x2: CVTPI2PD(Vo,Qq); - 0x3: WarnUnimpl::movntpd_Mo_Vo(); - 0x4: CVTTPD2PI(Pq,Wo); - 0x5: CVTPD2PI(Pq,Wo); - 0x6: UCOMISD(Vq,Wq); - 0x7: COMISD(Vq,Wq); - } - // repne (0xF2) - 0x8: decode OPCODE_OP_BOTTOM3 { - // The size of the V operand should be q, not dp - 0x2: CVTSI2SD(Vdp,Edp); - // The size of the W operand should be q, not dp - 0x4: CVTTSD2SI(Gdp,Wdp); - 0x5: CVTSD2SI(Gd,Wq); - default: UD2(); - } + default: UD2(); + } + 0x03: decode OPCODE_OP_BOTTOM3 { + //group16(); + 0x0: decode MODRM_REG { + 0x0: WarnUnimpl::prefetch_nta(); + 0x1: PREFETCH_T0(Mb); + 0x2: WarnUnimpl::prefetch_t1(); + 0x3: WarnUnimpl::prefetch_t2(); + default: HINT_NOP(); + } + 0x1: HINT_NOP(); + 0x2: HINT_NOP(); + 0x3: HINT_NOP(); + 0x4: HINT_NOP(); + 0x5: HINT_NOP(); + 0x6: HINT_NOP(); + 0x7: HINT_NOP(); + } + 0x04: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x0: MOV(Rd,Cd); + 0x1: MOV(Rd,Dd); + 0x2: MOV(Cd,Rd); + 0x3: MOV(Dd,Rd); default: UD2(); } + default: UD2(); } - 0x06: decode OPCODE_OP_BOTTOM3 { - 0x0: Inst::WRMSR(); - 0x1: Inst::RDTSC(); - 0x2: Inst::RDMSR(); - 0x3: rdpmc(); - 0x4: decode FullSystemInt { - 0: SyscallInst::sysenter('xc->syscall(Rax)', - IsSyscall, IsNonSpeculative, IsSerializeAfter); - default: sysenter(); + 0x05: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + //These moves should really use size o (octword), but + //because they are split in two, they use q (quadword). + 0x0: MOVAPS(Vq,Wq); + 0x1: MOVAPS(Wq,Vq); + 0x2: CVTPI2PS(Vq,Qq); + 0x3: WarnUnimpl::movntps_Mo_Vo(); + 0x4: CVTTPS2PI(Pq,Wq); + 0x5: CVTPS2PI(Pq,Wq); + 0x6: UCOMISS(Vd,Wd); + 0x7: COMISS(Vd,Wd); + } + // repe (0xF3) + 0x4: decode OPCODE_OP_BOTTOM3 { + 0x2: CVTSI2SS(Vd,Ed); + 0x4: CVTTSS2SI(Gd,Wd); + 0x5: CVTSS2SI(Gd,Wd); + default: UD2(); + } + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x0: MOVAPD(Vo,Wo); + 0x1: MOVAPD(Wo,Vo); + 0x2: CVTPI2PD(Vo,Qq); + 0x3: WarnUnimpl::movntpd_Mo_Vo(); + 0x4: CVTTPD2PI(Pq,Wo); + 0x5: CVTPD2PI(Pq,Wo); + 0x6: UCOMISD(Vq,Wq); + 0x7: COMISD(Vq,Wq); } - 0x5: sysexit(); - 0x6: Inst::UD2(); - 0x7: getsec(); + // repne (0xF2) + 0x8: decode OPCODE_OP_BOTTOM3 { + // The size of the V operand should be q, not dp + 0x2: CVTSI2SD(Vdp,Edp); + // The size of the W operand should be q, not dp + 0x4: CVTTSD2SI(Gdp,Wdp); + 0x5: CVTSD2SI(Gd,Wq); + default: UD2(); + } + default: UD2(); + } + } + 0x06: decode OPCODE_OP_BOTTOM3 { + 0x0: Inst::WRMSR(); + 0x1: Inst::RDTSC(); + 0x2: Inst::RDMSR(); + 0x3: rdpmc(); + 0x4: decode FullSystemInt { + 0: SyscallInst::sysenter('xc->syscall(Rax)', + IsSyscall, IsNonSpeculative, IsSerializeAfter); + default: sysenter(); } - 0x07: decode OPCODE_OP_BOTTOM3 { - 0x0: M5InternalError::error( - {{"Three byte opcode shouldn't be handled by " - "two_byte_opcodes.isa!"}}); - 0x2: M5InternalError::error( - {{"Three byte opcode shouldn't be handled by " - "two_byte_opcodes.isa!"}}); + 0x5: sysexit(); + 0x6: Inst::UD2(); + 0x7: getsec(); + } + 0x07: decode OPCODE_OP_BOTTOM3 { + 0x0: M5InternalError::error( + {{"Three byte opcode shouldn't be handled by " + "two_byte_opcodes.isa!"}}); + 0x2: M5InternalError::error( + {{"Three byte opcode shouldn't be handled by " + "two_byte_opcodes.isa!"}}); + default: UD2(); + } + format Inst { + 0x08: decode OPCODE_OP_BOTTOM3 { + 0x0: CMOVO(Gv,Ev); + 0x1: CMOVNO(Gv,Ev); + 0x2: CMOVB(Gv,Ev); + 0x3: CMOVNB(Gv,Ev); + 0x4: CMOVZ(Gv,Ev); + 0x5: CMOVNZ(Gv,Ev); + 0x6: CMOVBE(Gv,Ev); + 0x7: CMOVNBE(Gv,Ev); + } + 0x09: decode OPCODE_OP_BOTTOM3 { + 0x0: CMOVS(Gv,Ev); + 0x1: CMOVNS(Gv,Ev); + 0x2: CMOVP(Gv,Ev); + 0x3: CMOVNP(Gv,Ev); + 0x4: CMOVL(Gv,Ev); + 0x5: CMOVNL(Gv,Ev); + 0x6: CMOVLE(Gv,Ev); + 0x7: CMOVNLE(Gv,Ev); + } + 0x0A: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x0: MOVMSKPS(Gd,VRo); + 0x1: SQRTPS(Vo,Wo); + 0x2: WarnUnimpl::rqsrtps_Vo_Wo(); + 0x3: WarnUnimpl::rcpps_Vo_Wo(); + 0x4: ANDPS(Vo,Wo); + 0x5: ANDNPS(Vo,Wo); + 0x6: ORPS(Vo,Wo); + 0x7: XORPS(Vo,Wo); + } + // repe (0xF3) + 0x4: decode OPCODE_OP_BOTTOM3 { + 0x1: SQRTSS(Vd,Wd); + 0x2: WarnUnimpl::rsqrtss_Vd_Wd(); + 0x3: WarnUnimpl::rcpss_Vd_Wd(); + default: UD2(); + } + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x0: MOVMSKPD(Gd,VRo); + 0x1: SQRTPD(Vo,Wo); + 0x4: ANDPD(Vo,Wo); + 0x5: ANDNPD(Vo,Wo); + 0x6: ORPD(Vo,Wo); + 0x7: XORPD(Vo,Wo); + default: UD2(); + } + // repne (0xF2) + 0x8: decode OPCODE_OP_BOTTOM3 { + 0x1: SQRTSD(Vq,Wq); + default: UD2(); + } default: UD2(); } - format Inst { - 0x08: decode OPCODE_OP_BOTTOM3 { - 0x0: CMOVO(Gv,Ev); - 0x1: CMOVNO(Gv,Ev); - 0x2: CMOVB(Gv,Ev); - 0x3: CMOVNB(Gv,Ev); - 0x4: CMOVZ(Gv,Ev); - 0x5: CMOVNZ(Gv,Ev); - 0x6: CMOVBE(Gv,Ev); - 0x7: CMOVNBE(Gv,Ev); + 0x0B: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x0: ADDPS(Vo,Wo); + 0x1: MULPS(Vo,Wo); + 0x2: CVTPS2PD(Vo,Wq); + 0x3: CVTDQ2PS(Vo,Wo); + 0x4: SUBPS(Vo,Wo); + 0x5: MINPS(Vo,Wo); + 0x6: DIVPS(Vo,Wo); + 0x7: MAXPS(Vo,Wo); } - 0x09: decode OPCODE_OP_BOTTOM3 { - 0x0: CMOVS(Gv,Ev); - 0x1: CMOVNS(Gv,Ev); - 0x2: CMOVP(Gv,Ev); - 0x3: CMOVNP(Gv,Ev); - 0x4: CMOVL(Gv,Ev); - 0x5: CMOVNL(Gv,Ev); - 0x6: CMOVLE(Gv,Ev); - 0x7: CMOVNLE(Gv,Ev); + // repe (0xF3) + 0x4: decode OPCODE_OP_BOTTOM3 { + 0x0: ADDSS(Vd,Wd); + 0x1: MULSS(Vd,Wd); + 0x2: CVTSS2SD(Vq,Wd); + 0x3: CVTTPS2DQ(Vo,Wo); + 0x4: SUBSS(Vd,Wd); + 0x5: MINSS(Vd,Wd); + 0x6: DIVSS(Vd,Wd); + 0x7: MAXSS(Vd,Wd); } - 0x0A: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x0: MOVMSKPS(Gd,VRo); - 0x1: SQRTPS(Vo,Wo); - 0x2: WarnUnimpl::rqsrtps_Vo_Wo(); - 0x3: WarnUnimpl::rcpps_Vo_Wo(); - 0x4: ANDPS(Vo,Wo); - 0x5: ANDNPS(Vo,Wo); - 0x6: ORPS(Vo,Wo); - 0x7: XORPS(Vo,Wo); - } - // repe (0xF3) - 0x4: decode OPCODE_OP_BOTTOM3 { - 0x1: SQRTSS(Vd,Wd); - 0x2: WarnUnimpl::rsqrtss_Vd_Wd(); - 0x3: WarnUnimpl::rcpss_Vd_Wd(); - default: UD2(); - } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x0: MOVMSKPD(Gd,VRo); - 0x1: SQRTPD(Vo,Wo); - 0x4: ANDPD(Vo,Wo); - 0x5: ANDNPD(Vo,Wo); - 0x6: ORPD(Vo,Wo); - 0x7: XORPD(Vo,Wo); - default: UD2(); - } - // repne (0xF2) - 0x8: decode OPCODE_OP_BOTTOM3 { - 0x1: SQRTSD(Vq,Wq); - default: UD2(); - } + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x0: ADDPD(Vo,Wo); + 0x1: MULPD(Vo,Wo); + 0x2: CVTPD2PS(Vo,Wo); + 0x3: CVTPS2DQ(Vo,Wo); + 0x4: SUBPD(Vo,Wo); + 0x5: MINPD(Vo,Wo); + 0x6: DIVPD(Vo,Wo); + 0x7: MAXPD(Vo,Wo); + } + // repne (0xF2) + 0x8: decode OPCODE_OP_BOTTOM3 { + 0x0: ADDSD(Vq,Wq); + 0x1: MULSD(Vq,Wq); + 0x2: CVTSD2SS(Vd,Wq); + 0x4: SUBSD(Vq,Wq); + 0x5: MINSD(Vq,Wq); + 0x6: DIVSD(Vq,Wq); + 0x7: MAXSD(Vq,Wq); default: UD2(); } - 0x0B: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x0: ADDPS(Vo,Wo); - 0x1: MULPS(Vo,Wo); - 0x2: CVTPS2PD(Vo,Wq); - 0x3: CVTDQ2PS(Vo,Wo); - 0x4: SUBPS(Vo,Wo); - 0x5: MINPS(Vo,Wo); - 0x6: DIVPS(Vo,Wo); - 0x7: MAXPS(Vo,Wo); - } - // repe (0xF3) - 0x4: decode OPCODE_OP_BOTTOM3 { - 0x0: ADDSS(Vd,Wd); - 0x1: MULSS(Vd,Wd); - 0x2: CVTSS2SD(Vq,Wd); - 0x3: CVTTPS2DQ(Vo,Wo); - 0x4: SUBSS(Vd,Wd); - 0x5: MINSS(Vd,Wd); - 0x6: DIVSS(Vd,Wd); - 0x7: MAXSS(Vd,Wd); - } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x0: ADDPD(Vo,Wo); - 0x1: MULPD(Vo,Wo); - 0x2: CVTPD2PS(Vo,Wo); - 0x3: CVTPS2DQ(Vo,Wo); - 0x4: SUBPD(Vo,Wo); - 0x5: MINPD(Vo,Wo); - 0x6: DIVPD(Vo,Wo); - 0x7: MAXPD(Vo,Wo); - } - // repne (0xF2) - 0x8: decode OPCODE_OP_BOTTOM3 { - 0x0: ADDSD(Vq,Wq); - 0x1: MULSD(Vq,Wq); - 0x2: CVTSD2SS(Vd,Wq); - 0x4: SUBSD(Vq,Wq); - 0x5: MINSD(Vq,Wq); - 0x6: DIVSD(Vq,Wq); - 0x7: MAXSD(Vq,Wq); - default: UD2(); - } + default: UD2(); + } + 0x0C: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x0: PUNPCKLBW(Pq,Qd); + 0x1: PUNPCKLWD(Pq,Qd); + 0x2: PUNPCKLDQ(Pq,Qd); + 0x3: PACKSSWB(Pq,Qq); + 0x4: PCMPGTB(Pq,Qq); + 0x5: PCMPGTW(Pq,Qq); + 0x6: PCMPGTD(Pq,Qq); + 0x7: PACKUSWB(Pq,Qq); + } + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x0: PUNPCKLBW(Vo,Wq); + 0x1: PUNPCKLWD(Vo,Wq); + 0x2: PUNPCKLDQ(Vo,Wq); + 0x3: PACKSSWB(Vo,Wo); + 0x4: PCMPGTB(Vo,Wo); + 0x5: PCMPGTW(Vo,Wo); + 0x6: PCMPGTD(Vo,Wo); + 0x7: PACKUSWB(Vo,Wo); + } + default: UD2(); + } + 0x0D: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x0: PUNPCKHBW(Pq,Qq); + 0x1: PUNPCKHWD(Pq,Qq); + 0x2: PUNPCKHDQ(Pq,Qq); + 0x3: PACKSSDW(Pq,Qq); + 0x6: MOVD(Pq,Edp); + 0x7: MOVQ(Pq,Qq); default: UD2(); } - 0x0C: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x0: PUNPCKLBW(Pq,Qd); - 0x1: PUNPCKLWD(Pq,Qd); - 0x2: PUNPCKLDQ(Pq,Qd); - 0x3: PACKSSWB(Pq,Qq); - 0x4: PCMPGTB(Pq,Qq); - 0x5: PCMPGTW(Pq,Qq); - 0x6: PCMPGTD(Pq,Qq); - 0x7: PACKUSWB(Pq,Qq); - } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x0: PUNPCKLBW(Vo,Wq); - 0x1: PUNPCKLWD(Vo,Wq); - 0x2: PUNPCKLDQ(Vo,Wq); - 0x3: PACKSSWB(Vo,Wo); - 0x4: PCMPGTB(Vo,Wo); - 0x5: PCMPGTW(Vo,Wo); - 0x6: PCMPGTD(Vo,Wo); - 0x7: PACKUSWB(Vo,Wo); - } + // repe (0xF3) + 0x4: decode OPCODE_OP_BOTTOM3 { + 0x7: MOVDQU(Vo,Wo); default: UD2(); } - 0x0D: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x0: PUNPCKHBW(Pq,Qq); - 0x1: PUNPCKHWD(Pq,Qq); - 0x2: PUNPCKHDQ(Pq,Qq); - 0x3: PACKSSDW(Pq,Qq); - 0x6: MOVD(Pq,Edp); - 0x7: MOVQ(Pq,Qq); + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x0: PUNPCKHBW(Vo,Wo); + 0x1: PUNPCKHWD(Vo,Wo); + 0x2: PUNPCKHDQ(Vo,Wo); + 0x3: PACKSSDW(Vo,Wo); + 0x4: PUNPCKLQDQ(Vo,Wq); + 0x5: PUNPCKHQDQ(Vo,Wq); + 0x6: MOVD(Vo,Edp); + 0x7: MOVDQA(Vo,Wo); + } + default: UD2(); + } + 0x0E: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x0: PSHUFW(Pq,Qq,Ib); + //0x1: group12_pshimw(); + 0x1: decode MODRM_REG { + 0x2: PSRLW(PRq,Ib); + 0x4: PSRAW(PRq,Ib); + 0x6: PSLLW(PRq,Ib); default: UD2(); } - // repe (0xF3) - 0x4: decode OPCODE_OP_BOTTOM3 { - 0x7: MOVDQU(Vo,Wo); + //0x2: group13_pshimd(); + 0x2: decode MODRM_REG { + 0x2: PSRLD(PRq,Ib); + 0x4: PSRAD(PRq,Ib); + 0x6: PSLLD(PRq,Ib); default: UD2(); } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x0: PUNPCKHBW(Vo,Wo); - 0x1: PUNPCKHWD(Vo,Wo); - 0x2: PUNPCKHDQ(Vo,Wo); - 0x3: PACKSSDW(Vo,Wo); - 0x4: PUNPCKLQDQ(Vo,Wq); - 0x5: PUNPCKHQDQ(Vo,Wq); - 0x6: MOVD(Vo,Edp); - 0x7: MOVDQA(Vo,Wo); + //0x3: group14_pshimq(); + 0x3: decode MODRM_REG { + 0x2: PSRLQ(PRq,Ib); + 0x6: PSLLQ(PRq,Ib); + default: Inst::UD2(); } + 0x4: Inst::PCMPEQB(Pq,Qq); + 0x5: Inst::PCMPEQW(Pq,Qq); + 0x6: Inst::PCMPEQD(Pq,Qq); + 0x7: Inst::EMMS(); + } + // repe (0xF3) + 0x4: decode OPCODE_OP_BOTTOM3 { + 0x0: PSHUFHW(Vo,Wo,Ib); default: UD2(); } - 0x0E: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x0: PSHUFW(Pq,Qq,Ib); - //0x1: group12_pshimw(); - 0x1: decode MODRM_REG { - 0x2: PSRLW(PRq,Ib); - 0x4: PSRAW(PRq,Ib); - 0x6: PSLLW(PRq,Ib); - default: UD2(); - } - //0x2: group13_pshimd(); - 0x2: decode MODRM_REG { - 0x2: PSRLD(PRq,Ib); - 0x4: PSRAD(PRq,Ib); - 0x6: PSLLD(PRq,Ib); - default: UD2(); - } - //0x3: group14_pshimq(); - 0x3: decode MODRM_REG { - 0x2: PSRLQ(PRq,Ib); - 0x6: PSLLQ(PRq,Ib); - default: Inst::UD2(); - } - 0x4: Inst::PCMPEQB(Pq,Qq); - 0x5: Inst::PCMPEQW(Pq,Qq); - 0x6: Inst::PCMPEQD(Pq,Qq); - 0x7: Inst::EMMS(); - } - // repe (0xF3) - 0x4: decode OPCODE_OP_BOTTOM3 { - 0x0: PSHUFHW(Vo,Wo,Ib); - default: UD2(); - } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x0: PSHUFD(Vo,Wo,Ib); - //0x1: group12_pshimw(); - 0x1: decode MODRM_REG { - 0x2: PSRLW(VRo,Ib); - 0x4: PSRAW(VRo,Ib); - 0x6: PSLLW(VRo,Ib); - } - //0x2: group13_pshimd(); - 0x2: decode MODRM_REG { - 0x2: PSRLD(VRo,Ib); - 0x4: PSRAD(VRo,Ib); - 0x6: PSLLD(VRo,Ib); - default: UD2(); - } - //0x3: group14_pshimq(); - 0x3: decode MODRM_REG { - 0x2: PSRLQ(VRo,Ib); - 0x3: PSRLDQ(VRo,Ib); - 0x6: PSLLQ(VRo,Ib); - 0x7: PSLLDQ(VRo,Ib); - default: UD2(); - } - 0x4: PCMPEQB(Vo,Wo); - 0x5: PCMPEQW(Vo,Wo); - 0x6: PCMPEQD(Vo,Wo); + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x0: PSHUFD(Vo,Wo,Ib); + //0x1: group12_pshimw(); + 0x1: decode MODRM_REG { + 0x2: PSRLW(VRo,Ib); + 0x4: PSRAW(VRo,Ib); + 0x6: PSLLW(VRo,Ib); + } + //0x2: group13_pshimd(); + 0x2: decode MODRM_REG { + 0x2: PSRLD(VRo,Ib); + 0x4: PSRAD(VRo,Ib); + 0x6: PSLLD(VRo,Ib); default: UD2(); } - // repne (0xF2) - 0x8: decode OPCODE_OP_BOTTOM3 { - 0x0: PSHUFLW(Vo,Wo,Ib); + //0x3: group14_pshimq(); + 0x3: decode MODRM_REG { + 0x2: PSRLQ(VRo,Ib); + 0x3: PSRLDQ(VRo,Ib); + 0x6: PSLLQ(VRo,Ib); + 0x7: PSLLDQ(VRo,Ib); default: UD2(); } + 0x4: PCMPEQB(Vo,Wo); + 0x5: PCMPEQW(Vo,Wo); + 0x6: PCMPEQD(Vo,Wo); default: UD2(); } - 0x0F: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x0: WarnUnimpl::vmread_Edp_Gdp(); - 0x1: WarnUnimpl::vmwrite_Gdp_Edp(); - 0x6: MOVD(Edp,Pdp); - 0x7: MOVQ(Qq,Pq); - default: UD2(); - } - // repe (0xF3) - 0x4: decode OPCODE_OP_BOTTOM3 { - 0x6: MOVQ(Vq,Wq); - 0x7: MOVDQU(Wo,Vo); - default: UD2(); - } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x4: HADDPD(Vo,Wo); - 0x5: WarnUnimpl::hsubpd_Vo_Wo(); - 0x6: MOVD(Edp,Vd); - 0x7: MOVDQA(Wo,Vo); - default: UD2(); - } - // repne (0xF2) - 0x8: decode OPCODE_OP_BOTTOM3 { - 0x4: HADDPS(Vo,Wo); - 0x5: WarnUnimpl::hsubps_Vo_Wo(); - default: UD2(); - } + // repne (0xF2) + 0x8: decode OPCODE_OP_BOTTOM3 { + 0x0: PSHUFLW(Vo,Wo,Ib); default: UD2(); } - 0x10: decode OPCODE_OP_BOTTOM3 { - 0x0: JO(Jz); - 0x1: JNO(Jz); - 0x2: JB(Jz); - 0x3: JNB(Jz); - 0x4: JZ(Jz); - 0x5: JNZ(Jz); - 0x6: JBE(Jz); - 0x7: JNBE(Jz); + default: UD2(); + } + 0x0F: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x0: WarnUnimpl::vmread_Edp_Gdp(); + 0x1: WarnUnimpl::vmwrite_Gdp_Edp(); + 0x6: MOVD(Edp,Pdp); + 0x7: MOVQ(Qq,Pq); + default: UD2(); } - 0x11: decode OPCODE_OP_BOTTOM3 { - 0x0: JS(Jz); - 0x1: JNS(Jz); - 0x2: JP(Jz); - 0x3: JNP(Jz); - 0x4: JL(Jz); - 0x5: JNL(Jz); - 0x6: JLE(Jz); - 0x7: JNLE(Jz); + // repe (0xF3) + 0x4: decode OPCODE_OP_BOTTOM3 { + 0x6: MOVQ(Vq,Wq); + 0x7: MOVDQU(Wo,Vo); + default: UD2(); } - 0x12: decode OPCODE_OP_BOTTOM3 { - 0x0: SETO(Eb); - 0x1: SETNO(Eb); - 0x2: SETB(Eb); - 0x3: SETNB(Eb); - 0x4: SETZ(Eb); - 0x5: SETNZ(Eb); - 0x6: SETBE(Eb); - 0x7: SETNBE(Eb); + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x4: HADDPD(Vo,Wo); + 0x5: WarnUnimpl::hsubpd_Vo_Wo(); + 0x6: MOVD(Edp,Vd); + 0x7: MOVDQA(Wo,Vo); + default: UD2(); } - 0x13: decode OPCODE_OP_BOTTOM3 { - 0x0: SETS(Eb); - 0x1: SETNS(Eb); - 0x2: SETP(Eb); - 0x3: SETNP(Eb); - 0x4: SETL(Eb); - 0x5: SETNL(Eb); - 0x6: SETLE(Eb); - 0x7: SETNLE(Eb); + // repne (0xF2) + 0x8: decode OPCODE_OP_BOTTOM3 { + 0x4: HADDPS(Vo,Wo); + 0x5: WarnUnimpl::hsubps_Vo_Wo(); + default: UD2(); } + default: UD2(); } - 0x14: decode OPCODE_OP_BOTTOM3 { - 0x0: push_fs(); - 0x1: pop_fs(); - 0x2: CPUIDInst::CPUID({{ - CpuidResult result; - bool success = doCpuid(xc->tcBase(), bits(Rax, 31, 0), - bits(Rcx, 31, 0), result); - if (success) { - Rax = result.rax; - Rbx = result.rbx; - Rcx = result.rcx; - Rdx = result.rdx; - } else { - Rax = Rax; - Rbx = Rbx; - Rcx = Rcx; - Rdx = Rdx; - } - }}); - 0x3: Inst::BT(Ev,Gv); - 0x4: Inst::SHLD(Ev,Gv,Ib); - 0x5: Inst::SHLD(Ev,Gv); - default: Inst::UD2(); + 0x10: decode OPCODE_OP_BOTTOM3 { + 0x0: JO(Jz); + 0x1: JNO(Jz); + 0x2: JB(Jz); + 0x3: JNB(Jz); + 0x4: JZ(Jz); + 0x5: JNZ(Jz); + 0x6: JBE(Jz); + 0x7: JNBE(Jz); } - 0x15: decode OPCODE_OP_BOTTOM3 { - 0x0: push_gs(); - 0x1: pop_gs(); - 0x2: rsm_smm(); - 0x3: Inst::BTS(Ev,Gv); - 0x4: Inst::SHRD(Ev,Gv,Ib); - 0x5: Inst::SHRD(Ev,Gv); - //0x6: group15(); - 0x6: decode MODRM_MOD { - 0x3: decode MODRM_REG { - 0x5: BasicOperate::LFENCE( - {{/*Nothing*/}}, IsReadBarrier); - 0x6: BasicOperate::MFENCE( - {{/*Nothing*/}}, IsMemBarrier); - 0x7: BasicOperate::SFENCE( - {{/*Nothing*/}}, IsWriteBarrier); - default: Inst::UD2(); - } - default: decode MODRM_REG { - 0x0: decode OPSIZE { - 4: Inst::FXSAVE(M); - 8: Inst::FXSAVE64(M); - default: fxsave(); - } - 0x1: decode OPSIZE { - 4: Inst::FXRSTOR(M); - 8: Inst::FXRSTOR64(M); - default: fxrstor(); - } - 0x2: Inst::LDMXCSR(Md); - 0x3: Inst::STMXCSR(Md); - 0x4: xsave(); - 0x5: xrstor(); - 0x6: Inst::UD2(); - 0x7: clflush(); - } + 0x11: decode OPCODE_OP_BOTTOM3 { + 0x0: JS(Jz); + 0x1: JNS(Jz); + 0x2: JP(Jz); + 0x3: JNP(Jz); + 0x4: JL(Jz); + 0x5: JNL(Jz); + 0x6: JLE(Jz); + 0x7: JNLE(Jz); + } + 0x12: decode OPCODE_OP_BOTTOM3 { + 0x0: SETO(Eb); + 0x1: SETNO(Eb); + 0x2: SETB(Eb); + 0x3: SETNB(Eb); + 0x4: SETZ(Eb); + 0x5: SETNZ(Eb); + 0x6: SETBE(Eb); + 0x7: SETNBE(Eb); + } + 0x13: decode OPCODE_OP_BOTTOM3 { + 0x0: SETS(Eb); + 0x1: SETNS(Eb); + 0x2: SETP(Eb); + 0x3: SETNP(Eb); + 0x4: SETL(Eb); + 0x5: SETNL(Eb); + 0x6: SETLE(Eb); + 0x7: SETNLE(Eb); + } + } + 0x14: decode OPCODE_OP_BOTTOM3 { + 0x0: push_fs(); + 0x1: pop_fs(); + 0x2: CPUIDInst::CPUID({{ + CpuidResult result; + bool success = doCpuid(xc->tcBase(), bits(Rax, 31, 0), + bits(Rcx, 31, 0), result); + if (success) { + Rax = result.rax; + Rbx = result.rbx; + Rcx = result.rcx; + Rdx = result.rdx; + } else { + Rax = Rax; + Rbx = Rbx; + Rcx = Rcx; + Rdx = Rdx; + } + }}); + 0x3: Inst::BT(Ev,Gv); + 0x4: Inst::SHLD(Ev,Gv,Ib); + 0x5: Inst::SHLD(Ev,Gv); + default: Inst::UD2(); + } + 0x15: decode OPCODE_OP_BOTTOM3 { + 0x0: push_gs(); + 0x1: pop_gs(); + 0x2: rsm_smm(); + 0x3: Inst::BTS(Ev,Gv); + 0x4: Inst::SHRD(Ev,Gv,Ib); + 0x5: Inst::SHRD(Ev,Gv); + //0x6: group15(); + 0x6: decode MODRM_MOD { + 0x3: decode MODRM_REG { + 0x5: BasicOperate::LFENCE( + {{/*Nothing*/}}, IsReadBarrier); + 0x6: BasicOperate::MFENCE( + {{/*Nothing*/}}, IsMemBarrier); + 0x7: BasicOperate::SFENCE( + {{/*Nothing*/}}, IsWriteBarrier); + default: Inst::UD2(); + } + default: decode MODRM_REG { + 0x0: decode OPSIZE { + 4: Inst::FXSAVE(M); + 8: Inst::FXSAVE64(M); + default: fxsave(); + } + 0x1: decode OPSIZE { + 4: Inst::FXRSTOR(M); + 8: Inst::FXRSTOR64(M); + default: fxrstor(); + } + 0x2: Inst::LDMXCSR(Md); + 0x3: Inst::STMXCSR(Md); + 0x4: xsave(); + 0x5: xrstor(); + 0x6: Inst::UD2(); + 0x7: clflush(); } - 0x7: Inst::IMUL(Gv,Ev); } - format Inst { - 0x16: decode OPCODE_OP_BOTTOM3 { - 0x0: CMPXCHG(Eb,Gb); - 0x1: CMPXCHG(Ev,Gv); - 0x2: WarnUnimpl::lss_Gz_Mp(); - 0x3: BTR(Ev,Gv); - 0x4: WarnUnimpl::lfs_Gz_Mp(); - 0x5: WarnUnimpl::lgs_Gz_Mp(); - //The size of the second operand in these instructions - //should really be "b" or "w", but it's set to v in order - //to have a consistent register size. This shouldn't - //affect behavior. - 0x6: MOVZX_B(Gv,Ev); - 0x7: MOVZX_W(Gv,Ev); + 0x7: Inst::IMUL(Gv,Ev); + } + format Inst { + 0x16: decode OPCODE_OP_BOTTOM3 { + 0x0: CMPXCHG(Eb,Gb); + 0x1: CMPXCHG(Ev,Gv); + 0x2: WarnUnimpl::lss_Gz_Mp(); + 0x3: BTR(Ev,Gv); + 0x4: WarnUnimpl::lfs_Gz_Mp(); + 0x5: WarnUnimpl::lgs_Gz_Mp(); + //The size of the second operand in these instructions + //should really be "b" or "w", but it's set to v in order + //to have a consistent register size. This shouldn't + //affect behavior. + 0x6: MOVZX_B(Gv,Ev); + 0x7: MOVZX_W(Gv,Ev); + } + 0x17: decode OPCODE_OP_BOTTOM3 { + 0x0: decode LEGACY_REP { + 0x0: WarnUnimpl::jmpe_Jz(); + 0x1: WarnUnimpl::popcnt_Gv_Ev(); } - 0x17: decode OPCODE_OP_BOTTOM3 { - 0x0: decode LEGACY_REP { - 0x0: WarnUnimpl::jmpe_Jz(); - 0x1: WarnUnimpl::popcnt_Gv_Ev(); - } - //0x1: group10_UD2(); - 0x1: UD2(); - //0x2: group8_Ev_Ib(); - 0x2: decode MODRM_REG { - 0x4: BT(Ev,Ib); - 0x5: BTS(Ev,Ib); - 0x6: BTR(Ev,Ib); - 0x7: BTC(Ev,Ib); - default: UD2(); - } - 0x3: BTC(Ev,Gv); - 0x4: BSF(Gv,Ev); - 0x5: BSR(Gv,Ev); - //The size of the second operand in these instructions - //should really be "b" or "w", but it's set to v in order - //to have a consistent register size. This shouldn't - //affect behavior. - 0x6: MOVSX_B(Gv,Ev); - 0x7: MOVSX_W(Gv,Ev); + //0x1: group10_UD2(); + 0x1: UD2(); + //0x2: group8_Ev_Ib(); + 0x2: decode MODRM_REG { + 0x4: BT(Ev,Ib); + 0x5: BTS(Ev,Ib); + 0x6: BTR(Ev,Ib); + 0x7: BTC(Ev,Ib); + default: UD2(); } - 0x18: decode OPCODE_OP_BOTTOM3 { - 0x0: XADD(Eb,Gb); - 0x1: XADD(Ev,Gv); - //0x7: group9(); - 0x7: decode MODRM_REG { - //Also CMPXCHG16B - 0x1: CMPXCHG8B(Mdp); - 0x6: decode LEGACY_OP { - 0x1: WarnUnimpl::vmclear_Mq(); - default: decode LEGACY_REP { - 0x1: WarnUnimpl::vmxon_Mq(); - 0x0: WarnUnimpl::vmptrld_Mq(); - } - } - 0x7: WarnUnimpl::vmptrst_Mq(); - default: UD2(); - } - default: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x2: CMPPS(Vo,Wo,Ib); - 0x3: MOVNTI(Mdp,Gdp); - 0x4: PINSRW(Pq,Ew,Ib); - 0x5: PEXTRW(Gd,PRq,Ib); - 0x6: SHUFPS(Vps,Wps,Ib); - } - // repe (0xF3) - 0x4: decode OPCODE_OP_BOTTOM3 { - 0x2: CMPSS(Vd,Wd,Ib); - default: UD2(); - } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x2: CMPPD(Vo,Wo,Ib); - 0x4: PINSRW(Vdw,Ew,Ib); - 0x5: PEXTRW(Gd,VRdq,Ib); - 0x6: SHUFPD(Vpd,Wpd,Ib); - default: UD2(); - } - // repne (0xF2) - 0x8: decode OPCODE_OP_BOTTOM3 { - 0x2: CMPSD(Vq,Wq,Ib); - default: UD2(); + 0x3: BTC(Ev,Gv); + 0x4: BSF(Gv,Ev); + 0x5: BSR(Gv,Ev); + //The size of the second operand in these instructions + //should really be "b" or "w", but it's set to v in order + //to have a consistent register size. This shouldn't + //affect behavior. + 0x6: MOVSX_B(Gv,Ev); + 0x7: MOVSX_W(Gv,Ev); + } + 0x18: decode OPCODE_OP_BOTTOM3 { + 0x0: XADD(Eb,Gb); + 0x1: XADD(Ev,Gv); + //0x7: group9(); + 0x7: decode MODRM_REG { + //Also CMPXCHG16B + 0x1: CMPXCHG8B(Mdp); + 0x6: decode LEGACY_OP { + 0x1: WarnUnimpl::vmclear_Mq(); + default: decode LEGACY_REP { + 0x1: WarnUnimpl::vmxon_Mq(); + 0x0: WarnUnimpl::vmptrld_Mq(); } - default: UD2(); } - } - 0x19: decode OPSIZE { - 4: BSWAP_D(Bd); - 8: BSWAP_Q(Bq); + 0x7: WarnUnimpl::vmptrst_Mq(); default: UD2(); } - 0x1A: decode LEGACY_DECODEVAL { + default: decode LEGACY_DECODEVAL { // no prefix 0x0: decode OPCODE_OP_BOTTOM3 { - 0x1: PSRLW(Pq,Qq); - 0x2: PSRLD(Pq,Qq); - 0x3: PSRLQ(Pq,Qq); - 0x4: PADDQ(Pq,Qq); - 0x5: PMULLW(Pq,Qq); - 0x7: PMOVMSKB(Gd,PRq); - default: UD2(); + 0x2: CMPPS(Vo,Wo,Ib); + 0x3: MOVNTI(Mdp,Gdp); + 0x4: PINSRW(Pq,Ew,Ib); + 0x5: PEXTRW(Gd,PRq,Ib); + 0x6: SHUFPS(Vps,Wps,Ib); } // repe (0xF3) 0x4: decode OPCODE_OP_BOTTOM3 { - 0x6: MOVQ2DQ(Vo,PRq); + 0x2: CMPSS(Vd,Wd,Ib); default: UD2(); } // operand size (0x66) 0x1: decode OPCODE_OP_BOTTOM3 { - 0x0: WarnUnimpl::addsubpd_Vo_Wo(); - 0x1: PSRLW(Vo,Wo); - 0x2: PSRLD(Vo,Wo); - 0x3: PSRLQ(Vo,Wo); - 0x4: PADDQ(Vo,Wo); - 0x5: PMULLW(Vo,Wo); - 0x6: MOVQ(Wq,Vq); - 0x7: PMOVMSKB(Gd,VRo); + 0x2: CMPPD(Vo,Wo,Ib); + 0x4: PINSRW(Vdw,Ew,Ib); + 0x5: PEXTRW(Gd,VRdq,Ib); + 0x6: SHUFPD(Vpd,Wpd,Ib); + default: UD2(); } // repne (0xF2) 0x8: decode OPCODE_OP_BOTTOM3 { - 0x0: WarnUnimpl::addsubps_Vo_Wo(); - 0x6: MOVDQ2Q(Pq,VRq); + 0x2: CMPSD(Vq,Wq,Ib); default: UD2(); } default: UD2(); } - 0x1B: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x0: PSUBUSB(Pq,Qq); - 0x1: PSUBUSW(Pq,Qq); - 0x2: PMINUB(Pq,Qq); - 0x3: PAND(Pq,Qq); - 0x4: PADDUSB(Pq,Qq); - 0x5: PADDUSW(Pq,Qq); - 0x6: PMAXUB(Pq,Qq); - 0x7: PANDN(Pq,Qq); - } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x0: PSUBUSB(Vo,Wo); - 0x1: PSUBUSW(Vo,Wo); - 0x2: PMINUB(Vo,Wo); - 0x3: PAND(Vo,Wo); - 0x4: PADDUSB(Vo,Wo); - 0x5: PADDUSW(Vo,Wo); - 0x6: PMAXUB(Vo,Wo); - 0x7: PANDN(Vo,Wo); - } + } + 0x19: decode OPSIZE { + 4: BSWAP_D(Bd); + 8: BSWAP_Q(Bq); + default: UD2(); + } + 0x1A: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x1: PSRLW(Pq,Qq); + 0x2: PSRLD(Pq,Qq); + 0x3: PSRLQ(Pq,Qq); + 0x4: PADDQ(Pq,Qq); + 0x5: PMULLW(Pq,Qq); + 0x7: PMOVMSKB(Gd,PRq); default: UD2(); } - 0x1C: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x0: PAVGB(Pq,Qq); - 0x1: PSRAW(Pq,Qq); - 0x2: PSRAD(Pq,Qq); - 0x3: PAVGW(Pq,Qq); - 0x4: PMULHUW(Pq,Qq); - 0x5: PMULHW(Pq,Qq); - 0x7: WarnUnimpl::movntq_Mq_Pq(); - default: UD2(); - } - // repe (0xF3) - 0x4: decode OPCODE_OP_BOTTOM3 { - 0x6: CVTDQ2PD(Vo,Wq); - default: UD2(); - } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x0: PAVGB(Vo,Wo); - 0x1: PSRAW(Vo,Wo); - 0x2: PSRAD(Vo,Wo); - 0x3: PAVGW(Vo,Wo); - 0x4: PMULHUW(Vo,Wo); - 0x5: PMULHW(Vo,Wo); - 0x6: CVTTPD2DQ(Vo,Wo); - 0x7: WarnUnimpl::movntdq_Mo_Vo(); - } - // repne (0xF2) - 0x8: decode OPCODE_OP_BOTTOM3 { - 0x6: CVTPD2DQ(Vo,Wo); - default: UD2(); - } + // repe (0xF3) + 0x4: decode OPCODE_OP_BOTTOM3 { + 0x6: MOVQ2DQ(Vo,PRq); default: UD2(); } - 0x1D: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x0: PSUBSB(Pq,Qq); - 0x1: PSUBSW(Pq,Qq); - 0x2: PMINSW(Pq,Qq); - 0x3: POR(Pq,Qq); - 0x4: PADDSB(Pq,Qq); - 0x5: PADDSW(Pq,Qq); - 0x6: PMAXSW(Pq,Qq); - 0x7: PXOR(Pq,Qq); - } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x0: PSUBSB(Vo,Wo); - 0x1: PSUBSW(Vo,Wo); - 0x2: PMINSW(Vo,Wo); - 0x3: POR(Vo,Wo); - 0x4: PADDSB(Vo,Wo); - 0x5: PADDSW(Vo,Wo); - 0x6: PMAXSW(Vo,Wo); - 0x7: PXOR(Vo,Wo); - } + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x0: WarnUnimpl::addsubpd_Vo_Wo(); + 0x1: PSRLW(Vo,Wo); + 0x2: PSRLD(Vo,Wo); + 0x3: PSRLQ(Vo,Wo); + 0x4: PADDQ(Vo,Wo); + 0x5: PMULLW(Vo,Wo); + 0x6: MOVQ(Wq,Vq); + 0x7: PMOVMSKB(Gd,VRo); + } + // repne (0xF2) + 0x8: decode OPCODE_OP_BOTTOM3 { + 0x0: WarnUnimpl::addsubps_Vo_Wo(); + 0x6: MOVDQ2Q(Pq,VRq); default: UD2(); } - 0x1E: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x1: PSLLW(Pq,Qq); - 0x2: PSLLD(Pq,Qq); - 0x3: PSLLQ(Pq,Qq); - 0x4: PMULUDQ(Pq,Qq); - 0x5: PMADDWD(Pq,Qq); - 0x6: PSADBW(Pq,Qq); - 0x7: MASKMOVQ(Pq,PRq); - default: UD2(); - } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x1: PSLLW(Vo,Wo); - 0x2: PSLLD(Vo,Wo); - 0x3: PSLLQ(Vo,Wo); - 0x4: PMULUDQ(Vo,Wo); - 0x5: PMADDWD(Vo,Wo); - 0x6: PSADBW(Vo,Wo); - 0x7: MASKMOVDQU(Vo,VRo); - default: UD2(); - } - // repne (0xF2) - 0x8: decode OPCODE_OP_BOTTOM3 { - 0x0: WarnUnimpl::lddqu_Vo_Mo(); - default: UD2(); - } + default: UD2(); + } + 0x1B: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x0: PSUBUSB(Pq,Qq); + 0x1: PSUBUSW(Pq,Qq); + 0x2: PMINUB(Pq,Qq); + 0x3: PAND(Pq,Qq); + 0x4: PADDUSB(Pq,Qq); + 0x5: PADDUSW(Pq,Qq); + 0x6: PMAXUB(Pq,Qq); + 0x7: PANDN(Pq,Qq); + } + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x0: PSUBUSB(Vo,Wo); + 0x1: PSUBUSW(Vo,Wo); + 0x2: PMINUB(Vo,Wo); + 0x3: PAND(Vo,Wo); + 0x4: PADDUSB(Vo,Wo); + 0x5: PADDUSW(Vo,Wo); + 0x6: PMAXUB(Vo,Wo); + 0x7: PANDN(Vo,Wo); + } + default: UD2(); + } + 0x1C: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x0: PAVGB(Pq,Qq); + 0x1: PSRAW(Pq,Qq); + 0x2: PSRAD(Pq,Qq); + 0x3: PAVGW(Pq,Qq); + 0x4: PMULHUW(Pq,Qq); + 0x5: PMULHW(Pq,Qq); + 0x7: WarnUnimpl::movntq_Mq_Pq(); default: UD2(); } - 0x1F: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x0: PSUBB(Pq,Qq); - 0x1: PSUBW(Pq,Qq); - 0x2: PSUBD(Pq,Qq); - 0x3: PSUBQ(Pq,Qq); - 0x4: PADDB(Pq,Qq); - 0x5: PADDW(Pq,Qq); - 0x6: PADDD(Pq,Qq); - 0x7: UD2(); - } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x0: PSUBB(Vo,Wo); - 0x1: PSUBW(Vo,Wo); - 0x2: PSUBD(Vo,Wo); - 0x3: PSUBQ(Vo,Wo); - 0x4: PADDB(Vo,Wo); - 0x5: PADDW(Vo,Wo); - 0x6: PADDD(Vo,Wo); - 0x7: UD2(); - } + // repe (0xF3) + 0x4: decode OPCODE_OP_BOTTOM3 { + 0x6: CVTDQ2PD(Vo,Wq); default: UD2(); } + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x0: PAVGB(Vo,Wo); + 0x1: PSRAW(Vo,Wo); + 0x2: PSRAD(Vo,Wo); + 0x3: PAVGW(Vo,Wo); + 0x4: PMULHUW(Vo,Wo); + 0x5: PMULHW(Vo,Wo); + 0x6: CVTTPD2DQ(Vo,Wo); + 0x7: WarnUnimpl::movntdq_Mo_Vo(); + } + // repne (0xF2) + 0x8: decode OPCODE_OP_BOTTOM3 { + 0x6: CVTPD2DQ(Vo,Wo); + default: UD2(); + } + default: UD2(); + } + 0x1D: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x0: PSUBSB(Pq,Qq); + 0x1: PSUBSW(Pq,Qq); + 0x2: PMINSW(Pq,Qq); + 0x3: POR(Pq,Qq); + 0x4: PADDSB(Pq,Qq); + 0x5: PADDSW(Pq,Qq); + 0x6: PMAXSW(Pq,Qq); + 0x7: PXOR(Pq,Qq); + } + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x0: PSUBSB(Vo,Wo); + 0x1: PSUBSW(Vo,Wo); + 0x2: PMINSW(Vo,Wo); + 0x3: POR(Vo,Wo); + 0x4: PADDSB(Vo,Wo); + 0x5: PADDSW(Vo,Wo); + 0x6: PMAXSW(Vo,Wo); + 0x7: PXOR(Vo,Wo); + } + default: UD2(); + } + 0x1E: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x1: PSLLW(Pq,Qq); + 0x2: PSLLD(Pq,Qq); + 0x3: PSLLQ(Pq,Qq); + 0x4: PMULUDQ(Pq,Qq); + 0x5: PMADDWD(Pq,Qq); + 0x6: PSADBW(Pq,Qq); + 0x7: MASKMOVQ(Pq,PRq); + default: UD2(); + } + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x1: PSLLW(Vo,Wo); + 0x2: PSLLD(Vo,Wo); + 0x3: PSLLQ(Vo,Wo); + 0x4: PMULUDQ(Vo,Wo); + 0x5: PMADDWD(Vo,Wo); + 0x6: PSADBW(Vo,Wo); + 0x7: MASKMOVDQU(Vo,VRo); + default: UD2(); + } + // repne (0xF2) + 0x8: decode OPCODE_OP_BOTTOM3 { + 0x0: WarnUnimpl::lddqu_Vo_Mo(); + default: UD2(); + } + default: UD2(); + } + 0x1F: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x0: PSUBB(Pq,Qq); + 0x1: PSUBW(Pq,Qq); + 0x2: PSUBD(Pq,Qq); + 0x3: PSUBQ(Pq,Qq); + 0x4: PADDB(Pq,Qq); + 0x5: PADDW(Pq,Qq); + 0x6: PADDD(Pq,Qq); + 0x7: UD2(); + } + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x0: PSUBB(Vo,Wo); + 0x1: PSUBW(Vo,Wo); + 0x2: PSUBD(Vo,Wo); + 0x3: PSUBQ(Vo,Wo); + 0x4: PADDB(Vo,Wo); + 0x5: PADDW(Vo,Wo); + 0x6: PADDD(Vo,Wo); + 0x7: UD2(); + } + default: UD2(); } - default: FailUnimpl::twoByteOps(); } + default: FailUnimpl::twoByteOps(); } - default: M5InternalError::error( - {{"Unexpected first opcode byte in two byte opcode!"}}); } diff --git a/src/arch/x86/isa_traits.hh b/src/arch/x86/isa_traits.hh index a9e274ecc..f4fdb59e5 100644 --- a/src/arch/x86/isa_traits.hh +++ b/src/arch/x86/isa_traits.hh @@ -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. diff --git a/src/arch/x86/types.cc b/src/arch/x86/types.cc index 73177f467..830a131e5 100644 --- a/src/arch/x86/types.cc +++ b/src/arch/x86/types.cc @@ -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 §ion, 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; diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh index a604c3efc..dd60c0aec 100644 --- a/src/arch/x86/types.hh +++ b/src/arch/x86/types.hh @@ -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 ^ |