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