arch-x86: Fix style in plain C++ StaticInst base classes.

Change-Id: I826fce4071fe413f16caffbcd519396eec1967a0
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/39675
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2021-01-24 22:55:02 -08:00
parent c4cad07fc5
commit 086cc6c893
12 changed files with 918 additions and 915 deletions

View File

@@ -43,26 +43,20 @@
namespace X86ISA
{
/*
uint64_t FpOp::genFlags(uint64_t oldFlags, uint64_t flagMask,
uint64_t _dest, uint64_t _src1, uint64_t _src2,
bool subtract) const
{
}
*/
std::string
FpOp::generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream response;
std::string
FpOp::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();
}
printMnemonic(response, instMnem, mnemonic);
printDestReg(response, 0, dataSize);
response << ", ";
printSrcReg(response, 0, dataSize);
response << ", ";
printSrcReg(response, 1, dataSize);
return response.str();
}
}

View File

@@ -43,40 +43,35 @@
namespace X86ISA
{
/**
* Base classes for FpOps which provides a generateDisassembly method.
*/
class FpOp : public X86MicroopBase
{
protected:
const RegIndex src1;
const RegIndex src2;
const RegIndex dest;
const uint8_t dataSize;
const int8_t spm;
/**
* Base classes for FpOps which provides a generateDisassembly method.
*/
class FpOp : public X86MicroopBase
{
protected:
const RegIndex src1;
const RegIndex src2;
const RegIndex dest;
const uint8_t dataSize;
const int8_t spm;
// Constructor
FpOp(ExtMachInst _machInst,
const char *mnem, const char *_instMnem,
uint64_t setFlags,
InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
uint8_t _dataSize, int8_t _spm,
OpClass __opClass) :
X86MicroopBase(_machInst, mnem, _instMnem, setFlags,
__opClass),
src1(_src1.index()), src2(_src2.index()), dest(_dest.index()),
dataSize(_dataSize), spm(_spm)
{}
/*
//Figure out what the condition code flags should be.
uint64_t genFlags(uint64_t oldFlags, uint64_t flagMask,
uint64_t _dest, uint64_t _src1, uint64_t _src2,
bool subtract = false) const;
bool checkCondition(uint64_t flags) const;*/
// Constructor
FpOp(ExtMachInst _machInst,
const char *mnem, const char *_instMnem,
uint64_t setFlags,
InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
uint8_t _dataSize, int8_t _spm,
OpClass __opClass) :
X86MicroopBase(_machInst, mnem, _instMnem, setFlags,
__opClass),
src1(_src1.index()), src2(_src2.index()), dest(_dest.index()),
dataSize(_dataSize), spm(_spm)
{}
std::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
};
std::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
};
}
#endif //__ARCH_X86_INSTS_MICROFPOP_HH__

View File

@@ -42,38 +42,37 @@
namespace X86ISA
{
std::string
LdStOp::generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
if (flags[IsLoad])
printDestReg(response, 0, dataSize);
else
printSrcReg(response, 2, dataSize);
response << ", ";
printMem(response, segment, scale, index, base, disp,
addressSize, false);
return response.str();
}
std::string
LdStOp::generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
if (flags[IsLoad])
printDestReg(response, 0, dataSize);
else
printSrcReg(response, 2, dataSize);
response << ", ";
printMem(response, segment, scale, index, base, disp, addressSize, false);
return response.str();
}
std::string
LdStSplitOp::generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
int baseRegIdx = flags[IsLoad] ? 0 : 2;
response << "[";
printDestReg(response, baseRegIdx, dataSize);
response << ", ";
printDestReg(response, baseRegIdx+1, dataSize);
response << "], ";
printMem(response, segment, scale, index, base, disp, addressSize, false);
return response.str();
}
std::string
LdStSplitOp::generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
int baseRegIdx = flags[IsLoad] ? 0 : 2;
response << "[";
printDestReg(response, baseRegIdx, dataSize);
response << ", ";
printDestReg(response, baseRegIdx+1, dataSize);
response << "], ";
printMem(response, segment, scale, index, base, disp,
addressSize, false);
return response.str();
}
}

View File

