ldr.isa revision 7720:65d338a8dba4
1// -*- mode:c++ -*- 2 3// Copyright (c) 2010 ARM Limited 4// All rights reserved 5// 6// The license below extends only to copyright in the software and shall 7// not be construed as granting a license to any other intellectual 8// property including but not limited to intellectual property relating 9// to a hardware implementation of the functionality of the software 10// licensed hereunder. You may use the software subject to the license 11// terms below provided that you ensure that this notice is replicated 12// unmodified and in its entirety in all distributions of the software, 13// modified or unmodified, in source code or in binary form. 14// 15// Redistribution and use in source and binary forms, with or without 16// modification, are permitted provided that the following conditions are 17// met: redistributions of source code must retain the above copyright 18// notice, this list of conditions and the following disclaimer; 19// redistributions in binary form must reproduce the above copyright 20// notice, this list of conditions and the following disclaimer in the 21// documentation and/or other materials provided with the distribution; 22// neither the name of the copyright holders nor the names of its 23// contributors may be used to endorse or promote products derived from 24// this software without specific prior written permission. 25// 26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37// 38// Authors: Gabe Black 39 40let {{ 41 42 header_output = "" 43 decoder_output = "" 44 exec_output = "" 45 46 class LoadInst(LoadStoreInst): 47 execBase = 'Load' 48 49 def __init__(self, mnem, post, add, writeback, 50 size=4, sign=False, user=False, flavor="normal"): 51 super(LoadInst, self).__init__() 52 53 self.name = mnem 54 self.post = post 55 self.add = add 56 self.writeback = writeback 57 self.size = size 58 self.sign = sign 59 self.user = user 60 self.flavor = flavor 61 62 if self.add: 63 self.op = " +" 64 else: 65 self.op = " -" 66 67 self.memFlags = ["ArmISA::TLB::MustBeOne"] 68 self.codeBlobs = {"postacc_code" : ""} 69 70 def emitHelper(self, base = 'Memory', wbDecl = None, instFlags = []): 71 72 global header_output, decoder_output, exec_output 73 74 codeBlobs = self.codeBlobs 75 codeBlobs["predicate_test"] = pickPredicate(codeBlobs) 76 (newHeader, 77 newDecoder, 78 newExec) = self.fillTemplates(self.name, self.Name, codeBlobs, 79 self.memFlags, instFlags, base, wbDecl) 80 81 header_output += newHeader 82 decoder_output += newDecoder 83 exec_output += newExec 84 85 class RfeInst(LoadInst): 86 decConstBase = 'Rfe' 87 88 def __init__(self, mnem, post, add, writeback): 89 super(RfeInst, self).__init__(mnem, post, add, writeback) 90 self.Name = "RFE_" + loadImmClassName(post, add, writeback, 8) 91 92 self.memFlags.append("ArmISA::TLB::AlignWord") 93 94 def emit(self): 95 offset = 0 96 if self.post != self.add: 97 offset += 4 98 if not self.add: 99 offset -= 8 100 self.codeBlobs["ea_code"] = "EA = Base + %d;" % offset 101 102 wbDiff = -8 103 if self.add: 104 wbDiff = 8 105 accCode = ''' 106 CPSR cpsr = Cpsr; 107 SCTLR sctlr = Sctlr; 108 ArmISA::PCState pc = PCS; 109 pc.instNPC(cSwap<uint32_t>(Mem.ud, cpsr.e)); 110 uint32_t newCpsr = 111 cpsrWriteByInstr(cpsr | CondCodes, 112 cSwap<uint32_t>(Mem.ud >> 32, cpsr.e), 113 0xF, true, sctlr.nmfi); 114 Cpsr = ~CondCodesMask & newCpsr; 115 pc.nextThumb(((CPSR)newCpsr).t); 116 pc.nextJazelle(((CPSR)newCpsr).j); 117 PCS = pc; 118 CondCodes = CondCodesMask & newCpsr; 119 ''' 120 self.codeBlobs["memacc_code"] = accCode 121 122 wbDecl = None 123 if self.writeback: 124 wbDecl = "MicroAddiUop(machInst, base, base, %d);" % wbDiff 125 self.emitHelper('RfeOp', wbDecl, ["IsSerializeAfter", "IsNonSpeculative"]) 126 127 class LoadImmInst(LoadInst): 128 def __init__(self, *args, **kargs): 129 super(LoadImmInst, self).__init__(*args, **kargs) 130 self.offset = self.op + " imm" 131 132 if self.add: 133 self.wbDecl = "MicroAddiUop(machInst, base, base, imm);" 134 else: 135 self.wbDecl = "MicroSubiUop(machInst, base, base, imm);" 136 137 class LoadRegInst(LoadInst): 138 def __init__(self, *args, **kargs): 139 super(LoadRegInst, self).__init__(*args, **kargs) 140 self.offset = self.op + " shift_rm_imm(Index, shiftAmt," + \ 141 " shiftType, CondCodes<29:>)" 142 if self.add: 143 self.wbDecl = ''' 144 MicroAddUop(machInst, base, base, wbIndexReg, shiftAmt, shiftType); 145 ''' 146 else: 147 self.wbDecl = ''' 148 MicroSubUop(machInst, base, base, wbIndexReg, shiftAmt, shiftType); 149 ''' 150 151 class LoadSingle(LoadInst): 152 def __init__(self, *args, **kargs): 153 super(LoadSingle, self).__init__(*args, **kargs) 154 155 # Build the default class name 156 self.Name = self.nameFunc(self.post, self.add, self.writeback, 157 self.size, self.sign, self.user) 158 159 # Add memory request flags where necessary 160 self.memFlags.append("%d" % (self.size - 1)) 161 if self.user: 162 self.memFlags.append("ArmISA::TLB::UserMode") 163 164 if self.flavor == "prefetch": 165 self.memFlags.append("Request::PREFETCH") 166 elif self.flavor == "exclusive": 167 self.memFlags.append("Request::LLSC") 168 elif self.flavor == "normal": 169 self.memFlags.append("ArmISA::TLB::AllowUnaligned") 170 171 # Disambiguate the class name for different flavors of loads 172 if self.flavor != "normal": 173 self.Name = "%s_%s" % (self.name.upper(), self.Name) 174 175 def emit(self): 176 # Address compuation code 177 eaCode = "EA = Base" 178 if not self.post: 179 eaCode += self.offset 180 eaCode += ";" 181 182 if self.flavor == "fp": 183 eaCode += vfpEnabledCheckCode 184 185 self.codeBlobs["ea_code"] = eaCode 186 187 # Code that actually handles the access 188 if self.flavor == "prefetch": 189 accCode = 'uint64_t temp = Mem%s; temp = temp;' 190 elif self.flavor == "fp": 191 accCode = "FpDest.uw = cSwap(Mem%s, ((CPSR)Cpsr).e);\n" 192 else: 193 accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);" 194 accCode = accCode % buildMemSuffix(self.sign, self.size) 195 196 self.codeBlobs["memacc_code"] = accCode 197 198 # Push it out to the output files 199 base = buildMemBase(self.basePrefix, self.post, self.writeback) 200 wbDecl = None 201 if self.writeback: 202 wbDecl = self.wbDecl 203 self.emitHelper(base, wbDecl) 204 205 def loadImmClassName(post, add, writeback, size=4, sign=False, user=False): 206 return memClassName("LOAD_IMM", post, add, writeback, size, sign, user) 207 208 class LoadImm(LoadImmInst, LoadSingle): 209 decConstBase = 'LoadImm' 210 basePrefix = 'MemoryImm' 211 nameFunc = staticmethod(loadImmClassName) 212 213 def loadRegClassName(post, add, writeback, size=4, sign=False, user=False): 214 return memClassName("LOAD_REG", post, add, writeback, size, sign, user) 215 216 class LoadReg(LoadRegInst, LoadSingle): 217 decConstBase = 'LoadReg' 218 basePrefix = 'MemoryReg' 219 nameFunc = staticmethod(loadRegClassName) 220 221 class LoadDouble(LoadInst): 222 def __init__(self, *args, **kargs): 223 super(LoadDouble, self).__init__(*args, **kargs) 224 225 # Build the default class name 226 self.Name = self.nameFunc(self.post, self.add, self.writeback) 227 228 # Add memory request flags where necessary 229 if self.flavor == "exclusive": 230 self.memFlags.append("Request::LLSC") 231 self.memFlags.append("ArmISA::TLB::AlignDoubleWord") 232 else: 233 self.memFlags.append("ArmISA::TLB::AlignWord") 234 235 # Disambiguate the class name for different flavors of loads 236 if self.flavor != "normal": 237 self.Name = "%s_%s" % (self.name.upper(), self.Name) 238 239 def emit(self): 240 # Address computation code 241 eaCode = "EA = Base" 242 if not self.post: 243 eaCode += self.offset 244 eaCode += ";" 245 246 if self.flavor == "fp": 247 eaCode += vfpEnabledCheckCode 248 249 self.codeBlobs["ea_code"] = eaCode 250 251 # Code that actually handles the access 252 if self.flavor != "fp": 253 accCode = ''' 254 CPSR cpsr = Cpsr; 255 Dest = cSwap<uint32_t>(Mem.ud, cpsr.e); 256 Dest2 = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e); 257 ''' 258 else: 259 accCode = ''' 260 uint64_t swappedMem = cSwap(Mem.ud, ((CPSR)Cpsr).e); 261 FpDest.uw = (uint32_t)swappedMem; 262 FpDest2.uw = (uint32_t)(swappedMem >> 32); 263 ''' 264 265 self.codeBlobs["memacc_code"] = accCode 266 267 # Push it out to the output files 268 base = buildMemBase(self.basePrefix, self.post, self.writeback) 269 wbDecl = None 270 if self.writeback: 271 wbDecl = self.wbDecl 272 self.emitHelper(base, wbDecl) 273 274 def loadDoubleImmClassName(post, add, writeback): 275 return memClassName("LOAD_IMMD", post, add, writeback, 4, False, False) 276 277 class LoadDoubleImm(LoadImmInst, LoadDouble): 278 decConstBase = 'LoadStoreDImm' 279 basePrefix = 'MemoryDImm' 280 nameFunc = staticmethod(loadDoubleImmClassName) 281 282 def loadDoubleRegClassName(post, add, writeback): 283 return memClassName("LOAD_REGD", post, add, writeback, 4, False, False) 284 285 class LoadDoubleReg(LoadRegInst, LoadDouble): 286 decConstBase = 'LoadDReg' 287 basePrefix = 'MemoryDReg' 288 nameFunc = staticmethod(loadDoubleRegClassName) 289 290 def buildLoads(mnem, size=4, sign=False, user=False): 291 LoadImm(mnem, True, True, True, size, sign, user).emit() 292 LoadReg(mnem, True, True, True, size, sign, user).emit() 293 LoadImm(mnem, True, False, True, size, sign, user).emit() 294 LoadReg(mnem, True, False, True, size, sign, user).emit() 295 LoadImm(mnem, False, True, True, size, sign, user).emit() 296 LoadReg(mnem, False, True, True, size, sign, user).emit() 297 LoadImm(mnem, False, False, True, size, sign, user).emit() 298 LoadReg(mnem, False, False, True, size, sign, user).emit() 299 LoadImm(mnem, False, True, False, size, sign, user).emit() 300 LoadReg(mnem, False, True, False, size, sign, user).emit() 301 LoadImm(mnem, False, False, False, size, sign, user).emit() 302 LoadReg(mnem, False, False, False, size, sign, user).emit() 303 304 def buildDoubleLoads(mnem): 305 LoadDoubleImm(mnem, True, True, True).emit() 306 LoadDoubleReg(mnem, True, True, True).emit() 307 LoadDoubleImm(mnem, True, False, True).emit() 308 LoadDoubleReg(mnem, True, False, True).emit() 309 LoadDoubleImm(mnem, False, True, True).emit() 310 LoadDoubleReg(mnem, False, True, True).emit() 311 LoadDoubleImm(mnem, False, False, True).emit() 312 LoadDoubleReg(mnem, False, False, True).emit() 313 LoadDoubleImm(mnem, False, True, False).emit() 314 LoadDoubleReg(mnem, False, True, False).emit() 315 LoadDoubleImm(mnem, False, False, False).emit() 316 LoadDoubleReg(mnem, False, False, False).emit() 317 318 def buildRfeLoads(mnem): 319 RfeInst(mnem, True, True, True).emit() 320 RfeInst(mnem, True, True, False).emit() 321 RfeInst(mnem, True, False, True).emit() 322 RfeInst(mnem, True, False, False).emit() 323 RfeInst(mnem, False, True, True).emit() 324 RfeInst(mnem, False, True, False).emit() 325 RfeInst(mnem, False, False, True).emit() 326 RfeInst(mnem, False, False, False).emit() 327 328 def buildPrefetches(mnem): 329 LoadReg(mnem, False, False, False, size=1, flavor="prefetch").emit() 330 LoadImm(mnem, False, False, False, size=1, flavor="prefetch").emit() 331 LoadReg(mnem, False, True, False, size=1, flavor="prefetch").emit() 332 LoadImm(mnem, False, True, False, size=1, flavor="prefetch").emit() 333 334 buildLoads("ldr") 335 buildLoads("ldrt", user=True) 336 buildLoads("ldrb", size=1) 337 buildLoads("ldrbt", size=1, user=True) 338 buildLoads("ldrsb", size=1, sign=True) 339 buildLoads("ldrsbt", size=1, sign=True, user=True) 340 buildLoads("ldrh", size=2) 341 buildLoads("ldrht", size=2, user=True) 342 buildLoads("hdrsh", size=2, sign=True) 343 buildLoads("ldrsht", size=2, sign=True, user=True) 344 345 buildDoubleLoads("ldrd") 346 347 buildRfeLoads("rfe") 348 349 buildPrefetches("pld") 350 buildPrefetches("pldw") 351 buildPrefetches("pli") 352 353 LoadImm("ldrex", False, True, False, size=4, flavor="exclusive").emit() 354 LoadImm("ldrexh", False, True, False, size=2, flavor="exclusive").emit() 355 LoadImm("ldrexb", False, True, False, size=1, flavor="exclusive").emit() 356 LoadDoubleImm("ldrexd", False, True, False, flavor="exclusive").emit() 357 358 LoadImm("vldr", False, True, False, size=4, flavor="fp").emit() 359 LoadImm("vldr", False, False, False, size=4, flavor="fp").emit() 360 LoadDoubleImm("vldr", False, True, False, flavor="fp").emit() 361 LoadDoubleImm("vldr", False, False, False, flavor="fp").emit() 362}}; 363