util.isa revision 12294:650a9d8b23cc
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 166def template EACompExecute {{ 167 Fault 168 %(class_name)s::eaComp(ExecContext *xc, 169 Trace::InstRecord *traceData) const 170 { 171 Addr EA; 172 Fault fault = NoFault; 173 %(op_decl)s; 174 %(op_rd)s; 175 %(ea_code)s; 176 %(fault_check)s; 177 178 // NOTE: Trace Data is written using execute or completeAcc templates 179 if (fault == NoFault) { 180 %(EA_trunc)s 181 xc->setEA(EA); 182 } 183 184 return fault; 185 } 186}}; 187 188// Here are some code snippets which check for various fault conditions 189let {{ 190 LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc] 191 StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc] 192 193 # The LSB can be zero, since it's really the MSB in doubles and quads 194 # and we're dealing with doubles 195 BlockAlignmentFaultCheck = ''' 196 if (RD & 0xe) 197 fault = std::make_shared<IllegalInstruction>(); 198 else if (EA & 0x3f) 199 fault = std::make_shared<MemAddressNotAligned>(); 200 ''' 201 TwinAlignmentFaultCheck = ''' 202 if (RD & 0x1) 203 fault = std::make_shared<IllegalInstruction>(); 204 else if (EA & 0xf) 205 fault = std::make_shared<MemAddressNotAligned>(); 206 ''' 207 # XXX Need to take care of pstate.hpriv as well. The lower ASIs 208 # are split into ones that are available in priv and hpriv, and 209 # those that are only available in hpriv 210 AlternateASIPrivFaultCheck = ''' 211 if ((!Pstate.priv && !Hpstate.hpriv && 212 !asiIsUnPriv((ASI)EXT_ASI)) || 213 (!Hpstate.hpriv && asiIsHPriv((ASI)EXT_ASI))) 214 fault = std::make_shared<PrivilegedAction>(); 215 else if (asiIsAsIfUser((ASI)EXT_ASI) && !Pstate.priv) 216 fault = std::make_shared<PrivilegedAction>(); 217 ''' 218 219 TruncateEA = ''' 220 if (!FullSystem) { 221 EA = Pstate.am ? EA<31:0> : EA; 222 } 223 ''' 224}}; 225 226// A simple function to generate the name of the macro op of a certain 227// instruction at a certain micropc 228let {{ 229 def makeMicroName(name, microPc): 230 return name + "::" + name + "_" + str(microPc) 231}}; 232 233// This function properly generates the execute functions for one of the 234// templates above. This is needed because in one case, ea computation, 235// fault checks and the actual code all occur in the same function, 236// and in the other they're distributed across two. Also note that for 237// execute functions, the name of the base class doesn't matter. 238let {{ 239 def doSplitExecute(execute, name, Name, asi, opt_flags, microParam): 240 microParam["asi_val"] = asi; 241 iop = InstObjParams(name, Name, '', microParam, opt_flags) 242 (execf, initf, compf) = execute 243 return execf.subst(iop) + initf.subst(iop) + compf.subst(iop) 244 245 246 def doDualSplitExecute(code, postacc_code, eaRegCode, eaImmCode, execute, 247 faultCode, nameReg, nameImm, NameReg, NameImm, asi, opt_flags): 248 executeCode = '' 249 for (eaCode, name, Name) in ( 250 (eaRegCode, nameReg, NameReg), 251 (eaImmCode, nameImm, NameImm)): 252 microParams = {"code": code, "postacc_code" : postacc_code, 253 "ea_code": eaCode, "fault_check": faultCode, 254 "EA_trunc" : TruncateEA} 255 executeCode += doSplitExecute(execute, name, Name, 256 asi, opt_flags, microParams) 257 return executeCode 258}}; 259