Add in support for condition code flags.
Some microops can set the condition codes, and some of them can be predicated on them. Some of the codes aren't implemented because it was unclear from the AMD patent what they actually did. They are used with string instructions, but they use variables IP, DTF, and SSTF which don't appear to be documented. --HG-- extra : convert_revision : 2236cccd07d0091762b50148975f301bb1d2da3f
This commit is contained in:
parent
cf846d5205
commit
a6757095c3
3 changed files with 309 additions and 87 deletions
|
@ -56,10 +56,109 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "arch/x86/insts/microregop.hh"
|
#include "arch/x86/insts/microregop.hh"
|
||||||
|
#include "arch/x86/miscregs.hh"
|
||||||
|
#include "base/condcodes.hh"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace X86ISA
|
namespace X86ISA
|
||||||
{
|
{
|
||||||
|
uint64_t RegOpBase::genFlags(uint64_t oldFlags, uint64_t flagMask,
|
||||||
|
uint64_t _dest, uint64_t _src1, uint64_t _src2) const
|
||||||
|
{
|
||||||
|
uint64_t flags = oldFlags & ~flagMask;
|
||||||
|
if(flagMask & CFBit && findCarry(dataSize, _dest, _src1, _src2))
|
||||||
|
flags |= CFBit;
|
||||||
|
if(flagMask & PFBit && findParity(dataSize, _dest))
|
||||||
|
flags |= PFBit;
|
||||||
|
if(flagMask & ECFBit && findCarry(dataSize, _dest, _src1, _src2))
|
||||||
|
flags |= ECFBit;
|
||||||
|
if(flagMask & AFBit && findCarry(4, _dest, _src1, _src2))
|
||||||
|
flags |= AFBit;
|
||||||
|
if(flagMask & EZFBit && findZero(dataSize, _dest))
|
||||||
|
flags |= EZFBit;
|
||||||
|
if(flagMask & ZFBit && findZero(dataSize, _dest))
|
||||||
|
flags |= ZFBit;
|
||||||
|
if(flagMask & SFBit && findNegative(dataSize, _dest))
|
||||||
|
flags |= SFBit;
|
||||||
|
if(flagMask & OFBit && findOverflow(dataSize, _dest, _src1, _src2))
|
||||||
|
flags |= OFBit;
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RegOpBase::checkCondition(uint64_t flags) const
|
||||||
|
{
|
||||||
|
CCFlagBits ccflags = flags;
|
||||||
|
switch(ext)
|
||||||
|
{
|
||||||
|
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::STRZnZF:
|
||||||
|
panic("This condition is not implemented!");
|
||||||
|
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::NotSTRZnZF:
|
||||||
|
panic("This condition is not implemented!");
|
||||||
|
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", ext);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::string RegOp::generateDisassembly(Addr pc,
|
std::string RegOp::generateDisassembly(Addr pc,
|
||||||
const SymbolTable *symtab) const
|
const SymbolTable *symtab) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -62,18 +62,84 @@
|
||||||
|
|
||||||
namespace X86ISA
|
namespace X86ISA
|
||||||
{
|
{
|
||||||
|
namespace ConditionTests
|
||||||
|
{
|
||||||
|
enum CondTest {
|
||||||
|
True,
|
||||||
|
NotFalse = True,
|
||||||
|
ECF,
|
||||||
|
EZF,
|
||||||
|
SZnZF,
|
||||||
|
MSTRZ,
|
||||||
|
STRZ,
|
||||||
|
MSTRC,
|
||||||
|
STRZnZF,
|
||||||
|
OF,
|
||||||
|
CF,
|
||||||
|
ZF,
|
||||||
|
CvZF,
|
||||||
|
SF,
|
||||||
|
PF,
|
||||||
|
SxOF,
|
||||||
|
SxOvZF,
|
||||||
|
|
||||||
|
False,
|
||||||
|
NotTrue = False,
|
||||||
|
NotECF,
|
||||||
|
NotEZF,
|
||||||
|
NotSZnZF,
|
||||||
|
NotMSTRZ,
|
||||||
|
NotSTRZ,
|
||||||
|
NotMSTRC,
|
||||||
|
NotSTRZnZF,
|
||||||
|
NotOF,
|
||||||
|
NotCF,
|
||||||
|
NotZF,
|
||||||
|
NotCvZF,
|
||||||
|
NotSF,
|
||||||
|
NotPF,
|
||||||
|
NotSxOF,
|
||||||
|
NotSxOvZF
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base classes for RegOps which provides a generateDisassembly method.
|
* Base classes for RegOps which provides a generateDisassembly method.
|
||||||
*/
|
*/
|
||||||
class RegOp : public X86MicroopBase
|
class RegOpBase : public X86MicroopBase
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
const RegIndex src1;
|
const RegIndex src1;
|
||||||
const RegIndex src2;
|
|
||||||
const RegIndex dest;
|
const RegIndex dest;
|
||||||
const bool setStatus;
|
|
||||||
const uint8_t dataSize;
|
const uint8_t dataSize;
|
||||||
const uint8_t ext;
|
const uint16_t ext;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
RegOpBase(ExtMachInst _machInst,
|
||||||
|
const char *mnem, const char *_instMnem,
|
||||||
|
bool isMicro, bool isDelayed,
|
||||||
|
bool isFirst, bool isLast,
|
||||||
|
RegIndex _src1, RegIndex _dest,
|
||||||
|
uint8_t _dataSize, uint16_t _ext,
|
||||||
|
OpClass __opClass) :
|
||||||
|
X86MicroopBase(_machInst, mnem, _instMnem,
|
||||||
|
isMicro, isDelayed, isFirst, isLast,
|
||||||
|
__opClass),
|
||||||
|
src1(_src1), dest(_dest),
|
||||||
|
dataSize(_dataSize), ext(_ext)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//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) const;
|
||||||
|
bool checkCondition(uint64_t flags) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RegOp : public RegOpBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const RegIndex src2;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
RegOp(ExtMachInst _machInst,
|
RegOp(ExtMachInst _machInst,
|
||||||
|
@ -81,13 +147,13 @@ namespace X86ISA
|
||||||
bool isMicro, bool isDelayed,
|
bool isMicro, bool isDelayed,
|
||||||
bool isFirst, bool isLast,
|
bool isFirst, bool isLast,
|
||||||
RegIndex _src1, RegIndex _src2, RegIndex _dest,
|
RegIndex _src1, RegIndex _src2, RegIndex _dest,
|
||||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext,
|
uint8_t _dataSize, uint16_t _ext,
|
||||||
OpClass __opClass) :
|
OpClass __opClass) :
|
||||||
X86MicroopBase(_machInst, mnem, _instMnem,
|
RegOpBase(_machInst, mnem, _instMnem,
|
||||||
isMicro, isDelayed, isFirst, isLast,
|
isMicro, isDelayed, isFirst, isLast,
|
||||||
|
_src1, _dest, _dataSize, _ext,
|
||||||
__opClass),
|
__opClass),
|
||||||
src1(_src1), src2(_src2), dest(_dest),
|
src2(_src2)
|
||||||
setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,15 +161,10 @@ namespace X86ISA
|
||||||
const SymbolTable *symtab) const;
|
const SymbolTable *symtab) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RegOpImm : public X86MicroopBase
|
class RegOpImm : public RegOpBase
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
const RegIndex src1;
|
|
||||||
const uint8_t imm8;
|
const uint8_t imm8;
|
||||||
const RegIndex dest;
|
|
||||||
const bool setStatus;
|
|
||||||
const uint8_t dataSize;
|
|
||||||
const uint8_t ext;
|
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
RegOpImm(ExtMachInst _machInst,
|
RegOpImm(ExtMachInst _machInst,
|
||||||
|
@ -111,13 +172,13 @@ namespace X86ISA
|
||||||
bool isMicro, bool isDelayed,
|
bool isMicro, bool isDelayed,
|
||||||
bool isFirst, bool isLast,
|
bool isFirst, bool isLast,
|
||||||
RegIndex _src1, uint8_t _imm8, RegIndex _dest,
|
RegIndex _src1, uint8_t _imm8, RegIndex _dest,
|
||||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext,
|
uint8_t _dataSize, uint16_t _ext,
|
||||||
OpClass __opClass) :
|
OpClass __opClass) :
|
||||||
X86MicroopBase(_machInst, mnem, _instMnem,
|
RegOpBase(_machInst, mnem, _instMnem,
|
||||||
isMicro, isDelayed, isFirst, isLast,
|
isMicro, isDelayed, isFirst, isLast,
|
||||||
|
_src1, _dest, _dataSize, _ext,
|
||||||
__opClass),
|
__opClass),
|
||||||
src1(_src1), imm8(_imm8), dest(_dest),
|
imm8(_imm8)
|
||||||
setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,8 +67,12 @@ def template MicroRegOpExecute {{
|
||||||
|
|
||||||
%(op_decl)s;
|
%(op_decl)s;
|
||||||
%(op_rd)s;
|
%(op_rd)s;
|
||||||
|
|
||||||
|
if(%(cond_check)s)
|
||||||
|
{
|
||||||
%(code)s;
|
%(code)s;
|
||||||
%(flag_code)s;
|
%(flag_code)s;
|
||||||
|
}
|
||||||
|
|
||||||
//Write the resulting state to the execution context
|
//Write the resulting state to the execution context
|
||||||
if(fault == NoFault)
|
if(fault == NoFault)
|
||||||
|
@ -87,8 +91,12 @@ def template MicroRegOpImmExecute {{
|
||||||
|
|
||||||
%(op_decl)s;
|
%(op_decl)s;
|
||||||
%(op_rd)s;
|
%(op_rd)s;
|
||||||
|
|
||||||
|
if(%(cond_check)s)
|
||||||
|
{
|
||||||
%(code)s;
|
%(code)s;
|
||||||
%(flag_code)s;
|
%(flag_code)s;
|
||||||
|
}
|
||||||
|
|
||||||
//Write the resulting state to the execution context
|
//Write the resulting state to the execution context
|
||||||
if(fault == NoFault)
|
if(fault == NoFault)
|
||||||
|
@ -110,12 +118,12 @@ def template MicroRegOpDeclare {{
|
||||||
const char * instMnem,
|
const char * instMnem,
|
||||||
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
||||||
RegIndex _src1, RegIndex _src2, RegIndex _dest,
|
RegIndex _src1, RegIndex _src2, RegIndex _dest,
|
||||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext);
|
uint8_t _dataSize, uint8_t _ext);
|
||||||
|
|
||||||
%(class_name)s(ExtMachInst _machInst,
|
%(class_name)s(ExtMachInst _machInst,
|
||||||
const char * instMnem,
|
const char * instMnem,
|
||||||
RegIndex _src1, RegIndex _src2, RegIndex _dest,
|
RegIndex _src1, RegIndex _src2, RegIndex _dest,
|
||||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext);
|
uint8_t _dataSize, uint8_t _ext);
|
||||||
|
|
||||||
%(BasicExecDeclare)s
|
%(BasicExecDeclare)s
|
||||||
};
|
};
|
||||||
|
@ -133,12 +141,12 @@ def template MicroRegOpImmDeclare {{
|
||||||
const char * instMnem,
|
const char * instMnem,
|
||||||
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
||||||
RegIndex _src1, uint8_t _imm8, RegIndex _dest,
|
RegIndex _src1, uint8_t _imm8, RegIndex _dest,
|
||||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext);
|
uint8_t _dataSize, uint8_t _ext);
|
||||||
|
|
||||||
%(class_name)sImm(ExtMachInst _machInst,
|
%(class_name)sImm(ExtMachInst _machInst,
|
||||||
const char * instMnem,
|
const char * instMnem,
|
||||||
RegIndex _src1, uint8_t _imm8, RegIndex _dest,
|
RegIndex _src1, uint8_t _imm8, RegIndex _dest,
|
||||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext);
|
uint8_t _dataSize, uint8_t _ext);
|
||||||
|
|
||||||
%(BasicExecDeclare)s
|
%(BasicExecDeclare)s
|
||||||
};
|
};
|
||||||
|
@ -154,10 +162,10 @@ def template MicroRegOpConstructor {{
|
||||||
inline %(class_name)s::%(class_name)s(
|
inline %(class_name)s::%(class_name)s(
|
||||||
ExtMachInst machInst, const char * instMnem,
|
ExtMachInst machInst, const char * instMnem,
|
||||||
RegIndex _src1, RegIndex _src2, RegIndex _dest,
|
RegIndex _src1, RegIndex _src2, RegIndex _dest,
|
||||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
|
uint8_t _dataSize, uint8_t _ext) :
|
||||||
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||||
false, false, false, false,
|
false, false, false, false,
|
||||||
_src1, _src2, _dest, _setStatus, _dataSize, _ext,
|
_src1, _src2, _dest, _dataSize, _ext,
|
||||||
%(op_class)s)
|
%(op_class)s)
|
||||||
{
|
{
|
||||||
buildMe();
|
buildMe();
|
||||||
|
@ -167,10 +175,10 @@ def template MicroRegOpConstructor {{
|
||||||
ExtMachInst machInst, const char * instMnem,
|
ExtMachInst machInst, const char * instMnem,
|
||||||
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
||||||
RegIndex _src1, RegIndex _src2, RegIndex _dest,
|
RegIndex _src1, RegIndex _src2, RegIndex _dest,
|
||||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
|
uint8_t _dataSize, uint8_t _ext) :
|
||||||
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||||
isMicro, isDelayed, isFirst, isLast,
|
isMicro, isDelayed, isFirst, isLast,
|
||||||
_src1, _src2, _dest, _setStatus, _dataSize, _ext,
|
_src1, _src2, _dest, _dataSize, _ext,
|
||||||
%(op_class)s)
|
%(op_class)s)
|
||||||
{
|
{
|
||||||
buildMe();
|
buildMe();
|
||||||
|
@ -187,10 +195,10 @@ def template MicroRegOpImmConstructor {{
|
||||||
inline %(class_name)sImm::%(class_name)sImm(
|
inline %(class_name)sImm::%(class_name)sImm(
|
||||||
ExtMachInst machInst, const char * instMnem,
|
ExtMachInst machInst, const char * instMnem,
|
||||||
RegIndex _src1, uint8_t _imm8, RegIndex _dest,
|
RegIndex _src1, uint8_t _imm8, RegIndex _dest,
|
||||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
|
uint8_t _dataSize, uint8_t _ext) :
|
||||||
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||||
false, false, false, false,
|
false, false, false, false,
|
||||||
_src1, _imm8, _dest, _setStatus, _dataSize, _ext,
|
_src1, _imm8, _dest, _dataSize, _ext,
|
||||||
%(op_class)s)
|
%(op_class)s)
|
||||||
{
|
{
|
||||||
buildMe();
|
buildMe();
|
||||||
|
@ -200,10 +208,10 @@ def template MicroRegOpImmConstructor {{
|
||||||
ExtMachInst machInst, const char * instMnem,
|
ExtMachInst machInst, const char * instMnem,
|
||||||
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
||||||
RegIndex _src1, uint8_t _imm8, RegIndex _dest,
|
RegIndex _src1, uint8_t _imm8, RegIndex _dest,
|
||||||
bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
|
uint8_t _dataSize, uint8_t _ext) :
|
||||||
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||||
isMicro, isDelayed, isFirst, isLast,
|
isMicro, isDelayed, isFirst, isLast,
|
||||||
_src1, _imm8, _dest, _setStatus, _dataSize, _ext,
|
_src1, _imm8, _dest, _dataSize, _ext,
|
||||||
%(op_class)s)
|
%(op_class)s)
|
||||||
{
|
{
|
||||||
buildMe();
|
buildMe();
|
||||||
|
@ -211,46 +219,74 @@ def template MicroRegOpImmConstructor {{
|
||||||
}};
|
}};
|
||||||
|
|
||||||
let {{
|
let {{
|
||||||
|
class X86MicroMeta(type):
|
||||||
|
def __new__(mcls, name, bases, dict):
|
||||||
|
abstract = False
|
||||||
|
if "abstract" in dict:
|
||||||
|
abstract = dict['abstract']
|
||||||
|
del dict['abstract']
|
||||||
|
|
||||||
|
cls = type.__new__(mcls, name, bases, dict)
|
||||||
|
if not abstract:
|
||||||
|
allClasses[name] = cls
|
||||||
|
return cls
|
||||||
|
|
||||||
|
class XXX86Microop(object):
|
||||||
|
__metaclass__ = X86MicroMeta
|
||||||
|
abstract = True
|
||||||
|
|
||||||
class RegOp(X86Microop):
|
class RegOp(X86Microop):
|
||||||
def __init__(self, dest, src1, src2, setStatus):
|
abstract = True
|
||||||
|
def __init__(self, dest, src1, src2, flags):
|
||||||
self.dest = dest
|
self.dest = dest
|
||||||
self.src1 = src1
|
self.src1 = src1
|
||||||
self.src2 = src2
|
self.src2 = src2
|
||||||
self.setStatus = setStatus
|
self.flags = flags
|
||||||
self.dataSize = "env.dataSize"
|
self.dataSize = "env.dataSize"
|
||||||
|
if flags is None:
|
||||||
self.ext = 0
|
self.ext = 0
|
||||||
|
else:
|
||||||
|
if not isinstance(flags, (list, tuple)):
|
||||||
|
raise Exception, "flags must be a list or tuple of flags"
|
||||||
|
self.ext = " | ".join(flags)
|
||||||
|
self.className += "Flags"
|
||||||
|
|
||||||
def getAllocator(self, *microFlags):
|
def getAllocator(self, *microFlags):
|
||||||
allocator = '''new %(class_name)s(machInst, mnemonic
|
allocator = '''new %(class_name)s(machInst, mnemonic
|
||||||
%(flags)s, %(src1)s, %(src2)s, %(dest)s,
|
%(flags)s, %(src1)s, %(src2)s, %(dest)s,
|
||||||
%(setStatus)s, %(dataSize)s, %(ext)s)''' % {
|
%(dataSize)s, %(ext)s)''' % {
|
||||||
"class_name" : self.className,
|
"class_name" : self.className,
|
||||||
"flags" : self.microFlagsText(microFlags),
|
"flags" : self.microFlagsText(microFlags),
|
||||||
"src1" : self.src1, "src2" : self.src2,
|
"src1" : self.src1, "src2" : self.src2,
|
||||||
"dest" : self.dest,
|
"dest" : self.dest,
|
||||||
"setStatus" : self.cppBool(self.setStatus),
|
|
||||||
"dataSize" : self.dataSize,
|
"dataSize" : self.dataSize,
|
||||||
"ext" : self.ext}
|
"ext" : self.ext}
|
||||||
return allocator
|
return allocator
|
||||||
|
|
||||||
class RegOpImm(X86Microop):
|
class RegOpImm(X86Microop):
|
||||||
def __init__(self, dest, src1, imm8, setStatus):
|
abstract = True
|
||||||
|
def __init__(self, dest, src1, imm8, flags):
|
||||||
self.dest = dest
|
self.dest = dest
|
||||||
self.src1 = src1
|
self.src1 = src1
|
||||||
self.imm8 = imm8
|
self.imm8 = imm8
|
||||||
self.setStatus = setStatus
|
self.flags = flags
|
||||||
self.dataSize = "env.dataSize"
|
self.dataSize = "env.dataSize"
|
||||||
|
if flags is None:
|
||||||
self.ext = 0
|
self.ext = 0
|
||||||
|
else:
|
||||||
|
if not isinstance(flags, (list, tuple)):
|
||||||
|
raise Exception, "flags must be a list or tuple of flags"
|
||||||
|
self.ext = " | ".join(flags)
|
||||||
|
self.className += "Flags"
|
||||||
|
|
||||||
def getAllocator(self, *microFlags):
|
def getAllocator(self, *microFlags):
|
||||||
allocator = '''new %(class_name)s(machInst, mnemonic
|
allocator = '''new %(class_name)s(machInst, mnemonic
|
||||||
%(flags)s, %(src1)s, %(imm8)s, %(dest)s,
|
%(flags)s, %(src1)s, %(imm8)s, %(dest)s,
|
||||||
%(setStatus)s, %(dataSize)s, %(ext)s)''' % {
|
%(dataSize)s, %(ext)s)''' % {
|
||||||
"class_name" : self.className,
|
"class_name" : self.className,
|
||||||
"flags" : self.microFlagsText(microFlags),
|
"flags" : self.microFlagsText(microFlags),
|
||||||
"src1" : self.src1, "imm8" : self.imm8,
|
"src1" : self.src1, "imm8" : self.imm8,
|
||||||
"dest" : self.dest,
|
"dest" : self.dest,
|
||||||
"setStatus" : self.cppBool(self.setStatus),
|
|
||||||
"dataSize" : self.dataSize,
|
"dataSize" : self.dataSize,
|
||||||
"ext" : self.ext}
|
"ext" : self.ext}
|
||||||
return allocator
|
return allocator
|
||||||
|
@ -264,7 +300,8 @@ let {{
|
||||||
decoder_output = ""
|
decoder_output = ""
|
||||||
exec_output = ""
|
exec_output = ""
|
||||||
|
|
||||||
def setUpMicroRegOp(name, Name, base, code, child, flagCode):
|
# A function which builds the C++ classes that implement the microops
|
||||||
|
def setUpMicroRegOp(name, Name, base, code, flagCode, condCheck):
|
||||||
global header_output
|
global header_output
|
||||||
global decoder_output
|
global decoder_output
|
||||||
global exec_output
|
global exec_output
|
||||||
|
@ -272,14 +309,20 @@ let {{
|
||||||
|
|
||||||
iop = InstObjParams(name, Name, base,
|
iop = InstObjParams(name, Name, base,
|
||||||
{"code" : code,
|
{"code" : code,
|
||||||
"flag_code" : flagCode})
|
"flag_code" : flagCode,
|
||||||
|
"cond_check" : condCheck})
|
||||||
header_output += MicroRegOpDeclare.subst(iop)
|
header_output += MicroRegOpDeclare.subst(iop)
|
||||||
decoder_output += MicroRegOpConstructor.subst(iop)
|
decoder_output += MicroRegOpConstructor.subst(iop)
|
||||||
exec_output += MicroRegOpExecute.subst(iop)
|
exec_output += MicroRegOpExecute.subst(iop)
|
||||||
|
|
||||||
microopClasses[name] = child
|
|
||||||
|
|
||||||
def defineMicroRegOp(mnemonic, code, flagCode):
|
checkCCFlagBits = "checkCondition(ccFlagBits)"
|
||||||
|
genCCFlagBits = "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, SrcReg1, %s);"
|
||||||
|
|
||||||
|
|
||||||
|
# This creates a python representations of a microop which are a cross
|
||||||
|
# product of reg/immediate and flag/no flag versions.
|
||||||
|
def defineMicroRegOp(mnemonic, code, secondSrc = "op2", cc=False):
|
||||||
Name = mnemonic
|
Name = mnemonic
|
||||||
name = mnemonic.lower()
|
name = mnemonic.lower()
|
||||||
|
|
||||||
|
@ -290,35 +333,47 @@ let {{
|
||||||
regCode = matcher.sub("SrcReg2", code)
|
regCode = matcher.sub("SrcReg2", code)
|
||||||
immCode = matcher.sub("imm8", code)
|
immCode = matcher.sub("imm8", code)
|
||||||
|
|
||||||
# Build the all register version of this micro op
|
if not cc:
|
||||||
|
flagCode = genCCFlagBits % secondSrc
|
||||||
|
condCode = "true"
|
||||||
|
else:
|
||||||
|
flagCode = ""
|
||||||
|
condCode = checkCCFlagBits
|
||||||
|
|
||||||
|
regFlagCode = matcher.sub("SrcReg2", flagCode)
|
||||||
|
immFlagCode = matcher.sub("imm8", flagCode)
|
||||||
|
|
||||||
class RegOpChild(RegOp):
|
class RegOpChild(RegOp):
|
||||||
def __init__(self, dest, src1, src2, setStatus=False):
|
mnemonic = name
|
||||||
super(RegOpChild, self).__init__(dest, src1, src2, setStatus)
|
className = Name
|
||||||
self.className = Name
|
def __init__(self, dest, src1, src2, flags=None):
|
||||||
self.mnemonic = name
|
super(RegOpChild, self).__init__(dest, src1, src2, flags)
|
||||||
|
|
||||||
setUpMicroRegOp(name, Name, "X86ISA::RegOp", \
|
microopClasses[name] = RegOpChild
|
||||||
regCode, RegOpChild, flagCode);
|
|
||||||
|
setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode, "", "true");
|
||||||
|
setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", regCode, regFlagCode, condCode);
|
||||||
|
|
||||||
# Build the immediate version of this micro op
|
|
||||||
class RegOpChildImm(RegOpImm):
|
class RegOpChildImm(RegOpImm):
|
||||||
def __init__(self, dest, src1, src2, setStatus=False):
|
mnemonic = name + 'i'
|
||||||
super(RegOpChildImm, self).__init__(dest, src1, src2, setStatus)
|
className = Name + 'Imm'
|
||||||
self.className = Name + "Imm"
|
def __init__(self, dest, src1, src2, flags=None):
|
||||||
self.mnemonic = name + "i"
|
super(RegOpChildImm, self).__init__(dest, src1, src2, flags)
|
||||||
|
|
||||||
setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", \
|
microopClasses[name + 'i'] = RegOpChildImm
|
||||||
immCode, RegOpChildImm, flagCode);
|
|
||||||
|
|
||||||
defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to set OF,CF,SF
|
setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", immCode, "", "true");
|
||||||
defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)', "")
|
setUpMicroRegOp(name + "i", Name + "ImmFlags", "X86ISA::RegOpImm", immCode, immFlagCode, condCode);
|
||||||
defineMicroRegOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to add in CF, set OF,CF,SF
|
|
||||||
defineMicroRegOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to subtract CF, set OF,CF,SF
|
defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)')
|
||||||
defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)', "")
|
defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)')
|
||||||
defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to set OF,CF,SF
|
defineMicroRegOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)')
|
||||||
defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)', "")
|
defineMicroRegOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', '-op2')
|
||||||
defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)', "") #Needs to set OF,CF,SF and not DestReg
|
defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)')
|
||||||
defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)', "")
|
defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', '-op2')
|
||||||
|
defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)')
|
||||||
|
defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)', '-op2')
|
||||||
|
defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)', cc=True)
|
||||||
|
|
||||||
# This has it's own function because Wr ops have implicit destinations
|
# This has it's own function because Wr ops have implicit destinations
|
||||||
def defineMicroRegOpWr(mnemonic, code):
|
def defineMicroRegOpWr(mnemonic, code):
|
||||||
|
@ -332,24 +387,27 @@ let {{
|
||||||
regCode = matcher.sub("SrcReg2", code)
|
regCode = matcher.sub("SrcReg2", code)
|
||||||
immCode = matcher.sub("imm8", code)
|
immCode = matcher.sub("imm8", code)
|
||||||
|
|
||||||
# Build the all register version of this micro op
|
|
||||||
class RegOpChild(RegOp):
|
class RegOpChild(RegOp):
|
||||||
def __init__(self, src1, src2):
|
mnemonic = name
|
||||||
super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2, False)
|
className = Name
|
||||||
self.className = Name
|
def __init__(self, src1, src2, flags=None):
|
||||||
self.mnemonic = name
|
super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2, flags)
|
||||||
|
|
||||||
setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode, RegOpChild, "");
|
microopClasses[name] = RegOpChild
|
||||||
|
|
||||||
|
setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode, "", "true");
|
||||||
|
setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", regCode, "", checkCCFlagBits);
|
||||||
|
|
||||||
# Build the immediate version of this micro op
|
|
||||||
class RegOpChildImm(RegOpImm):
|
class RegOpChildImm(RegOpImm):
|
||||||
|
mnemonic = name
|
||||||
|
className = Name
|
||||||
def __init__(self, src1, src2):
|
def __init__(self, src1, src2):
|
||||||
super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2, False)
|
super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2, None)
|
||||||
self.className = Name + "Imm"
|
|
||||||
self.mnemonic = name + "i"
|
|
||||||
|
|
||||||
setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", \
|
microopClasses[name + 'i'] = RegOpChildImm
|
||||||
immCode, RegOpChildImm, "");
|
|
||||||
|
setUpMicroRegOp(name + 'i', Name + "Imm", "X86ISA::RegOpImm", immCode, "", "true");
|
||||||
|
setUpMicroRegOp(name + 'i', Name + "ImmFlags", "X86ISA::RegOpImm", immCode, "", checkCCFlagBits);
|
||||||
|
|
||||||
defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2')
|
defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2')
|
||||||
|
|
||||||
|
@ -360,11 +418,13 @@ let {{
|
||||||
|
|
||||||
class RegOpChild(RegOp):
|
class RegOpChild(RegOp):
|
||||||
def __init__(self, dest, src1 = "NUM_INTREGS"):
|
def __init__(self, dest, src1 = "NUM_INTREGS"):
|
||||||
super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", False)
|
super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", None)
|
||||||
self.className = Name
|
self.className = Name
|
||||||
self.mnemonic = name
|
self.mnemonic = name
|
||||||
|
|
||||||
setUpMicroRegOp(name, Name, "X86ISA::RegOp", code, RegOpChild, "");
|
microopClasses[name] = RegOpChild
|
||||||
|
|
||||||
|
setUpMicroRegOp(name, Name, "X86ISA::RegOp", code, "", "true");
|
||||||
|
|
||||||
defineMicroRegOpRd('Rdip', 'DestReg = RIP')
|
defineMicroRegOpRd('Rdip', 'DestReg = RIP')
|
||||||
|
|
||||||
|
@ -374,11 +434,13 @@ let {{
|
||||||
|
|
||||||
class RegOpChild(RegOpImm):
|
class RegOpChild(RegOpImm):
|
||||||
def __init__(self, dest, src1, src2):
|
def __init__(self, dest, src1, src2):
|
||||||
super(RegOpChild, self).__init__(dest, src1, src2, False)
|
super(RegOpChild, self).__init__(dest, src1, src2, None)
|
||||||
self.className = Name
|
self.className = Name
|
||||||
self.mnemonic = name
|
self.mnemonic = name
|
||||||
|
|
||||||
setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code, RegOpChild, "");
|
microopClasses[name] = RegOpChild
|
||||||
|
|
||||||
|
setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code, "", "true");
|
||||||
|
|
||||||
defineMicroRegOpImm('Sext', '''
|
defineMicroRegOpImm('Sext', '''
|
||||||
IntReg val = SrcReg1;
|
IntReg val = SrcReg1;
|
||||||
|
|
Loading…
Reference in a new issue