/*
* Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2015 Advanced Micro Devices, Inc.
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
namespace X86ISA
{
/**
- * Base class for load and store ops
+ * Base class for memory ops
*/
- class LdStOp : public X86MicroopBase
+ class MemOp : public X86MicroopBase
{
protected:
const uint8_t scale;
const RegIndex base;
const uint64_t disp;
const uint8_t segment;
- const RegIndex data;
const uint8_t dataSize;
const uint8_t addressSize;
const Request::FlagsType memFlags;
RegIndex foldOBit, foldABit;
//Constructor
- LdStOp(ExtMachInst _machInst,
+ MemOp(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) :
X86MicroopBase(_machInst, mnem, _instMnem, setFlags, __opClass),
scale(_scale), index(_index.idx), base(_base.idx),
disp(_disp), segment(_segment.idx),
- data(_data.idx),
dataSize(_dataSize), addressSize(_addressSize),
memFlags(_memFlags | _segment.idx)
{
assert(_segment.idx < NUM_SEGMENTREGS);
- foldOBit = (dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
+ 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;
+
+ //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.idx)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+
+ /**
+ * 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;
+
+ //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.idx),
+ dataHi(_dataHi.idx)
+ {
+ }
std::string generateDisassembly(Addr pc,
const SymbolTable *symtab) const;
// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
+// Copyright (c) 2015 Advanced Micro Devices, Inc.
// All rights reserved.
//
// The license below extends only to copyright in the software and shall
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
- fault = readMemAtomic(xc, traceData, EA, Mem, dataSize, memFlags);
+ fault = readMemAtomic(xc, traceData, EA, Mem,
+ %(memDataSize)s, memFlags);
if (fault == NoFault) {
%(code)s;
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
- fault = initiateMemRead(xc, traceData, EA, dataSize, memFlags);
+ fault = initiateMemRead(xc, traceData, EA,
+ %(memDataSize)s, memFlags);
return fault;
}
%(op_decl)s;
%(op_rd)s;
- getMem(pkt, Mem, dataSize, traceData);
+ getMem(pkt, Mem, %(memDataSize)s, traceData);
%(code)s;
if(fault == NoFault)
{
- fault = writeMemAtomic(xc, traceData, Mem, dataSize, EA,
+ fault = writeMemAtomic(xc, traceData, Mem, %(memDataSize)s, EA,
memFlags, NULL);
if(fault == NoFault)
{
if(fault == NoFault)
{
- fault = writeMemTiming(xc, traceData, Mem, dataSize, EA,
+ fault = writeMemTiming(xc, traceData, Mem, %(memDataSize)s, EA,
memFlags, NULL);
}
return fault;
};
}};
+// LdStSplitOp is a load or store that uses a pair of regs as the
+// source or destination. Used for cmpxchg{8,16}b.
+def template MicroLdStSplitOpDeclare {{
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ %(class_name)s(ExtMachInst _machInst,
+ 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);
+
+ %(BasicExecDeclare)s
+
+ %(InitiateAccDeclare)s
+
+ %(CompleteAccDeclare)s
+ };
+}};
+
def template MicroLdStOpConstructor {{
%(class_name)s::%(class_name)s(
ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
}
}};
+def template MicroLdStSplitOpConstructor {{
+ %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, 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) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
+ _scale, _index, _base,
+ _disp, _segment, _dataLow, _dataHi,
+ _dataSize, _addressSize, _memFlags, %(op_class)s)
+ {
+ %(constructor)s;
+ }
+}};
+
let {{
class LdStOp(X86Microop):
def __init__(self, data, segment, addr, disp,
"dataSize" : self.dataSize, "addressSize" : self.addressSize,
"memFlags" : self.memFlags}
return allocator
+
+ class LdStSplitOp(LdStOp):
+ def __init__(self, data, segment, addr, disp,
+ dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec):
+ super(LdStSplitOp, self).__init__(0, segment, addr, disp,
+ dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec)
+ (self.dataLow, self.dataHi) = data
+
+ def getAllocator(self, microFlags):
+ allocString = '''(StaticInstPtr)(new %(class_name)s(machInst,
+ macrocodeBlock, %(flags)s, %(scale)s, %(index)s,
+ %(base)s, %(disp)s, %(segment)s,
+ %(dataLow)s, %(dataHi)s,
+ %(dataSize)s, %(addressSize)s, %(memFlags)s))
+ '''
+ allocator = allocString % {
+ "class_name" : self.className,
+ "flags" : self.microFlagsText(microFlags) + self.instFlags,
+ "scale" : self.scale, "index" : self.index,
+ "base" : self.base,
+ "disp" : self.disp,
+ "segment" : self.segment,
+ "dataLow" : self.dataLow, "dataHi" : self.dataHi,
+ "dataSize" : self.dataSize, "addressSize" : self.addressSize,
+ "memFlags" : self.memFlags}
+ return allocator
+
}};
let {{
decoder_output = ""
exec_output = ""
- calculateEA = '''
- EA = SegBase + bits(scale * Index + Base + disp, addressSize * 8 - 1, 0);
- '''
+ segmentEAExpr = \
+ 'bits(scale * Index + Base + disp, addressSize * 8 - 1, 0);'
+
+ calculateEA = 'EA = SegBase + ' + segmentEAExpr
def defineMicroLoadOp(mnemonic, code, bigCode='',
- mem_flags="0", big=True):
+ mem_flags="0", big=True, nonSpec=False):
global header_output
global decoder_output
global exec_output
# Build up the all register version of this micro op
iops = [InstObjParams(name, Name, 'X86ISA::LdStOp',
- {"code": code, "ea_code": calculateEA})]
+ { "code": code,
+ "ea_code": calculateEA,
+ "memDataSize": "dataSize" })]
if big:
iops += [InstObjParams(name, Name + "Big", 'X86ISA::LdStOp',
- {"code": bigCode, "ea_code": calculateEA})]
+ { "code": bigCode,
+ "ea_code": calculateEA,
+ "memDataSize": "dataSize" })]
for iop in iops:
header_output += MicroLdStOpDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
def __init__(self, data, segment, addr, disp = 0,
dataSize="env.dataSize",
addressSize="env.addressSize",
- atCPL0=False, prefetch=False, nonSpec=False):
+ atCPL0=False, prefetch=False, nonSpec=nonSpec):
super(LoadOp, self).__init__(data, segment, addr,
disp, dataSize, addressSize, mem_flags,
atCPL0, prefetch, nonSpec)
'(StoreCheck << FlagShift)')
defineMicroLoadOp('Ldstl', 'Data = merge(Data, Mem, dataSize);',
'Data = Mem & mask(dataSize * 8);',
- '(StoreCheck << FlagShift) | Request::LOCKED_RMW')
+ '(StoreCheck << FlagShift) | Request::LOCKED_RMW',
+ nonSpec=True)
defineMicroLoadOp('Ldfp', code='FpData_uqw = Mem', big = False)
}
''', big = False)
+ def defineMicroLoadSplitOp(mnemonic, code, mem_flags="0", nonSpec=False):
+ global header_output
+ global decoder_output
+ global exec_output
+ global microopClasses
+ Name = mnemonic
+ name = mnemonic.lower()
+
+ iop = InstObjParams(name, Name, 'X86ISA::LdStSplitOp',
+ { "code": code,
+ "ea_code": calculateEA,
+ "memDataSize": "2 * dataSize" })
+
+ header_output += MicroLdStSplitOpDeclare.subst(iop)
+ decoder_output += MicroLdStSplitOpConstructor.subst(iop)
+ exec_output += MicroLoadExecute.subst(iop)
+ exec_output += MicroLoadInitiateAcc.subst(iop)
+ exec_output += MicroLoadCompleteAcc.subst(iop)
+
+ class LoadOp(LdStSplitOp):
+ def __init__(self, data, segment, addr, disp = 0,
+ dataSize="env.dataSize",
+ addressSize="env.addressSize",
+ atCPL0=False, prefetch=False, nonSpec=nonSpec):
+ super(LoadOp, self).__init__(data, segment, addr,
+ disp, dataSize, addressSize, mem_flags,
+ atCPL0, prefetch, nonSpec)
+ self.className = Name
+ self.mnemonic = name
+
+ microopClasses[name] = LoadOp
+
+ code = '''
+ switch (dataSize) {
+ case 4:
+ DataLow = bits(Mem_u2qw[0], 31, 0);
+ DataHi = bits(Mem_u2qw[0], 63, 32);
+ break;
+ case 8:
+ DataLow = Mem_u2qw[0];
+ DataHi = Mem_u2qw[1];
+ break;
+ default:
+ panic("Unhandled data size %d in LdSplit.\\n", dataSize);
+ }'''
+
+ defineMicroLoadSplitOp('LdSplit', code,
+ '(StoreCheck << FlagShift)')
+
+ defineMicroLoadSplitOp('LdSplitl', code,
+ '(StoreCheck << FlagShift) | Request::LOCKED_RMW',
+ nonSpec=True)
+
def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0"):
global header_output
global decoder_output
# Build up the all register version of this micro op
iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
- {"code": code,
- "complete_code": completeCode,
- "ea_code": calculateEA})
+ { "code": code,
+ "complete_code": completeCode,
+ "ea_code": calculateEA,
+ "memDataSize": "dataSize" })
header_output += MicroLdStOpDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroStoreExecute.subst(iop)
defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS")
+ def defineMicroStoreSplitOp(mnemonic, code,
+ completeCode="", mem_flags="0"):
+ global header_output
+ global decoder_output
+ global exec_output
+ global microopClasses
+ Name = mnemonic
+ name = mnemonic.lower()
+
+ iop = InstObjParams(name, Name, 'X86ISA::LdStSplitOp',
+ { "code": code,
+ "complete_code": completeCode,
+ "ea_code": calculateEA,
+ "memDataSize": "2 * dataSize" })
+
+ header_output += MicroLdStSplitOpDeclare.subst(iop)
+ decoder_output += MicroLdStSplitOpConstructor.subst(iop)
+ exec_output += MicroStoreExecute.subst(iop)
+ exec_output += MicroStoreInitiateAcc.subst(iop)
+ exec_output += MicroStoreCompleteAcc.subst(iop)
+
+ class StoreOp(LdStSplitOp):
+ def __init__(self, data, segment, addr, disp = 0,
+ dataSize="env.dataSize",
+ addressSize="env.addressSize",
+ atCPL0=False, nonSpec=False):
+ super(StoreOp, self).__init__(data, segment, addr, disp,
+ dataSize, addressSize, mem_flags, atCPL0, False,
+ nonSpec)
+ self.className = Name
+ self.mnemonic = name
+
+ microopClasses[name] = StoreOp
+
+ code = '''
+ switch (dataSize) {
+ case 4:
+ Mem_u2qw[0] = (DataHi << 32) | DataLow;
+ break;
+ case 8:
+ Mem_u2qw[0] = DataLow;
+ Mem_u2qw[1] = DataHi;
+ break;
+ default:
+ panic("Unhandled data size %d in StSplit.\\n", dataSize);
+ }'''
+
+ defineMicroStoreSplitOp('StSplit', code);
+
+ defineMicroStoreSplitOp('StSplitul', code,
+ mem_flags='Request::LOCKED_RMW')
+
iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
- {"code": "Data = merge(Data, EA, dataSize);",
- "ea_code": '''
- EA = bits(scale * Index + Base + disp, addressSize * 8 - 1, 0);
- '''})
+ { "code": "Data = merge(Data, EA, dataSize);",
+ "ea_code": "EA = " + segmentEAExpr,
+ "memDataSize": "dataSize" })
header_output += MicroLeaDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLeaExecute.subst(iop)
iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
- {"code": "xc->demapPage(EA, 0);",
- "ea_code": calculateEA})
+ { "code": "xc->demapPage(EA, 0);",
+ "ea_code": calculateEA,
+ "memDataSize": "dataSize" })
header_output += MicroLeaDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLeaExecute.subst(iop)