Merge zizzer.eecs.umich.edu:/bk/newmem

into  ahchoo.blinky.homelinux.org:/home/gblack/m5/newmem-x86

--HG--
extra : convert_revision : cf2cc07f18b877f980e2d1fc83916f7849d9c7d9
This commit is contained in:
Gabe Black 2007-03-15 19:16:36 +00:00
commit 05c71c6194
4 changed files with 149 additions and 61 deletions

View file

@ -61,6 +61,7 @@
#include "arch/x86/types.hh" #include "arch/x86/types.hh"
#include "base/bitfield.hh" #include "base/bitfield.hh"
#include "base/misc.hh" #include "base/misc.hh"
#include "base/trace.hh"
#include "sim/host.hh" #include "sim/host.hh"
class ThreadContext; class ThreadContext;
@ -70,8 +71,11 @@ namespace X86ISA
class Predecoder class Predecoder
{ {
private: private:
//These are defined and documented in predecoder_tables.cc
static const uint8_t Prefixes[256]; static const uint8_t Prefixes[256];
static const uint8_t UsesModRM[2][256]; static const uint8_t UsesModRM[2][256];
static const uint8_t ImmediateType[2][256];
static const uint8_t ImmediateTypeToSize[3][10];
protected: protected:
ThreadContext * tc; ThreadContext * tc;
@ -133,7 +137,6 @@ namespace X86ISA
void process() void process()
{ {
warn("About to process some bytes\n");
assert(!outOfBytes); assert(!outOfBytes);
assert(!emiIsReady); assert(!emiIsReady);
while(!emiIsReady && !outOfBytes) while(!emiIsReady && !outOfBytes)
@ -143,60 +146,51 @@ namespace X86ISA
{ {
case Prefix: case Prefix:
uint8_t prefix = Prefixes[nextByte]; uint8_t prefix = Prefixes[nextByte];
if(prefix)
offset++;
switch(prefix) switch(prefix)
{ {
//Operand size override prefixes //Operand size override prefixes
case OperandSizeOverride: case OperandSizeOverride:
warn("Found operand size override prefix!\n"); DPRINTF(Predecoder, "Found operand size override prefix.\n");
offset++;
break; break;
case AddressSizeOverride: case AddressSizeOverride:
warn("Found address size override prefix!\n"); DPRINTF(Predecoder, "Found address size override prefix.\n");
offset++;
break; break;
//Segment override prefixes //Segment override prefixes
case CSOverride: case CSOverride:
warn("Found cs segment override!\n"); DPRINTF(Predecoder, "Found cs segment override.\n");
offset++;
break; break;
case DSOverride: case DSOverride:
warn("Found ds segment override!\n"); DPRINTF(Predecoder, "Found ds segment override.\n");
offset++;
break; break;
case ESOverride: case ESOverride:
warn("Found es segment override!\n"); DPRINTF(Predecoder, "Found es segment override.\n");
offset++;
break; break;
case FSOverride: case FSOverride:
warn("Found fs segment override!\n"); DPRINTF(Predecoder, "Found fs segment override.\n");
offset++;
break; break;
case GSOverride: case GSOverride:
warn("Found gs segment override!\n"); DPRINTF(Predecoder, "Found gs segment override.\n");
offset++;
break; break;
case SSOverride: case SSOverride:
warn("Found ss segment override!\n"); DPRINTF(Predecoder, "Found ss segment override.\n");
offset++;
break; break;
case Lock: case Lock:
warn("Found lock prefix!\n"); DPRINTF(Predecoder, "Found lock prefix.\n");
offset++;
break; break;
case Rep: case Rep:
warn("Found rep prefix!\n"); DPRINTF(Predecoder, "Found rep prefix.\n");
offset++;
break; break;
case Repne: case Repne:
warn("Found repne prefix!\n"); DPRINTF(Predecoder, "Found repne prefix.\n");
offset++;
break; break;
case Rex: case Rex:
warn("Found Rex prefix %#x!\n", nextByte); DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte);
offset++; emi.rexPrefix = nextByte;
break; break;
case 0: case 0:
emi.twoByteOpcode = false; emi.numOpcodes = 0;
state = Opcode; state = Opcode;
break; break;
default: default:
@ -204,20 +198,30 @@ namespace X86ISA
} }
break; break;
case Opcode: case Opcode:
emi.numOpcodes++;
assert(emi.numOpcodes < 2);
if(nextByte == 0xf0) if(nextByte == 0xf0)
{ {
warn("Found two byte opcode!\n"); DPRINTF(Predecoder, "Found two byte opcode.\n");
emi.twoByteOpcode = true;
} }
else else
{ {
warn("Found opcode %#x!\n", nextByte);
if (UsesModRM[emi.twoByteOpcode ? 1 : 0][nextByte]) {
state = ModRM;
} else if(0 /* uses immediate */) {
//Figure out how big the immediate should be
immediateCollected = 0; immediateCollected = 0;
displacementCollected = 0;
emi.immediate = 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(immediateSize) {
state = Immediate; state = Immediate;
} else { } else {
emiIsReady = true; emiIsReady = true;
@ -227,25 +231,25 @@ namespace X86ISA
offset++; offset++;
break; break;
case ModRM: case ModRM:
warn("Found modrm byte %#x!\n", nextByte); DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte);
if (0) {//in 16 bit mode if (0) {//in 16 bit mode
//figure out 16 bit displacement size //figure out 16 bit displacement size
if(nextByte & 0xC7 == 0x06 || if(nextByte & 0xC7 == 0x06 ||
nextByte & 0xC0 == 0x40) nextByte & 0xC0 == 0x80)
displacementSize = 1;
else if(nextByte & 0xC7 == 0x80)
displacementSize = 2; displacementSize = 2;
else if(nextByte & 0xC0 == 0x40)
displacementSize = 1;
else else
displacementSize = 0; displacementSize = 0;
} else { } else {
//figure out 32/64 bit displacement size //figure out 32/64 bit displacement size
if(nextByte & 0xC7 == 0x06 || if(nextByte & 0xC7 == 0x05 ||
nextByte & 0xC0 == 0x40) nextByte & 0xC0 == 0x80)
displacementSize = 4; displacementSize = 4;
else if(nextByte & 0xC7 == 0x80) else if(nextByte & 0xC0 == 0x40)
displacementSize = 2; displacementSize = 2;
else else
displacementSize = 4; displacementSize = 0;
} }
//If there's an SIB, get that next. //If there's an SIB, get that next.
//There is no SIB in 16 bit mode. //There is no SIB in 16 bit mode.
@ -254,12 +258,8 @@ namespace X86ISA
// && in 32/64 bit mode) // && in 32/64 bit mode)
state = SIB; state = SIB;
} else if(displacementSize) { } else if(displacementSize) {
displacementCollected = 0;
emi.displacement = 0;
state = Displacement; state = Displacement;
} else if(immediateSize) { } else if(immediateSize) {
immediateCollected = 0;
emi.immediate = 0;
state = Immediate; state = Immediate;
} else { } else {
emiIsReady = true; emiIsReady = true;
@ -269,15 +269,11 @@ namespace X86ISA
offset++; offset++;
break; break;
case SIB: case SIB:
warn("Found SIB byte %#x!\n", nextByte); DPRINTF(Predecoder, "Found SIB byte %#x.\n", nextByte);
offset++; offset++;
if(displacementSize) { if(displacementSize) {
displacementCollected = 0;
emi.displacement = 0;
state = Displacement; state = Displacement;
} else if(immediateSize) { } else if(immediateSize) {
immediateCollected = 0;
emi.immediate = 0;
state = Immediate; state = Immediate;
} else { } else {
emiIsReady = true; emiIsReady = true;
@ -297,15 +293,18 @@ namespace X86ISA
toGet = toGet > remaining ? remaining : toGet; toGet = toGet > remaining ? remaining : toGet;
//Shift the bytes we want to be all the way to the right //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 //Mask off what we don't want
partialDisp &= mask(toGet * 8); partialDisp &= mask(toGet * 8);
//Shift it over to overlay with our displacement. //Shift it over to overlay with our displacement.
partialDisp <<= displacementCollected; partialDisp <<= (displacementCollected * 8);
//Put it into our displacement //Put it into our displacement
emi.displacement |= partialDisp; emi.displacement |= partialDisp;
//Update how many bytes we've collected. //Update how many bytes we've collected.
displacementCollected += toGet; displacementCollected += toGet;
offset += toGet;
DPRINTF(Predecoder, "Collecting %d byte displacement, got %d bytes.\n",
displacementSize, displacementCollected);
if(displacementSize == displacementCollected) { if(displacementSize == displacementCollected) {
//Sign extend the displacement //Sign extend the displacement
@ -323,9 +322,9 @@ namespace X86ISA
default: default:
panic("Undefined displacement size!\n"); panic("Undefined displacement size!\n");
} }
DPRINTF(Predecoder, "Collected displacement %#x.\n",
emi.displacement);
if(immediateSize) { if(immediateSize) {
immediateCollected = 0;
emi.immediate = 0;
state = Immediate; state = Immediate;
} else { } else {
emiIsReady = true; emiIsReady = true;
@ -346,17 +345,23 @@ namespace X86ISA
toGet = toGet > remaining ? remaining : toGet; toGet = toGet > remaining ? remaining : toGet;
//Shift the bytes we want to be all the way to the right //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 //Mask off what we don't want
partialDisp &= mask(toGet * 8); partialDisp &= mask(toGet * 8);
//Shift it over to overlay with our immediate. //Shift it over to overlay with our immediate.
partialDisp <<= displacementCollected; partialDisp <<= (immediateCollected * 8);
//Put it into our immediate //Put it into our immediate
emi.displacement |= partialDisp; emi.immediate |= partialDisp;
//Update how many bytes we've collected. //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) if(immediateSize == immediateCollected)
{ {
DPRINTF(Predecoder, "Collected immediate %#x.\n",
emi.immediate);
emiIsReady = true; emiIsReady = true;
state = Prefix; state = Prefix;
} }
@ -378,7 +383,6 @@ namespace X86ISA
fetchChunk = data; fetchChunk = data;
assert(off < sizeof(MachInst)); assert(off < sizeof(MachInst));
outOfBytes = false; outOfBytes = false;
warn("About to call process.\n");
process(); process();
} }

View file

@ -140,4 +140,83 @@ namespace X86ISA
/* F */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 /* 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
}
};
} }

View file

@ -94,7 +94,11 @@ namespace X86ISA
uint8_t legacyPrefixes; uint8_t legacyPrefixes;
uint8_t rexPrefix; 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; uint8_t opcode;
uint64_t immediate; uint64_t immediate;
uint64_t displacement; uint64_t displacement;

View file

@ -137,6 +137,7 @@ baseFlags = [
'PciConfigAll', 'PciConfigAll',
'Pipeline', 'Pipeline',
'Printf', 'Printf',
'Predecoder',
'Quiesce', 'Quiesce',
'ROB', 'ROB',
'Regs', 'Regs',