1// Copyright (c) 2006-2007 The Regents of The University of Michigan 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer; 8// redistributions in binary form must reproduce the above copyright 9// notice, this list of conditions and the following disclaimer in the 10// documentation and/or other materials provided with the distribution; 11// neither the name of the copyright holders nor the names of its 12// contributors may be used to endorse or promote products derived from 13// this software without specific prior written permission. 14// 15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26// 27// Authors: Ali Saidi 28// Gabe Black 29// Steve Reinhardt 30 31//////////////////////////////////////////////////////////////////// 32// 33// Mem utility templates and functions 34// 35 36// This template provides the execute functions for a load 37def template LoadExecute {{ 38 Fault %(class_name)s::execute(ExecContext *xc, 39 Trace::InstRecord *traceData) const 40 { 41 Fault fault = NoFault; 42 Addr EA; 43 %(fp_enable_check)s; 44 %(op_decl)s; 45 %(op_rd)s; 46 %(ea_code)s; 47 DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); 48 %(fault_check)s; 49 if (fault == NoFault) { 50 %(EA_trunc)s 51 fault = readMemAtomic(xc, traceData, EA, Mem, %(asi_val)s); 52 } 53 if (fault == NoFault) { 54 %(code)s; 55 } 56 if (fault == NoFault) { 57 // Write the resulting state to the execution context 58 %(op_wb)s; 59 } 60 61 return fault; 62 } 63}}; 64 65def template LoadInitiateAcc {{ 66 Fault %(class_name)s::initiateAcc(ExecContext * xc, 67 Trace::InstRecord * traceData) const 68 { 69 Fault fault = NoFault; 70 Addr EA; 71 %(fp_enable_check)s; 72 %(op_decl)s; 73 %(op_rd)s; 74 %(ea_code)s; 75 DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); 76 %(fault_check)s; 77 if (fault == NoFault) { 78 %(EA_trunc)s 79 fault = initiateMemRead(xc, traceData, EA, Mem, %(asi_val)s); 80 } 81 return fault; 82 } 83}}; 84 85def template LoadCompleteAcc {{ 86 Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext * xc, 87 Trace::InstRecord * traceData) const 88 { 89 Fault fault = NoFault; 90 %(op_decl)s; 91 %(op_rd)s; 92 getMem(pkt, Mem, traceData); 93 %(code)s; 94 if (fault == NoFault) { 95 %(op_wb)s; 96 } 97 return fault; 98 } 99}}; 100 101// This template provides the execute functions for a store 102def template StoreExecute {{ 103 Fault %(class_name)s::execute(ExecContext *xc, 104 Trace::InstRecord *traceData) const 105 { 106 Fault fault = NoFault; 107 // This is to support the conditional store in cas instructions. 108 // It should be optomized out in all the others 109 bool storeCond = true; 110 Addr EA; 111 %(fp_enable_check)s; 112 %(op_decl)s; 113 %(op_rd)s; 114 %(ea_code)s; 115 DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); 116 %(fault_check)s; 117 if (fault == NoFault) { 118 %(code)s; 119 } 120 if (storeCond && fault == NoFault) { 121 %(EA_trunc)s 122 fault = writeMemAtomic(xc, traceData, Mem, EA, %(asi_val)s, 0); 123 } 124 if (fault == NoFault) { 125 // Write the resulting state to the execution context 126 %(op_wb)s; 127 } 128 129 return fault; 130 } 131}}; 132 133def template StoreInitiateAcc {{ 134 Fault %(class_name)s::initiateAcc(ExecContext * xc, 135 Trace::InstRecord * traceData) const 136 { 137 Fault fault = NoFault; 138 bool storeCond = true; 139 Addr EA; 140 %(fp_enable_check)s; 141 %(op_decl)s; 142 143 %(op_rd)s; 144 %(ea_code)s; 145 DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); 146 %(fault_check)s; 147 if (fault == NoFault) { 148 %(code)s; 149 } 150 if (storeCond && fault == NoFault) { 151 %(EA_trunc)s 152 fault = writeMemTiming(xc, traceData, Mem, EA, %(asi_val)s, 0); 153 } 154 return fault; 155 } 156}}; 157 158def template StoreCompleteAcc {{ 159 Fault %(class_name)s::completeAcc(PacketPtr, ExecContext * xc, 160 Trace::InstRecord * traceData) const 161 { 162 return NoFault; 163 } 164}}; 165 166// Here are some code snippets which check for various fault conditions 167let {{ 168 LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc] 169 StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc] 170 171 # The LSB can be zero, since it's really the MSB in doubles and quads 172 # and we're dealing with doubles 173 BlockAlignmentFaultCheck = ''' 174 if (RD & 0xe) 175 fault = std::make_shared<IllegalInstruction>(); 176 else if (EA & 0x3f) 177 fault = std::make_shared<MemAddressNotAligned>(); 178 ''' 179 TwinAlignmentFaultCheck = ''' 180 if (RD & 0x1) 181 fault = std::make_shared<IllegalInstruction>(); 182 else if (EA & 0xf) 183 fault = std::make_shared<MemAddressNotAligned>(); 184 ''' 185 # XXX Need to take care of pstate.hpriv as well. The lower ASIs 186 # are split into ones that are available in priv and hpriv, and 187 # those that are only available in hpriv 188 AlternateASIPrivFaultCheck = ''' 189 if ((!Pstate.priv && !Hpstate.hpriv && 190 !asiIsUnPriv((ASI)EXT_ASI)) || 191 (!Hpstate.hpriv && asiIsHPriv((ASI)EXT_ASI))) 192 fault = std::make_shared<PrivilegedAction>(); 193 else if (asiIsAsIfUser((ASI)EXT_ASI) && !Pstate.priv) 194 fault = std::make_shared<PrivilegedAction>(); 195 ''' 196 197 TruncateEA = ''' 198 if (!FullSystem) { 199 EA = Pstate.am ? EA<31:0> : EA; 200 } 201 ''' 202}}; 203 204// A simple function to generate the name of the macro op of a certain 205// instruction at a certain micropc 206let {{ 207 def makeMicroName(name, microPc): 208 return name + "::" + name + "_" + str(microPc) 209}}; 210 211// This function properly generates the execute functions for one of the 212// templates above. This is needed because in one case, ea computation, 213// fault checks and the actual code all occur in the same function, 214// and in the other they're distributed across two. Also note that for 215// execute functions, the name of the base class doesn't matter. 216let {{ 217 def doSplitExecute(execute, name, Name, asi, opt_flags, microParam): 218 microParam["asi_val"] = asi; 219 iop = InstObjParams(name, Name, '', microParam, opt_flags) 220 (execf, initf, compf) = execute 221 return execf.subst(iop) + initf.subst(iop) + compf.subst(iop) 222 223 224 def doDualSplitExecute(code, postacc_code, eaRegCode, eaImmCode, execute, 225 faultCode, nameReg, nameImm, NameReg, NameImm, asi, opt_flags): 226 executeCode = '' 227 for (eaCode, name, Name) in ( 228 (eaRegCode, nameReg, NameReg), 229 (eaImmCode, nameImm, NameImm)): 230 microParams = {"code": code, "postacc_code" : postacc_code, 231 "ea_code": eaCode, "fault_check": faultCode, 232 "EA_trunc" : TruncateEA} 233 executeCode += doSplitExecute(execute, name, Name, 234 asi, opt_flags, microParams) 235 return executeCode 236}}; 237