@@ -47,108 +47,108 @@
namespace X86ISA
{
/**
* Base class for memory ops
*/
class MemOp : public X86MicroopBase
/**
* Base class for memory ops
*/
class MemOp : public X86MicroopBase
{
protected:
const uint8_t scale;
const RegIndex index;
const RegIndex base;
const uint64_t disp;
const uint8_t segment;
const uint8_t dataSize;
const uint8_t addressSize;
const Request::FlagsType memFlags;
RegIndex foldOBit, foldABit;
//Constructor
MemOp(ExtMachInst _machInst,
const char * mnem, const char * _instMnem,
uint64_t setFlags,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags,
OpClass __opClass) :
X86MicroopBase(_machInst, mnem, _instMnem, setFlags, __opClass),
scale(_scale), index(_index.index()), base(_base.index()),
disp(_disp), segment(_segment.index()),
dataSize(_dataSize), addressSize(_addressSize),
memFlags(_memFlags | _segment.index())
{
protected:
const uint8_t scale;
const RegIndex index;
const RegIndex base;
const uint64_t disp;
const uint8_t segment;
const uint8_t dataSize;
const uint8_t addressSize;
const Request::FlagsType memFlags;
RegIndex foldOBit, foldABit;
assert(_segment.index() < NUM_SEGMENTREGS);
foldOBit = (dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
foldABit = (addressSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
}
};
//Constructor
MemOp(ExtMachInst _machInst,
const char * mnem, const char * _instMnem,
uint64_t setFlags,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags,
OpClass __opClass) :
X86MicroopBase(_machInst, mnem, _instMnem, setFlags, __opClass),
scale(_scale), index(_index.index()), base(_base.index()),
disp(_disp), segment(_segment.index()),
dataSize(_dataSize), addressSize(_addressSize),
memFlags(_memFlags | _segment.index())
{
assert(_segment.index() < NUM_SEGMENTREGS);
foldOBit =
(dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
foldABit =
(addressSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
}
};
/**
* Base class for load and store ops using one register
*/
class LdStOp : public MemOp
{
protected:
const RegIndex data;
/**
* Base class for load and store ops using one register
*/
class LdStOp : public MemOp
//Constructor
LdStOp(ExtMachInst _machInst,
const char * mnem, const char * _instMnem,
uint64_t setFlags,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags,
OpClass __opClass) :
MemOp(_machInst, mnem, _instMnem, setFlags,
_scale, _index, _base, _disp, _segment,
_dataSize, _addressSize, _memFlags,
__opClass),
data(_data.index())
{
protected:
const RegIndex data;
}
//Constructor
LdStOp(ExtMachInst _machInst,
const char * mnem, const char * _instMnem,
uint64_t setFlags,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags,
OpClass __opClass) :
MemOp(_machInst, mnem, _instMnem, setFlags,
_scale, _index, _base, _disp, _segment,
_dataSize, _addressSize, _memFlags,
__opClass),
data(_data.index())
{
}
std::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
};
std::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
};
/**
* Base class for load and store ops using two registers, we will
* call them split ops for this reason. These are mainly used to
* implement cmpxchg8b and cmpxchg16b.
*/
class LdStSplitOp : public MemOp
{
protected:
const RegIndex dataLow;
const RegIndex dataHi;
/**
* Base class for load and store ops using two registers, we will
* call them split ops for this reason. These are mainly used to
* implement cmpxchg8b and cmpxchg16b.
*/
class LdStSplitOp : public MemOp
//Constructor
LdStSplitOp(ExtMachInst _machInst,
const char * mnem, const char * _instMnem,
uint64_t setFlags,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _dataLow, InstRegIndex _dataHi,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags,
OpClass __opClass) :
MemOp(_machInst, mnem, _instMnem, setFlags,
_scale, _index, _base, _disp, _segment,
_dataSize, _addressSize, _memFlags,
__opClass),
dataLow(_dataLow.index()),
dataHi(_dataHi.index())
{
protected:
const RegIndex dataLow;
const RegIndex dataHi;
}
//Constructor
LdStSplitOp(ExtMachInst _machInst,
const char * mnem, const char * _instMnem,
uint64_t setFlags,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _dataLow, InstRegIndex _dataHi,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags,
OpClass __opClass) :
MemOp(_machInst, mnem, _instMnem, setFlags,
_scale, _index, _base, _disp, _segment,
_dataSize, _addressSize, _memFlags,
__opClass),
dataLow(_dataLow.index()),
dataHi(_dataHi.index())
{
}
std::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
};
std::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
};
}
#endif //__ARCH_X86_INSTS_MICROLDSTOP_HH__

View File

@@ -34,32 +34,34 @@
namespace X86ISA
{
std::string
MediaOpReg::generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
printDestReg(response, 0, destSize);
response << ", ";
printSrcReg(response, 0, srcSize);
response << ", ";
printSrcReg(response, 1, srcSize);
return response.str();
}
std::string
MediaOpReg::generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
printDestReg(response, 0, destSize);
response << ", ";
printSrcReg(response, 0, srcSize);
response << ", ";
printSrcReg(response, 1, srcSize);
return response.str();
}
std::string
MediaOpImm::generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
printDestReg(response, 0, destSize);
response << ", ";
printSrcReg(response, 0, srcSize);
ccprintf(response, ", %#x", imm8);
return response.str();
}
std::string
MediaOpImm::generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, instMnem, mnemonic);
printDestReg(response, 0, destSize);
response << ", ";
printSrcReg(response, 0, srcSize);
ccprintf(response, ", %#x", imm8);
return response.str();
}
}

View File

