| // 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, RegIndex _index, RegIndex _base, |
| uint64_t _disp, uint8_t _segment, |
| RegIndex _data, |
| uint8_t _dataSize, uint8_t _addressSize); |
| |
| %(class_name)s(ExtMachInst _machInst, |
| const char * instMnem, |
| uint8_t _scale, RegIndex _index, RegIndex _base, |
| uint64_t _disp, uint8_t _segment, |
| RegIndex _data, |
| uint8_t _dataSize, uint8_t _addressSize); |
| |
| %(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, (%(mem_flags)s) | segment); |
| |
| if(fault == NoFault) |
| { |
| %(code)s; |
| } |
| 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, (%(mem_flags)s) | segment); |
| |
| 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; |
| |
| Mem = pkt->get<typeof(Mem)>(); |
| |
| %(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, (%(mem_flags)s) | segment); |
| if(fault == NoFault) |
| { |
| %(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) |
| { |
| fault = write(xc, Mem, EA, (%(mem_flags)s) | segment); |
| if(fault == NoFault) |
| { |
| %(op_wb)s; |
| } |
| } |
| return fault; |
| } |
| }}; |
| |
| def template MicroStoreCompleteAcc {{ |
| Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc, |
| Trace::InstRecord * traceData) const |
| { |
| 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, RegIndex _index, RegIndex _base, |
| uint64_t _disp, uint8_t _segment, |
| RegIndex _data, |
| uint8_t _dataSize, uint8_t _addressSize); |
| |
| %(class_name)s(ExtMachInst _machInst, |
| const char * instMnem, |
| uint8_t _scale, RegIndex _index, RegIndex _base, |
| uint64_t _disp, uint8_t _segment, |
| RegIndex _data, |
| uint8_t _dataSize, uint8_t _addressSize); |
| |
| %(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, RegIndex _index, RegIndex _base, |
| uint64_t _disp, uint8_t _segment, |
| RegIndex _data, |
| uint8_t _dataSize, uint8_t _addressSize) : |
| %(base_class)s(machInst, "%(mnemonic)s", instMnem, |
| false, false, false, false, |
| _scale, _index, _base, |
| _disp, _segment, _data, |
| _dataSize, _addressSize, %(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, RegIndex _index, RegIndex _base, |
| uint64_t _disp, uint8_t _segment, |
| RegIndex _data, |
| uint8_t _dataSize, uint8_t _addressSize) : |
| %(base_class)s(machInst, "%(mnemonic)s", instMnem, |
| isMicro, isDelayed, isFirst, isLast, |
| _scale, _index, _base, |
| _disp, _segment, _data, |
| _dataSize, _addressSize, %(op_class)s) |
| { |
| buildMe(); |
| } |
| }}; |
| |
| let {{ |
| class LdStOp(X86Microop): |
| def __init__(self, data, segment, addr, disp, dataSize, addressSize): |
| self.data = data |
| [self.scale, self.index, self.base] = addr |
| self.disp = disp |
| self.segment = segment |
| self.dataSize = dataSize |
| self.addressSize = addressSize |
| |
| def getAllocator(self, *microFlags): |
| allocator = '''new %(class_name)s(machInst, mnemonic |
| %(flags)s, %(scale)s, %(index)s, %(base)s, |
| %(disp)s, %(segment)s, %(data)s, |
| %(dataSize)s, %(addressSize)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} |
| return allocator |
| }}; |
| |
| let {{ |
| |
| # Make these empty strings so that concatenating onto |
| # them will always work. |
| header_output = "" |
| decoder_output = "" |
| exec_output = "" |
| |
| calculateEA = "EA = SegBase + scale * Index + Base + disp;" |
| |
| 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, |
| "mem_flags": mem_flags}) |
| 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"): |
| super(LoadOp, self).__init__(data, segment, |
| addr, disp, dataSize, addressSize) |
| self.className = Name |
| self.mnemonic = name |
| |
| microopClasses[name] = LoadOp |
| |
| defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);') |
| defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', 'StoreCheck') |
| defineMicroLoadOp('Ldfp', 'FpData.uqw = Mem;') |
| |
| def defineMicroStoreOp(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, |
| "mem_flags": mem_flags}) |
| 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"): |
| super(StoreOp, self).__init__(data, segment, |
| addr, disp, dataSize, addressSize) |
| self.className = Name |
| self.mnemonic = name |
| |
| microopClasses[name] = StoreOp |
| |
| defineMicroStoreOp('St', 'Mem = Data;') |
| defineMicroStoreOp('Stfp', 'Mem = FpData.uqw;') |
| defineMicroStoreOp('Stupd', ''' |
| Mem = Data; |
| Base = merge(Base, EA - SegBase, addressSize); |
| '''); |
| |
| |
| iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp', |
| {"code": "Data = merge(Data, EA, dataSize);", |
| "ea_code": calculateEA, |
| "mem_flags": 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) |
| self.className = "Lea" |
| self.mnemonic = "lea" |
| |
| microopClasses["lea"] = LeaOp |
| |
| |
| iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp', |
| {"code": "xc->demapPage(EA, 0);", |
| "ea_code": calculateEA, |
| "mem_flags": 0}) |
| 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__("NUM_INTREGS", segment, |
| addr, disp, dataSize, addressSize) |
| self.className = "Tia" |
| self.mnemonic = "tia" |
| |
| microopClasses["tia"] = TiaOp |
| |
| iop = InstObjParams("cda", "Cda", 'X86ISA::LdStOp', |
| {"code": ''' |
| Addr paddr; |
| fault = xc->translateDataWriteAddr(EA, paddr, |
| dataSize, (1 << segment)); |
| ''', |
| "ea_code": calculateEA}) |
| header_output += MicroLeaDeclare.subst(iop) |
| decoder_output += MicroLdStOpConstructor.subst(iop) |
| exec_output += MicroLeaExecute.subst(iop) |
| |
| class CdaOp(LdStOp): |
| def __init__(self, segment, addr, disp = 0, |
| dataSize="env.dataSize", addressSize="env.addressSize"): |
| super(CdaOp, self).__init__("NUM_INTREGS", segment, |
| addr, disp, dataSize, addressSize) |
| self.className = "Cda" |
| self.mnemonic = "cda" |
| |
| microopClasses["cda"] = CdaOp |
| }}; |
| |