void
Decoder::process()
{
- //This function drives the decoder state machine.
+ // This function drives the decoder state machine.
- //Some sanity checks. You shouldn't try to process more bytes if
- //there aren't any, and you shouldn't overwrite an already
- //decoder ExtMachInst.
+ // Some sanity checks. You shouldn't try to process more bytes if
+ // there aren't any, and you shouldn't overwrite an already decoded
+ // ExtMachInst.
assert(!outOfBytes);
assert(!instDone);
instBytes->chunks.push_back(fetchChunk);
}
- //While there's still something to do...
+ // While there's still something to do...
while (!instDone && !outOfBytes) {
uint8_t nextByte = getNextByte();
switch (state) {
}
}
-//Either get a prefix and record it in the ExtMachInst, or send the
-//state machine on to get the opcode(s).
+// Either get a prefix and record it in the ExtMachInst, or send the
+// state machine on to get the opcode(s).
Decoder::State
Decoder::doPrefixState(uint8_t nextByte)
{
prefix = 0;
if (prefix)
consumeByte();
- switch(prefix)
- {
- //Operand size override prefixes
+ switch(prefix) {
+ // Operand size override prefixes
case OperandSizeOverride:
DPRINTF(Decoder, "Found operand size override prefix.\n");
emi.legacy.op = true;
DPRINTF(Decoder, "Found address size override prefix.\n");
emi.legacy.addr = true;
break;
- //Segment override prefixes
+ // Segment override prefixes
case CSOverride:
case DSOverride:
case ESOverride:
State nextState = ErrorState;
const uint8_t opcode = emi.opcode.op;
- //Figure out the effective operand size. This can be overriden to
- //a fixed value at the decoder level.
+ // Figure out the effective operand size. This can be overriden to
+ // a fixed value at the decoder level.
int logOpSize;
if (emi.rex.w)
logOpSize = 3; // 64 bit operand size
else
logOpSize = defOp;
- //Set the actual op size
+ // 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.
+ // 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
+ // 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.
+ // 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.
+ // Figure out how big of an immediate we'll retreive based
+ // on the opcode.
int immType = immTable[opcode];
if (addrSizedImm)
immediateSize = SizeTypeToSize[logAddrSize - 1][immType];
else
immediateSize = SizeTypeToSize[logOpSize - 1][immType];
- //Determine what to expect next
+ // Determine what to expect next.
if (modrmTable[opcode]) {
nextState = ModRMState;
} else {
return nextState;
}
-//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.
+// 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.
Decoder::State
Decoder::doModRMState(uint8_t nextByte)
{
ModRM modRM = nextByte;
DPRINTF(Decoder, "Found modrm byte %#x.\n", nextByte);
if (defOp == 1) {
- //figure out 16 bit displacement size
+ // Figure out 16 bit displacement size.
if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
displacementSize = 2;
else if (modRM.mod == 1)
else
displacementSize = 0;
} else {
- //figure out 32/64 bit displacement size
+ // Figure out 32/64 bit displacement size.
if ((modRM.mod == 0 && modRM.rm == 5) || modRM.mod == 2)
displacementSize = 4;
else if (modRM.mod == 1)
immediateSize = (emi.opSize == 8) ? 4 : emi.opSize;
}
- //If there's an SIB, get that next.
- //There is no SIB in 16 bit mode.
+ // If there's an SIB, get that next.
+ // There is no SIB in 16 bit mode.
if (modRM.rm == 4 && modRM.mod != 3) {
// && in 32/64 bit mode)
nextState = SIBState;
instDone = true;
nextState = ResetState;
}
- //The ModRM byte is consumed no matter what
+ // The ModRM byte is consumed no matter what.
consumeByte();
emi.modRM = modRM;
return nextState;
}
-//Get the SIB byte. We don't do anything with it at this point, other
-//than storing it in the ExtMachInst. Determine if we need to get a
-//displacement or immediate next.
+// Get the SIB byte. We don't do anything with it at this point, other
+// than storing it in the ExtMachInst. Determine if we need to get a
+// displacement or immediate next.
Decoder::State
Decoder::doSIBState(uint8_t nextByte)
{
return nextState;
}
-//Gather up the displacement, or at least as much of it
-//as we can get.
+// Gather up the displacement, or at least as much of it as we can get.
Decoder::State
Decoder::doDisplacementState()
{
displacementSize, immediateCollected);
if (displacementSize == immediateCollected) {
- //Reset this for other immediates.
+ // Reset this for other immediates.
immediateCollected = 0;
- //Sign extend the displacement
+ // Sign extend the displacement.
switch(displacementSize)
{
case 1:
return nextState;
}
-//Gather up the immediate, or at least as much of it
-//as we can get
+// Gather up the immediate, or at least as much of it as we can get.
Decoder::State
Decoder::doImmediateState()
{
State nextState = ErrorState;
- getImmediate(immediateCollected,
- emi.immediate,
- immediateSize);
+ getImmediate(immediateCollected, emi.immediate, immediateSize);
DPRINTF(Decoder, "Collecting %d byte immediate, got %d bytes.\n",
immediateSize, immediateCollected);
- if (immediateSize == immediateCollected)
- {
- //Reset this for other immediates.
+ if (immediateSize == immediateCollected) {
+ // Reset this for other immediates.
immediateCollected = 0;
//XXX Warning! The following is an observed pattern and might
- //not always be true!
-
- //Instructions which use 64 bit operands but 32 bit immediates
- //need to have the immediate sign extended to 64 bits.
- //Instructions which use true 64 bit immediates won't be
- //affected, and instructions that use true 32 bit immediates
- //won't notice.
- switch(immediateSize)
- {
+ // not always be true!
+
+ // Instructions which use 64 bit operands but 32 bit immediates
+ // need to have the immediate sign extended to 64 bits.
+ // Instructions which use true 64 bit immediates won't be
+ // affected, and instructions that use true 32 bit immediates
+ // won't notice.
+ switch(immediateSize) {
case 4:
emi.immediate = sext<32>(emi.immediate);
break;
emi.immediate);
instDone = true;
nextState = ResetState;
- }
- else
+ } else {
nextState = ImmediateState;
+ }
return nextState;
}
class Decoder : public InstDecoder
{
private:
- //These are defined and documented in decoder_tables.cc
+ // These are defined and documented in decoder_tables.cc
static const uint8_t SizeTypeToSize[3][10];
typedef const uint8_t ByteTable[256];
static ByteTable Prefixes;
static InstBytes dummy;
- //The bytes to be predecoded
+ // The bytes to be predecoded.
MachInst fetchChunk;
InstBytes *instBytes;
int chunkIdx;
- //The pc of the start of fetchChunk
+ // The pc of the start of fetchChunk.
Addr basePC;
- //The pc the current instruction started at
+ // The pc the current instruction started at.
Addr origPC;
- //The offset into fetchChunk of current processing
+ // The offset into fetchChunk of current processing.
int offset;
- //The extended machine instruction being generated
+ // The extended machine instruction being generated.
ExtMachInst emi;
- //Predecoding state
+ // Predecoding state.
X86Mode mode;
X86SubMode submode;
uint8_t altOp;
uint8_t defAddr;
uint8_t stack;
- uint8_t getNextByte()
+ uint8_t
+ getNextByte()
{
return ((uint8_t *)&fetchChunk)[offset];
}
- void getImmediate(int &collected, uint64_t ¤t, int size)
+ void
+ getImmediate(int &collected, uint64_t ¤t, int size)
{
- //Figure out how many bytes we still need to get for the
- //immediate.
+ // Figure out how many bytes we still need to get for the
+ // immediate.
int toGet = size - collected;
- //Figure out how many bytes are left in our "buffer"
+ // Figure out how many bytes are left in our "buffer".
int remaining = sizeof(MachInst) - offset;
- //Get as much as we need, up to the amount available.
+ // 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
+ // Shift the bytes we want to be all the way to the right
uint64_t partialImm = fetchChunk >> (offset * 8);
- //Mask off what we don't want
+ // Mask off what we don't want.
partialImm &= mask(toGet * 8);
- //Shift it over to overlay with our displacement.
+ // Shift it over to overlay with our displacement.
partialImm <<= (immediateCollected * 8);
- //Put it into our displacement
+ // Put it into our displacement.
current |= partialImm;
- //Update how many bytes we've collected.
+ // Update how many bytes we've collected.
collected += toGet;
consumeBytes(toGet);
}
- void updateOffsetState()
+ void
+ updateOffsetState()
{
assert(offset <= sizeof(MachInst));
if (offset == sizeof(MachInst)) {
}
}
- void consumeByte()
+ void
+ consumeByte()
{
offset++;
updateOffsetState();
}
- void consumeBytes(int numBytes)
+ void
+ consumeBytes(int numBytes)
{
offset += numBytes;
updateOffsetState();
}
- //State machine state
+ // State machine state.
protected:
- //Whether or not we're out of bytes
+ // Whether or not we're out of bytes.
bool outOfBytes;
- //Whether we've completed generating an ExtMachInst
+ // Whether we've completed generating an ExtMachInst.
bool instDone;
- //The size of the displacement value
+ // The size of the displacement value.
int displacementSize;
- //The size of the immediate value
+ // The size of the immediate value.
int immediateSize;
- //This is how much of any immediate value we've gotten. This is used
- //for both the actual immediate and the displacement.
+ // This is how much of any immediate value we've gotten. This is used
+ // for both the actual immediate and the displacement.
int immediateCollected;
enum State {
SIBState,
DisplacementState,
ImmediateState,
- //We should never get to this state. Getting here is an error.
+ // We should never get to this state. Getting here is an error.
ErrorState
};
State state;
- //Functions to handle each of the states
+ // Functions to handle each of the states
State doResetState();
State doFromCacheState();
State doPrefixState(uint8_t);
State doDisplacementState();
State doImmediateState();
- //Process the actual opcode found earlier, using the supplied tables.
+ // Process the actual opcode found earlier, using the supplied tables.
State processOpcode(ByteTable &immTable, ByteTable &modrmTable,
bool addrSizedImm = false);
// Process the opcode found with VEX / XOP prefix.
public:
Decoder(ISA* isa = nullptr) : basePC(0), origPC(0), offset(0),
- outOfBytes(true), instDone(false),
- state(ResetState)
+ outOfBytes(true), instDone(false), state(ResetState)
{
emi.reset();
mode = LongMode;
instMap = NULL;
}
- void setM5Reg(HandyM5Reg m5Reg)
+ void
+ setM5Reg(HandyM5Reg m5Reg)
{
mode = (X86Mode)(uint64_t)m5Reg.mode;
submode = (X86SubMode)(uint64_t)m5Reg.submode;
}
}
- void takeOverFrom(Decoder *old)
+ void
+ takeOverFrom(Decoder *old)
{
mode = old->mode;
submode = old->submode;
stack = old->stack;
}
- void reset()
- {
- state = ResetState;
- }
+ void reset() { state = ResetState; }
void process();
- //Use this to give data to the decoder. This should be used
- //when there is control flow.
- void moreBytes(const PCState &pc, Addr fetchPC, MachInst data)
+ // Use this to give data to the decoder. This should be used
+ // when there is control flow.
+ void
+ moreBytes(const PCState &pc, Addr fetchPC, MachInst data)
{
DPRINTF(Decoder, "Getting more bytes.\n");
basePC = fetchPC;
process();
}
- bool needMoreBytes()
- {
- return outOfBytes;
- }
-
- bool instReady()
- {
- return instDone;
- }
+ bool needMoreBytes() { return outOfBytes; }
+ bool instReady() { return instDone; }
void
updateNPC(X86ISA::PCState &nextPC)