#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;
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.