Split the x86 "process" predecoder method into it's own file.
--HG-- extra : convert_revision : 88185e592df2a7527d36efcce7376fb05f469cbc
This commit is contained in:
@@ -88,6 +88,7 @@ if env['TARGET_ISA'] == 'x86':
|
||||
Source('floatregfile.cc')
|
||||
Source('intregfile.cc')
|
||||
Source('miscregfile.cc')
|
||||
Source('predecoder.cc')
|
||||
Source('predecoder_tables.cc')
|
||||
Source('regfile.cc')
|
||||
Source('remote_gdb.cc')
|
||||
|
||||
@@ -59,9 +59,6 @@
|
||||
#define __ARCH_X86_PREDECODER_HH__
|
||||
|
||||
#include "arch/x86/types.hh"
|
||||
#include "base/bitfield.hh"
|
||||
#include "base/misc.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "sim/host.hh"
|
||||
|
||||
class ThreadContext;
|
||||
@@ -135,244 +132,7 @@ namespace X86ISA
|
||||
tc = _tc;
|
||||
}
|
||||
|
||||
void process()
|
||||
{
|
||||
assert(!outOfBytes);
|
||||
assert(!emiIsReady);
|
||||
while(!emiIsReady && !outOfBytes)
|
||||
{
|
||||
uint8_t nextByte = (fetchChunk >> (offset * 8)) & 0xff;
|
||||
switch(state)
|
||||
{
|
||||
case Prefix:
|
||||
uint8_t prefix = Prefixes[nextByte];
|
||||
if(prefix)
|
||||
offset++;
|
||||
switch(prefix)
|
||||
{
|
||||
//Operand size override prefixes
|
||||
case OperandSizeOverride:
|
||||
DPRINTF(Predecoder, "Found operand size override prefix.\n");
|
||||
break;
|
||||
case AddressSizeOverride:
|
||||
DPRINTF(Predecoder, "Found address size override prefix.\n");
|
||||
break;
|
||||
//Segment override prefixes
|
||||
case CSOverride:
|
||||
DPRINTF(Predecoder, "Found cs segment override.\n");
|
||||
break;
|
||||
case DSOverride:
|
||||
DPRINTF(Predecoder, "Found ds segment override.\n");
|
||||
break;
|
||||
case ESOverride:
|
||||
DPRINTF(Predecoder, "Found es segment override.\n");
|
||||
break;
|
||||
case FSOverride:
|
||||
DPRINTF(Predecoder, "Found fs segment override.\n");
|
||||
break;
|
||||
case GSOverride:
|
||||
DPRINTF(Predecoder, "Found gs segment override.\n");
|
||||
break;
|
||||
case SSOverride:
|
||||
DPRINTF(Predecoder, "Found ss segment override.\n");
|
||||
break;
|
||||
case Lock:
|
||||
DPRINTF(Predecoder, "Found lock prefix.\n");
|
||||
break;
|
||||
case Rep:
|
||||
DPRINTF(Predecoder, "Found rep prefix.\n");
|
||||
break;
|
||||
case Repne:
|
||||
DPRINTF(Predecoder, "Found repne prefix.\n");
|
||||
break;
|
||||
case Rex:
|
||||
DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte);
|
||||
emi.rexPrefix = nextByte;
|
||||
break;
|
||||
case 0:
|
||||
emi.numOpcodes = 0;
|
||||
state = Opcode;
|
||||
break;
|
||||
default:
|
||||
panic("Unrecognized prefix %#x\n", nextByte);
|
||||
}
|
||||
break;
|
||||
case Opcode:
|
||||
emi.numOpcodes++;
|
||||
assert(emi.numOpcodes < 2);
|
||||
if(nextByte == 0xf0)
|
||||
{
|
||||
DPRINTF(Predecoder, "Found two byte opcode.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
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(immediateSize) {
|
||||
state = Immediate;
|
||||
} else {
|
||||
emiIsReady = true;
|
||||
state = Prefix;
|
||||
}
|
||||
}
|
||||
offset++;
|
||||
break;
|
||||
case ModRM:
|
||||
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 == 0x80)
|
||||
displacementSize = 2;
|
||||
else if(nextByte & 0xC0 == 0x40)
|
||||
displacementSize = 1;
|
||||
else
|
||||
displacementSize = 0;
|
||||
} else {
|
||||
//figure out 32/64 bit displacement size
|
||||
if(nextByte & 0xC7 == 0x05 ||
|
||||
nextByte & 0xC0 == 0x80)
|
||||
displacementSize = 4;
|
||||
else if(nextByte & 0xC0 == 0x40)
|
||||
displacementSize = 2;
|
||||
else
|
||||
displacementSize = 0;
|
||||
}
|
||||
//If there's an SIB, get that next.
|
||||
//There is no SIB in 16 bit mode.
|
||||
if(nextByte & 0x7 == 4 &&
|
||||
nextByte & 0xC0 != 0xC0) {
|
||||
// && in 32/64 bit mode)
|
||||
state = SIB;
|
||||
} else if(displacementSize) {
|
||||
state = Displacement;
|
||||
} else if(immediateSize) {
|
||||
state = Immediate;
|
||||
} else {
|
||||
emiIsReady = true;
|
||||
state = Prefix;
|
||||
}
|
||||
//The ModRM byte is consumed no matter what
|
||||
offset++;
|
||||
break;
|
||||
case SIB:
|
||||
DPRINTF(Predecoder, "Found SIB byte %#x.\n", nextByte);
|
||||
offset++;
|
||||
if(displacementSize) {
|
||||
state = Displacement;
|
||||
} else if(immediateSize) {
|
||||
state = Immediate;
|
||||
} else {
|
||||
emiIsReady = true;
|
||||
state = Prefix;
|
||||
}
|
||||
break;
|
||||
case Displacement:
|
||||
//Gather up the displacement, or at least as much of it
|
||||
//as we can get.
|
||||
|
||||
//Figure out how many bytes we still need to get for the
|
||||
//displacement.
|
||||
toGet = displacementSize - displacementCollected;
|
||||
//Figure out how many bytes are left in our "buffer"
|
||||
remaining = sizeof(MachInst) - offset;
|
||||
//Get as much as we need, up to the amount available.
|
||||
toGet = toGet > remaining ? remaining : toGet;
|
||||
|
||||
//Shift the bytes we want to be all the way to the right
|
||||
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 * 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
|
||||
switch(displacementSize)
|
||||
{
|
||||
case 1:
|
||||
emi.displacement = sext<8>(emi.displacement);
|
||||
break;
|
||||
case 2:
|
||||
emi.displacement = sext<16>(emi.displacement);
|
||||
break;
|
||||
case 4:
|
||||
emi.displacement = sext<32>(emi.displacement);
|
||||
break;
|
||||
default:
|
||||
panic("Undefined displacement size!\n");
|
||||
}
|
||||
DPRINTF(Predecoder, "Collected displacement %#x.\n",
|
||||
emi.displacement);
|
||||
if(immediateSize) {
|
||||
state = Immediate;
|
||||
} else {
|
||||
emiIsReady = true;
|
||||
state = Prefix;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Immediate:
|
||||
//Gather up the displacement, or at least as much of it
|
||||
//as we can get
|
||||
|
||||
//Figure out how many bytes we still need to get for the
|
||||
//immediate.
|
||||
toGet = immediateSize - immediateCollected;
|
||||
//Figure out how many bytes are left in our "buffer"
|
||||
remaining = sizeof(MachInst) - offset;
|
||||
//Get as much as we need, up to the amount available.
|
||||
toGet = toGet > remaining ? remaining : toGet;
|
||||
|
||||
//Shift the bytes we want to be all the way to the right
|
||||
partialDisp = fetchChunk >> (offset * 8);
|
||||
//Mask off what we don't want
|
||||
partialDisp &= mask(toGet * 8);
|
||||
//Shift it over to overlay with our immediate.
|
||||
partialDisp <<= (immediateCollected * 8);
|
||||
//Put it into our immediate
|
||||
emi.immediate |= partialDisp;
|
||||
//Update how many bytes we've collected.
|
||||
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;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
panic("Unrecognized state! %d\n", state);
|
||||
}
|
||||
if(offset == sizeof(MachInst))
|
||||
outOfBytes = true;
|
||||
}
|
||||
}
|
||||
void process();
|
||||
|
||||
//Use this to give data to the predecoder. This should be used
|
||||
//when there is control flow.
|
||||
|
||||
Reference in New Issue
Block a user