ldr.isa revision 7725:00ea9430643b
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 self.instFlags = [] 165 if self.flavor == "dprefetch": 166 self.memFlags.append("Request::PREFETCH") 167 self.instFlags = ['IsDataPrefetch'] 168 elif self.flavor == "iprefetch": 169 self.memFlags.append("Request::PREFETCH") 170 self.instFlags = ['IsInstPrefetch'] 171 elif self.flavor == "exclusive": 172 self.memFlags.append("Request::LLSC") 173 elif self.flavor == "normal": 174 self.memFlags.append("ArmISA::TLB::AllowUnaligned") 175 176 # Disambiguate the class name for different flavors of loads 177 if self.flavor != "normal": 178 self.Name = "%s_%s" % (self.name.upper(), self.Name) 179 180 def emit(self): 181 # Address compuation code 182 eaCode = "EA = Base" 183 if not self.post: 184 eaCode += self.offset 185 eaCode += ";" 186 187 if self.flavor == "fp": 188 eaCode += vfpEnabledCheckCode 189 190 self.codeBlobs["ea_code"] = eaCode 191 192 # Code that actually handles the access 193 if self.flavor == "dprefetch" or self.flavor == "iprefetch": 194 accCode = 'uint64_t temp = Mem%s; temp = temp;' 195 elif self.flavor == "fp": 196 accCode = "FpDest.uw = cSwap(Mem%s, ((CPSR)Cpsr).e);\n" 197 else: 198 accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);" 199 accCode = accCode % buildMemSuffix(self.sign, self.size) 200 201 self.codeBlobs["memacc_code"] = accCode 202 203 # Push it out to the output files 204 base = buildMemBase(self.basePrefix, self.post, self.writeback) 205 wbDecl = None 206 if self.writeback: 207 wbDecl = self.wbDecl 208 self.emitHelper(base, wbDecl, self.instFlags) 209 210 def loadImmClassName(post, add, writeback, size=4, sign=False, user=False): 211 return memClassName("LOAD_IMM", post, add, writeback, size, sign, user) 212 213 class LoadImm(LoadImmInst, LoadSingle): 214 decConstBase = 'LoadImm' 215 basePrefix = 'MemoryImm' 216 nameFunc = staticmethod(loadImmClassName) 217 218 def loadRegClassName(post, add, writeback, size=4, sign=False, user=False): 219 return memClassName("LOAD_REG", post, add, writeback, size, sign, user) 220 221 class LoadReg(LoadRegInst, LoadSingle): 222 decConstBase = 'LoadReg' 223 basePrefix = 'MemoryReg' 224 nameFunc = staticmethod(loadRegClassName) 225 226 class LoadDouble(LoadInst): 227 def __init__(self, *args, **kargs): 228 super(LoadDouble, self).__init__(*args, **kargs) 229 230 # Build the default class name 231 self.Name = self.nameFunc(self.post, self.add, self.writeback) 232 233 # Add memory request flags where necessary 234 if self.flavor == "exclusive": 235 self.memFlags.append("Request::LLSC") 236 self.memFlags.append("ArmISA::TLB::AlignDoubleWord") 237 else: 238 self.memFlags.append("ArmISA::TLB::AlignWord") 239 240 # Disambiguate the class name for different flavors of loads 241 if self.flavor != "normal": 242 self.Name = "%s_%s" % (self.name.upper(), self.Name) 243 244 def emit(self): 245 # Address computation code 246 eaCode = "EA = Base" 247 if not self.post: 248 eaCode += self.offset 249 eaCode += ";" 250 251 if self.flavor == "fp": 252 eaCode += vfpEnabledCheckCode 253 254 self.codeBlobs["ea_code"] = eaCode 255 256 # Code that actually handles the access 257 if self.flavor != "fp": 258 accCode = ''' 259 CPSR cpsr = Cpsr; 260 Dest = cSwap<uint32_t>(Mem.ud, cpsr.e); 261 Dest2 = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e); 262 ''' 263 else: 264 accCode = ''' 265 uint64_t swappedMem = cSwap(Mem.ud, ((CPSR)Cpsr).e); 266 FpDest.uw = (uint32_t)swappedMem; 267 FpDest2.uw = (uint32_t)(swappedMem >> 32); 268 ''' 269 270 self.codeBlobs["memacc_code"] = accCode 271 272 # Push it out to the output files 273 base = buildMemBase(self.basePrefix, self.post, self.writeback) 274 wbDecl = None 275 if self.writeback: 276 wbDecl = self.wbDecl 277 self.emitHelper(base, wbDecl) 278 279 def loadDoubleImmClassName(post, add, writeback): 280 return memClassName("LOAD_IMMD", post, add, writeback, 4, False, False) 281 282 class LoadDoubleImm(LoadImmInst, LoadDouble): 283 decConstBase = 'LoadStoreDImm' 284 basePrefix = 'MemoryDImm' 285 nameFunc = staticmethod(loadDoubleImmClassName) 286 287 def loadDoubleRegClassName(post, add, writeback): 288 return memClassName("LOAD_REGD", post, add, writeback, 4, False, False) 289 290 class LoadDoubleReg(LoadRegInst, LoadDouble): 291 decConstBase = 'LoadDReg' 292 basePrefix = 'MemoryDReg' 293 nameFunc = staticmethod(loadDoubleRegClassName) 294 295 def buildLoads(mnem, size=4, sign=False, user=False): 296 LoadImm(mnem, True, True, True, size, sign, user).emit() 297 LoadReg(mnem, True, True, True, size, sign, user).emit() 298 LoadImm(mnem, True, False, True, size, sign, user).emit() 299 LoadReg(mnem, True, False, True, size, sign, user).emit() 300 LoadImm(mnem, False, True, True, size, sign, user).emit() 301 LoadReg(mnem, False, True, True, size, sign, user).emit() 302 LoadImm(mnem, False, False, True, size, sign, user).emit() 303 LoadReg(mnem, False, False, True, size, sign, user).emit() 304 LoadImm(mnem, False, True, False, size, sign, user).emit() 305 LoadReg(mnem, False, True, False, size, sign, user).emit() 306 LoadImm(mnem, False, False, False, size, sign, user).emit() 307 LoadReg(mnem, False, False, False, size, sign, user).emit() 308 309 def buildDoubleLoads(mnem): 310 LoadDoubleImm(mnem, True, True, True).emit() 311 LoadDoubleReg(mnem, True, True, True).emit() 312 LoadDoubleImm(mnem, True, False, True).emit() 313 LoadDoubleReg(mnem, True, False, True).emit() 314 LoadDoubleImm(mnem, False, True, True).emit() 315 LoadDoubleReg(mnem, False, True, True).emit() 316 LoadDoubleImm(mnem, False, False, True).emit() 317 LoadDoubleReg(mnem, False, False, True).emit() 318 LoadDoubleImm(mnem, False, True, False).emit() 319 LoadDoubleReg(mnem, False, True, False).emit() 320 LoadDoubleImm(mnem, False, False, False).emit() 321 LoadDoubleReg(mnem, False, False, False).emit() 322 323 def buildRfeLoads(mnem): 324 RfeInst(mnem, True, True, True).emit() 325 RfeInst(mnem, True, True, False).emit() 326 RfeInst(mnem, True, False, True).emit() 327 RfeInst(mnem, True, False, False).emit() 328 RfeInst(mnem, False, True, True).emit() 329 RfeInst(mnem, False, True, False).emit() 330 RfeInst(mnem, False, False, True).emit() 331 RfeInst(mnem, False, False, False).emit() 332 333 def buildPrefetches(mnem, type): 334 LoadReg(mnem, False, False, False, size=1, flavor=type).emit() 335 LoadImm(mnem, False, False, False, size=1, flavor=type).emit() 336 LoadReg(mnem, False, True, False, size=1, flavor=type).emit() 337 LoadImm(mnem, False, True, False, size=1, flavor=type).emit() 338 339 buildLoads("ldr") 340 buildLoads("ldrt", user=True) 341 buildLoads("ldrb", size=1) 342 buildLoads("ldrbt", size=1, user=True) 343 buildLoads("ldrsb", size=1, sign=True) 344 buildLoads("ldrsbt", size=1, sign=True, user=True) 345 buildLoads("ldrh", size=2) 346 buildLoads("ldrht", size=2, user=True) 347 buildLoads("hdrsh", size=2, sign=True) 348 buildLoads("ldrsht", size=2, sign=True, user=True) 349 350 buildDoubleLoads("ldrd") 351 352 buildRfeLoads("rfe") 353 354 buildPrefetches("pld", "dprefetch") 355 buildPrefetches("pldw", "dprefetch") 356 buildPrefetches("pli", "iprefetch") 357 358 LoadImm("ldrex", False, True, False, size=4, flavor="exclusive").emit() 359 LoadImm("ldrexh", False, True, False, size=2, flavor="exclusive").emit() 360 LoadImm("ldrexb", False, True, False, size=1, flavor="exclusive").emit() 361 LoadDoubleImm("ldrexd", False, True, False, flavor="exclusive").emit() 362 363 LoadImm("vldr", False, True, False, size=4, flavor="fp").emit() 364 LoadImm("vldr", False, False, False, size=4, flavor="fp").emit() 365 LoadDoubleImm("vldr", False, True, False, flavor="fp").emit() 366 LoadDoubleImm("vldr", False, False, False, flavor="fp").emit() 367}}; 368