summaryrefslogtreecommitdiff
path: root/src/arch/x86/decoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/decoder.cc')
-rw-r--r--src/arch/x86/decoder.cc219
1 files changed, 126 insertions, 93 deletions
diff --git a/src/arch/x86/decoder.cc b/src/arch/x86/decoder.cc
index 324eb0219..930c2b951 100644
--- a/src/arch/x86/decoder.cc
+++ b/src/arch/x86/decoder.cc
@@ -96,19 +96,18 @@ Decoder::process()
case PrefixState:
state = doPrefixState(nextByte);
break;
-
- case TwoByteVexState:
- state = doTwoByteVexState(nextByte);
+ case Vex2Of2State:
+ state = doVex2Of2State(nextByte);
break;
-
- case ThreeByteVexFirstState:
- state = doThreeByteVexFirstState(nextByte);
+ case Vex2Of3State:
+ state = doVex2Of3State(nextByte);
break;
-
- case ThreeByteVexSecondState:
- state = doThreeByteVexSecondState(nextByte);
+ case Vex3Of3State:
+ state = doVex3Of3State(nextByte);
+ break;
+ case VexOpcodeState:
+ state = doVexOpcodeState(nextByte);
break;
-
case OneByteOpcodeState:
state = doOneByteOpcodeState(nextByte);
break;
@@ -222,19 +221,16 @@ 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;
+ emi.vex.present = 1;
+ nextState = Vex2Of2State;
break;
-
case Vex3Prefix:
DPRINTF(Decoder, "Found VEX three-byte prefix %#x.\n", nextByte);
- emi.vex.zero = nextByte;
- nextState = ThreeByteVexFirstState;
+ emi.vex.present = 1;
+ nextState = Vex2Of3State;
break;
-
case 0:
nextState = OneByteOpcodeState;
break;
@@ -246,42 +242,132 @@ Decoder::doPrefixState(uint8_t nextByte)
}
Decoder::State
-Decoder::doTwoByteVexState(uint8_t nextByte)
+Decoder::doVex2Of2State(uint8_t nextByte)
{
- assert(emi.vex.zero == 0xc5);
consumeByte();
- TwoByteVex tbe = 0;
- tbe.first = nextByte;
+ Vex2Of2 vex = nextByte;
+
+ emi.rex.r = !vex.r;
- 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.l = vex.l;
+ emi.vex.v = ~vex.v;
+
+ switch (vex.p) {
+ case 0:
+ break;
+ case 1:
+ emi.legacy.op = 1;
+ break;
+ case 2:
+ emi.legacy.rep = 1;
+ break;
+ case 3:
+ emi.legacy.repne = 1;
+ break;
+ }
- 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 = TwoByteOpcode;
- emi.opcode.type = Vex;
- return OneByteOpcodeState;
+ return VexOpcodeState;
}
Decoder::State
-Decoder::doThreeByteVexFirstState(uint8_t nextByte)
+Decoder::doVex2Of3State(uint8_t nextByte)
{
+ if (emi.mode.submode != SixtyFourBitMode && bits(nextByte, 7, 6) == 0x3) {
+ // This was actually an LDS instruction. Reroute to that path.
+ emi.vex.present = 0;
+ emi.opcode.type = OneByteOpcode;
+ emi.opcode.op = 0xC4;
+ return processOpcode(ImmediateTypeOneByte, UsesModRMOneByte,
+ nextByte >= 0xA0 && nextByte <= 0xA3);
+ }
+
consumeByte();
- emi.vex.first = nextByte;
- return ThreeByteVexSecondState;
+ Vex2Of3 vex = nextByte;
+
+ emi.rex.r = !vex.r;
+ emi.rex.x = !vex.x;
+ emi.rex.b = !vex.b;
+
+ switch (vex.m) {
+ case 1:
+ emi.opcode.type = TwoByteOpcode;
+ break;
+ case 2:
+ emi.opcode.type = ThreeByte0F38Opcode;
+ break;
+ case 3:
+ emi.opcode.type = ThreeByte0F3AOpcode;
+ break;
+ default:
+ // These encodings are reserved. Pretend this was an undefined
+ // instruction so the main decoder will behave correctly, and stop
+ // trying to interpret bytes.
+ emi.opcode.type = TwoByteOpcode;
+ emi.opcode.op = 0x0B;
+ instDone = true;
+ return ResetState;
+ }
+ return Vex3Of3State;
}
Decoder::State
-Decoder::doThreeByteVexSecondState(uint8_t nextByte)
+Decoder::doVex3Of3State(uint8_t nextByte)
{
+ if (emi.mode.submode != SixtyFourBitMode && bits(nextByte, 7, 6) == 0x3) {
+ // This was actually an LES instruction. Reroute to that path.
+ emi.vex.present = 0;
+ emi.opcode.type = OneByteOpcode;
+ emi.opcode.op = 0xC5;
+ return processOpcode(ImmediateTypeOneByte, UsesModRMOneByte,
+ nextByte >= 0xA0 && nextByte <= 0xA3);
+ }
+
consumeByte();
- emi.vex.second = nextByte;
- emi.opcode.type = Vex;
- return OneByteOpcodeState;
+ Vex3Of3 vex = nextByte;
+
+ emi.rex.w = vex.w;
+
+ emi.vex.l = vex.l;
+ emi.vex.v = ~vex.v;
+
+ switch (vex.p) {
+ case 0:
+ break;
+ case 1:
+ emi.legacy.op = 1;
+ break;
+ case 2:
+ emi.legacy.rep = 1;
+ break;
+ case 3:
+ emi.legacy.repne = 1;
+ break;
+ }
+
+ return VexOpcodeState;
+}
+
+Decoder::State
+Decoder::doVexOpcodeState(uint8_t nextByte)
+{
+ DPRINTF(Decoder, "Found VEX opcode %#x.\n", nextByte);
+
+ emi.opcode.op = nextByte;
+
+ switch (emi.opcode.type) {
+ case TwoByteOpcode:
+ return processOpcode(ImmediateTypeTwoByte, UsesModRMTwoByte);
+ case ThreeByte0F38Opcode:
+ return processOpcode(ImmediateTypeThreeByte0F38,
+ UsesModRMThreeByte0F38);
+ case ThreeByte0F3AOpcode:
+ return processOpcode(ImmediateTypeThreeByte0F3A,
+ UsesModRMThreeByte0F3A);
+ default:
+ panic("Unrecognized opcode type %d.\n", emi.opcode.type);
+ }
}
// Load the first opcode byte. Determine if there are more opcode bytes, and
@@ -292,14 +378,9 @@ Decoder::doOneByteOpcodeState(uint8_t nextByte)
State nextState = ErrorState;
consumeByte();
- 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;
+ if (nextByte == 0x0f) {
DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
+ nextState = TwoByteOpcodeState;
} else {
DPRINTF(Decoder, "Found one byte opcode %#x.\n", nextByte);
emi.opcode.type = OneByteOpcode;
@@ -421,54 +502,6 @@ 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.