@@ -33,100 +33,103 @@
namespace X86ISA
{
enum MediaFlag {
MediaMultHiOp = 1,
MediaSignedOp = 64,
MediaScalarOp = 128
};
class MediaOpBase : public X86MicroopBase
enum MediaFlag
{
MediaMultHiOp = 1,
MediaSignedOp = 64,
MediaScalarOp = 128
};
class MediaOpBase : public X86MicroopBase
{
protected:
const RegIndex src1;
const RegIndex dest;
const uint8_t srcSize;
const uint8_t destSize;
const uint8_t ext;
static const RegIndex foldOBit = 0;
// Constructor
MediaOpBase(ExtMachInst _machInst,
const char *mnem, const char *_instMnem, uint64_t setFlags,
InstRegIndex _src1, InstRegIndex _dest,
uint8_t _srcSize, uint8_t _destSize, uint8_t _ext,
OpClass __opClass) :
X86MicroopBase(_machInst, mnem, _instMnem, setFlags,
__opClass),
src1(_src1.index()), dest(_dest.index()),
srcSize(_srcSize), destSize(_destSize), ext(_ext)
{}
bool
scalarOp() const
{
protected:
const RegIndex src1;
const RegIndex dest;
const uint8_t srcSize;
const uint8_t destSize;
const uint8_t ext;
static const RegIndex foldOBit = 0;
return ext & MediaScalarOp;
}
// Constructor
MediaOpBase(ExtMachInst _machInst,
const char *mnem, const char *_instMnem, uint64_t setFlags,
InstRegIndex _src1, InstRegIndex _dest,
uint8_t _srcSize, uint8_t _destSize, uint8_t _ext,
OpClass __opClass) :
X86MicroopBase(_machInst, mnem, _instMnem, setFlags,
__opClass),
src1(_src1.index()), dest(_dest.index()),
srcSize(_srcSize), destSize(_destSize), ext(_ext)
{}
bool
scalarOp() const
{
return ext & MediaScalarOp;
}
int
numItems(int size) const
{
return scalarOp() ? 1 : (sizeof(uint64_t) / size);
}
bool
multHi() const
{
return ext & MediaMultHiOp;
}
bool
signedOp() const
{
return ext & MediaSignedOp;
}
};
class MediaOpReg : public MediaOpBase
int
numItems(int size) const
{
protected:
const RegIndex src2;
return scalarOp() ? 1 : (sizeof(uint64_t) / size);
}
// Constructor
MediaOpReg(ExtMachInst _machInst,
const char *mnem, const char *_instMnem, uint64_t setFlags,
InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
uint8_t _srcSize, uint8_t _destSize, uint8_t _ext,
OpClass __opClass) :
MediaOpBase(_machInst, mnem, _instMnem, setFlags,
_src1, _dest, _srcSize, _destSize, _ext,
__opClass),
src2(_src2.index())
{}
std::string generateDisassembly(Addr pc,
const Loader::SymbolTable *symtab) const override;
};
class MediaOpImm : public MediaOpBase
bool
multHi() const
{
protected:
uint8_t imm8;
return ext & MediaMultHiOp;
}
// Constructor
MediaOpImm(ExtMachInst _machInst,
const char *mnem, const char *_instMnem, uint64_t setFlags,
InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
uint8_t _srcSize, uint8_t _destSize, uint8_t _ext,
OpClass __opClass) :
MediaOpBase(_machInst, mnem, _instMnem, setFlags,
_src1, _dest, _srcSize, _destSize, _ext,
__opClass),
imm8(_imm8)
{}
bool
signedOp() const
{
return ext & MediaSignedOp;
}
};
class MediaOpReg : public MediaOpBase
{
protected:
const RegIndex src2;
// Constructor
MediaOpReg(ExtMachInst _machInst,
const char *mnem, const char *_instMnem, uint64_t setFlags,
InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
uint8_t _srcSize, uint8_t _destSize, uint8_t _ext,
OpClass __opClass) :
MediaOpBase(_machInst, mnem, _instMnem, setFlags,
_src1, _dest, _srcSize, _destSize, _ext,
__opClass),
src2(_src2.index())
{}
std::string generateDisassembly(Addr pc,
const Loader::SymbolTable *symtab) const override;
};
class MediaOpImm : public MediaOpBase
{
protected:
uint8_t imm8;
// Constructor
MediaOpImm(ExtMachInst _machInst,
const char *mnem, const char *_instMnem, uint64_t setFlags,
InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
uint8_t _srcSize, uint8_t _destSize, uint8_t _ext,
OpClass __opClass) :
MediaOpBase(_machInst, mnem, _instMnem, setFlags,
_src1, _dest, _srcSize, _destSize, _ext,
__opClass),
imm8(_imm8)
{}
std::string generateDisassembly(Addr pc,
const Loader::SymbolTable *symtab) const override;
};
std::string generateDisassembly(Addr pc,
const Loader::SymbolTable *symtab) const override;
};
}
#endif //__ARCH_X86_INSTS_MICROMEDIAOP_HH__

View File

