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