arch-x86: Fix style in arch/x86/types.hh.
Change-Id: I5e32eea9b843d4f68adf5430516d0636317c8a57 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40103 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br> Maintainer: Gabe Black <gabe.black@gmail.com>
This commit is contained in:
@@ -48,336 +48,339 @@
|
||||
|
||||
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,
|
||||
};
|
||||
//This really determines how many bytes are passed to the decoder.
|
||||
typedef uint64_t MachInst;
|
||||
|
||||
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)
|
||||
enum Prefixes {
|
||||
NoOverride,
|
||||
ESOverride,
|
||||
CSOverride,
|
||||
SSOverride,
|
||||
DSOverride,
|
||||
FSOverride,
|
||||
GSOverride,
|
||||
RexPrefix,
|
||||
OperandSizeOverride,
|
||||
AddressSizeOverride,
|
||||
Lock,
|
||||
Rep,
|
||||
Repne,
|
||||
Vex2Prefix,
|
||||
Vex3Prefix,
|
||||
XopPrefix,
|
||||
};
|
||||
|
||||
BitUnion8(ModRM)
|
||||
Bitfield<7,6> mod;
|
||||
Bitfield<5,3> reg;
|
||||
Bitfield<2,0> rm;
|
||||
EndBitUnion(ModRM)
|
||||
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(Sib)
|
||||
Bitfield<7,6> scale;
|
||||
Bitfield<5,3> index;
|
||||
Bitfield<2,0> base;
|
||||
EndBitUnion(Sib)
|
||||
BitUnion8(ModRM)
|
||||
Bitfield<7,6> mod;
|
||||
Bitfield<5,3> reg;
|
||||
Bitfield<2,0> rm;
|
||||
EndBitUnion(ModRM)
|
||||
|
||||
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(Sib)
|
||||
Bitfield<7,6> scale;
|
||||
Bitfield<5,3> index;
|
||||
Bitfield<2,0> base;
|
||||
EndBitUnion(Sib)
|
||||
|
||||
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(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(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(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(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(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(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)
|
||||
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)
|
||||
|
||||
enum OpcodeType {
|
||||
BadOpcode,
|
||||
OneByteOpcode,
|
||||
TwoByteOpcode,
|
||||
ThreeByte0F38Opcode,
|
||||
ThreeByte0F3AOpcode,
|
||||
};
|
||||
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)
|
||||
|
||||
static inline const char *
|
||||
opcodeTypeToStr(OpcodeType type)
|
||||
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!";
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
enum X86Mode {
|
||||
LongMode,
|
||||
LegacyMode
|
||||
};
|
||||
|
||||
enum X86SubMode {
|
||||
SixtyFourBitMode,
|
||||
CompatabilityMode,
|
||||
ProtectedMode,
|
||||
Virtual8086Mode,
|
||||
RealMode
|
||||
};
|
||||
|
||||
//The intermediate structure used by the x86 decoder.
|
||||
struct ExtMachInst
|
||||
void
|
||||
setNPC(Addr val)
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
Base::setNPC(val);
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
inline static bool
|
||||
operator == (const ExtMachInst &emi1, const ExtMachInst &emi2)
|
||||
uint8_t size() const { return _size; }
|
||||
void size(uint8_t newSize) { _size = newSize; }
|
||||
|
||||
bool
|
||||
branching() 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;
|
||||
return (this->npc() != this->pc() + size()) ||
|
||||
(this->nupc() != this->upc() + 1);
|
||||
}
|
||||
|
||||
class PCState : public GenericISA::UPCState<MachInst>
|
||||
void
|
||||
advance()
|
||||
{
|
||||
protected:
|
||||
typedef GenericISA::UPCState<MachInst> Base;
|
||||
Base::advance();
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
uint8_t _size;
|
||||
void
|
||||
uEnd()
|
||||
{
|
||||
Base::uEnd();
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
void
|
||||
set(Addr val)
|
||||
{
|
||||
Base::set(val);
|
||||
_size = 0;
|
||||
}
|
||||
void
|
||||
serialize(CheckpointOut &cp) const
|
||||
{
|
||||
Base::serialize(cp);
|
||||
SERIALIZE_SCALAR(_size);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
void
|
||||
unserialize(CheckpointIn &cp)
|
||||
{
|
||||
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__
|
||||
|
||||
Reference in New Issue
Block a user