@@ -42,79 +42,81 @@
namespace X86ISA
{
bool X86MicroopBase::checkCondition(uint64_t flags, int condition) const
bool
X86MicroopBase::checkCondition(uint64_t flags, int condition) const
{
CCFlagBits ccflags = flags;
switch(condition)
{
CCFlagBits ccflags = flags;
switch(condition)
{
case ConditionTests::True:
return true;
case ConditionTests::ECF:
return ccflags.ecf;
case ConditionTests::EZF:
return ccflags.ezf;
case ConditionTests::SZnZF:
return !(!ccflags.ezf && ccflags.zf);
case ConditionTests::MSTRZ:
panic("This condition is not implemented!");
case ConditionTests::STRZ:
panic("This condition is not implemented!");
case ConditionTests::MSTRC:
panic("This condition is not implemented!");
case ConditionTests::STRZnEZF:
return !ccflags.ezf && ccflags.zf;
//And no interrupts or debug traps are waiting
case ConditionTests::OF:
return ccflags.of;
case ConditionTests::CF:
return ccflags.cf;
case ConditionTests::ZF:
return ccflags.zf;
case ConditionTests::CvZF:
return ccflags.cf | ccflags.zf;
case ConditionTests::SF:
return ccflags.sf;
case ConditionTests::PF:
return ccflags.pf;
case ConditionTests::SxOF:
return ccflags.sf ^ ccflags.of;
case ConditionTests::SxOvZF:
return (ccflags.sf ^ ccflags.of) | ccflags.zf;
case ConditionTests::False:
return false;
case ConditionTests::NotECF:
return !ccflags.ecf;
case ConditionTests::NotEZF:
return !ccflags.ezf;
case ConditionTests::NotSZnZF:
return !ccflags.ezf && ccflags.zf;
case ConditionTests::NotMSTRZ:
panic("This condition is not implemented!");
case ConditionTests::NotSTRZ:
panic("This condition is not implemented!");
case ConditionTests::NotMSTRC:
panic("This condition is not implemented!");
case ConditionTests::STRnZnEZF:
return !ccflags.ezf && !ccflags.zf;
//And no interrupts or debug traps are waiting
case ConditionTests::NotOF:
return !ccflags.of;
case ConditionTests::NotCF:
return !ccflags.cf;
case ConditionTests::NotZF:
return !ccflags.zf;
case ConditionTests::NotCvZF:
return !(ccflags.cf | ccflags.zf);
case ConditionTests::NotSF:
return !ccflags.sf;
case ConditionTests::NotPF:
return !ccflags.pf;
case ConditionTests::NotSxOF:
return !(ccflags.sf ^ ccflags.of);
case ConditionTests::NotSxOvZF:
return !((ccflags.sf ^ ccflags.of) | ccflags.zf);
}
panic("Unknown condition: %d\n", condition);
case ConditionTests::True:
return true;
case ConditionTests::ECF:
return ccflags.ecf;
case ConditionTests::EZF:
return ccflags.ezf;
case ConditionTests::SZnZF:
return !(!ccflags.ezf && ccflags.zf);
case ConditionTests::MSTRZ:
panic("This condition is not implemented!");
case ConditionTests::STRZ:
panic("This condition is not implemented!");
case ConditionTests::MSTRC:
panic("This condition is not implemented!");
case ConditionTests::STRZnEZF:
return !ccflags.ezf && ccflags.zf;
//And no interrupts or debug traps are waiting
case ConditionTests::OF:
return ccflags.of;
case ConditionTests::CF:
return ccflags.cf;
case ConditionTests::ZF:
return ccflags.zf;
case ConditionTests::CvZF:
return ccflags.cf | ccflags.zf;
case ConditionTests::SF:
return ccflags.sf;
case ConditionTests::PF:
return ccflags.pf;
case ConditionTests::SxOF:
return ccflags.sf ^ ccflags.of;
case ConditionTests::SxOvZF:
return (ccflags.sf ^ ccflags.of) | ccflags.zf;
case ConditionTests::False:
return false;
case ConditionTests::NotECF:
return !ccflags.ecf;
case ConditionTests::NotEZF:
return !ccflags.ezf;
case ConditionTests::NotSZnZF:
return !ccflags.ezf && ccflags.zf;
case ConditionTests::NotMSTRZ:
panic("This condition is not implemented!");
case ConditionTests::NotSTRZ:
panic("This condition is not implemented!");
case ConditionTests::NotMSTRC:
panic("This condition is not implemented!");
case ConditionTests::STRnZnEZF:
return !ccflags.ezf && !ccflags.zf;
//And no interrupts or debug traps are waiting
case ConditionTests::NotOF:
return !ccflags.of;
case ConditionTests::NotCF:
return !ccflags.cf;
case ConditionTests::NotZF:
return !ccflags.zf;
case ConditionTests::NotCvZF:
return !(ccflags.cf | ccflags.zf);
case ConditionTests::NotSF:
return !ccflags.sf;
case ConditionTests::NotPF:
return !ccflags.pf;
case ConditionTests::NotSxOF:
return !(ccflags.sf ^ ccflags.of);
case ConditionTests::NotSxOvZF:
return !((ccflags.sf ^ ccflags.of) | ccflags.zf);
}
panic("Unknown condition: %d\n", condition);
return true;
}
}

View File

@@ -42,95 +42,100 @@
namespace X86ISA
{
namespace ConditionTests
{
enum CondTest {
True,
NotFalse = True,
ECF,
EZF,
SZnZF,
MSTRZ,
STRZ,
MSTRC,
STRZnEZF,
OF,
CF,
ZF,
CvZF,
SF,
PF,
SxOF,
SxOvZF,
False,
NotTrue = False,
NotECF,
NotEZF,
NotSZnZF,
NotMSTRZ,
NotSTRZ,
NotMSTRC,
STRnZnEZF,
NotOF,
NotCF,
NotZF,
NotCvZF,
NotSF,
NotPF,
NotSxOF,
NotSxOvZF
};
namespace ConditionTests
{
enum CondTest
{
True,
NotFalse = True,
ECF,
EZF,
SZnZF,
MSTRZ,
STRZ,
MSTRC,
STRZnEZF,
OF,
CF,
ZF,
CvZF,
SF,
PF,
SxOF,
SxOvZF,
False,
NotTrue = False,
NotECF,
NotEZF,
NotSZnZF,
NotMSTRZ,
NotSTRZ,
NotMSTRC,
STRnZnEZF,
NotOF,
NotCF,
NotZF,
NotCvZF,
NotSF,
NotPF,
NotSxOF,
NotSxOvZF
};
}
//A class which is the base of all x86 micro ops. It provides a function to
//set necessary flags appropriately.
class X86MicroopBase : public X86StaticInst
{
protected:
const char * instMnem;
uint8_t opSize;
uint8_t addrSize;
X86MicroopBase(ExtMachInst _machInst,
const char *mnem, const char *_instMnem,
uint64_t setFlags, OpClass __opClass) :
X86ISA::X86StaticInst(mnem, _machInst, __opClass),
instMnem(_instMnem)
{
const int ChunkSize = sizeof(unsigned long);
const int Chunks = sizeof(setFlags) / ChunkSize;
// Since the bitset constructor can only handle unsigned long
// sized chunks, feed it those one at a time while oring them in.
for (int i = 0; i < Chunks; i++) {
unsigned shift = i * ChunkSize * 8;
flags |= (std::bitset<Num_Flags>(setFlags >> shift) << shift);
}
}
//A class which is the base of all x86 micro ops. It provides a function to
//set necessary flags appropriately.
class X86MicroopBase : public X86StaticInst
std::string
generateDisassembly(Addr pc,
const Loader::SymbolTable *symtab) const override
{
protected:
const char * instMnem;
uint8_t opSize;
uint8_t addrSize;
std::stringstream ss;
X86MicroopBase(ExtMachInst _machInst,
const char *mnem, const char *_instMnem,
uint64_t setFlags, OpClass __opClass) :
X86ISA::X86StaticInst(mnem, _machInst, __opClass),
instMnem(_instMnem)
{
const int ChunkSize = sizeof(unsigned long);
const int Chunks = sizeof(setFlags) / ChunkSize;
ccprintf(ss, "\t%s.%s", instMnem, mnemonic);
// Since the bitset constructor can only handle unsigned long
// sized chunks, feed it those one at a time while oring them in.
for (int i = 0; i < Chunks; i++) {
unsigned shift = i * ChunkSize * 8;
flags |= (std::bitset<Num_Flags>(setFlags >> shift) << shift);
}
}
return ss.str();
}
std::string
generateDisassembly(Addr pc,
const Loader::SymbolTable *symtab) const override
{
std::stringstream ss;
bool checkCondition(uint64_t flags, int condition) const;
ccprintf(ss, "\t%s.%s", instMnem, mnemonic);
void
advancePC(PCState &pcState) const override
{
if (flags[IsLastMicroop])
pcState.uEnd();
else
pcState.uAdvance();
}
};
return ss.str();
}
bool checkCondition(uint64_t flags, int condition) const;
void
advancePC(PCState &pcState) const override
{
if (flags[IsLastMicroop])
pcState.uEnd();
else
pcState.uAdvance();
}
};
}
#endif //__ARCH_X86_INSTS_MICROOP_HH__

