#ifndef __ARCH_X86_TYPES_HH__
#define __ARCH_X86_TYPES_HH__
-#include <inttypes.h>
#include <iostream>
-#include "base/bitfield.hh"
+#include "base/bitunion.hh"
#include "base/cprintf.hh"
+#include "base/types.hh"
namespace X86ISA
{
typedef uint64_t MachInst;
enum Prefixes {
- NoOverride = 0,
- CSOverride = 1,
- DSOverride = 2,
- ESOverride = 3,
- FSOverride = 4,
- GSOverride = 5,
- SSOverride = 6,
- //The Rex prefix obviously doesn't fit in with the above, but putting
- //it here lets us save double the space the enums take up.
- RexPrefix = 7,
+ NoOverride,
+ ESOverride,
+ CSOverride,
+ SSOverride,
+ DSOverride,
+ FSOverride,
+ GSOverride,
+ RexPrefix,
+ OperandSizeOverride,
+ AddressSizeOverride,
+ Lock,
+ Rep,
+ Repne
+ };
+
+ BitUnion8(LegacyPrefixVector)
+ Bitfield<7, 4> decodeVal;
+ Bitfield<7> repne;
+ Bitfield<6> rep;
+ Bitfield<5> lock;
+ Bitfield<4> op;
+ Bitfield<3> addr;
//There can be only one segment override, so they share the
//first 3 bits in the legacyPrefixes bitfield.
- SegmentOverride = 0x7,
- OperandSizeOverride = 8,
- AddressSizeOverride = 16,
- Lock = 32,
- Rep = 64,
- Repne = 128
- };
+ Bitfield<2,0> seg;
+ EndBitUnion(LegacyPrefixVector)
BitUnion8(ModRM)
Bitfield<7,6> mod;
EndBitUnion(Sib)
BitUnion8(Rex)
+ //This bit doesn't mean anything according to the ISA, but in
+ //this implementation, it being set means an REX prefix was present.
+ Bitfield<6> present;
Bitfield<3> w;
Bitfield<2> r;
Bitfield<1> x;
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
{
//Prefixes
- uint8_t legacy;
+ LegacyPrefixVector legacy;
Rex rex;
//This holds all of the bytes of the opcode
struct
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.
+ //The second byte detected in a 3+ byte opcode. Could be 0x38-0x3F
+ //for some SSE instructions. 3dNow! instructions are handled as
+ //two byte opcodes and then split out further by the immediate
+ //byte.
uint8_t prefixB;
//The main opcode byte. The highest addressed byte in the opcode.
Opcode op;
} opcode;
//Modifier bytes
ModRM modRM;
- uint8_t sib;
+ Sib 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;
+ //The size of the displacement
+ uint8_t dispSize;
+
+ //Mode information
+ OperatingMode mode;
};
inline static std::ostream &
"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,
+ "immediate = %#x,\n\tdisplacement = %#x\n\t"
+ "dispSize = %d}\n",
+ (uint8_t)emi.legacy, (uint8_t)emi.rex,
+ emi.opcode.num, (uint8_t)emi.opcode.op,
emi.opcode.prefixA, emi.opcode.prefixB,
(uint8_t)emi.modRM, (uint8_t)emi.sib,
- emi.immediate, emi.displacement);
+ emi.immediate, emi.displacement, emi.dispSize);
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;
+ if(emi1.dispSize != emi2.dispSize)
+ return false;
return true;
}
- typedef uint64_t IntReg;
- //XXX Should this be a 128 bit structure for XMM memory ops?
- typedef uint64_t LargestRead;
- typedef uint64_t MiscReg;
-
- //These floating point types are correct for mmx, but not
- //technically for x87 (80 bits) or at all for xmm (128 bits)
- typedef double FloatReg;
- typedef uint64_t FloatRegBits;
- typedef union
- {
- IntReg intReg;
- FloatReg fpReg;
- MiscReg ctrlReg;
- } AnyReg;
-
- //XXX This is very hypothetical. X87 instructions would need to
- //change their "context" constantly. It's also not clear how
- //this would be handled as far as out of order execution.
- //Maybe x87 instructions are in order?
- enum RegContextParam
- {
- CONTEXT_X87_TOP
+ struct CoreSpecific {
+ int core_type;
};
-
- typedef int RegContextVal;
-
- typedef uint8_t RegIndex;
};
#endif // __ARCH_X86_TYPES_HH__