#define __ARCH_X86_TYPES_HH__
#include <inttypes.h>
+#include <iostream>
+
+#include "base/bitfield.hh"
+#include "base/cprintf.hh"
namespace X86ISA
{
//This really determines how many bytes are passed to the predecoder.
typedef uint64_t MachInst;
+
+ enum Prefixes {
+ NoOverride,
+ CSOverride,
+ DSOverride,
+ ESOverride,
+ FSOverride,
+ GSOverride,
+ SSOverride,
+ RexPrefix,
+ OperandSizeOverride,
+ AddressSizeOverride,
+ Lock,
+ Rep,
+ Repne
+ };
+
+ BitUnion8(LegacyPrefixVector)
+ Bitfield<7> repne;
+ Bitfield<6> rep;
+ Bitfield<5> lock;
+ Bitfield<4> addr;
+ Bitfield<3> op;
+ //There can be only one segment override, so they share the
+ //first 3 bits in the legacyPrefixes bitfield.
+ Bitfield<2,0> seg;
+ EndBitUnion(LegacyPrefixVector)
+
+ BitUnion8(ModRM)
+ Bitfield<7,6> mod;
+ Bitfield<5,3> reg;
+ Bitfield<2,0> rm;
+ EndBitUnion(ModRM)
+
+ BitUnion8(Sib)
+ Bitfield<7,6> scale;
+ Bitfield<5,3> index;
+ Bitfield<2,0> base;
+ EndBitUnion(Sib)
+
+ BitUnion8(Rex)
+ Bitfield<3> w;
+ Bitfield<2> r;
+ Bitfield<1> x;
+ Bitfield<0> b;
+ EndBitUnion(Rex)
+
+ BitUnion8(Opcode)
+ Bitfield<7,3> top5;
+ Bitfield<2,0> bottom3;
+ EndBitUnion(Opcode)
+
+ BitUnion8(OperatingMode)
+ Bitfield<3> mode;
+ Bitfield<2,0> submode;
+ EndBitUnion(OperatingMode)
+
+ enum X86Mode {
+ LongMode,
+ LegacyMode
+ };
+
+ enum X86SubMode {
+ SixtyFourBitMode,
+ CompatabilityMode,
+ ProtectedMode,
+ Virtual8086Mode,
+ RealMode
+ };
+
//The intermediate structure the x86 predecoder returns.
struct ExtMachInst
{
- //Empty for now...
+ //Prefixes
+ LegacyPrefixVector legacy;
+ Rex rex;
+ //This holds all of the bytes of the opcode
+ struct
+ {
+ //The number of bytes in this opcode. Right now, we ignore that
+ //this can be 3 in some cases
+ uint8_t num;
+ //The first byte detected in a 2+ byte opcode. Should be 0xF0.
+ uint8_t prefixA;
+ //The second byte detected in a 3+ byte opcode. Could be 0xF0 for
+ //3dnow instructions, or 0x38-0x3F for some SSE instructions.
+ uint8_t prefixB;
+ //The main opcode byte. The highest addressed byte in the opcode.
+ Opcode op;
+ } opcode;
+ //Modifier bytes
+ ModRM modRM;
+ uint8_t sib;
+ //Immediate fields
+ uint64_t immediate;
+ uint64_t displacement;
+
+ //The effective operand size.
+ uint8_t opSize;
+ //The effective address size.
+ uint8_t addrSize;
+ //The effective stack size.
+ uint8_t stackSize;
+
+ //Mode information
+ OperatingMode mode;
};
- bool operator == (const ExtMachInst &emi1, const ExtMachInst &emi2)
+ inline static std::ostream &
+ operator << (std::ostream & os, const ExtMachInst & emi)
+ {
+ ccprintf(os, "\n{\n\tleg = %#x,\n\trex = %#x,\n\t"
+ "op = {\n\t\tnum = %d,\n\t\top = %#x,\n\t\t"
+ "prefixA = %#x,\n\t\tprefixB = %#x\n\t},\n\t"
+ "modRM = %#x,\n\tsib = %#x,\n\t"
+ "immediate = %#x,\n\tdisplacement = %#x\n}\n",
+ emi.legacy, (uint8_t)emi.rex,
+ emi.opcode.num, emi.opcode.op,
+ emi.opcode.prefixA, emi.opcode.prefixB,
+ (uint8_t)emi.modRM, (uint8_t)emi.sib,
+ emi.immediate, emi.displacement);
+ return os;
+ }
+
+ inline static bool
+ operator == (const ExtMachInst &emi1, const ExtMachInst &emi2)
{
- //Since this is empty, it's always equal
+ if(emi1.legacy != emi2.legacy)
+ return false;
+ if(emi1.rex != emi2.rex)
+ return false;
+ if(emi1.opcode.num != emi2.opcode.num)
+ return false;
+ if(emi1.opcode.op != emi2.opcode.op)
+ return false;
+ if(emi1.opcode.prefixA != emi2.opcode.prefixA)
+ return false;
+ if(emi1.opcode.prefixB != emi2.opcode.prefixB)
+ return false;
+ if(emi1.modRM != emi2.modRM)
+ return false;
+ if(emi1.sib != emi2.sib)
+ return false;
+ if(emi1.immediate != emi2.immediate)
+ return false;
+ if(emi1.displacement != emi2.displacement)
+ return false;
+ if(emi1.mode != emi2.mode)
+ return false;
+ if(emi1.opSize != emi2.opSize)
+ return false;
+ if(emi1.addrSize != emi2.addrSize)
+ return false;
+ if(emi1.stackSize != emi2.stackSize)
+ return false;
return true;
}