View File

@@ -45,63 +45,61 @@
namespace X86ISA
{
uint64_t RegOpBase::genFlags(uint64_t oldFlags, uint64_t flagMask,
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))
{
if (findCarry(dataSize*8, _dest, _src1, _src2))
flags |= (flagMask & (ECFBit | CFBit));
if (subtract)
flags ^= (flagMask & (ECFBit | CFBit));
}
if (flagMask & PFBit && !findParity(8, _dest))
flags |= PFBit;
if (flagMask & 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))
flags |= SFBit;
if (flagMask & OFBit && findOverflow(dataSize*8, _dest, _src1, _src2))
flags |= OFBit;
return flags;
uint64_t
RegOpBase::genFlags(uint64_t oldFlags, uint64_t flagMask,
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)) {
if (findCarry(dataSize*8, _dest, _src1, _src2))
flags |= (flagMask & (ECFBit | CFBit));
if (subtract)
flags ^= (flagMask & (ECFBit | CFBit));
}
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();
if (flagMask & PFBit && !findParity(8, _dest))
flags |= PFBit;
if (flagMask & 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))
flags |= SFBit;
if (flagMask & 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

@@ -42,81 +42,83 @@
namespace X86ISA
{
/**
* Base classes for RegOps which provides a generateDisassembly method.
*/
class RegOpBase : public X86MicroopBase
/**
* Base classes for RegOps which provides a generateDisassembly method.
*/
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)
{
protected:
const RegIndex src1;
const RegIndex dest;
const uint8_t dataSize;
const uint16_t ext;
RegIndex foldOBit;
foldOBit = (dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
}
// 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;
}
//Figure out what the condition code flags should be.
uint64_t genFlags(uint64_t oldFlags, uint64_t flagMask,
uint64_t _dest, uint64_t _src1, uint64_t _src2,
bool subtract = false) const;
};
//Figure out what the condition code flags should be.
uint64_t genFlags(uint64_t oldFlags, uint64_t flagMask,
uint64_t _dest, uint64_t _src1, uint64_t _src2,
bool subtract = false) const;
};
class RegOp : public RegOpBase
{
protected:
const RegIndex src2;
class RegOp : public RegOpBase
// 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())
{
protected:
const RegIndex src2;
}
// 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::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
};
class RegOpImm : public RegOpBase
{
protected:
const uint8_t imm8;
class RegOpImm : public RegOpBase
// 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)
{
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;
};
std::string generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const override;
};
}
#endif //__ARCH_X86_INSTS_MICROREGOP_HH__

View File

