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:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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__
|
||||
|
||||
Reference in New Issue
Block a user