gem5/src/arch/x86/isa/microops/ldstop.isa

540 lines
19 KiB
Plaintext
Raw Normal View History

// Copyright (c) 2008 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: Gabe Black
// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
// All rights reserved.
//
// Redistribution and use of this software in source and binary forms,
// with or without modification, are permitted provided that the
// following conditions are met:
//
// The software must be used only for Non-Commercial Use which means any
// use which is NOT directed to receiving any direct monetary
// compensation for, or commercial advantage from such use. Illustrative
// examples of non-commercial use are academic research, personal study,
// teaching, education and corporate research & development.
// Illustrative examples of commercial use are distributing products for
// commercial advantage and providing services using the software for
// commercial advantage.
//
// If you wish to use this software or functionality therein that may be
// covered by patents for commercial use, please contact:
// Director of Intellectual Property Licensing
// Office of Strategy and Technology
// Hewlett-Packard Company
// 1501 Page Mill Road
// Palo Alto, California 94304
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. Redistributions
// in binary form must reproduce the above copyright notice, this list of
// conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution. Neither the name of
// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission. No right of
// sublicense is granted herewith. Derivatives of the software and
// output created using the software may be prepared, but only for
// Non-Commercial Uses. Derivatives of the software may be shared with
// others provided: (i) the others agree to abide by the list of
// conditions herein which includes the Non-Commercial Use restrictions;
// and (ii) such Derivatives of the software include the above copyright
// notice to acknowledge the contribution from this software where
// applicable, this list of conditions and the disclaimer below.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: Gabe Black
//////////////////////////////////////////////////////////////////////////
//
// LdStOp Microop templates
//
//////////////////////////////////////////////////////////////////////////
// LEA template
def template MicroLeaExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
Addr EA;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
%(code)s;
if(fault == NoFault)
{
%(op_wb)s;
}
return fault;
}
}};
def template MicroLeaDeclare {{
class %(class_name)s : public %(base_class)s
{
protected:
void buildMe();
public:
%(class_name)s(ExtMachInst _machInst,
const char * instMnem,
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags);
%(class_name)s(ExtMachInst _machInst,
const char * instMnem,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags);
%(BasicExecDeclare)s
};
}};
// Load templates
def template MicroLoadExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
Addr EA;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
fault = read(xc, EA, Mem, memFlags);
if (fault == NoFault) {
%(code)s;
} else if (memFlags & Request::PREFETCH) {
// For prefetches, ignore any faults/exceptions.
return NoFault;
}
if(fault == NoFault)
{
%(op_wb)s;
}
return fault;
}
}};
def template MicroLoadInitiateAcc {{
Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
Addr EA;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
fault = read(xc, EA, Mem, memFlags);
return fault;
}
}};
def template MicroLoadCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
%(CPU_exec_context)s * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
%(op_rd)s;
2008-11-10 06:55:43 +01:00
Mem = get(pkt);
%(code)s;
if(fault == NoFault)
{
%(op_wb)s;
}
return fault;
}
}};
// Store templates
def template MicroStoreExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s * xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
Addr EA;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
%(code)s;
if(fault == NoFault)
{
fault = write(xc, Mem, EA, memFlags);
if(fault == NoFault)
{
%(post_code)s;
%(op_wb)s;
}
}
return fault;
}
}};
def template MicroStoreInitiateAcc {{
Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
Addr EA;
%(op_decl)s;
%(op_rd)s;
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
%(code)s;
if(fault == NoFault)
{
write(xc, Mem, EA, memFlags);
}
return fault;
}
}};
def template MicroStoreCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
%(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const
{
%(op_decl)s;
%(op_rd)s;
%(complete_code)s;
%(op_wb)s;
return NoFault;
}
}};
// Common templates
//This delcares the initiateAcc function in memory operations
def template InitiateAccDeclare {{
Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
}};
//This declares the completeAcc function in memory operations
def template CompleteAccDeclare {{
Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
}};
def template MicroLdStOpDeclare {{
class %(class_name)s : public %(base_class)s
{
protected:
void buildMe();
public:
%(class_name)s(ExtMachInst _machInst,
const char * instMnem,
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags);
%(class_name)s(ExtMachInst _machInst,
const char * instMnem,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags);
%(BasicExecDeclare)s
%(InitiateAccDeclare)s
%(CompleteAccDeclare)s
};
}};
def template MicroLdStOpConstructor {{
inline void %(class_name)s::buildMe()
{
%(constructor)s;
}
inline %(class_name)s::%(class_name)s(
ExtMachInst machInst, const char * instMnem,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
false, false, false, false,
_scale, _index, _base,
_disp, _segment, _data,
_dataSize, _addressSize, _memFlags, %(op_class)s)
{
buildMe();
}
inline %(class_name)s::%(class_name)s(
ExtMachInst machInst, const char * instMnem,
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
uint64_t _disp, InstRegIndex _segment,
InstRegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
Request::FlagsType _memFlags) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
isMicro, isDelayed, isFirst, isLast,
_scale, _index, _base,
_disp, _segment, _data,
_dataSize, _addressSize, _memFlags, %(op_class)s)
{
buildMe();
}
}};
let {{
class LdStOp(X86Microop):
def __init__(self, data, segment, addr, disp,
dataSize, addressSize, baseFlags, atCPL0, prefetch):
self.data = data
[self.scale, self.index, self.base] = addr
self.disp = disp
self.segment = segment
self.dataSize = dataSize
self.addressSize = addressSize
self.memFlags = baseFlags
if atCPL0:
self.memFlags += " | (CPL0FlagBit << FlagShift)"
if prefetch:
self.memFlags += " | Request::PREFETCH"
2009-02-27 18:23:50 +01:00
self.memFlags += " | (machInst.legacy.addr ? " + \
"(AddrSizeFlagBit << FlagShift) : 0)"
def getAllocator(self, *microFlags):
allocator = '''new %(class_name)s(machInst, macrocodeBlock
%(flags)s, %(scale)s, %(index)s, %(base)s,
%(disp)s, %(segment)s, %(data)s,
%(dataSize)s, %(addressSize)s, %(memFlags)s)''' % {
"class_name" : self.className,
"flags" : self.microFlagsText(microFlags),
"scale" : self.scale, "index" : self.index,
"base" : self.base,
"disp" : self.disp,
"segment" : self.segment, "data" : self.data,
"dataSize" : self.dataSize, "addressSize" : self.addressSize,
"memFlags" : self.memFlags}
return allocator
}};
let {{
# Make these empty strings so that concatenating onto
# them will always work.
header_output = ""
decoder_output = ""
exec_output = ""
calculateEA = '''
EA = bits(SegBase + scale * Index + Base + disp, addressSize * 8 - 1, 0);
'''
def defineMicroLoadOp(mnemonic, code, mem_flags="0"):
global header_output
global decoder_output
global exec_output
global microopClasses
Name = mnemonic
name = mnemonic.lower()
# Build up the all register version of this micro op
iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
{"code": code,
"ea_code": calculateEA})
header_output += MicroLdStOpDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLoadExecute.subst(iop)
exec_output += MicroLoadInitiateAcc.subst(iop)
exec_output += MicroLoadCompleteAcc.subst(iop)
class LoadOp(LdStOp):
def __init__(self, data, segment, addr, disp = 0,
dataSize="env.dataSize",
addressSize="env.addressSize",
atCPL0=False, prefetch=False):
super(LoadOp, self).__init__(data, segment, addr,
disp, dataSize, addressSize, mem_flags,
atCPL0, prefetch)
self.className = Name
self.mnemonic = name
microopClasses[name] = LoadOp
defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);')
defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);',
'(StoreCheck << FlagShift)')
defineMicroLoadOp('Ldstl', 'Data = merge(Data, Mem, dataSize);',
'(StoreCheck << FlagShift) | Request::LOCKED')
defineMicroLoadOp('Ldfp', 'FpData.uqw = Mem;')
def defineMicroStoreOp(mnemonic, code, \
2009-02-27 18:23:50 +01:00
postCode="", completeCode="", mem_flags="0"):
global header_output
global decoder_output
global exec_output
global microopClasses
Name = mnemonic
name = mnemonic.lower()
# Build up the all register version of this micro op
iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
{"code": code,
"post_code": postCode,
"complete_code": completeCode,
"ea_code": calculateEA})
header_output += MicroLdStOpDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroStoreExecute.subst(iop)
exec_output += MicroStoreInitiateAcc.subst(iop)
exec_output += MicroStoreCompleteAcc.subst(iop)
class StoreOp(LdStOp):
def __init__(self, data, segment, addr, disp = 0,
dataSize="env.dataSize",
addressSize="env.addressSize",
atCPL0=False):
super(StoreOp, self).__init__(data, segment, addr,
disp, dataSize, addressSize, mem_flags, atCPL0, False)
self.className = Name
self.mnemonic = name
microopClasses[name] = StoreOp
defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);')
defineMicroStoreOp('Stul', 'Mem = pick(Data, 2, dataSize);',
mem_flags="Request::LOCKED")
defineMicroStoreOp('Stfp', 'Mem = FpData.uqw;')
defineMicroStoreOp('Stupd', 'Mem = pick(Data, 2, dataSize);',
'Base = merge(Base, EA - SegBase, addressSize);',
'Base = merge(Base, pkt->req->getVaddr() - SegBase, addressSize);');
defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS")
iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
{"code": "Data = merge(Data, EA, dataSize);",
"ea_code": '''
EA = bits(scale * Index + Base + disp, addressSize * 8 - 1, 0);
'''})
header_output += MicroLeaDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLeaExecute.subst(iop)
class LeaOp(LdStOp):
def __init__(self, data, segment, addr, disp = 0,
dataSize="env.dataSize", addressSize="env.addressSize"):
super(LeaOp, self).__init__(data, segment,
addr, disp, dataSize, addressSize, "0", False, False)
self.className = "Lea"
self.mnemonic = "lea"
microopClasses["lea"] = LeaOp
iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
{"code": "xc->demapPage(EA, 0);",
"ea_code": calculateEA})
header_output += MicroLeaDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLeaExecute.subst(iop)
class TiaOp(LdStOp):
def __init__(self, segment, addr, disp = 0,
dataSize="env.dataSize",
addressSize="env.addressSize"):
super(TiaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
addr, disp, dataSize, addressSize, "0", False, False)
self.className = "Tia"
self.mnemonic = "tia"
microopClasses["tia"] = TiaOp
class CdaOp(LdStOp):
def __init__(self, segment, addr, disp = 0,
dataSize="env.dataSize",
addressSize="env.addressSize", atCPL0=False):
super(CdaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
addr, disp, dataSize, addressSize, "Request::NO_ACCESS",
atCPL0, False)
self.className = "Cda"
self.mnemonic = "cda"
microopClasses["cda"] = CdaOp
}};