@@ -43,235 +43,236 @@
namespace X86ISA
{
void X86StaticInst::printMnemonic(std::ostream &os,
const char * mnemonic) const
void
X86StaticInst::printMnemonic(std::ostream &os, const char *mnemonic) const
{
ccprintf(os, " %s ", mnemonic);
}
void
X86StaticInst::printMnemonic(std::ostream &os, const char *instMnemonic,
const char *mnemonic) const
{
ccprintf(os, " %s : %s ", instMnemonic, mnemonic);
}
void X86StaticInst::printSegment(std::ostream &os, int segment) const
{
switch (segment)
{
ccprintf(os, " %s ", mnemonic);
}
void X86StaticInst::printMnemonic(std::ostream &os,
const char * instMnemonic, const char * mnemonic) const
{
ccprintf(os, " %s : %s ", instMnemonic, mnemonic);
}
void X86StaticInst::printSegment(std::ostream &os, int segment) const
{
switch (segment)
{
case SEGMENT_REG_ES:
ccprintf(os, "ES");
break;
case SEGMENT_REG_CS:
ccprintf(os, "CS");
break;
case SEGMENT_REG_SS:
ccprintf(os, "SS");
break;
case SEGMENT_REG_DS:
ccprintf(os, "DS");
break;
case SEGMENT_REG_FS:
ccprintf(os, "FS");
break;
case SEGMENT_REG_GS:
ccprintf(os, "GS");
break;
case SEGMENT_REG_HS:
ccprintf(os, "HS");
break;
case SEGMENT_REG_TSL:
ccprintf(os, "TSL");
break;
case SEGMENT_REG_TSG:
ccprintf(os, "TSG");
break;
case SEGMENT_REG_LS:
ccprintf(os, "LS");
break;
case SEGMENT_REG_MS:
ccprintf(os, "MS");
break;
case SYS_SEGMENT_REG_TR:
ccprintf(os, "TR");
break;
case SYS_SEGMENT_REG_IDTR:
ccprintf(os, "IDTR");
break;
default:
panic("Unrecognized segment %d\n", segment);
}
}
void
X86StaticInst::printSrcReg(std::ostream &os, int reg, int size) const
{
if (_numSrcRegs > reg)
printReg(os, srcRegIdx(reg), size);
}
void
X86StaticInst::printDestReg(std::ostream &os, int reg, int size) const
{
if (_numDestRegs > reg)
printReg(os, destRegIdx(reg), size);
}
void
X86StaticInst::printReg(std::ostream &os, RegId reg, int size) const
{
assert(size == 1 || size == 2 || size == 4 || size == 8);
static const char * abcdFormats[9] =
{"", "%s", "%sx", "", "e%sx", "", "", "", "r%sx"};
static const char * piFormats[9] =
{"", "%s", "%s", "", "e%s", "", "", "", "r%s"};
static const char * longFormats[9] =
{"", "r%sb", "r%sw", "", "r%sd", "", "", "", "r%s"};
static const char * microFormats[9] =
{"", "t%db", "t%dw", "", "t%dd", "", "", "", "t%d"};
RegIndex reg_idx = reg.index();
if (reg.isIntReg()) {
const char * suffix = "";
bool fold = reg_idx & IntFoldBit;
reg_idx &= ~IntFoldBit;
if (fold)
suffix = "h";
else if (reg_idx < 8 && size == 1)
suffix = "l";
switch (reg_idx) {
case INTREG_RAX:
ccprintf(os, abcdFormats[size], "a");
break;
case INTREG_RBX:
ccprintf(os, abcdFormats[size], "b");
break;
case INTREG_RCX:
ccprintf(os, abcdFormats[size], "c");
break;
case INTREG_RDX:
ccprintf(os, abcdFormats[size], "d");
break;
case INTREG_RSP:
ccprintf(os, piFormats[size], "sp");
break;
case INTREG_RBP:
ccprintf(os, piFormats[size], "bp");
break;
case INTREG_RSI:
ccprintf(os, piFormats[size], "si");
break;
case INTREG_RDI:
ccprintf(os, piFormats[size], "di");
break;
case INTREG_R8W:
ccprintf(os, longFormats[size], "8");
break;
case INTREG_R9W:
ccprintf(os, longFormats[size], "9");
break;
case INTREG_R10W:
ccprintf(os, longFormats[size], "10");
break;
case INTREG_R11W:
ccprintf(os, longFormats[size], "11");
break;
case INTREG_R12W:
ccprintf(os, longFormats[size], "12");
break;
case INTREG_R13W:
ccprintf(os, longFormats[size], "13");
break;
case INTREG_R14W:
ccprintf(os, longFormats[size], "14");
break;
case INTREG_R15W:
ccprintf(os, longFormats[size], "15");
break;
default:
ccprintf(os, microFormats[size], reg_idx - NUM_INTREGS);
}
ccprintf(os, suffix);
} else if (reg.isFloatReg()) {
if (reg_idx < NumMMXRegs) {
ccprintf(os, "%%mmx%d", reg_idx);
return;
}
reg_idx -= NumMMXRegs;
if (reg_idx < NumXMMRegs * 2) {
ccprintf(os, "%%xmm%d_%s", reg_idx / 2,
(reg_idx % 2) ? "high": "low");
return;
}
reg_idx -= NumXMMRegs * 2;
if (reg_idx < NumMicroFpRegs) {
ccprintf(os, "%%ufp%d", reg_idx);
return;
}
reg_idx -= NumMicroFpRegs;
ccprintf(os, "%%st(%d)", reg_idx);
} else if (reg.isCCReg()) {
ccprintf(os, "%%cc%d", reg_idx);
} else if (reg.isMiscReg()) {
switch (reg_idx) {
default:
ccprintf(os, "%%ctrl%d", reg_idx);
}
}
}
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
{
bool someAddr = false;
printSegment(os, segment);
os << ":[";
if (rip) {
os << "rip";
someAddr = true;
} else {
if (scale != 0 && index != ZeroReg)
{
if (scale != 1)
ccprintf(os, "%d*", scale);
printReg(os, InstRegIndex(index), addressSize);
someAddr = true;
}
if (base != ZeroReg)
{
if (someAddr)
os << " + ";
printReg(os, InstRegIndex(base), addressSize);
someAddr = true;
}
}
if (disp != 0)
{
if (someAddr)
os << " + ";
ccprintf(os, "%#x", disp);
someAddr = true;
}
if (!someAddr)
os << "0";
os << "]";
}
std::string
X86StaticInst::generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream ss;
printMnemonic(ss, mnemonic);
return ss.str();
case SEGMENT_REG_ES:
ccprintf(os, "ES");
break;
case SEGMENT_REG_CS:
ccprintf(os, "CS");
break;
case SEGMENT_REG_SS:
ccprintf(os, "SS");
break;
case SEGMENT_REG_DS:
ccprintf(os, "DS");
break;
case SEGMENT_REG_FS:
ccprintf(os, "FS");
break;
case SEGMENT_REG_GS:
ccprintf(os, "GS");
break;
case SEGMENT_REG_HS:
ccprintf(os, "HS");
break;
case SEGMENT_REG_TSL:
ccprintf(os, "TSL");
break;
case SEGMENT_REG_TSG:
ccprintf(os, "TSG");
break;
case SEGMENT_REG_LS:
ccprintf(os, "LS");
break;
case SEGMENT_REG_MS:
ccprintf(os, "MS");
break;
case SYS_SEGMENT_REG_TR:
ccprintf(os, "TR");
break;
case SYS_SEGMENT_REG_IDTR:
ccprintf(os, "IDTR");
break;
default:
panic("Unrecognized segment %d\n", segment);
}
}
void
X86StaticInst::printSrcReg(std::ostream &os, int reg, int size) const
{
if (_numSrcRegs > reg)
printReg(os, srcRegIdx(reg), size);
}
void
X86StaticInst::printDestReg(std::ostream &os, int reg, int size) const
{
if (_numDestRegs > reg)
printReg(os, destRegIdx(reg), size);
}
void
X86StaticInst::printReg(std::ostream &os, RegId reg, int size) const
{
assert(size == 1 || size == 2 || size == 4 || size == 8);
static const char * abcdFormats[9] =
{"", "%s", "%sx", "", "e%sx", "", "", "", "r%sx"};
static const char * piFormats[9] =
{"", "%s", "%s", "", "e%s", "", "", "", "r%s"};
static const char * longFormats[9] =
{"", "r%sb", "r%sw", "", "r%sd", "", "", "", "r%s"};
static const char * microFormats[9] =
{"", "t%db", "t%dw", "", "t%dd", "", "", "", "t%d"};
RegIndex reg_idx = reg.index();
if (reg.isIntReg()) {
const char * suffix = "";
bool fold = reg_idx & IntFoldBit;
reg_idx &= ~IntFoldBit;
if (fold)
suffix = "h";
else if (reg_idx < 8 && size == 1)
suffix = "l";
switch (reg_idx) {
case INTREG_RAX:
ccprintf(os, abcdFormats[size], "a");
break;
case INTREG_RBX:
ccprintf(os, abcdFormats[size], "b");
break;
case INTREG_RCX:
ccprintf(os, abcdFormats[size], "c");
break;
case INTREG_RDX:
ccprintf(os, abcdFormats[size], "d");
break;
case INTREG_RSP:
ccprintf(os, piFormats[size], "sp");
break;
case INTREG_RBP:
ccprintf(os, piFormats[size], "bp");
break;
case INTREG_RSI:
ccprintf(os, piFormats[size], "si");
break;
case INTREG_RDI:
ccprintf(os, piFormats[size], "di");
break;
case INTREG_R8W:
ccprintf(os, longFormats[size], "8");
break;
case INTREG_R9W:
ccprintf(os, longFormats[size], "9");
break;
case INTREG_R10W:
ccprintf(os, longFormats[size], "10");
break;
case INTREG_R11W:
ccprintf(os, longFormats[size], "11");
break;
case INTREG_R12W:
ccprintf(os, longFormats[size], "12");
break;
case INTREG_R13W:
ccprintf(os, longFormats[size], "13");
break;
case INTREG_R14W:
ccprintf(os, longFormats[size], "14");
break;
case INTREG_R15W:
ccprintf(os, longFormats[size], "15");
break;
default:
ccprintf(os, microFormats[size], reg_idx - NUM_INTREGS);
}
ccprintf(os, suffix);
} else if (reg.isFloatReg()) {
if (reg_idx < NumMMXRegs) {
ccprintf(os, "%%mmx%d", reg_idx);
return;
}
reg_idx -= NumMMXRegs;
if (reg_idx < NumXMMRegs * 2) {
ccprintf(os, "%%xmm%d_%s", reg_idx / 2,
(reg_idx % 2) ? "high": "low");
return;
}
reg_idx -= NumXMMRegs * 2;
if (reg_idx < NumMicroFpRegs) {
ccprintf(os, "%%ufp%d", reg_idx);
return;
}
reg_idx -= NumMicroFpRegs;
ccprintf(os, "%%st(%d)", reg_idx);
} else if (reg.isCCReg()) {
ccprintf(os, "%%cc%d", reg_idx);
} else if (reg.isMiscReg()) {
switch (reg_idx) {
default:
ccprintf(os, "%%ctrl%d", reg_idx);
}
}
}
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
{
bool someAddr = false;
printSegment(os, segment);
os << ":[";
if (rip) {
os << "rip";
someAddr = true;
} else {
if (scale != 0 && index != ZeroReg) {
if (scale != 1)
ccprintf(os, "%d*", scale);
printReg(os, InstRegIndex(index), addressSize);
someAddr = true;
}
if (base != ZeroReg) {
if (someAddr)
os << " + ";
printReg(os, InstRegIndex(base), addressSize);
someAddr = true;
}
}
if (disp != 0) {
if (someAddr)
os << " + ";
ccprintf(os, "%#x", disp);
someAddr = true;
}
if (!someAddr)
os << "0";
os << "]";
}
std::string
X86StaticInst::generateDisassembly(
Addr pc, const Loader::SymbolTable *symtab) const
{
std::stringstream ss;
printMnemonic(ss, mnemonic);
return ss.str();
}
}

