summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-03-15 19:16:36 +0000
committerGabe Black <gblack@eecs.umich.edu>2007-03-15 19:16:36 +0000
commit05c71c6194bcd94e0e51634970ed9ceda37a47ad (patch)
tree44a3f580de538b34ef00da2c830e51b45ba26bba /src/arch
parentc6e1dc61c23dc1f5300610ce8348f9a0e9c128cc (diff)
parent6cdd434f7f94afc81aa09c411c00969cd80cc833 (diff)
downloadgem5-05c71c6194bcd94e0e51634970ed9ceda37a47ad.tar.xz
Merge zizzer.eecs.umich.edu:/bk/newmem
into ahchoo.blinky.homelinux.org:/home/gblack/m5/newmem-x86 --HG-- extra : convert_revision : cf2cc07f18b877f980e2d1fc83916f7849d9c7d9
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/x86/predecoder.hh124
-rw-r--r--src/arch/x86/predecoder_tables.cc79
-rw-r--r--src/arch/x86/types.hh6
3 files changed, 148 insertions, 61 deletions
diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh
index 371ce9db9..f1dee6bf4 100644
--- a/src/arch/x86/predecoder.hh
+++ b/src/arch/x86/predecoder.hh
@@ -61,6 +61,7 @@
#include "arch/x86/types.hh"
#include "base/bitfield.hh"
#include "base/misc.hh"
+#include "base/trace.hh"
#include "sim/host.hh"
class ThreadContext;
@@ -70,8 +71,11 @@ namespace X86ISA
class Predecoder
{
private:
+ //These are defined and documented in predecoder_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 ImmediateTypeToSize[3][10];
protected:
ThreadContext * tc;
@@ -133,7 +137,6 @@ namespace X86ISA
void process()
{
- warn("About to process some bytes\n");
assert(!outOfBytes);
assert(!emiIsReady);
while(!emiIsReady && !outOfBytes)
@@ -143,60 +146,51 @@ namespace X86ISA
{
case Prefix:
uint8_t prefix = Prefixes[nextByte];
+ if(prefix)
+ offset++;
switch(prefix)
{
//Operand size override prefixes
case OperandSizeOverride:
- warn("Found operand size override prefix!\n");
- offset++;
+ DPRINTF(Predecoder, "Found operand size override prefix.\n");
break;
case AddressSizeOverride:
- warn("Found address size override prefix!\n");
- offset++;
+ DPRINTF(Predecoder, "Found address size override prefix.\n");
break;
//Segment override prefixes
case CSOverride:
- warn("Found cs segment override!\n");
- offset++;
+ DPRINTF(Predecoder, "Found cs segment override.\n");
break;
case DSOverride:
- warn("Found ds segment override!\n");
- offset++;
+ DPRINTF(Predecoder, "Found ds segment override.\n");
break;
case ESOverride:
- warn("Found es segment override!\n");
- offset++;
+ DPRINTF(Predecoder, "Found es segment override.\n");
break;
case FSOverride:
- warn("Found fs segment override!\n");
- offset++;
+ DPRINTF(Predecoder, "Found fs segment override.\n");
break;
case GSOverride:
- warn("Found gs segment override!\n");
- offset++;
+ DPRINTF(Predecoder, "Found gs segment override.\n");
break;
case SSOverride:
- warn("Found ss segment override!\n");
- offset++;
+ DPRINTF(Predecoder, "Found ss segment override.\n");
break;
case Lock:
- warn("Found lock prefix!\n");
- offset++;
+ DPRINTF(Predecoder, "Found lock prefix.\n");
break;
case Rep:
- warn("Found rep prefix!\n");
- offset++;
+ DPRINTF(Predecoder, "Found rep prefix.\n");
break;
case Repne:
- warn("Found repne prefix!\n");
- offset++;
+ DPRINTF(Predecoder, "Found repne prefix.\n");
break;
case Rex:
- warn("Found Rex prefix %#x!\n", nextByte);
- offset++;
+ DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte);
+ emi.rexPrefix = nextByte;
break;
case 0:
- emi.twoByteOpcode = false;
+ emi.numOpcodes = 0;
state = Opcode;
break;
default:
@@ -204,20 +198,30 @@ namespace X86ISA
}
break;
case Opcode:
+ emi.numOpcodes++;
+ assert(emi.numOpcodes < 2);
if(nextByte == 0xf0)
{
- warn("Found two byte opcode!\n");
- emi.twoByteOpcode = true;
+ DPRINTF(Predecoder, "Found two byte opcode.\n");
}
else
{
- warn("Found opcode %#x!\n", nextByte);
- if (UsesModRM[emi.twoByteOpcode ? 1 : 0][nextByte]) {
+ immediateCollected = 0;
+ displacementCollected = 0;
+ emi.immediate = 0;
+ emi.displacement = 0;
+ int immType = ImmediateType[
+ emi.numOpcodes - 1][nextByte];
+ if(0) //16 bit mode
+ immediateSize = ImmediateTypeToSize[0][immType];
+ else if(!(emi.rexPrefix & 0x4)) //32 bit mode
+ immediateSize = ImmediateTypeToSize[1][immType];
+ else //64 bit mode
+ immediateSize = ImmediateTypeToSize[2][immType];
+ DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte);
+ if (UsesModRM[emi.numOpcodes - 1][nextByte]) {
state = ModRM;
- } else if(0 /* uses immediate */) {
- //Figure out how big the immediate should be
- immediateCollected = 0;
- emi.immediate = 0;
+ } else if(immediateSize) {
state = Immediate;
} else {
emiIsReady = true;
@@ -227,25 +231,25 @@ namespace X86ISA
offset++;
break;
case ModRM:
- warn("Found modrm byte %#x!\n", nextByte);
+ DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte);
if (0) {//in 16 bit mode
//figure out 16 bit displacement size
if(nextByte & 0xC7 == 0x06 ||
- nextByte & 0xC0 == 0x40)
- displacementSize = 1;
- else if(nextByte & 0xC7 == 0x80)
+ nextByte & 0xC0 == 0x80)
displacementSize = 2;
+ else if(nextByte & 0xC0 == 0x40)
+ displacementSize = 1;
else
displacementSize = 0;
} else {
//figure out 32/64 bit displacement size
- if(nextByte & 0xC7 == 0x06 ||
- nextByte & 0xC0 == 0x40)
+ if(nextByte & 0xC7 == 0x05 ||
+ nextByte & 0xC0 == 0x80)
displacementSize = 4;
- else if(nextByte & 0xC7 == 0x80)
+ else if(nextByte & 0xC0 == 0x40)
displacementSize = 2;
else
- displacementSize = 4;
+ displacementSize = 0;
}
//If there's an SIB, get that next.
//There is no SIB in 16 bit mode.
@@ -254,12 +258,8 @@ namespace X86ISA
// && in 32/64 bit mode)
state = SIB;
} else if(displacementSize) {
- displacementCollected = 0;
- emi.displacement = 0;
state = Displacement;
} else if(immediateSize) {
- immediateCollected = 0;
- emi.immediate = 0;
state = Immediate;
} else {
emiIsReady = true;
@@ -269,15 +269,11 @@ namespace X86ISA
offset++;
break;
case SIB:
- warn("Found SIB byte %#x!\n", nextByte);
+ DPRINTF(Predecoder, "Found SIB byte %#x.\n", nextByte);
offset++;
if(displacementSize) {
- displacementCollected = 0;
- emi.displacement = 0;
state = Displacement;
} else if(immediateSize) {
- immediateCollected = 0;
- emi.immediate = 0;
state = Immediate;
} else {
emiIsReady = true;
@@ -297,15 +293,18 @@ namespace X86ISA
toGet = toGet > remaining ? remaining : toGet;
//Shift the bytes we want to be all the way to the right
- partialDisp = fetchChunk >> offset;
+ partialDisp = fetchChunk >> (offset * 8);
//Mask off what we don't want
partialDisp &= mask(toGet * 8);
//Shift it over to overlay with our displacement.
- partialDisp <<= displacementCollected;
+ partialDisp <<= (displacementCollected * 8);
//Put it into our displacement
emi.displacement |= partialDisp;
//Update how many bytes we've collected.
displacementCollected += toGet;
+ offset += toGet;
+ DPRINTF(Predecoder, "Collecting %d byte displacement, got %d bytes.\n",
+ displacementSize, displacementCollected);
if(displacementSize == displacementCollected) {
//Sign extend the displacement
@@ -323,9 +322,9 @@ namespace X86ISA
default:
panic("Undefined displacement size!\n");
}
+ DPRINTF(Predecoder, "Collected displacement %#x.\n",
+ emi.displacement);
if(immediateSize) {
- immediateCollected = 0;
- emi.immediate = 0;
state = Immediate;
} else {
emiIsReady = true;
@@ -346,17 +345,23 @@ namespace X86ISA
toGet = toGet > remaining ? remaining : toGet;
//Shift the bytes we want to be all the way to the right
- partialDisp = fetchChunk >> offset;
+ partialDisp = fetchChunk >> (offset * 8);
//Mask off what we don't want
partialDisp &= mask(toGet * 8);
//Shift it over to overlay with our immediate.
- partialDisp <<= displacementCollected;
+ partialDisp <<= (immediateCollected * 8);
//Put it into our immediate
- emi.displacement |= partialDisp;
+ emi.immediate |= partialDisp;
//Update how many bytes we've collected.
- displacementCollected += toGet;
+ immediateCollected += toGet;
+ offset += toGet;
+ DPRINTF(Predecoder, "Collecting %d byte immediate, got %d bytes.\n",
+ immediateSize, immediateCollected);
+
if(immediateSize == immediateCollected)
{
+ DPRINTF(Predecoder, "Collected immediate %#x.\n",
+ emi.immediate);
emiIsReady = true;
state = Prefix;
}
@@ -378,7 +383,6 @@ namespace X86ISA
fetchChunk = data;
assert(off < sizeof(MachInst));
outOfBytes = false;
- warn("About to call process.\n");
process();
}
diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc
index 9304eee47..0cebef61a 100644
--- a/src/arch/x86/predecoder_tables.cc
+++ b/src/arch/x86/predecoder_tables.cc
@@ -140,4 +140,83 @@ namespace X86ISA
/* F */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0
}
};
+
+ enum ImmediateTypes {
+ NoImm,
+ NI = NoImm,
+ ByteImm,
+ BY = ByteImm,
+ WordImm,
+ WO = WordImm,
+ DWordImm,
+ DW = DWordImm,
+ QWordImm,
+ QW = QWordImm,
+ OWordImm,
+ OW = OWordImm,
+ VWordImm,
+ VW = VWordImm,
+ ZWordImm,
+ ZW = ZWordImm,
+ Pointer,
+ PO = Pointer,
+ //The enter instruction takes -2- immediates for a total of 3 bytes
+ Enter,
+ EN = Enter
+ };
+
+ const uint8_t Predecoder::ImmediateTypeToSize[3][10] =
+ {
+// noimm byte word dword qword oword vword zword enter
+ {0, 1, 2, 4, 8, 16, 2, 2, 3, 4}, //16 bit
+ {0, 1, 2, 4, 8, 16, 4, 4, 3, 6}, //32 bit
+ {0, 1, 2, 4, 8, 16, 4, 8, 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 Predecoder::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 */ BY, VW, BY, 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 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+/* 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, 0 , 0 , 0 , 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
+ }
+ };
}
diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh
index 68d95de94..583f03d55 100644
--- a/src/arch/x86/types.hh
+++ b/src/arch/x86/types.hh
@@ -94,7 +94,11 @@ namespace X86ISA
uint8_t legacyPrefixes;
uint8_t rexPrefix;
- bool twoByteOpcode;
+ //Right now, we ignore that this can be 3 in
+ //some cases
+ uint8_t numOpcodes;
+ //This will need to be decoded specially later
+ bool is3dnow;
uint8_t opcode;
uint64_t immediate;
uint64_t displacement;