arch-x86: Let individual reg uops specialize their arguments.

Rather than force all x86 microops to have one destination and two
sources, the second of which is a register or immediate, make it
possible for these microops to pick any combination of those elements by
modularizing the operand aspects of the base class. This prevents having
a bunch of extra parameters and members of the classes, or having a lot
of explicitly laid out classes with various combinations.

This also improves the accuracy/usefulness of Exec traces since register
types and therefore names will be determined correctly.

Also, there was a branchTarget override added to all register uops which
would be used when the macroop was an direct control transfer
instruction. The assumption was that the immediate value of the whole
instruction would be the PC offset, which is not necessarily correct but
is probably a fairly safe assumption.

This override was only provided for all *register* uops though, and
there's nothing saying the last uop in a branch instruction has to be a
a register uop. This change moves that override to the uop base class so
that *any* uop can be last in the macroop and still support branchTarget
correctly (or at least as correctly as a register uop would).

Change-Id: I9d42d22609d511fa757a784c04a5a9874beca479
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/42343
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2021-02-28 21:25:21 -08:00
parent fb7eb04f42
commit 4b1ac05dfa
10 changed files with 699 additions and 502 deletions

View File

@@ -119,4 +119,15 @@ X86MicroopBase::checkCondition(uint64_t flags, int condition) const
return true;
}
PCState
X86MicroopBase::branchTarget(const PCState &branchPC) const
{
PCState pcs = branchPC;
DPRINTF(X86, "branchTarget PC info: %s, Immediate: %lx\n", pcs,
(int64_t)machInst.immediate);
pcs.npc(pcs.npc() + (int64_t)machInst.immediate);
pcs.uEnd();
return pcs;
}
}

View File

@@ -134,6 +134,11 @@ class X86MicroopBase : public X86StaticInst
else
pcState.uAdvance();
}
PCState branchTarget(const PCState &branchPC) const override;
// Explicitly import the otherwise hidden branchTarget.
using StaticInst::branchTarget;
};
}

View File

