ldr.isa revision 7858:ee6641d7c713
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 // Use the version of NPC that gets set before NextThumb 109 pNPC = cSwap<uint32_t>(Mem.ud, cpsr.e); 110 uint32_t tempSpsr = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e); 111 uint32_t newCpsr = 112 cpsrWriteByInstr(cpsr | CondCodes, tempSpsr, 113 0xF, true, sctlr.nmfi); 114 Cpsr = ~CondCodesMask & newCpsr; 115 NextThumb = ((CPSR)newCpsr).t; 116 NextJazelle = ((CPSR)newCpsr).j; 117 ForcedItState = ((((CPSR)tempSpsr).it2 << 2) & 0xFC) 118 | (((CPSR)tempSpsr).it1 & 0x3); 119 CondCodes = CondCodesMask & newCpsr; 120 ''' 121 self.codeBlobs["memacc_code"] = accCode 122 123 wbDecl = None 124 if self.writeback: 125 wbDecl = "MicroAddiUop(machInst, base, base, %d);" % wbDiff 126 self.emitHelper('RfeOp', wbDecl, ["IsSerializeAfter", "IsNonSpeculative"]) 127 128 class LoadImmInst(LoadInst): 129 def __init__(self, *args, **kargs): 130 super(LoadImmInst, self).__init__(*args, **kargs) 131 self.offset = self.op + " imm" 132 133 if self.add: 134 self.wbDecl = "MicroAddiUop(machInst, base, base, imm);" 135 else: 136 self.wbDecl = "MicroSubiUop(machInst, base, base, imm);" 137 138 class LoadRegInst(LoadInst): 139 def __init__(self, *args, **kargs): 140 super(LoadRegInst, self).__init__(*args, **kargs) 141 self.offset = self.op + " shift_rm_imm(Index, shiftAmt," + \ 142 " shiftType, CondCodes<29:>)" 143 if self.add: 144 self.wbDecl = ''' 145 MicroAddUop(machInst, base, base, wbIndexReg, shiftAmt, shiftType); 146 ''' 147 else: 148 self.wbDecl = ''' 149 MicroSubUop(machInst, base, base, wbIndexReg, shiftAmt, shiftType); 150 ''' 151 152 class LoadSingle(LoadInst): 153 def __init__(self, *args, **kargs): 154 super(LoadSingle, self).__init__(*args, **kargs) 155 156 # Build the default class name 157 self.Name = self.nameFunc(self.post, self.add, self.writeback, 158 self.size, self.sign, self.user) 159 160 # Add memory request flags where necessary 161 self.memFlags.append("%d" % (self.size - 1)) 162 if self.user: 163 self.memFlags.append("ArmISA::TLB::UserMode") 164 165 self.instFlags = [] 166 if self.flavor == "dprefetch": 167 self.memFlags.append("Request::PREFETCH") 168 self.instFlags = ['IsDataPrefetch'] 169 elif self.flavor == "iprefetch": 170 self.memFlags.append("Request::PREFETCH") 171 self.instFlags = ['IsInstPrefetch'] 172 elif self.flavor == "exclusive": 173 self.memFlags.append("Request::LLSC") 174 elif self.flavor == "normal": 175 self.memFlags.append("ArmISA::TLB::AllowUnaligned") 176 177 # Disambiguate the class name for different flavors of loads 178 if self.flavor != "normal": 179 self.Name = "%s_%s" % (self.name.upper(), self.Name) 180 181 def emit(self): 182 # Address compuation code 183 eaCode = "EA = Base" 184 if not self.post: 185 eaCode += self.offset 186 eaCode += ";" 187 188 if self.flavor == "fp": 189 eaCode += vfpEnabledCheckCode 190 191 self.codeBlobs["ea_code"] = eaCode 192 193 # Code that actually handles the access 194 if self.flavor == "dprefetch" or self.flavor == "iprefetch": 195 accCode = 'uint64_t temp = Mem%s; temp = temp;' 196 elif self.flavor == "fp": 197 accCode = "FpDest.uw = cSwap(Mem%s, ((CPSR)Cpsr).e);\n" 198 else: 199 accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);" 200 accCode = accCode % buildMemSuffix(self.sign, self.size) 201 202 self.codeBlobs["memacc_code"] = accCode 203 204 # Push it out to the output files 205 base = buildMemBase(self.basePrefix, self.post, self.writeback) 206 wbDecl = None 207 if self.writeback: 208 wbDecl = self.wbDecl 209 self.emitHelper(base, wbDecl, self.instFlags) 210 211 def loadImmClassName(post, add, writeback, size=4, sign=False, user=False): 212 return memClassName("LOAD_IMM", post, add, writeback, size, sign, user) 213 214 class LoadImm(LoadImmInst, LoadSingle): 215 decConstBase = 'LoadImm' 216 basePrefix = 'MemoryImm' 217 nameFunc = staticmethod(loadImmClassName) 218 219 def loadRegClassName(post, add, writeback, size=4, sign=False, user=False): 220 return memClassName("LOAD_REG", post, add, writeback, size, sign, user) 221 222 class LoadReg(LoadRegInst, LoadSingle): 223 decConstBase = 'LoadReg' 224 basePrefix = 'MemoryReg' 225 nameFunc = staticmethod(loadRegClassName) 226 227 class LoadDouble(LoadInst): 228 def __init__(self, *args, **kargs): 229 super(LoadDouble, self).__init__(*args, **kargs) 230 231 # Build the default class name 232 self.Name = self.nameFunc(self.post, self.add, self.writeback) 233 234 # Add memory request flags where necessary 235 if self.flavor == "exclusive": 236 self.memFlags.append("Request::LLSC") 237 self.memFlags.append("ArmISA::TLB::AlignDoubleWord") 238 else: 239 self.memFlags.append("ArmISA::TLB::AlignWord") 240 241 # Disambiguate the class name for different flavors of loads 242 if self.flavor != "normal": 243 self.Name = "%s_%s" % (self.name.upper(), self.Name) 244 245 def emit(self): 246 # Address computation code 247 eaCode = "EA = Base" 248 if not self.post: 249 eaCode += self.offset 250 eaCode += ";" 251 252 if self.flavor == "fp": 253 eaCode += vfpEnabledCheckCode 254 255 self.codeBlobs["ea_code"] = eaCode 256 257 # Code that actually handles the access 258 if self.flavor != "fp": 259 accCode = ''' 260 CPSR cpsr = Cpsr; 261 Dest = cSwap<uint32_t>(Mem.ud, cpsr.e); 262 Dest2 = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e); 263 ''' 264 else: 265 accCode = ''' 266 uint64_t swappedMem = cSwap(Mem.ud, ((CPSR)Cpsr).e); 267 FpDest.uw = (uint32_t)swappedMem; 268 FpDest2.uw = (uint32_t)(swappedMem >> 32); 269 ''' 270 271 self.codeBlobs["memacc_code"] = accCode 272 273 # Push it out to the output files 274 base = buildMemBase(self.basePrefix, self.post, self.writeback) 275 wbDecl = None 276 if self.writeback: 277 wbDecl = self.wbDecl 278 self.emitHelper(base, wbDecl) 279 280 def loadDoubleImmClassName(post, add, writeback): 281 return memClassName("LOAD_IMMD", post, add, writeback, 4, False, False) 282 283 class LoadDoubleImm(LoadImmInst, LoadDouble): 284 decConstBase = 'LoadStoreDImm' 285 basePrefix = 'MemoryDImm' 286 nameFunc = staticmethod(loadDoubleImmClassName) 287 288 def loadDoubleRegClassName(post, add, writeback): 289 return memClassName("LOAD_REGD", post, add, writeback, 4, False, False) 290 291 class LoadDoubleReg(LoadRegInst, LoadDouble): 292 decConstBase = 'LoadDReg' 293 basePrefix = 'MemoryDReg' 294 nameFunc = staticmethod(loadDoubleRegClassName) 295 296 def buildLoads(mnem, size=4, sign=False, user=False): 297 LoadImm(mnem, True, True, True, size, sign, user).emit() 298 LoadReg(mnem, True, True, True, size, sign, user).emit() 299 LoadImm(mnem, True, False, True, size, sign, user).emit() 300 LoadReg(mnem, True, False, True, size, sign, user).emit() 301 LoadImm(mnem, False, True, True, size, sign, user).emit() 302 LoadReg(mnem, False, True, True, size, sign, user).emit() 303 LoadImm(mnem, False, False, True, size, sign, user).emit() 304 LoadReg(mnem, False, False, True, size, sign, user).emit() 305 LoadImm(mnem, False, True, False, size, sign, user).emit() 306 LoadReg(mnem, False, True, False, size, sign, user).emit() 307 LoadImm(mnem, False, False, False, size, sign, user).emit() 308 LoadReg(mnem, False, False, False, size, sign, user).emit() 309 310 def buildDoubleLoads(mnem): 311 LoadDoubleImm(mnem, True, True, True).emit() 312 LoadDoubleReg(mnem, True, True, True).emit() 313 LoadDoubleImm(mnem, True, False, True).emit() 314 LoadDoubleReg(mnem, True, False, True).emit() 315 LoadDoubleImm(mnem, False, True, True).emit() 316 LoadDoubleReg(mnem, False, True, True).emit() 317 LoadDoubleImm(mnem, False, False, True).emit() 318 LoadDoubleReg(mnem, False, False, True).emit() 319 LoadDoubleImm(mnem, False, True, False).emit() 320 LoadDoubleReg(mnem, False, True, False).emit() 321 LoadDoubleImm(mnem, False, False, False).emit() 322 LoadDoubleReg(mnem, False, False, False).emit() 323 324 def buildRfeLoads(mnem): 325 RfeInst(mnem, True, True, True).emit() 326 RfeInst(mnem, True, True, False).emit() 327 RfeInst(mnem, True, False, True).emit() 328 RfeInst(mnem, True, False, False).emit() 329 RfeInst(mnem, False, True, True).emit() 330 RfeInst(mnem, False, True, False).emit() 331 RfeInst(mnem, False, False, True).emit() 332 RfeInst(mnem, False, False, False).emit() 333 334 def buildPrefetches(mnem, type): 335 LoadReg(mnem, False, False, False, size=1, flavor=type).emit() 336 LoadImm(mnem, False, False, False, size=1, flavor=type).emit() 337 LoadReg(mnem, False, True, False, size=1, flavor=type).emit() 338 LoadImm(mnem, False, True, False, size=1, flavor=type).emit() 339 340 buildLoads("ldr") 341 buildLoads("ldrt", user=True) 342 buildLoads("ldrb", size=1) 343 buildLoads("ldrbt", size=1, user=True) 344 buildLoads("ldrsb", size=1, sign=True) 345 buildLoads("ldrsbt", size=1, sign=True, user=True) 346 buildLoads("ldrh", size=2) 347 buildLoads("ldrht", size=2, user=True) 348 buildLoads("hdrsh", size=2, sign=True) 349 buildLoads("ldrsht", size=2, sign=True, user=True) 350 351 buildDoubleLoads("ldrd") 352 353 buildRfeLoads("rfe") 354 355 buildPrefetches("pld", "dprefetch") 356 buildPrefetches("pldw", "dprefetch") 357 buildPrefetches("pli", "iprefetch") 358 359 LoadImm("ldrex", False, True, False, size=4, flavor="exclusive").emit() 360 LoadImm("ldrexh", False, True, False, size=2, flavor="exclusive").emit() 361 LoadImm("ldrexb", False, True, False, size=1, flavor="exclusive").emit() 362 LoadDoubleImm("ldrexd", False, True, False, flavor="exclusive").emit() 363 364 LoadImm("vldr", False, True, False, size=4, flavor="fp").emit() 365 LoadImm("vldr", False, False, False, size=4, flavor="fp").emit() 366 LoadDoubleImm("vldr", False, True, False, flavor="fp").emit() 367 LoadDoubleImm("vldr", False, False, False, flavor="fp").emit() 368}}; 369