View File

@@ -44,144 +44,146 @@
namespace X86ISA
{
/**
* Class for register indices passed to instruction constructors. Using a
* wrapper struct for these lets take advantage of the compiler's type
* checking.
*/
struct InstRegIndex : public RegId
{
explicit InstRegIndex(RegIndex _idx) :
RegId(computeRegClass(_idx), _idx) {}
private:
// TODO: As X86 register index definition is highly built on the
// unified space concept, it is easier for the moment to rely on
// an helper function to compute the RegClass. It would be nice
// to fix those definition and get rid of this.
RegClass computeRegClass(RegIndex _idx) {
if (_idx < FP_Reg_Base) {
return IntRegClass;
} else if (_idx < CC_Reg_Base) {
return FloatRegClass;
} else if (_idx < Misc_Reg_Base) {
return CCRegClass;
} else {
return MiscRegClass;
}
/**
* Class for register indices passed to instruction constructors. Using a
* wrapper struct for these lets take advantage of the compiler's type
* checking.
*/
struct InstRegIndex : public RegId
{
explicit InstRegIndex(RegIndex _idx) :
RegId(computeRegClass(_idx), _idx) {}
private:
// TODO: As X86 register index definition is highly built on the
// unified space concept, it is easier for the moment to rely on
// an helper function to compute the RegClass. It would be nice
// to fix those definition and get rid of this.
RegClass
computeRegClass(RegIndex _idx)
{
if (_idx < FP_Reg_Base) {
return IntRegClass;
} else if (_idx < CC_Reg_Base) {
return FloatRegClass;
} else if (_idx < Misc_Reg_Base) {
return CCRegClass;
} else {
return MiscRegClass;
}
};
}
};
/**
* Base class for all X86 static instructions.
*/
/**
* Base class for all X86 static instructions.
*/
class X86StaticInst : public StaticInst
{
protected:
using ExtMachInst = X86ISA::ExtMachInst;
class X86StaticInst : public StaticInst
{
protected:
using ExtMachInst = X86ISA::ExtMachInst;
// Constructor.
X86StaticInst(const char *mnem,
ExtMachInst _machInst, OpClass __opClass)
: StaticInst(mnem, _machInst, __opClass)
{
}
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
// Constructor.
X86StaticInst(const char *mnem,
ExtMachInst _machInst, OpClass __opClass)
: StaticInst(mnem, _machInst, __opClass)
{
X86IntReg reg = into;
if (destRegIdx(0).index() & IntFoldBit)
{
reg.H = val;
return reg;
}
switch(size)
{
case 1:
reg.L = val;
break;
case 2:
reg.X = val;
break;
case 4:
//XXX Check if this should be zeroed or sign extended
reg = 0;
reg.E = val;
break;
case 8:
reg.R = val;
break;
default:
panic("Tried to merge with unrecognized size %d.\n", size);
}
}
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
{
X86IntReg reg = into;
if (destRegIdx(0).index() & IntFoldBit) {
reg.H = val;
return reg;
}
inline uint64_t pick(uint64_t from, int idx, int size) const
{
X86IntReg reg = from;
DPRINTF(X86, "Picking with size %d\n", size);
if (srcRegIdx(idx).index() & IntFoldBit)
return reg.H;
switch(size)
{
case 1:
return reg.L;
case 2:
return reg.X;
case 4:
return reg.E;
case 8:
return reg.R;
default:
panic("Tried to pick with unrecognized size %d.\n", size);
}
switch(size) {
case 1:
reg.L = val;
break;
case 2:
reg.X = val;
break;
case 4:
//XXX Check if this should be zeroed or sign extended
reg = 0;
reg.E = val;
break;
case 8:
reg.R = val;
break;
default:
panic("Tried to merge with unrecognized size %d.\n", size);
}
return reg;
}
inline int64_t signedPick(uint64_t from, int idx, int size) const
{
X86IntReg reg = from;
DPRINTF(X86, "Picking with size %d\n", size);
if (srcRegIdx(idx).index() & IntFoldBit)
return reg.SH;
switch(size)
{
case 1:
return reg.SL;
case 2:
return reg.SX;
case 4:
return reg.SE;
case 8:
return reg.SR;
default:
panic("Tried to pick with unrecognized size %d.\n", size);
}
inline uint64_t
pick(uint64_t from, int idx, int size) const
{
X86IntReg reg = from;
DPRINTF(X86, "Picking with size %d\n", size);
if (srcRegIdx(idx).index() & IntFoldBit)
return reg.H;
switch(size) {
case 1:
return reg.L;
case 2:
return reg.X;
case 4:
return reg.E;
case 8:
return reg.R;
default:
panic("Tried to pick with unrecognized size %d.\n", size);
}
}
void
advancePC(PCState &pcState) const override
{
pcState.advance();
inline int64_t
signedPick(uint64_t from, int idx, int size) const
{
X86IntReg reg = from;
DPRINTF(X86, "Picking with size %d\n", size);
if (srcRegIdx(idx).index() & IntFoldBit)
return reg.SH;
switch(size) {
case 1:
return reg.SL;
case 2:
return reg.SX;
case 4:
return reg.SE;
case 8:
return reg.SR;
default:
panic("Tried to pick with unrecognized size %d.\n", size);
}
};
}
void
advancePC(PCState &pcState) const override
{
pcState.advance();
}
};
}
#endif //__ARCH_X86_INSTS_STATICINST_HH__