ldr.isa revision 8588
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 self.rasPop = False 62 63 if self.add: 64 self.op = " +" 65 else: 66 self.op = " -" 67 68 self.memFlags = ["ArmISA::TLB::MustBeOne"] 69 self.codeBlobs = {"postacc_code" : ""} 70 71 def emitHelper(self, base = 'Memory', wbDecl = None, instFlags = [], pcDecl = None): 72 73 global header_output, decoder_output, exec_output 74 75 codeBlobs = self.codeBlobs 76 codeBlobs["predicate_test"] = pickPredicate(codeBlobs) 77 (newHeader, 78 newDecoder, 79 newExec) = self.fillTemplates(self.name, self.Name, codeBlobs, 80 self.memFlags, instFlags, base, 81 wbDecl, pcDecl, self.rasPop) 82 83 header_output += newHeader 84 decoder_output += newDecoder 85 exec_output += newExec 86 87 class RfeInst(LoadInst): 88 decConstBase = 'Rfe' 89 90 def __init__(self, mnem, post, add, writeback): 91 super(RfeInst, self).__init__(mnem, post, add, writeback) 92 self.Name = "RFE_" + loadImmClassName(post, add, writeback, 8) 93 94 self.memFlags.append("ArmISA::TLB::AlignWord") 95 96 def emit(self): 97 offset = 0 98 if self.post != self.add: 99 offset += 4 100 if not self.add: 101 offset -= 8 102 self.codeBlobs["ea_code"] = "EA = Base + %d;" % offset 103 104 wbDiff = -8 105 if self.add: 106 wbDiff = 8 107 accCode = ''' 108 CPSR cpsr = Cpsr; 109 cpsr.nz = CondCodesNZ; 110 cpsr.c = CondCodesC; 111 cpsr.v = CondCodesV; 112 cpsr.ge = CondCodesGE; 113 URc = cpsr; 114 URa = cSwap<uint32_t>(Mem_ud, cpsr.e); 115 URb = cSwap<uint32_t>(Mem_ud >> 32, cpsr.e); 116 ''' 117 self.codeBlobs["memacc_code"] = accCode 118 119 wbDecl = None 120 pcDecl = "MicroUopSetPCCPSR(machInst, INTREG_UREG0, INTREG_UREG1, INTREG_UREG2);" 121 122 if self.writeback: 123 wbDecl = "MicroAddiUop(machInst, base, base, %d);" % wbDiff 124 self.emitHelper('RfeOp', wbDecl, ["IsSerializeAfter", "IsNonSpeculative"], pcDecl) 125 126 class LoadImmInst(LoadInst): 127 def __init__(self, *args, **kargs): 128 super(LoadImmInst, self).__init__(*args, **kargs) 129 self.offset = self.op + " imm" 130 131 if self.add: 132 self.wbDecl = "MicroAddiUop(machInst, base, base, imm);" 133 else: 134 self.wbDecl = "MicroSubiUop(machInst, base, base, imm);" 135 136 if self.add and self.post and self.writeback and not self.sign and \ 137 not self.user and self.size == 4: 138 self.rasPop = True 139 140 class LoadRegInst(LoadInst): 141 def __init__(self, *args, **kargs): 142 super(LoadRegInst, self).__init__(*args, **kargs) 143 self.offset = self.op + " shift_rm_imm(Index, shiftAmt," + \ 144 " shiftType, OptShiftRmCondCodesC)" 145 if self.add: 146 self.wbDecl = ''' 147 MicroAddUop(machInst, base, base, wbIndexReg, shiftAmt, shiftType); 148 ''' 149 else: 150 self.wbDecl = ''' 151 MicroSubUop(machInst, base, base, wbIndexReg, shiftAmt, shiftType); 152 ''' 153 154 class LoadSingle(LoadInst): 155 def __init__(self, *args, **kargs): 156 super(LoadSingle, self).__init__(*args, **kargs) 157 158 # Build the default class name 159 self.Name = self.nameFunc(self.post, self.add, self.writeback, 160 self.size, self.sign, self.user) 161 162 # Add memory request flags where necessary 163 self.memFlags.append("%d" % (self.size - 1)) 164 if self.user: 165 self.memFlags.append("ArmISA::TLB::UserMode") 166 167 self.instFlags = [] 168 if self.flavor == "dprefetch": 169 self.memFlags.append("Request::PREFETCH") 170 self.instFlags = ['IsDataPrefetch'] 171 elif self.flavor == "iprefetch": 172 self.memFlags.append("Request::PREFETCH") 173 self.instFlags = ['IsInstPrefetch'] 174 elif self.flavor == "exclusive": 175 self.memFlags.append("Request::LLSC") 176 elif self.flavor == "normal": 177 self.memFlags.append("ArmISA::TLB::AllowUnaligned") 178 179 # Disambiguate the class name for different flavors of loads 180 if self.flavor != "normal": 181 self.Name = "%s_%s" % (self.name.upper(), self.Name) 182 183 def emit(self): 184 # Address compuation code 185 eaCode = "EA = Base" 186 if not self.post: 187 eaCode += self.offset 188 eaCode += ";" 189 190 if self.flavor == "fp": 191 eaCode += vfpEnabledCheckCode 192 193 self.codeBlobs["ea_code"] = eaCode 194 195 # Code that actually handles the access 196 if self.flavor == "dprefetch" or self.flavor == "iprefetch": 197 accCode = 'uint64_t temp = Mem%s; temp = temp;' 198 elif self.flavor == "fp": 199 accCode = "FpDest_uw = cSwap(Mem%s, ((CPSR)Cpsr).e);\n" 200 else: 201 accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);" 202 accCode = accCode % buildMemSuffix(self.sign, self.size) 203 204 self.codeBlobs["memacc_code"] = accCode 205 206 # Push it out to the output files 207 base = buildMemBase(self.basePrefix, self.post, self.writeback) 208 wbDecl = None 209 if self.writeback: 210 wbDecl = self.wbDecl 211 self.emitHelper(base, wbDecl, self.instFlags) 212 213 def loadImmClassName(post, add, writeback, size=4, sign=False, user=False): 214 return memClassName("LOAD_IMM", post, add, writeback, size, sign, user) 215 216 class LoadImm(LoadImmInst, LoadSingle): 217 decConstBase = 'LoadImm' 218 basePrefix = 'MemoryImm' 219 nameFunc = staticmethod(loadImmClassName) 220 221 def loadRegClassName(post, add, writeback, size=4, sign=False, user=False): 222 return memClassName("LOAD_REG", post, add, writeback, size, sign, user) 223 224 class LoadReg(LoadRegInst, LoadSingle): 225 decConstBase = 'LoadReg' 226 basePrefix = 'MemoryReg' 227 nameFunc = staticmethod(loadRegClassName) 228 229 class LoadDouble(LoadInst): 230 def __init__(self, *args, **kargs): 231 super(LoadDouble, self).__init__(*args, **kargs) 232 233 # Build the default class name 234 self.Name = self.nameFunc(self.post, self.add, self.writeback) 235 236 # Add memory request flags where necessary 237 if self.flavor == "exclusive": 238 self.memFlags.append("Request::LLSC") 239 self.memFlags.append("ArmISA::TLB::AlignDoubleWord") 240 else: 241 self.memFlags.append("ArmISA::TLB::AlignWord") 242 243 # Disambiguate the class name for different flavors of loads 244 if self.flavor != "normal": 245 self.Name = "%s_%s" % (self.name.upper(), self.Name) 246 247 def emit(self): 248 # Address computation code 249 eaCode = "EA = Base" 250 if not self.post: 251 eaCode += self.offset 252 eaCode += ";" 253 254 if self.flavor == "fp": 255 eaCode += vfpEnabledCheckCode 256 257 self.codeBlobs["ea_code"] = eaCode 258 259 # Code that actually handles the access 260 if self.flavor != "fp": 261 accCode = ''' 262 CPSR cpsr = Cpsr; 263 Dest = cSwap<uint32_t>(Mem_ud, cpsr.e); 264 Dest2 = cSwap<uint32_t>(Mem_ud >> 32, cpsr.e); 265 ''' 266 else: 267 accCode = ''' 268 uint64_t swappedMem = cSwap(Mem_ud, ((CPSR)Cpsr).e); 269 FpDest_uw = (uint32_t)swappedMem; 270 FpDest2_uw = (uint32_t)(swappedMem >> 32); 271 ''' 272 273 self.codeBlobs["memacc_code"] = accCode 274 275 # Push it out to the output files 276 base = buildMemBase(self.basePrefix, self.post, self.writeback) 277 wbDecl = None 278 if self.writeback: 279 wbDecl = self.wbDecl 280 self.emitHelper(base, wbDecl) 281 282 def loadDoubleImmClassName(post, add, writeback): 283 return memClassName("LOAD_IMMD", post, add, writeback, 4, False, False) 284 285 class LoadDoubleImm(LoadImmInst, LoadDouble): 286 decConstBase = 'LoadStoreDImm' 287 basePrefix = 'MemoryDImm' 288 nameFunc = staticmethod(loadDoubleImmClassName) 289 290 def loadDoubleRegClassName(post, add, writeback): 291 return memClassName("LOAD_REGD", post, add, writeback, 4, False, False) 292 293 class LoadDoubleReg(LoadRegInst, LoadDouble): 294 decConstBase = 'LoadDReg' 295 basePrefix = 'MemoryDReg' 296 nameFunc = staticmethod(loadDoubleRegClassName) 297 298 def buildLoads(mnem, size=4, sign=False, user=False): 299 LoadImm(mnem, True, True, True, size, sign, user).emit() 300 LoadReg(mnem, True, True, True, size, sign, user).emit() 301 LoadImm(mnem, True, False, True, size, sign, user).emit() 302 LoadReg(mnem, True, False, True, size, sign, user).emit() 303 LoadImm(mnem, False, True, True, size, sign, user).emit() 304 LoadReg(mnem, False, True, True, size, sign, user).emit() 305 LoadImm(mnem, False, False, True, size, sign, user).emit() 306 LoadReg(mnem, False, False, True, size, sign, user).emit() 307 LoadImm(mnem, False, True, False, size, sign, user).emit() 308 LoadReg(mnem, False, True, False, size, sign, user).emit() 309 LoadImm(mnem, False, False, False, size, sign, user).emit() 310 LoadReg(mnem, False, False, False, size, sign, user).emit() 311 312 def buildDoubleLoads(mnem): 313 LoadDoubleImm(mnem, True, True, True).emit() 314 LoadDoubleReg(mnem, True, True, True).emit() 315 LoadDoubleImm(mnem, True, False, True).emit() 316 LoadDoubleReg(mnem, True, False, True).emit() 317 LoadDoubleImm(mnem, False, True, True).emit() 318 LoadDoubleReg(mnem, False, True, True).emit() 319 LoadDoubleImm(mnem, False, False, True).emit() 320 LoadDoubleReg(mnem, False, False, True).emit() 321 LoadDoubleImm(mnem, False, True, False).emit() 322 LoadDoubleReg(mnem, False, True, False).emit() 323 LoadDoubleImm(mnem, False, False, False).emit() 324 LoadDoubleReg(mnem, False, False, False).emit() 325 326 def buildRfeLoads(mnem): 327 RfeInst(mnem, True, True, True).emit() 328 RfeInst(mnem, True, True, False).emit() 329 RfeInst(mnem, True, False, True).emit() 330 RfeInst(mnem, True, False, False).emit() 331 RfeInst(mnem, False, True, True).emit() 332 RfeInst(mnem, False, True, False).emit() 333 RfeInst(mnem, False, False, True).emit() 334 RfeInst(mnem, False, False, False).emit() 335 336 def buildPrefetches(mnem, type): 337 LoadReg(mnem, False, False, False, size=1, flavor=type).emit() 338 LoadImm(mnem, False, False, False, size=1, flavor=type).emit() 339 LoadReg(mnem, False, True, False, size=1, flavor=type).emit() 340 LoadImm(mnem, False, True, False, size=1, flavor=type).emit() 341 342 buildLoads("ldr") 343 buildLoads("ldrt", user=True) 344 buildLoads("ldrb", size=1) 345 buildLoads("ldrbt", size=1, user=True) 346 buildLoads("ldrsb", size=1, sign=True) 347 buildLoads("ldrsbt", size=1, sign=True, user=True) 348 buildLoads("ldrh", size=2) 349 buildLoads("ldrht", size=2, user=True) 350 buildLoads("hdrsh", size=2, sign=True) 351 buildLoads("ldrsht", size=2, sign=True, user=True) 352 353 buildDoubleLoads("ldrd") 354 355 buildRfeLoads("rfe") 356 357 buildPrefetches("pld", "dprefetch") 358 buildPrefetches("pldw", "dprefetch") 359 buildPrefetches("pli", "iprefetch") 360 361 LoadImm("ldrex", False, True, False, size=4, flavor="exclusive").emit() 362 LoadImm("ldrexh", False, True, False, size=2, flavor="exclusive").emit() 363 LoadImm("ldrexb", False, True, False, size=1, flavor="exclusive").emit() 364 LoadDoubleImm("ldrexd", False, True, False, flavor="exclusive").emit() 365 366 LoadImm("vldr", False, True, False, size=4, flavor="fp").emit() 367 LoadImm("vldr", False, False, False, size=4, flavor="fp").emit() 368 LoadDoubleImm("vldr", False, True, False, flavor="fp").emit() 369 LoadDoubleImm("vldr", False, False, False, flavor="fp").emit() 370}}; 371