@@ -47,59 +47,32 @@ namespace X86ISA
{
uint64_t
RegOpBase::genFlags(uint64_t oldFlags, uint64_t flagMask,
RegOpBase::genFlags(uint64_t old_flags, uint64_t flag_mask,
uint64_t _dest, uint64_t _src1, uint64_t _src2, bool subtract) const
{
DPRINTF(X86, "flagMask = %#x\n", flagMask);
uint64_t flags = oldFlags & ~flagMask;
if (flagMask & (ECFBit | CFBit)) {
DPRINTF(X86, "flag_mask = %#x\n", flag_mask);
uint64_t flags = old_flags & ~flag_mask;
if (flag_mask & (ECFBit | CFBit)) {
if (findCarry(dataSize*8, _dest, _src1, _src2))
flags |= (flagMask & (ECFBit | CFBit));
flags |= (flag_mask & (ECFBit | CFBit));
if (subtract)
flags ^= (flagMask & (ECFBit | CFBit));
flags ^= (flag_mask & (ECFBit | CFBit));
}
if (flagMask & PFBit && !findParity(8, _dest))
if (flag_mask & PFBit && !findParity(8, _dest))
flags |= PFBit;
if (flagMask & AFBit) {
if (flag_mask & AFBit) {
if (findCarry(4, _dest, _src1, _src2))
flags |= AFBit;
if (subtract)
flags ^= AFBit;
}
if (flagMask & (EZFBit | ZFBit) && findZero(dataSize*8, _dest))
flags |= (flagMask & (EZFBit | ZFBit));
if (flagMask & SFBit && findNegative(dataSize*8, _dest))
if (flag_mask & (EZFBit | ZFBit) && findZero(dataSize * 8, _dest))
flags |= (flag_mask & (EZFBit | ZFBit));
if (flag_mask & SFBit && findNegative(dataSize * 8, _dest))
flags |= SFBit;
if (flagMask & OFBit && findOverflow(dataSize*8, _dest, _src1, _src2))
if (flag_mask & OFBit && findOverflow(dataSize * 8, _dest, _src1, _src2))
flags |= OFBit;
return flags;
}
std::string
RegOp::generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
printDestReg(response, 0, dataSize);
response << ", ";
printSrcReg(response, 0, dataSize);
response << ", ";
printSrcReg(response, 1, dataSize);
return response.str();
}
std::string
RegOpImm::generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
printDestReg(response, 0, dataSize);
response << ", ";
printSrcReg(response, 0, dataSize);
ccprintf(response, ", %#x", imm8);
return response.str();
}
}

View File

@@ -43,80 +43,279 @@
namespace X86ISA
{
/**
* Base classes for RegOps which provides a generateDisassembly method.
*/
struct RegOpDest
{
using ArgType = InstRegIndex;
RegIndex dest;
size_t size;
template <class InstType>
RegOpDest(InstType *inst, ArgType idx) :
dest(INTREG_FOLDED(idx.index(), inst->foldOBit)),
size(inst->dataSize)
{}
void
print(std::ostream &os) const
{
X86StaticInst::printReg(os, RegId(IntRegClass, dest), size);
}
};
struct RegOpDbgDest
{
using ArgType = InstRegIndex;
RegIndex dest;
size_t size;
template <class InstType>
RegOpDbgDest(InstType *inst, ArgType idx) : dest(idx.index()),
size(inst->dataSize)
{}
void
print(std::ostream &os) const
{
ccprintf(os, "dr%d", dest);
}
};
struct RegOpCrDest
{
using ArgType = InstRegIndex;
RegIndex dest;
size_t size;
template <class InstType>
RegOpCrDest(InstType *inst, ArgType idx) : dest(idx.index()),
size(inst->dataSize)
{}
void
print(std::ostream &os) const
{
ccprintf(os, "cr%d", dest);
}
};
struct RegOpSegDest
{
using ArgType = InstRegIndex;
RegIndex dest;
size_t size;
template <class InstType>
RegOpSegDest(InstType *inst, ArgType idx) : dest(idx.index()),
size(inst->dataSize)
{}
void
print(std::ostream &os) const
{
X86StaticInst::printSegment(os, dest);
}
};
struct RegOpMiscDest
{
using ArgType = InstRegIndex;
RegIndex dest;
size_t size;
template <class InstType>
RegOpMiscDest(InstType *inst, ArgType idx) : dest(idx.index()),
size(inst->dataSize)
{}
void
print(std::ostream &os) const
{
X86StaticInst::printReg(os, RegId(MiscRegClass, dest), size);
}
};
struct RegOpSrc1
{
using ArgType = InstRegIndex;
RegIndex src1;
size_t size;
template <class InstType>
RegOpSrc1(InstType *inst, ArgType idx) :
src1(INTREG_FOLDED(idx.index(), inst->foldOBit)),
size(inst->dataSize)
{}
void
print(std::ostream &os) const
{
X86StaticInst::printReg(os, RegId(IntRegClass, src1), size);
}
};
struct RegOpDbgSrc1
{
using ArgType = InstRegIndex;
RegIndex src1;
size_t size;
template <class InstType>
RegOpDbgSrc1(InstType *inst, ArgType idx) : src1(idx.index()),
size(inst->dataSize)
{}
void
print(std::ostream &os) const
{
ccprintf(os, "dr%d", src1);
}
};
struct RegOpCrSrc1
{
using ArgType = InstRegIndex;
RegIndex src1;
size_t size;
template <class InstType>
RegOpCrSrc1(InstType *inst, ArgType idx) : src1(idx.index()),
size(inst->dataSize)
{}
void
print(std::ostream &os) const
{
ccprintf(os, "cr%d", src1);
}
};
struct RegOpSegSrc1
{
using ArgType = InstRegIndex;
RegIndex src1;
size_t size;
template <class InstType>
RegOpSegSrc1(InstType *inst, ArgType idx) : src1(idx.index()),
size(inst->dataSize)
{}
void
print(std::ostream &os) const
{
X86StaticInst::printSegment(os, src1);
}
};
struct RegOpMiscSrc1
{
using ArgType = InstRegIndex;
RegIndex src1;
size_t size;
template <class InstType>
RegOpMiscSrc1(InstType *inst, ArgType idx) : src1(idx.index()),
size(inst->dataSize)
{}
void
print(std::ostream &os) const
{
X86StaticInst::printReg(os, RegId(MiscRegClass, src1), size);
}
};
struct RegOpSrc2
{
using ArgType = InstRegIndex;
RegIndex src2;
size_t size;
template <class InstType>
RegOpSrc2(InstType *inst, ArgType idx) :
src2(INTREG_FOLDED(idx.index(), inst->foldOBit)),
size(inst->dataSize)
{}
void
print(std::ostream &os) const
{
X86StaticInst::printReg(os, RegId(IntRegClass, src2), size);
}
};
struct RegOpImm8
{
using ArgType = uint8_t;
uint8_t imm8;
template <class InstType>
RegOpImm8(InstType *inst, ArgType _imm8) : imm8(_imm8) {}
void
print(std::ostream &os) const
{
ccprintf(os, "%#x", imm8);
}
};
class RegOpBase : public X86MicroopBase
{
protected:
const RegIndex src1;
const RegIndex dest;
const uint8_t dataSize;
const uint16_t ext;
RegIndex foldOBit;
// Constructor
RegOpBase(ExtMachInst _machInst,
const char *mnem, const char *_instMnem, uint64_t setFlags,
InstRegIndex _src1, InstRegIndex _dest,
uint8_t _dataSize, uint16_t _ext,
OpClass __opClass) :
X86MicroopBase(_machInst, mnem, _instMnem, setFlags,
__opClass),
src1(_src1.index()), dest(_dest.index()),
dataSize(_dataSize), ext(_ext)
{
foldOBit = (dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
}
RegOpBase(ExtMachInst mach_inst, const char *mnem, const char *inst_mnem,
uint64_t set_flags, uint8_t data_size, uint16_t _ext,
OpClass op_class) :
X86MicroopBase(mach_inst, mnem, inst_mnem, set_flags, op_class),
ext(_ext), dataSize(data_size),
foldOBit((data_size == 1 && !mach_inst.rex.present) ? 1 << 6 : 0)
{}
//Figure out what the condition code flags should be.
uint64_t genFlags(uint64_t oldFlags, uint64_t flagMask,
uint64_t genFlags(uint64_t old_flags, uint64_t flag_mask,
uint64_t _dest, uint64_t _src1, uint64_t _src2,
bool subtract = false) const;
bool subtract=false)const ;
public:
const uint8_t dataSize;
const RegIndex foldOBit;
};
class RegOp : public RegOpBase
template <typename ...Operands>
class RegOpT : public RegOpBase, public Operands...
{
protected:
const RegIndex src2;
RegOpT(ExtMachInst mach_inst, const char *mnem, const char *inst_mnem,
uint64_t set_flags, uint8_t data_size, uint16_t _ext,
OpClass op_class, typename Operands::ArgType... args) :
RegOpBase(mach_inst, mnem, inst_mnem, set_flags, data_size, _ext,
op_class), Operands(this, args)...
{}
// Constructor
RegOp(ExtMachInst _machInst,
const char *mnem, const char *_instMnem, uint64_t setFlags,
InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
uint8_t _dataSize, uint16_t _ext,
OpClass __opClass) :
RegOpBase(_machInst, mnem, _instMnem, setFlags,
_src1, _dest, _dataSize, _ext,
__opClass),
src2(_src2.index())
std::string
generateDisassembly(Addr pc,
const Loader::SymbolTable *symtab) const override
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
int count = 0;
M5_FOR_EACH_IN_PACK(ccprintf(response, count++ ? ", " : ""),
Operands::print(response));
return response.str();
}
std::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
};
class RegOpImm : public RegOpBase
{
protected:
const uint8_t imm8;
// Constructor
RegOpImm(ExtMachInst _machInst,
const char * mnem, const char *_instMnem, uint64_t setFlags,
InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
uint8_t _dataSize, uint16_t _ext,
OpClass __opClass) :
RegOpBase(_machInst, mnem, _instMnem, setFlags,
_src1, _dest, _dataSize, _ext,
__opClass),
imm8(_imm8)
{
}
std::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
};
}

View File

@@ -45,19 +45,19 @@ namespace X86ISA
{
void
X86StaticInst::printMnemonic(std::ostream &os, const char *mnemonic) const
X86StaticInst::printMnemonic(std::ostream &os, const char *mnemonic)
{
ccprintf(os, " %s ", mnemonic);
}
void
X86StaticInst::printMnemonic(std::ostream &os, const char *instMnemonic,
const char *mnemonic) const
const char *mnemonic)
{
ccprintf(os, " %s : %s ", instMnemonic, mnemonic);
}
void X86StaticInst::printSegment(std::ostream &os, int segment) const
void X86StaticInst::printSegment(std::ostream &os, int segment)
{
switch (segment)
{
@@ -120,7 +120,7 @@ X86StaticInst::printDestReg(std::ostream &os, int reg, int size) const
}
void
X86StaticInst::printReg(std::ostream &os, RegId reg, int size) const
X86StaticInst::printReg(std::ostream &os, RegId reg, int size)
{
assert(size == 1 || size == 2 || size == 4 || size == 8);
static const char * abcdFormats[9] =
@@ -231,7 +231,7 @@ X86StaticInst::printReg(std::ostream &os, RegId reg, int size) const
void
X86StaticInst::printMem(std::ostream &os, uint8_t segment,
uint8_t scale, RegIndex index, RegIndex base,
uint64_t disp, uint8_t addressSize, bool rip) const
uint64_t disp, uint8_t addressSize, bool rip)
{
bool someAddr = false;
printSegment(os, segment);

View File

@@ -81,6 +81,18 @@ struct InstRegIndex : public RegId
class X86StaticInst : public StaticInst
{
public:
static void printMnemonic(std::ostream &os, const char *mnemonic);
static void printMnemonic(std::ostream &os, const char *instMnemonic,
const char *mnemonic);
static void printMem(std::ostream &os, uint8_t segment,
uint8_t scale, RegIndex index, RegIndex base,
uint64_t disp, uint8_t addressSize, bool rip);
static void printSegment(std::ostream &os, int segment);
static void printReg(std::ostream &os, RegId reg, int size);
protected:
using ExtMachInst = X86ISA::ExtMachInst;
@@ -95,19 +107,8 @@ class X86StaticInst : public StaticInst
std::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
void printMnemonic(std::ostream &os, const char * mnemonic) const;
void printMnemonic(std::ostream &os, const char * instMnemonic,
const char * mnemonic) const;
void printSegment(std::ostream &os, int segment) const;
void printReg(std::ostream &os, RegId reg, int size) const;
void printSrcReg(std::ostream &os, int reg, int size) const;
void printDestReg(std::ostream &os, int reg, int size) const;
void printMem(std::ostream &os, uint8_t segment,
uint8_t scale, RegIndex index, RegIndex base,
uint64_t disp, uint8_t addressSize, bool rip) const;
inline uint64_t
merge(uint64_t into, uint64_t val, int size) const

View File

@@ -77,6 +77,7 @@ output decoder {{
#include "arch/x86/faults.hh"
#include "arch/x86/microcode_rom.hh"
#include "arch/x86/regs/float.hh"
#include "arch/x86/regs/int.hh"
#include "arch/x86/regs/misc.hh"
#include "arch/x86/regs/segment.hh"
#include "arch/x86/tlb.hh"

View File

@@ -135,7 +135,8 @@ let {{
for reg in ('ah', 'bh', 'ch', 'dh'):
assembler.symbols[reg] = \
regIdx("INTREG_FOLDED(INTREG_%s, IntFoldBit)" % reg.upper())
regIdx("X86ISA::INTREG_FOLDED(INTREG_%s, IntFoldBit)" %
reg.upper())
for reg in range(16):
assembler.symbols["cr%d" % reg] = regIdx("MISCREG_CR%d" % reg)

File diff suppressed because it is too large Load Diff

View File

@@ -55,12 +55,14 @@ def operand_types {{
let {{
def foldInt(idx, foldBit, id):
return ('IntReg', 'uqw', 'INTREG_FOLDED(%s, %s)' % (idx, foldBit),
'IsInteger', id)
return ('IntReg', 'uqw',
'X86ISA::INTREG_FOLDED(%s, %s)' % (idx, foldBit), 'IsInteger',
id)
def intReg(idx, id):
return ('IntReg', 'uqw', idx, 'IsInteger', id)
def impIntReg(idx, id):
return ('IntReg', 'uqw', 'INTREG_IMPLICIT(%s)' % idx, 'IsInteger', id)
return ('IntReg', 'uqw', 'X86ISA::INTREG_IMPLICIT(%s)' % idx,
'IsInteger', id)
def floatReg(idx, id):
return ('FloatReg', 'df', idx, 'IsFloating', id)
def ccReg(idx, id):
@@ -81,7 +83,7 @@ let {{
def squashCReg(idx, id, ctype = 'uqw'):
return squashCheckReg(idx, id, 'true', ctype)
def squashCSReg(idx, id, ctype = 'uqw'):
return squashCheckReg(idx, id, 'dest == SEGMENT_REG_CS', ctype)
return squashCheckReg(idx, id, 'dest == X86ISA::SEGMENT_REG_CS', ctype)
def squashCR0Reg(idx, id, ctype = 'uqw'):
return squashCheckReg(idx, id, 'dest == 0', ctype)
}};
@@ -104,16 +106,16 @@ def operands {{
'Remainder': impIntReg(3, 10),
'Divisor': impIntReg(4, 11),
'DoubleBits': impIntReg(5, 11),
'Rax': intReg('(INTREG_RAX)', 12),
'Rbx': intReg('(INTREG_RBX)', 13),
'Rcx': intReg('(INTREG_RCX)', 14),
'Rdx': intReg('(INTREG_RDX)', 15),
'Rsp': intReg('(INTREG_RSP)', 16),
'Rbp': intReg('(INTREG_RBP)', 17),
'Rsi': intReg('(INTREG_RSI)', 18),
'Rdi': intReg('(INTREG_RDI)', 19),
'R8': intReg('(INTREG_R8)', 20),
'R9': intReg('(INTREG_R9)', 21),
'Rax': intReg('X86ISA::INTREG_RAX', 12),
'Rbx': intReg('X86ISA::INTREG_RBX', 13),
'Rcx': intReg('X86ISA::INTREG_RCX', 14),
'Rdx': intReg('X86ISA::INTREG_RDX', 15),
'Rsp': intReg('X86ISA::INTREG_RSP', 16),
'Rbp': intReg('X86ISA::INTREG_RBP', 17),
'Rsi': intReg('X86ISA::INTREG_RSI', 18),
'Rdi': intReg('X86ISA::INTREG_RDI', 19),
'R8': intReg('X86ISA::INTREG_R8', 20),
'R9': intReg('X86ISA::INTREG_R9', 21),
'FpSrcReg1': floatReg('src1', 22),
'FpSrcReg2': floatReg('src2', 23),
'FpDestReg': floatReg('dest', 24),
@@ -126,11 +128,11 @@ def operands {{
(None, None, 'IsControl'), 50),
# These registers hold the condition code portion of the flag
# register. The nccFlagBits version holds the rest.
'ccFlagBits': ccReg('(CCREG_ZAPS)', 60),
'cfofBits': ccReg('(CCREG_CFOF)', 61),
'dfBit': ccReg('(CCREG_DF)', 62),
'ecfBit': ccReg('(CCREG_ECF)', 63),
'ezfBit': ccReg('(CCREG_EZF)', 64),
'ccFlagBits': ccReg('X86ISA::CCREG_ZAPS', 60),
'cfofBits': ccReg('X86ISA::CCREG_CFOF', 61),
'dfBit': ccReg('X86ISA::CCREG_DF', 62),
'ecfBit': ccReg('X86ISA::CCREG_ECF', 63),
'ezfBit': ccReg('X86ISA::CCREG_EZF', 64),
# These Pred registers are to be used where reading the portions of
# condition code registers is possibly optional, depending on how the
@@ -147,65 +149,72 @@ def operands {{
# would be retained, the write predicate checks if any of the bits
# are being written.
'PredccFlagBits': ('CCReg', 'uqw', '(CCREG_ZAPS)', None,
60, None, None, '''(((ext & (PFBit | AFBit | ZFBit | SFBit
)) != (PFBit | AFBit | ZFBit | SFBit )) &&
((ext & (PFBit | AFBit | ZFBit | SFBit )) != 0))''',
'((ext & (PFBit | AFBit | ZFBit | SFBit )) != 0)'),
'PredcfofBits': ('CCReg', 'uqw', '(CCREG_CFOF)', None,
61, None, None, '''(((ext & CFBit) == 0 ||
(ext & OFBit) == 0) && ((ext & (CFBit | OFBit)) != 0))''',
'((ext & (CFBit | OFBit)) != 0)'),
'PreddfBit': ('CCReg', 'uqw', '(CCREG_DF)', None,
62, None, None, '(false)', '((ext & DFBit) != 0)'),
'PredecfBit': ('CCReg', 'uqw', '(CCREG_ECF)', None,
63, None, None, '(false)', '((ext & ECFBit) != 0)'),
'PredezfBit': ('CCReg', 'uqw', '(CCREG_EZF)', None,
64, None, None, '(false)', '((ext & EZFBit) != 0)'),
'PredccFlagBits': ('CCReg', 'uqw', '(X86ISA::CCREG_ZAPS)', None,
60, None, None,
'''(((ext & (X86ISA::PFBit | X86ISA::AFBit |
X86ISA::ZFBit | X86ISA::SFBit)) !=
(X86ISA::PFBit | X86ISA::AFBit |
X86ISA::ZFBit | X86ISA::SFBit)) &&
((ext & (X86ISA::PFBit | X86ISA::AFBit |
X86ISA::ZFBit | X86ISA::SFBit)) != 0))''',
'''((ext & (X86ISA::PFBit | X86ISA::AFBit |
X86ISA::ZFBit | X86ISA::SFBit)) != 0)'''),
'PredcfofBits': ('CCReg', 'uqw', '(X86ISA::CCREG_CFOF)', None,
61, None, None, '''(((ext & X86ISA::CFBit) == 0 ||
(ext & X86ISA::OFBit) == 0) &&
((ext & (X86ISA::CFBit | X86ISA::OFBit)) != 0))''',
'((ext & (X86ISA::CFBit | X86ISA::OFBit)) != 0)'),
'PreddfBit': ('CCReg', 'uqw', '(X86ISA::CCREG_DF)', None,
62, None, None, '(false)', '((ext & X86ISA::DFBit) != 0)'),
'PredecfBit': ('CCReg', 'uqw', '(X86ISA::CCREG_ECF)', None,
63, None, None, '(false)', '((ext & X86ISA::ECFBit) != 0)'),
'PredezfBit': ('CCReg', 'uqw', '(X86ISA::CCREG_EZF)', None,
64, None, None, '(false)', '((ext & X86ISA::EZFBit) != 0)'),
# These register should needs to be more protected so that later
# instructions don't map their indexes with an old value.
'nccFlagBits': controlReg('MISCREG_RFLAGS', 65),
'nccFlagBits': controlReg('X86ISA::MISCREG_RFLAGS', 65),
# Registers related to the state of x87 floating point unit.
'TOP': controlReg('MISCREG_X87_TOP', 66, ctype='ub'),
'FSW': controlReg('MISCREG_FSW', 67, ctype='uw'),
'FTW': controlReg('MISCREG_FTW', 68, ctype='uw'),
'FCW': controlReg('MISCREG_FCW', 69, ctype='uw'),
'TOP': controlReg('X86ISA::MISCREG_X87_TOP', 66, ctype='ub'),
'FSW': controlReg('X86ISA::MISCREG_FSW', 67, ctype='uw'),
'FTW': controlReg('X86ISA::MISCREG_FTW', 68, ctype='uw'),
'FCW': controlReg('X86ISA::MISCREG_FCW', 69, ctype='uw'),
# The segment base as used by memory instructions.
'SegBase': controlReg('MISCREG_SEG_EFF_BASE(segment)', 70),
'SegBase': controlReg('X86ISA::MISCREG_SEG_EFF_BASE(segment)',
70),
# Operands to get and set registers indexed by the operands of the
# original instruction.
'ControlDest': squashCR0Reg('MISCREG_CR(dest)', 100),
'ControlSrc1': controlReg('MISCREG_CR(src1)', 101),
'DebugDest': controlReg('MISCREG_DR(dest)', 102),
'DebugSrc1': controlReg('MISCREG_DR(src1)', 103),
'SegBaseDest': squashCSReg('MISCREG_SEG_BASE(dest)', 104),
'SegBaseSrc1': controlReg('MISCREG_SEG_BASE(src1)', 105),
'SegLimitDest': squashCSReg('MISCREG_SEG_LIMIT(dest)', 106),
'SegLimitSrc1': controlReg('MISCREG_SEG_LIMIT(src1)', 107),
'SegSelDest': controlReg('MISCREG_SEG_SEL(dest)', 108),
'SegSelSrc1': controlReg('MISCREG_SEG_SEL(src1)', 109),
'SegAttrDest': squashCSReg('MISCREG_SEG_ATTR(dest)', 110),
'SegAttrSrc1': controlReg('MISCREG_SEG_ATTR(src1)', 111),
'ControlDest': squashCR0Reg('X86ISA::MISCREG_CR(dest)', 100),
'ControlSrc1': controlReg('X86ISA::MISCREG_CR(src1)', 101),
'DebugDest': controlReg('X86ISA::MISCREG_DR(dest)', 102),
'DebugSrc1': controlReg('X86ISA::MISCREG_DR(src1)', 103),
'SegBaseDest': squashCSReg('X86ISA::MISCREG_SEG_BASE(dest)', 104),
'SegBaseSrc1': controlReg('X86ISA::MISCREG_SEG_BASE(src1)', 105),
'SegLimitDest': squashCSReg('X86ISA::MISCREG_SEG_LIMIT(dest)', 106),
'SegLimitSrc1': controlReg('X86ISA::MISCREG_SEG_LIMIT(src1)', 107),
'SegSelDest': controlReg('X86ISA::MISCREG_SEG_SEL(dest)', 108),
'SegSelSrc1': controlReg('X86ISA::MISCREG_SEG_SEL(src1)', 109),
'SegAttrDest': squashCSReg('X86ISA::MISCREG_SEG_ATTR(dest)', 110),
'SegAttrSrc1': controlReg('X86ISA::MISCREG_SEG_ATTR(src1)', 111),
# Operands to access specific control registers directly.
'EferOp': squashCReg('MISCREG_EFER', 200),
'CR4Op': controlReg('MISCREG_CR4', 201),
'DR7Op': controlReg('MISCREG_DR7', 202),
'LDTRBase': controlReg('MISCREG_TSL_BASE', 203),
'LDTRLimit': controlReg('MISCREG_TSL_LIMIT', 204),
'LDTRSel': controlReg('MISCREG_TSL', 205),
'GDTRBase': controlReg('MISCREG_TSG_BASE', 206),
'GDTRLimit': controlReg('MISCREG_TSG_LIMIT', 207),
'CSBase': squashCReg('MISCREG_CS_EFF_BASE', 208),
'CSAttr': squashCReg('MISCREG_CS_ATTR', 209),
'EferOp': squashCReg('X86ISA::MISCREG_EFER', 200),
'CR4Op': controlReg('X86ISA::MISCREG_CR4', 201),
'DR7Op': controlReg('X86ISA::MISCREG_DR7', 202),
'LDTRBase': controlReg('X86ISA::MISCREG_TSL_BASE', 203),
'LDTRLimit': controlReg('X86ISA::MISCREG_TSL_LIMIT', 204),
'LDTRSel': controlReg('X86ISA::MISCREG_TSL', 205),
'GDTRBase': controlReg('X86ISA::MISCREG_TSG_BASE', 206),
'GDTRLimit': controlReg('X86ISA::MISCREG_TSG_LIMIT', 207),
'CSBase': squashCReg('X86ISA::MISCREG_CS_EFF_BASE', 208),
'CSAttr': squashCReg('X86ISA::MISCREG_CS_ATTR', 209),
'MiscRegDest': controlReg('dest', 210),
'MiscRegSrc1': controlReg('src1', 211),
'TscOp': controlReg('MISCREG_TSC', 212),
'M5Reg': squashCReg('MISCREG_M5_REG', 213),
'TscOp': controlReg('X86ISA::MISCREG_TSC', 212),
'M5Reg': squashCReg('X86ISA::MISCREG_M5_REG', 213),
'Mem': ('Mem', 'uqw', None, \
(None, 'IsLoad', 'IsStore'), 300)
}};