summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86/decoder.cc127
-rw-r--r--src/arch/x86/decoder.hh9
-rw-r--r--src/arch/x86/decoder_tables.cc74
-rw-r--r--src/arch/x86/isa/bitfields.isa9
-rw-r--r--src/arch/x86/isa/decoder/decoder.isa1
-rw-r--r--src/arch/x86/isa/decoder/vex_opcodes.isa1431
-rw-r--r--src/arch/x86/isa_traits.hh3
-rw-r--r--src/arch/x86/types.cc5
-rw-r--r--src/arch/x86/types.hh58
9 files changed, 1710 insertions, 7 deletions
diff --git a/src/arch/x86/decoder.cc b/src/arch/x86/decoder.cc
index 59f2e0f4f..fb5a4e001 100644
--- a/src/arch/x86/decoder.cc
+++ b/src/arch/x86/decoder.cc
@@ -48,6 +48,8 @@ Decoder::doResetState()
emi.rex = 0;
emi.legacy = 0;
+ emi.vex = 0;
+
emi.opcode.type = BadOpcode;
emi.opcode.op = 0;
@@ -93,6 +95,19 @@ Decoder::process()
case PrefixState:
state = doPrefixState(nextByte);
break;
+
+ case TwoByteVexState:
+ state = doTwoByteVexState(nextByte);
+ break;
+
+ case ThreeByteVexFirstState:
+ state = doThreeByteVexFirstState(nextByte);
+ break;
+
+ case ThreeByteVexSecondState:
+ state = doThreeByteVexSecondState(nextByte);
+ break;
+
case OneByteOpcodeState:
state = doOneByteOpcodeState(nextByte);
break;
@@ -206,15 +221,68 @@ Decoder::doPrefixState(uint8_t nextByte)
DPRINTF(Decoder, "Found Rex prefix %#x.\n", nextByte);
emi.rex = nextByte;
break;
+
+ case Vex2Prefix:
+ DPRINTF(Decoder, "Found VEX two-byte prefix %#x.\n", nextByte);
+ emi.vex.zero = nextByte;
+ nextState = TwoByteVexState;
+ break;
+
+ case Vex3Prefix:
+ DPRINTF(Decoder, "Found VEX three-byte prefix %#x.\n", nextByte);
+ emi.vex.zero = nextByte;
+ nextState = ThreeByteVexFirstState;
+ break;
+
case 0:
nextState = OneByteOpcodeState;
break;
+
default:
panic("Unrecognized prefix %#x\n", nextByte);
}
return nextState;
}
+Decoder::State
+Decoder::doTwoByteVexState(uint8_t nextByte)
+{
+ assert(emi.vex.zero == 0xc5);
+ consumeByte();
+ TwoByteVex tbe = 0;
+ tbe.first = nextByte;
+
+ emi.vex.first.r = tbe.first.r;
+ emi.vex.first.x = 1;
+ emi.vex.first.b = 1;
+ emi.vex.first.map_select = 1;
+
+ emi.vex.second.w = 0;
+ emi.vex.second.vvvv = tbe.first.vvvv;
+ emi.vex.second.l = tbe.first.l;
+ emi.vex.second.pp = tbe.first.pp;
+
+ emi.opcode.type = Vex;
+ return OneByteOpcodeState;
+}
+
+Decoder::State
+Decoder::doThreeByteVexFirstState(uint8_t nextByte)
+{
+ consumeByte();
+ emi.vex.first = nextByte;
+ return ThreeByteVexSecondState;
+}
+
+Decoder::State
+Decoder::doThreeByteVexSecondState(uint8_t nextByte)
+{
+ consumeByte();
+ emi.vex.second = nextByte;
+ emi.opcode.type = Vex;
+ return OneByteOpcodeState;
+}
+
// Load the first opcode byte. Determine if there are more opcode bytes, and
// if not, what immediate and/or ModRM is needed.
Decoder::State
@@ -222,7 +290,13 @@ Decoder::doOneByteOpcodeState(uint8_t nextByte)
{
State nextState = ErrorState;
consumeByte();
- if (nextByte == 0x0f) {
+
+ if (emi.vex.zero != 0) {
+ DPRINTF(Decoder, "Found VEX opcode %#x.\n", nextByte);
+ emi.opcode.op = nextByte;
+ const uint8_t opcode_map = emi.vex.first.map_select;
+ nextState = processExtendedOpcode(ImmediateTypeVex[opcode_map]);
+ } else if (nextByte == 0x0f) {
nextState = TwoByteOpcodeState;
DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
} else {
@@ -346,6 +420,54 @@ Decoder::processOpcode(ByteTable &immTable, ByteTable &modrmTable,
return nextState;
}
+Decoder::State
+Decoder::processExtendedOpcode(ByteTable &immTable)
+{
+ //Figure out the effective operand size. This can be overriden to
+ //a fixed value at the decoder level.
+ int logOpSize;
+ if (emi.vex.second.w)
+ logOpSize = 3; // 64 bit operand size
+ else if (emi.vex.second.pp == 1)
+ logOpSize = altOp;
+ else
+ logOpSize = defOp;
+
+ //Set the actual op size
+ emi.opSize = 1 << logOpSize;
+
+ //Figure out the effective address size. This can be overriden to
+ //a fixed value at the decoder level.
+ int logAddrSize;
+ if(emi.legacy.addr)
+ logAddrSize = altAddr;
+ else
+ logAddrSize = defAddr;
+
+ //Set the actual address size
+ emi.addrSize = 1 << logAddrSize;
+
+ //Figure out the effective stack width. This can be overriden to
+ //a fixed value at the decoder level.
+ emi.stackSize = 1 << stack;
+
+ //Figure out how big of an immediate we'll retreive based
+ //on the opcode.
+ const uint8_t opcode = emi.opcode.op;
+
+ if (emi.vex.zero == 0xc5 || emi.vex.zero == 0xc4) {
+ int immType = immTable[opcode];
+ // Assume 64-bit mode;
+ immediateSize = SizeTypeToSize[2][immType];
+ }
+
+ if (opcode == 0x77) {
+ instDone = true;
+ return ResetState;
+ }
+ return ModRMState;
+}
+
//Get the ModRM byte and determine what displacement, if any, there is.
//Also determine whether or not to get the SIB byte, displacement, or
//immediate next.
@@ -353,8 +475,7 @@ Decoder::State
Decoder::doModRMState(uint8_t nextByte)
{
State nextState = ErrorState;
- ModRM modRM;
- modRM = nextByte;
+ ModRM modRM = nextByte;
DPRINTF(Decoder, "Found modrm byte %#x.\n", nextByte);
if (defOp == 1) {
//figure out 16 bit displacement size
diff --git a/src/arch/x86/decoder.hh b/src/arch/x86/decoder.hh
index a37fccfb1..6cd0c6199 100644
--- a/src/arch/x86/decoder.hh
+++ b/src/arch/x86/decoder.hh
@@ -64,6 +64,7 @@ class Decoder
static ByteTable ImmediateTypeTwoByte;
static ByteTable ImmediateTypeThreeByte0F38;
static ByteTable ImmediateTypeThreeByte0F3A;
+ static ByteTable ImmediateTypeVex[10];
protected:
struct InstBytes
@@ -175,6 +176,9 @@ class Decoder
ResetState,
FromCacheState,
PrefixState,
+ TwoByteVexState,
+ ThreeByteVexFirstState,
+ ThreeByteVexSecondState,
OneByteOpcodeState,
TwoByteOpcodeState,
ThreeByte0F38OpcodeState,
@@ -193,6 +197,9 @@ class Decoder
State doResetState();
State doFromCacheState();
State doPrefixState(uint8_t);
+ State doTwoByteVexState(uint8_t);
+ State doThreeByteVexFirstState(uint8_t);
+ State doThreeByteVexSecondState(uint8_t);
State doOneByteOpcodeState(uint8_t);
State doTwoByteOpcodeState(uint8_t);
State doThreeByte0F38OpcodeState(uint8_t);
@@ -205,6 +212,8 @@ class Decoder
//Process the actual opcode found earlier, using the supplied tables.
State processOpcode(ByteTable &immTable, ByteTable &modrmTable,
bool addrSizedImm = false);
+ // Process the opcode found with VEX / XOP prefix.
+ State processExtendedOpcode(ByteTable &immTable);
protected:
/// Caching for decoded instruction objects.
diff --git a/src/arch/x86/decoder_tables.cc b/src/arch/x86/decoder_tables.cc
index d5fcceef8..58160756c 100644
--- a/src/arch/x86/decoder_tables.cc
+++ b/src/arch/x86/decoder_tables.cc
@@ -55,6 +55,8 @@ namespace X86ISA
const uint8_t RE = Rep;
const uint8_t RN = Repne;
const uint8_t RX = RexPrefix;
+ const uint8_t V2 = Vex2Prefix;
+ const uint8_t V3 = Vex3Prefix;
//This table identifies whether a byte is a prefix, and if it is,
//which prefix it is.
@@ -73,7 +75,7 @@ namespace X86ISA
/* 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,
+/* C*/ 0 , 0 , 0 , 0 , V3, V2, 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*/ LO, 0 , RN, RE, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
@@ -282,4 +284,74 @@ namespace X86ISA
/* 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::ImmediateTypeVex[10] =
+ {
+ // Table for opcode map 1
+ {
+ //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 */ BY, BY, BY, BY, 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 , 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
+ },
+
+ // Table for opcode map 2
+ {
+ //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
+ },
+
+ // Table for opcode map 3
+ {
+ //LSB
+ // MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
+ /* 0 */ 0 , 0 , 0 , 0 , BY, BY, BY, 0 , BY, BY, BY, BY, BY, BY, BY, BY,
+ /* 1 */ 0 , 0 , 0 , 0 , BY, BY, BY, BY, BY, BY, 0 , 0 , 0 , BY, 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 e2751a8ef..b5121f4e3 100644
--- a/src/arch/x86/isa/bitfields.isa
+++ b/src/arch/x86/isa/bitfields.isa
@@ -87,3 +87,12 @@ def bitfield STACKSIZE stackSize;
def bitfield MODE mode;
def bitfield MODE_MODE mode.mode;
def bitfield MODE_SUBMODE mode.submode;
+
+def bitfield VEX_R vex.first.r;
+def bitfield VEX_X vex.first.x;
+def bitfield VEX_B vex.first.b;
+def bitfield VEX_MAP vex.first.map_select;
+def bitfield VEX_W vex.second.w;
+def bitfield VEX_VVVV vex.second.vvvv;
+def bitfield VEX_L vex.second.l;
+def bitfield VEX_PP vex.second.pp;
diff --git a/src/arch/x86/isa/decoder/decoder.isa b/src/arch/x86/isa/decoder/decoder.isa
index eaa579817..07006fe1a 100644
--- a/src/arch/x86/isa/decoder/decoder.isa
+++ b/src/arch/x86/isa/decoder/decoder.isa
@@ -49,6 +49,7 @@ decode LEGACY_LOCK default Unknown::unknown()
##include "two_byte_opcodes.isa"
##include "three_byte_0f38_opcodes.isa"
##include "three_byte_0f3a_opcodes.isa"
+ ##include "vex_opcodes.isa"
}
//Lock prefix
##include "locked_opcodes.isa"
diff --git a/src/arch/x86/isa/decoder/vex_opcodes.isa b/src/arch/x86/isa/decoder/vex_opcodes.isa
new file mode 100644
index 000000000..0f412feee
--- /dev/null
+++ b/src/arch/x86/isa/decoder/vex_opcodes.isa
@@ -0,0 +1,1431 @@
+// Copyright (c) 2015 Mark D. Hill and David A. Wood
+// 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: Nilay Vaish
+
+////////////////////////////////////////////////////////////////////
+//
+// Decode the opcodes with vex prefix.
+//
+format WarnUnimpl {
+ 'X86ISA::Vex': decode VEX_MAP {
+ 0x01: decode OPCODE_OP_TOP5 {
+ 0x02: decode VEX_PP {
+ 0x0: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_VVVV {
+ 0x15: vmovups();
+ default: Inst::UD2();
+ }
+ 0x1: decode VEX_VVVV {
+ 0x15: vmovups();
+ default: Inst::UD2();
+ }
+ 0x2: decode VEX_L {
+ 0x0: decode MODRM_MOD {
+ 0x03: vmovhlps();
+ default: decode VEX_VVVV {
+ 0x15: vmovlps();
+ default: Inst::UD2();
+ }
+ }
+ default: Inst::UD2();
+ }
+ 0x3: decode VEX_VVVV {
+ 0x15: decode VEX_L {
+ 0x0: vmovlps();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+ 0x4: vunpcklps();
+ 0x5: vunpckhps();
+ 0x6: decode VEX_L {
+ 0x0: decode MODRM_MOD {
+ 0x03: vmovlhps();
+ 0x0: vmovhps();
+ }
+ default: Inst::UD2();
+ }
+ 0x7: decode VEX_L {
+ 0x0: vmovhps();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_VVVV {
+ 0x15: vmovupd();
+ default: Inst::UD2();
+ }
+ 0x1: decode VEX_VVVV {
+ 0x15: vmovupd();
+ default: Inst::UD2();
+ }
+ 0x2: decode VEX_L {
+ 0x0: vmovlpd();
+ default: Inst::UD2();
+ }
+ 0x3: decode VEX_L {
+ 0x0: vmovlpd();
+ default: Inst::UD2();
+ }
+ 0x4: vunpcklpd();
+ 0x5: vunpckhpd();
+ 0x6: decode VEX_L {
+ 0x0: vmovhpd();
+ default: Inst::UD2();
+ }
+ 0x7: decode VEX_L {
+ 0x0: vmovhpd();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x2: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode MODRM_MOD {
+ 0x03: vmovss();
+ default: vmovss();
+ }
+ 0x1: decode MODRM_MOD {
+ 0x03: vmovss();
+ default: vmovss();
+ }
+ 0x2: decode VEX_VVVV {
+ 0x15: vmovsldup();
+ default: Inst::UD2();
+ }
+ 0x6: decode VEX_VVVV {
+ 0x15: vmovshdup();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x3: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode MODRM_MOD {
+ 0x03: vmovsd();
+ default: vmovsd();
+ }
+ 0x1: decode MODRM_MOD {
+ 0x03: vmovsd();
+ default: vmovsd();
+ }
+ 0x2: decode VEX_VVVV {
+ 0x15: decode VEX_L {
+ 0x0: vmovddup();
+ default: vmovddup();
+ }
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x0A: decode VEX_PP {
+ 0x0: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_VVVV {
+ 0x15: vmovmskps();
+ default: Inst::UD2();
+ }
+ 0x1: decode VEX_VVVV {
+ 0x015: vsqrtps();
+ default: Inst::UD2();
+ }
+ 0x2: decode VEX_VVVV {
+ 0x15: vrsqrtps();
+ default: Inst::UD2();
+ }
+ 0x3: decode VEX_VVVV {
+ 0x15: vrcpps();
+ default: Inst::UD2();
+ }
+ 0x4: vandps();
+ 0x5: vandnps();
+ 0x6: vorps();
+ 0x7: vxorps();
+ default: Inst::UD2();
+ }
+
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_VVVV {
+ 0x15: vmovmskpd();
+ default: Inst::UD2();
+ }
+ 0x1: decode VEX_VVVV {
+ 0x15: vsqrtpd();
+ default: Inst::UD2();
+ }
+ 0x4: vandpd();
+ 0x5: vandnpd();
+ 0x6: vorpd();
+ 0x7: vxorpd();
+ default: Inst::UD2();
+ }
+
+ 0x2: decode OPCODE_OP_BOTTOM3 {
+ 0x1: vsqrtss();
+ 0x2: vrsqrtss();
+ 0x3: vrcpss();
+ default: Inst::UD2();
+ }
+
+ 0x3: decode OPCODE_OP_BOTTOM3 {
+ 0x1: vsqrtsd();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x0C: decode VEX_PP {
+ 0x1: decode VEX_L {
+ 0x0: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vpunpcklbw();
+ 0x1: vpunpcklwd();
+ 0x2: vpunpckldq();
+ 0x3: vpacksswb();
+ 0x4: vpcmpgtb();
+ 0x5: vpcmpgtw();
+ 0x6: vpcmpgtd();
+ 0x7: vpackuswb();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x0E: decode VEX_PP {
+ 0x0: decode OPCODE_OP_BOTTOM3 {
+ 0x7: decode VEX_L {
+ 0x0: vzeroupper();
+ 0x1: vzeroall();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_VVVV {
+ 0x15: vpshufd();
+ default: Inst::UD2();
+ }
+ 0x1: decode VEX_L {
+ 0x0: decode MODRM_REG {
+ 0x2: vpsrlw();
+ 0x4: vpsraw();
+ 0x6: vpsllw();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x2: decode VEX_L {
+ 0x0: decode MODRM_REG {
+ 0x2: vpsrld();
+ 0x4: vpsrad();
+ 0x6: vpslld();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x3: decode VEX_L {
+ 0x0: decode MODRM_REG {
+ 0x2: vpsrlq();
+ 0x3: vpsrldq();
+ 0x6: vpsllq();
+ 0x7: vpslldq();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x4: decode VEX_L {
+ 0x0: vpcmpeqb();
+ default: Inst::UD2();
+ }
+
+ 0x5: decode VEX_L {
+ 0x0: vpcmpeqw();
+ default: Inst::UD2();
+ }
+ 0x6: decode VEX_L {
+ 0x0: vpcmpeqd();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+ 0x2: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_VVVV {
+ 0x15: decode VEX_L {
+ 0x0: vpshufhw();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+ 0x3: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_VVVV {
+ 0x15: decode VEX_L {
+ 0x0: vpshuflw();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x18: decode VEX_PP {
+ 0x0: decode OPCODE_OP_BOTTOM3 {
+ 0x2: vcmpccps();
+ 0x6: vshufps();
+ default: Inst::UD2();
+ }
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x2: vcmpccpd();
+ 0x4: decode MODRM_MOD {
+ 0x03: vpinsrw();
+ default: vpinsrw();
+ }
+ 0x5: decode VEX_VVVV {
+ 0x15: decode VEX_L {
+ 0x0: vpextrw();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+ 0x6: vshufpd();
+ default: Inst::UD2();
+ }
+ 0x2: decode OPCODE_OP_BOTTOM3 {
+ 0x2: vcmpccss();
+ default: Inst::UD2();
+ }
+ 0x3: decode OPCODE_OP_BOTTOM3 {
+ 0x2: vcmpccsd();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x1A: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vaddsubpd();
+ 0x1: decode VEX_L {
+ 0x0: vpsrlw();
+ default: Inst::UD2();
+ }
+ 0x2: decode VEX_L {
+ 0x0: vpsrld();
+ default: Inst::UD2();
+ }
+ 0x3: decode VEX_L {
+ 0x0: vpsrlq();
+ default: Inst::UD2();
+ }
+ 0x4: decode VEX_L {
+ 0x0: vpaddq();
+ default: Inst::UD2();
+ }
+ 0x5: decode VEX_L {
+ 0x0: vpmullw();
+ default: Inst::UD2();
+ }
+ 0x6: decode VEX_VVVV {
+ 0x15: decode VEX_L {
+ 0x0: vmovq();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+ 0x7: decode VEX_VVVV {
+ 0x15: vpmovmskb();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+ 0x3: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vaddsubps();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x1C: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_L {
+ 0x0: vpavgb();
+ default: Inst::UD2();
+ }
+ 0x1: vpsraw();
+ 0x2: vpsrad();
+ 0x3: decode VEX_L {
+ 0x0: vpavgw();
+ default: Inst::UD2();
+ }
+ 0x4: vpmulhuw();
+ 0x5: vpmulhw();
+ 0x6: vcvttpd2dq();
+ 0x7: decode VEX_VVVV {
+ 0x015: decode VEX_L {
+ 0x0: vmovntdq();
+ default: vmovntdq();
+ }
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x2: decode OPCODE_OP_BOTTOM3 {
+ 0x6: vcvtdq2pd();
+ default: Inst::UD2();
+ }
+
+ 0x3: decode OPCODE_OP_BOTTOM3 {
+ 0x6: vcvtpd2dq();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x1E: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x1: vpsllw();
+ 0x2: vpslld();
+ 0x3: vpsllq();
+ 0x4: vpmuludq();
+ 0x5: vpmaddwd();
+ 0x6: vpsadbw();
+ 0x7: decode VEX_L {
+ 0x0: vmaskmovdqu();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x3: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_L {
+ 0x0: vlddqu();
+ default: vlddqu();
+ }
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x05: decode VEX_PP {
+ 0x0: decode VEX_VVVV {
+ 0x15: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vmovaps();
+ 0x1: vmovaps();
+ 0x3: vmovntps();
+ 0x6: vucomiss();
+ 0x7: vcomiss();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x1: decode VEX_VVVV {
+ 0x15: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vmovapd();
+ 0x1: vmovapd();
+ 0x3: vmovntpd();
+ 0x6: vucomisd();
+ 0x7: vcomisd();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x2: decode OPCODE_OP_BOTTOM3 {
+ 0x2: vcvtsi2ss();
+ 0x4: vcvttss2si();
+ 0x5: vcvtss2si();
+ default: Inst::UD2();
+ }
+
+ 0x3: decode OPCODE_OP_BOTTOM3 {
+ 0x2: vcvtsi2sd();
+ 0x4: vcvttsd2si();
+ 0x5: vcvtsd2si();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x0B: decode VEX_PP {
+ 0x0: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vaddps();
+ 0x1: vmulps();
+ 0x2: vcvtps2pd();
+ 0x3: vcvtdq2ps();
+ 0x4: vsubps();
+ 0x5: vminps();
+ 0x6: vdivps();
+ 0x7: vmaxps();
+ default: Inst::UD2();
+ }
+
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vaddpd();
+ 0x1: vmulpd();
+ 0x2: vcvtpd2ps();
+ 0x3: vcvtps2dq();
+ 0x4: vsubpd();
+ 0x5: vminpd();
+ 0x6: vdivpd();
+ 0x7: vmaxpd();
+ default: Inst::UD2();
+ }
+
+ 0x2: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vaddss();
+ 0x1: vmulss();
+ 0x2: vcvtss2sd();
+ 0x3: vcvttps2dq();
+ 0x4: vsubss();
+ 0x5: vminss();
+ 0x6: vdivss();
+ 0x7: vmaxss();
+ default: Inst::UD2();
+ }
+
+ 0x3: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vaddsd();
+ 0x1: vmulsd();
+ 0x2: vcvtsd2ss();
+ 0x4: vsubsd();
+ 0x5: vminsd();
+ 0x6: vdivsd();
+ 0x7: vmaxsd();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x0D: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vpunpckhbw();
+ 0x1: vpunpckhbd();
+ 0x2: vpunpckhdq();
+ 0x3: decode VEX_L {
+ 0x0: vpackssdw();
+ default: Inst::UD2();
+ }
+ 0x4: vpunpcklqdq();
+ 0x5: vpunpckhqdq();
+ 0x6: decode VEX_L {
+ 0x0: vmovdvmovq();
+ default: Inst::UD2();
+ }
+ 0x7: decode VEX_VVVV {
+ 0x15: vmovdqa();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x2: decode OPCODE_OP_BOTTOM3 {
+ 0x7: vmovdqu();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x0F: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x4: vhaddpd();
+ 0x5: vhsubpd();
+ 0x6: decode VEX_L {
+ 0x1: vmovdvmovq();
+ default: Inst::UD2();
+ }
+ 0x7: decode VEX_VVVV {
+ 0x15: vmovdqa();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x2: decode OPCODE_OP_BOTTOM3 {
+ 0x6: decode VEX_L {
+ 0x0: vmovq();
+ default: Inst::UD2();
+ }
+ 0x7: vmovdqu();
+ default: Inst::UD2();
+ }
+
+ 0x3: decode OPCODE_OP_BOTTOM3 {
+ 0x4: vhaddps();
+ 0x5: vhsubps();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x15: decode VEX_PP {
+ 0x0: decode OPCODE_OP_BOTTOM3 {
+ 0x6: decode MODRM_REG {
+ 0x2: vldmxcsr();
+ 0x3: vstmxcsr();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ 0x1B: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vpsubusb();
+ 0x1: vpsubusw();
+ 0x2: vpminub();
+ 0x3: decode VEX_L {
+ 0x0: vpand();
+ default: Inst::UD2();
+ }
+ 0x4: vpaddusb();
+ 0x5: decode VEX_L {
+ 0x0: vpaddusw();
+ default: Inst::UD2();
+ }
+ 0x6: vpmaxub();
+ 0x7: decode VEX_L {
+ 0x0: vpandn();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x1D: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vpsubsb();
+ 0x1: vpsubsw();
+ 0x2: vpminsw();
+ 0x3: vpor();
+ 0x4: decode VEX_L {
+ 0x0: vpaddsb();
+ default: Inst::UD2();
+ }
+ 0x5: decode VEX_L {
+ 0x0: vpaddsw();
+ default: Inst::UD2();
+ }
+ 0x6: vpmaxsw();
+ 0x7: vpxor();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x1F: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vpsubb();
+ 0x1: vpsubw();
+ 0x2: vpsubd();
+ 0x3: vpsubq();
+ 0x4: vpaddb();
+ 0x5: decode VEX_L {
+ 0x0: vpaddw();
+ default: Inst::UD2();
+ }
+ 0x6: decode VEX_L {
+ 0x0: vpaddd();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x02: decode OPCODE_OP_TOP5 {
+ 0x00: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vpshufb();
+ 0x1: vphaddw();
+ 0x2: vphaddd();
+ 0x3: vphaddsw();
+ 0x4: vpmaddubsw();
+ 0x5: vphsubw();
+ 0x6: vphsubd();
+ 0x7: vphsubsw();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x02: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x3: vcvtph2ps();
+ 0x7: vptest();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x04: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vpmovsxbw();
+ 0x1: vpmovsxbd();
+ 0x2: vpmovsxbq();
+ 0x3: vpmovsxwd();
+ 0x4: vpmovsxwq();
+ 0x5: vpmovsxdq();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x06: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vpmovzxbw();
+ 0x1: vpmovzxbd();
+ 0x2: vpmovzxbq();
+ 0x3: vpmovzxwd();
+ 0x4: vpmovzxwq();
+ 0x5: vpmovzxdq();
+ 0x7: vpcmpgtq();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x08: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vpmulld();
+ 0x1: vphminposuw();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x12: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x6: decode VEX_W {
+ 0x0: vfmaddsub132ps();
+ 0x1: vfmaddsub132pd();
+ default: Inst::UD2();
+ }
+
+ 0x7: decode VEX_W {
+ 0x0: vfmsubadd132ps();
+ 0x1: vfmaddsub132pd();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x14: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x6: decode VEX_W {
+ 0x0: vfmaddsub213ps();
+ 0x1: vfmaddsub213pd();
+ default: Inst::UD2();
+ }
+
+ 0x7: decode VEX_W {
+ 0x0: vfmsubadd213ps();
+ 0x1: vfmaddsub213pd();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x16: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x6: decode VEX_W {
+ 0x0: vfmaddsub231ps();
+ 0x1: vfmaddsub231pd();
+ default: Inst::UD2();
+ }
+
+ 0x7: decode VEX_W {
+ 0x0: vfmsubadd231ps();
+ 0x1: vfmaddsub231pd();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x1E: decode VEX_PP {
+ 0x0: decode OPCODE_OP_BOTTOM3 {
+ 0x2: andn();
+ 0x3: decode MODRM_REG {
+ 0x1: blsr();
+ 0x2: blsmsk();
+ 0x3: blsi();
+ default: Inst::UD2();
+ }
+
+ 0x7: bextr();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x01: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vpsignb();
+ 0x1: vpsignw();
+ 0x2: vpsignd();
+ 0x3: vpmulhrsw();
+ 0x4: vpermilps();
+ 0x5: vpermilpd();
+ 0x6: vtestps();
+ 0x7: vtestpd();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x03: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vbroadcastss();
+ 0x1: decode VEX_L {
+ 0x1: vbroadcastsd();
+ default: Inst::UD2();
+ }
+
+ 0x2: decode VEX_L {
+ 0x1: vbroadcastF128();
+ default: Inst::UD2();
+ }
+
+ 0x4: decode VEX_L {
+ 0x0: vpabsb();
+ default: Inst::UD2();
+ }
+ 0x5: decode VEX_L {
+ 0x0: vpabsw();
+ default: Inst::UD2();
+ }
+ 0x6: decode VEX_L {
+ 0x0: vpabsd();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x05: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vpmuldq();
+ 0x1: vpcmpeqq();
+ 0x2: decode VEX_VVVV {
+ 0x15: vmovntdqa();
+ default: Inst::UD2();
+ }
+ 0x3: decode VEX_L {
+ 0x0: vpackusdw();
+ default: Inst::UD2();
+ }
+ 0x4: vmaskmovps();
+ 0x5: vmaskmovpd();
+ 0x6: vmaskmovps();
+ 0x7: vmaskmovpd();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x07: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vpminsb();
+ 0x1: vpminsd();
+ 0x2: vpminuw();
+ 0x3: vpminud();
+ 0x4: vpmaxsb();
+ 0x5: vpmaxsd();
+ 0x6: vpmaxuw();
+ 0x7: vpmaxud();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x0B: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x2: vbroadcasti128();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x13: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_W {
+ 0x0: vfmadd132ps();
+ 0x1: vfmadd132pd();
+ default: Inst::UD2();
+ }
+
+ 0x1: decode VEX_W {
+ 0x0: vfmadd132ss();
+ 0x1: vfmadd132sd();
+ default: Inst::UD2();
+ }
+
+ 0x2: decode VEX_W {
+ 0x0: vfmsub132ps();
+ 0x1: vfmsub132pd();
+ default: Inst::UD2();
+ }
+
+ 0x3: decode VEX_W {
+ 0x0: vfmsub132ss();
+ 0x1: vfmsub132sd();
+ default: Inst::UD2();
+ }
+
+ 0x4: decode VEX_W {
+ 0x0: vfnmadd132ps();
+ 0x1: vfnmadd132pd();
+ default: Inst::UD2();
+ }
+
+ 0x5: decode VEX_W {
+ 0x0: vfnmadd132ss();
+ 0x1: vfnmadd132sd();
+ default: Inst::UD2();
+ }
+
+ 0x6: decode VEX_W {
+ 0x0: vfnsub132ps();
+ 0x1: vfnsub132pd();
+ default: Inst::UD2();
+ }
+
+ 0x7: decode VEX_W {
+ 0x0: vfnsub132ss();
+ 0x1: vfnsub132sd();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x15: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_W {
+ 0x0: vfmadd213ps();
+ 0x1: vfmadd213pd();
+ default: Inst::UD2();
+ }
+
+ 0x1: decode VEX_W {
+ 0x0: vfmadd213ss();
+ 0x1: vfmadd213sd();
+ default: Inst::UD2();
+ }
+
+ 0x2: decode VEX_W {
+ 0x0: vfmsub213ps();
+ 0x1: vfmsub213pd();
+ default: Inst::UD2();
+ }
+
+ 0x3: decode VEX_W {
+ 0x0: vfmsub213ss();
+ 0x1: vfmsub213sd();
+ default: Inst::UD2();
+ }
+
+ 0x4: decode VEX_W {
+ 0x0: vfnmadd213ps();
+ 0x1: vfnmadd213pd();
+ default: Inst::UD2();
+ }
+
+ 0x5: decode VEX_W {
+ 0x0: vfnmadd213ss();
+ 0x1: vfnmadd213sd();
+ default: Inst::UD2();
+ }
+
+ 0x6: decode VEX_W {
+ 0x0: vfnsub213ps();
+ 0x1: vfnsub213pd();
+ default: Inst::UD2();
+ }
+
+ 0x7: decode VEX_W {
+ 0x0: vfnsub213ss();
+ 0x1: vfnsub213sd();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x17: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_W {
+ 0x0: vfmadd231ps();
+ 0x1: vfmadd231pd();
+ default: Inst::UD2();
+ }
+
+ 0x1: decode VEX_W {
+ 0x0: vfmadd231ss();
+ 0x1: vfmadd231sd();
+ default: Inst::UD2();
+ }
+
+ 0x2: decode VEX_W {
+ 0x0: vfmsub231ps();
+ 0x1: vfmsub231pd();
+ default: Inst::UD2();
+ }
+
+ 0x3: decode VEX_W {
+ 0x0: vfmsub231ss();
+ 0x1: vfmsub231sd();
+ default: Inst::UD2();
+ }
+
+ 0x4: decode VEX_W {
+ 0x0: vfnmadd231ps();
+ 0x1: vfnmadd231pd();
+ default: Inst::UD2();
+ }
+
+ 0x5: decode VEX_W {
+ 0x0: vfnmadd231ss();
+ 0x1: vfnmadd231sd();
+ default: Inst::UD2();
+ }
+
+ 0x6: decode VEX_W {
+ 0x0: vfnsub231ps();
+ 0x1: vfnsub231pd();
+ default: Inst::UD2();
+ }
+
+ 0x7: decode VEX_W {
+ 0x0: vfnsub231ss();
+ 0x1: vfnsub231sd();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x1B: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x3: vaesimc();
+ 0x4: vaesenc();
+ 0x5: vaesenclast();
+ 0x6: vaesdec();
+ 0x7: vaesdeclast();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x03: decode OPCODE_OP_TOP5 {
+ 0x00: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x4: vpermilps();
+ 0x5: vpermilpd();
+ 0x6: vperm2f128();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x02: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x4: decode MODRM_MOD {
+ 0x03: vpextrb();
+ default: vpextrb();
+ }
+
+ 0x5: decode VEX_VVVV {
+ 0x15: decode VEX_L {
+ 0x0: decode MODRM_MOD {
+ 0x03: vpextrw();
+ default: vpextrw();
+ }
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+ 0x6: decode VEX_W {
+ 0x0: vpextrd();
+ 0x1: vpextrq();
+ default: Inst::UD2();
+ }
+ 0x7: decode MODRM_MOD {
+ 0x03: vextractps();
+ default: vextractps();
+ }
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x04: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode MODRM_MOD {
+ 0x03: vpinsrb();
+ default: vpinsrb();
+ }
+ 0x1: decode MODRM_MOD {
+ 0x03: vinsertps();
+ default: vinsertps();
+ }
+ 0x2: decode VEX_W {
+ 0x0: vpinsrd();
+ 0x1: vpinsrq();
+ }
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x08: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vdpps();
+ 0x1: vdppd();
+ 0x2: decode VEX_L {
+ 0x0: vmpsadbw();
+ default: Inst::UD2();
+ }
+ 0x4: vpclmulqdq();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x0C: decode VEX_PP {
+ 0x1: decode VEX_L {
+ 0x0: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_VVVV {
+ 0x15: vpcmpestrm();
+ default: Inst::UD2();
+ }
+ 0x1: decode VEX_VVVV {
+ 0x15: vpcmpestri();
+ default: Inst::UD2();
+ }
+ 0x2: vpcmpistrm();
+ 0x3: vpcmpistri();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x01: decode VEX_PP {
+ 0x0: decode OPCODE_OP_BOTTOM3 {
+ 0x7: palignr();
+ default: Inst::UD2();
+ }
+
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_VVVV {
+ 0x15: vroundps();
+ default: Inst::UD2();
+ }
+ 0x1: decode VEX_VVVV {
+ 0x15: vroundpd();
+ default: Inst::UD2();
+ }
+ 0x2: vroundss();
+ 0x3: vroundsd();
+ 0x4: vblendps();
+ 0x5: vblendpd();
+ 0x6: decode VEX_L {
+ 0x0: vpblendw();
+ default: Inst::UD2();
+ }
+ 0x7: decode VEX_L {
+ 0x0: vpalignr();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x03: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vinsertf128();
+ 0x1: vextractf128();
+ 0x5: vcvtps2ph();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x09: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: vpermil2ps();
+ 0x1: vpermil2pd();
+ 0x2: vblendvps();
+ 0x3: vblendvpd();
+ 0x4: decode VEX_L {
+ 0x0: decode VEX_W {
+ 0x0: vpblendvb();
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x0B: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x4: decode VEX_W {
+ 0x0: vfmaddsubps();
+ 0x1: vfmaddsubps();
+ default: Inst::UD2();
+ }
+
+ 0x5: decode VEX_W {
+ 0x0: vfmaddsubpd();
+ 0x1: vfmaddsubpd();
+ default: Inst::UD2();
+ }
+
+ 0x6: decode VEX_W {
+ 0x0: vfmsubaddps();
+ 0x1: vfmsubaddps();
+ default: Inst::UD2();
+ }
+
+ 0x7: decode VEX_W {
+ 0x0: vfmsubaddpd();
+ 0x1: vfmsubaddpd();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x0D: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_W {
+ 0x0: vfmaddps();
+ 0x1: vfmaddps();
+ default: Inst::UD2();
+ }
+
+ 0x1: decode VEX_W {
+ 0x0: vfmaddpd();
+ 0x1: vfmaddpd();
+ default: Inst::UD2();
+ }
+
+ 0x2: decode VEX_W {
+ 0x0: vfmaddss();
+ 0x1: vfmaddss();
+ default: Inst::UD2();
+ }
+
+ 0x3: decode VEX_W {
+ 0x0: vfmaddsd();
+ 0x1: vfmaddsd();
+ default: Inst::UD2();
+ }
+
+ 0x4: decode VEX_W {
+ 0x0: vfmsubps();
+ 0x1: vfmsubps();
+ default: Inst::UD2();
+ }
+
+ 0x5: decode VEX_W {
+ 0x0: vfmsubpd();
+ 0x1: vfmsubpd();
+ default: Inst::UD2();
+ }
+
+ 0x6: decode VEX_W {
+ 0x0: vfmsubss();
+ 0x1: vfmsubss();
+ default: Inst::UD2();
+ }
+
+ 0x7: decode VEX_W {
+ 0x0: vfmsubsd();
+ 0x1: vfmsubsd();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x0F: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x0: decode VEX_W {
+ 0x0: vfnmaddps();
+ 0x1: vfnmaddps();
+ default: Inst::UD2();
+ }
+
+ 0x1: decode VEX_W {
+ 0x0: vfnmaddpd();
+ 0x1: vfnmaddpd();
+ default: Inst::UD2();
+ }
+
+ 0x2: decode VEX_W {
+ 0x0: vfnmaddss();
+ 0x1: vfnmaddss();
+ default: Inst::UD2();
+ }
+
+ 0x3: decode VEX_W {
+ 0x0: vfnmaddsd();
+ 0x1: vfnmaddsd();
+ default: Inst::UD2();
+ }
+
+ 0x4: decode VEX_W {
+ 0x0: vfnmsubps();
+ 0x1: vfnmsubps();
+ default: Inst::UD2();
+ }
+
+ 0x5: decode VEX_W {
+ 0x0: vfnmsubpd();
+ 0x1: vfnmsubpd();
+ default: Inst::UD2();
+ }
+
+ 0x6: decode VEX_W {
+ 0x0: vfnmsubss();
+ 0x1: vfnmsubss();
+ default: Inst::UD2();
+ }
+
+ 0x7: decode VEX_W {
+ 0x0: vfnmsubsd();
+ 0x1: vfnmsubsd();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ 0x1B: decode VEX_PP {
+ 0x1: decode OPCODE_OP_BOTTOM3 {
+ 0x7: vaeskeygenassist();
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+
+ default: Inst::UD2();
+ }
+}
diff --git a/src/arch/x86/isa_traits.hh b/src/arch/x86/isa_traits.hh
index 6e5373ca1..fcdffec1c 100644
--- a/src/arch/x86/isa_traits.hh
+++ b/src/arch/x86/isa_traits.hh
@@ -71,7 +71,8 @@ namespace X86ISA
const ExtMachInst NoopMachInst M5_VAR_USED = {
0x0, // No legacy prefixes.
0x0, // No rex prefix.
- { OneByteOpcode, 0x90 }, // One opcode byte, 0x90.
+ 0x0, // No two / three byte escape sequence
+ { 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 a960205b5..59f8b91de 100644
--- a/src/arch/x86/types.cc
+++ b/src/arch/x86/types.cc
@@ -41,6 +41,7 @@ paramOut(CheckpointOut &cp, const string &name, ExtMachInst const &machInst)
// Prefixes
paramOut(cp, name + ".legacy", (uint8_t)machInst.legacy);
paramOut(cp, name + ".rex", (uint8_t)machInst.rex);
+ paramOut(cp, name + ".vex", (uint32_t)machInst.vex);
// Opcode
paramOut(cp, name + ".opcode.type", (uint8_t)machInst.opcode.type);
@@ -75,6 +76,10 @@ paramIn(CheckpointIn &cp, const string &name, ExtMachInst &machInst)
paramIn(cp, name + ".rex", temp8);
machInst.rex = temp8;
+ uint32_t temp32;
+ paramIn(cp, name + ".vex", temp32);
+ machInst.vex = temp32;
+
// Opcode
paramIn(cp, name + ".opcode.type", temp8);
machInst.opcode.type = (OpcodeType)temp8;
diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh
index 23d60020b..88b000b6e 100644
--- a/src/arch/x86/types.hh
+++ b/src/arch/x86/types.hh
@@ -67,7 +67,10 @@ namespace X86ISA
AddressSizeOverride,
Lock,
Rep,
- Repne
+ Repne,
+ Vex2Prefix,
+ Vex3Prefix,
+ XopPrefix,
};
BitUnion8(LegacyPrefixVector)
@@ -104,12 +107,55 @@ namespace X86ISA
Bitfield<0> b;
EndBitUnion(Rex)
+ BitUnion(uint32_t, ThreeByteVex)
+ Bitfield<7,0> zero;
+ SubBitUnion(first, 15, 8)
+ // Inverted one-bit extension of ModRM reg field
+ Bitfield<15> r;
+ // Inverted one-bit extension of SIB index field
+ Bitfield<14> x;
+ // Inverted one-bit extension, r/m field or SIB base field
+ Bitfield<13> b;
+ // Opcode map select
+ Bitfield<12, 8> map_select;
+ EndSubBitUnion(first)
+ SubBitUnion(second, 23, 16)
+ // Default operand size override for a general purpose register to
+ // 64-bit size in 64-bit mode; operand configuration specifier for
+ // certain YMM/XMM-based operations.
+ Bitfield<23> w;
+ // Source or destination register selector, in ones' complement
+ // format
+ Bitfield<22, 19> vvvv;
+ // Vector length specifier
+ Bitfield<18> l;
+ // Implied 66, F2, or F3 opcode extension
+ Bitfield<17, 16> pp;
+ EndSubBitUnion(second)
+ EndBitUnion(ThreeByteVex)
+
+ BitUnion16(TwoByteVex)
+ Bitfield<7,0> zero;
+ SubBitUnion(first, 15, 8)
+ // Inverted one-bit extension of ModRM reg field
+ Bitfield<15> r;
+ // Source or destination register selector, in ones' complement
+ // format
+ Bitfield<14, 11> vvvv;
+ // Vector length specifier
+ Bitfield<10> l;
+ // Implied 66, F2, or F3 opcode extension
+ Bitfield<9, 8> pp;
+ EndSubBitUnion(first)
+ EndBitUnion(TwoByteVex)
+
enum OpcodeType {
BadOpcode,
OneByteOpcode,
TwoByteOpcode,
ThreeByte0F38Opcode,
- ThreeByte0F3AOpcode
+ ThreeByte0F3AOpcode,
+ Vex,
};
static inline const char *
@@ -126,6 +172,8 @@ namespace X86ISA
return "three byte 0f38";
case ThreeByte0F3AOpcode:
return "three byte 0f3a";
+ case Vex:
+ return "vex";
default:
return "unrecognized!";
}
@@ -160,6 +208,10 @@ namespace X86ISA
//Prefixes
LegacyPrefixVector legacy;
Rex rex;
+ // We use the following field for encoding both two byte and three byte
+ // escape sequences
+ ThreeByteVex vex;
+
//This holds all of the bytes of the opcode
struct
{
@@ -191,11 +243,13 @@ namespace X86ISA
operator << (std::ostream & os, const ExtMachInst & emi)
{
ccprintf(os, "\n{\n\tleg = %#x,\n\trex = %#x,\n\t"
+ "vex/xop = %#x,\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,
+ (uint32_t)emi.vex,
opcodeTypeToStr(emi.opcode.type), (uint8_t)emi.opcode.op,
(uint8_t)emi.modRM, (uint8_t)emi.sib,
emi.immediate, emi.displacement, emi.dispSize);