namespace X86ISA
{
- //This really determines how many bytes are passed to the decoder.
- typedef uint64_t MachInst;
-
- enum Prefixes {
- NoOverride,
- ESOverride,
- CSOverride,
- SSOverride,
- DSOverride,
- FSOverride,
- GSOverride,
- RexPrefix,
- OperandSizeOverride,
- AddressSizeOverride,
- Lock,
- Rep,
- Repne,
- Vex2Prefix,
- Vex3Prefix,
- XopPrefix,
- };
- 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.
- 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)
- //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<0> b;
- EndBitUnion(Rex)
-
- BitUnion8(Vex2Of3)
- // Inverted bits from the REX prefix.
- Bitfield<7> r;
- Bitfield<6> x;
- Bitfield<5> b;
- // Selector for what would be two or three byte opcode types.
- Bitfield<4, 0> m;
- EndBitUnion(Vex2Of3)
-
- BitUnion8(Vex3Of3)
- // Bit from the REX prefix.
- Bitfield<7> w;
- // Inverted extra register index.
- Bitfield<6, 3> v;
- // Vector length specifier.
- Bitfield<2> l;
- // Implied 66, F2, or F3 opcode prefix.
- Bitfield<1, 0> p;
- EndBitUnion(Vex3Of3)
-
- BitUnion8(Vex2Of2)
- // Inverted bit from the REX prefix.
- Bitfield<7> r;
- // Inverted extra register index.
- Bitfield<6, 3> v;
- // Vector length specifier
- Bitfield<2> l;
- // Implied 66, F2, or F3 opcode prefix.
- Bitfield<1, 0> p;
- EndBitUnion(Vex2Of2)
-
- BitUnion8(VexInfo)
- // Extra register index.
- Bitfield<6, 3> v;
- // Vector length specifier.
- Bitfield<2> l;
- // Whether the VEX prefix was used.
- Bitfield<0> present;
- EndBitUnion(VexInfo)
-
- enum OpcodeType {
- BadOpcode,
- OneByteOpcode,
- TwoByteOpcode,
- ThreeByte0F38Opcode,
- ThreeByte0F3AOpcode,
- };
+//This really determines how many bytes are passed to the decoder.
+typedef uint64_t MachInst;
+
+enum Prefixes {
+ NoOverride,
+ ESOverride,
+ CSOverride,
+ SSOverride,
+ DSOverride,
+ FSOverride,
+ GSOverride,
+ RexPrefix,
+ OperandSizeOverride,
+ AddressSizeOverride,
+ Lock,
+ Rep,
+ Repne,
+ Vex2Prefix,
+ Vex3Prefix,
+ XopPrefix,
+};
+
+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.
+ 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)
+ //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<0> b;
+EndBitUnion(Rex)
+
+BitUnion8(Vex2Of3)
+ // Inverted bits from the REX prefix.
+ Bitfield<7> r;
+ Bitfield<6> x;
+ Bitfield<5> b;
+ // Selector for what would be two or three byte opcode types.
+ Bitfield<4, 0> m;
+EndBitUnion(Vex2Of3)
+
+BitUnion8(Vex3Of3)
+ // Bit from the REX prefix.
+ Bitfield<7> w;
+ // Inverted extra register index.
+ Bitfield<6, 3> v;
+ // Vector length specifier.
+ Bitfield<2> l;
+ // Implied 66, F2, or F3 opcode prefix.
+ Bitfield<1, 0> p;
+EndBitUnion(Vex3Of3)
+
+BitUnion8(Vex2Of2)
+ // Inverted bit from the REX prefix.
+ Bitfield<7> r;
+ // Inverted extra register index.
+ Bitfield<6, 3> v;
+ // Vector length specifier
+ Bitfield<2> l;
+ // Implied 66, F2, or F3 opcode prefix.
+ Bitfield<1, 0> p;
+EndBitUnion(Vex2Of2)
+
+BitUnion8(VexInfo)
+ // Extra register index.
+ Bitfield<6, 3> v;
+ // Vector length specifier.
+ Bitfield<2> l;
+ // Whether the VEX prefix was used.
+ Bitfield<0> present;
+EndBitUnion(VexInfo)
+
+enum OpcodeType {
+ BadOpcode,
+ OneByteOpcode,
+ TwoByteOpcode,
+ ThreeByte0F38Opcode,
+ ThreeByte0F3AOpcode,
+};
+
+static inline const char *
+opcodeTypeToStr(OpcodeType type)
+{
+ switch (type) {
+ case BadOpcode:
+ return "bad";
+ case OneByteOpcode:
+ return "one byte";
+ case TwoByteOpcode:
+ return "two byte";
+ case ThreeByte0F38Opcode:
+ return "three byte 0f38";
+ case ThreeByte0F3AOpcode:
+ return "three byte 0f3a";
+ default:
+ return "unrecognized!";
+ }
+}
- static inline const char *
- opcodeTypeToStr(OpcodeType type)
+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 used by the x86 decoder.
+struct ExtMachInst
+{
+ void reset() { memset(static_cast<void *>(this), 0, sizeof(*this)); }
+
+ //Prefixes
+ LegacyPrefixVector legacy;
+ Rex rex;
+ VexInfo vex;
+
+ //This holds all of the bytes of the opcode
+ struct
{
- switch (type) {
- case BadOpcode:
- return "bad";
- case OneByteOpcode:
- return "one byte";
- case TwoByteOpcode:
- return "two byte";
- case ThreeByte0F38Opcode:
- return "three byte 0f38";
- case ThreeByte0F3AOpcode:
- return "three byte 0f3a";
- default:
- return "unrecognized!";
- }
+ OpcodeType type;
+ //The main opcode byte. The highest addressed byte in the opcode.
+ Opcode op;
+ } opcode;
+ //Modifier bytes
+ ModRM modRM;
+ 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 &
+operator << (std::ostream &os, const ExtMachInst &emi)
+{
+ ccprintf(os, "\n{\n\tleg = %#x,\n\trex = %#x,\n\t"
+ "vex/xop = %#x,\n\t"
+ "op = {\n\t\ttype = %s,\n\t\top = %#x,\n\t\t},\n\t"
+ "modRM = %#x,\n\tsib = %#x,\n\t"
+ "immediate = %#x,\n\tdisplacement = %#x\n\t"
+ "dispSize = %d}\n",
+ (uint8_t)emi.legacy, (uint8_t)emi.rex,
+ (uint8_t)emi.vex,
+ opcodeTypeToStr(emi.opcode.type), (uint8_t)emi.opcode.op,
+ (uint8_t)emi.modRM, (uint8_t)emi.sib,
+ emi.immediate, emi.displacement, emi.dispSize);
+ return os;
+}
+
+inline static bool
+operator == (const ExtMachInst &emi1, const ExtMachInst &emi2)
+{
+ if (emi1.legacy != emi2.legacy)
+ return false;
+ if (emi1.rex != emi2.rex)
+ return false;
+ if (emi1.vex != emi2.vex)
+ return false;
+ if (emi1.opcode.type != emi2.opcode.type)
+ return false;
+ if (emi1.opcode.op != emi2.opcode.op)
+ 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;
+}
+
+class PCState : public GenericISA::UPCState<MachInst>
+{
+ protected:
+ typedef GenericISA::UPCState<MachInst> Base;
+
+ uint8_t _size;
+
+ public:
+ void
+ set(Addr val)
+ {
+ Base::set(val);
+ _size = 0;
}
- BitUnion8(Opcode)
- Bitfield<7,3> top5;
- Bitfield<2,0> bottom3;
- EndBitUnion(Opcode)
+ PCState() {}
+ PCState(Addr val) { set(val); }
- BitUnion8(OperatingMode)
- Bitfield<3> mode;
- Bitfield<2,0> submode;
- EndBitUnion(OperatingMode)
+ void
+ setNPC(Addr val)
+ {
+ Base::setNPC(val);
+ _size = 0;
+ }
- enum X86Mode {
- LongMode,
- LegacyMode
- };
+ uint8_t size() const { return _size; }
+ void size(uint8_t newSize) { _size = newSize; }
- enum X86SubMode {
- SixtyFourBitMode,
- CompatabilityMode,
- ProtectedMode,
- Virtual8086Mode,
- RealMode
- };
+ bool
+ branching() const
+ {
+ return (this->npc() != this->pc() + size()) ||
+ (this->nupc() != this->upc() + 1);
+ }
- //The intermediate structure used by the x86 decoder.
- struct ExtMachInst
+ void
+ advance()
{
- void reset() {
- memset(static_cast<void *>(this), 0, sizeof(*this));
- }
-
- //Prefixes
- LegacyPrefixVector legacy;
- Rex rex;
- VexInfo vex;
-
- //This holds all of the bytes of the opcode
- struct
- {
- OpcodeType type;
- //The main opcode byte. The highest addressed byte in the opcode.
- Opcode op;
- } opcode;
- //Modifier bytes
- ModRM modRM;
- 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;
- };
+ Base::advance();
+ _size = 0;
+ }
- inline static std::ostream &
- operator << (std::ostream & os, const ExtMachInst & emi)
+ void
+ uEnd()
{
- ccprintf(os, "\n{\n\tleg = %#x,\n\trex = %#x,\n\t"
- "vex/xop = %#x,\n\t"
- "op = {\n\t\ttype = %s,\n\t\top = %#x,\n\t\t},\n\t"
- "modRM = %#x,\n\tsib = %#x,\n\t"
- "immediate = %#x,\n\tdisplacement = %#x\n\t"
- "dispSize = %d}\n",
- (uint8_t)emi.legacy, (uint8_t)emi.rex,
- (uint8_t)emi.vex,
- opcodeTypeToStr(emi.opcode.type), (uint8_t)emi.opcode.op,
- (uint8_t)emi.modRM, (uint8_t)emi.sib,
- emi.immediate, emi.displacement, emi.dispSize);
- return os;
+ Base::uEnd();
+ _size = 0;
}
- inline static bool
- operator == (const ExtMachInst &emi1, const ExtMachInst &emi2)
+ void
+ serialize(CheckpointOut &cp) const
{
- if (emi1.legacy != emi2.legacy)
- return false;
- if (emi1.rex != emi2.rex)
- return false;
- if (emi1.vex != emi2.vex)
- return false;
- if (emi1.opcode.type != emi2.opcode.type)
- return false;
- if (emi1.opcode.op != emi2.opcode.op)
- 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;
+ Base::serialize(cp);
+ SERIALIZE_SCALAR(_size);
}
- class PCState : public GenericISA::UPCState<MachInst>
+ void
+ unserialize(CheckpointIn &cp)
{
- protected:
- typedef GenericISA::UPCState<MachInst> Base;
-
- uint8_t _size;
-
- public:
- void
- set(Addr val)
- {
- Base::set(val);
- _size = 0;
- }
-
- PCState() {}
- PCState(Addr val) { set(val); }
-
- void
- setNPC(Addr val)
- {
- Base::setNPC(val);
- _size = 0;
- }
-
- uint8_t size() const { return _size; }
- void size(uint8_t newSize) { _size = newSize; }
-
- bool
- branching() const
- {
- return (this->npc() != this->pc() + size()) ||
- (this->nupc() != this->upc() + 1);
- }
-
- void
- advance()
- {
- Base::advance();
- _size = 0;
- }
-
- void
- uEnd()
- {
- Base::uEnd();
- _size = 0;
- }
-
- void
- serialize(CheckpointOut &cp) const
- {
- Base::serialize(cp);
- SERIALIZE_SCALAR(_size);
- }
-
- void
- unserialize(CheckpointIn &cp)
- {
- Base::unserialize(cp);
- UNSERIALIZE_SCALAR(_size);
- }
- };
+ Base::unserialize(cp);
+ UNSERIALIZE_SCALAR(_size);
+ }
+};
}
-namespace std {
- template<>
- struct hash<X86ISA::ExtMachInst> {
- size_t operator()(const X86ISA::ExtMachInst &emi) const {
- return (((uint64_t)emi.legacy << 48) |
- ((uint64_t)emi.rex << 40) |
- ((uint64_t)emi.vex << 32) |
- ((uint64_t)emi.modRM << 24) |
- ((uint64_t)emi.sib << 16) |
- ((uint64_t)emi.opcode.type << 8) |
- ((uint64_t)emi.opcode.op)) ^
- emi.immediate ^ emi.displacement ^
- emi.mode ^
- emi.opSize ^ emi.addrSize ^
- emi.stackSize ^ emi.dispSize;
- };
+namespace std
+{
+
+template<>
+struct hash<X86ISA::ExtMachInst>
+{
+ size_t
+ operator()(const X86ISA::ExtMachInst &emi) const
+ {
+ return (((uint64_t)emi.legacy << 48) |
+ ((uint64_t)emi.rex << 40) |
+ ((uint64_t)emi.vex << 32) |
+ ((uint64_t)emi.modRM << 24) |
+ ((uint64_t)emi.sib << 16) |
+ ((uint64_t)emi.opcode.type << 8) |
+ ((uint64_t)emi.opcode.op)) ^
+ emi.immediate ^ emi.displacement ^
+ emi.mode ^
+ emi.opSize ^ emi.addrSize ^
+ emi.stackSize ^ emi.dispSize;
};
+};
+
}
// These two functions allow ExtMachInst to be used with SERIALIZE_SCALAR
// and UNSERIALIZE_SCALAR.
template <>
-void
-paramOut(CheckpointOut &cp, const std::string &name,
- const X86ISA::ExtMachInst &machInst);
+void paramOut(CheckpointOut &cp, const std::string &name,
+ const X86ISA::ExtMachInst &machInst);
template <>
-void
-paramIn(CheckpointIn &cp, const std::string &name,
+void paramIn(CheckpointIn &cp, const std::string &name,
X86ISA::ExtMachInst &machInst);
#endif // __ARCH_X86_TYPES_HH__