3 // Copyright (c) 2010-2011,2019 ARM Limited
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.
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.
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.
45 class LoadInst(LoadStoreInst):
48 def __init__(self, mnem, post, add, writeback,
49 size=4, sign=False, user=False, flavor="normal"):
50 super(LoadInst, self).__init__()
55 self.writeback = writeback
67 self.memFlags = ["ArmISA::TLB::MustBeOne"]
68 self.codeBlobs = {"postacc_code" : ""}
70 def emitHelper(self, base = 'Memory', wbDecl = None, instFlags = [], pcDecl = None):
72 global header_output, decoder_output, exec_output
74 codeBlobs = self.codeBlobs
75 codeBlobs["predicate_test"] = pickPredicate(codeBlobs)
78 newExec) = self.fillTemplates(self.name, self.Name, codeBlobs,
79 self.memFlags, instFlags, base,
80 wbDecl, pcDecl, self.rasPop,
83 header_output += newHeader
84 decoder_output += newDecoder
85 exec_output += newExec
87 class RfeInst(LoadInst):
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)
94 self.memFlags.append("ArmISA::TLB::AlignWord")
98 if self.post != self.add:
102 self.codeBlobs["ea_code"] = "EA = Base + %d;" % offset
109 cpsr.nz = CondCodesNZ;
112 cpsr.ge = CondCodesGE;
114 URa = cSwap<uint32_t>(Mem_ud, cpsr.e);
115 URb = cSwap<uint32_t>(Mem_ud >> 32, cpsr.e);
117 self.codeBlobs["memacc_code"] = accCode
120 pcDecl = "MicroUopSetPCCPSR(machInst, INTREG_UREG0, INTREG_UREG1, INTREG_UREG2);"
123 wbDecl = "MicroAddiUop(machInst, base, base, %d);" % wbDiff
124 self.emitHelper('RfeOp', wbDecl, ["IsSerializeAfter", "IsNonSpeculative"], pcDecl)
126 class LoadImmInst(LoadInst):
127 def __init__(self, *args, **kargs):
128 super(LoadImmInst, self).__init__(*args, **kargs)
129 self.offset = self.op + " imm"
132 self.wbDecl = "MicroAddiUop(machInst, base, base, imm);"
134 self.wbDecl = "MicroSubiUop(machInst, base, base, imm);"
136 if self.add and self.post and self.writeback and not self.sign and \
137 not self.user and self.size == 4:
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)"
147 MicroAddUop(machInst, base, base, wbIndexReg, shiftAmt, shiftType);
151 MicroSubUop(machInst, base, base, wbIndexReg, shiftAmt, shiftType);
154 class LoadSingle(LoadInst):
155 def __init__(self, *args, **kargs):
156 super(LoadSingle, self).__init__(*args, **kargs)
158 # Build the default class name
159 self.Name = self.nameFunc(self.post, self.add, self.writeback,
160 self.size, self.sign, self.user)
162 # Add memory request flags where necessary
163 self.memFlags.append("%d" % int(math.log(self.size, 2)))
165 self.memFlags.append("ArmISA::TLB::UserMode")
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 == "normal":
175 self.memFlags.append("ArmISA::TLB::AllowUnaligned")
177 if self.flavor in ("exclusive", "acex"):
178 self.memFlags.append("Request::LLSC")
180 if self.flavor in ("acquire", "acex"):
181 self.instFlags.extend(["IsMemBarrier",
185 # Disambiguate the class name for different flavors of loads
186 if self.flavor != "normal":
187 self.Name = "%s_%s" % (self.name.upper(), self.Name)
190 # Address compuation code
193 eaCode += self.offset
196 if self.flavor == "fp":
197 eaCode += vfpEnabledCheckCode
199 self.codeBlobs["ea_code"] = eaCode
201 # Code that actually handles the access
202 if self.flavor == "dprefetch" or self.flavor == "iprefetch":
203 accCode = 'uint64_t temp = Mem%s; temp = temp;'
204 elif self.flavor == "fp":
205 accCode = "FpDest_uw = cSwap(Mem%s, ((CPSR)Cpsr).e);\n"
207 accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);"
208 accCode = accCode % buildMemSuffix(self.sign, self.size)
210 self.codeBlobs["memacc_code"] = accCode
212 # Push it out to the output files
213 base = buildMemBase(self.basePrefix, self.post, self.writeback)
217 self.emitHelper(base, wbDecl, self.instFlags)
219 def loadImmClassName(post, add, writeback, size=4, sign=False, user=False):
220 return memClassName("LOAD_IMM", post, add, writeback, size, sign, user)
222 class LoadImm(LoadImmInst, LoadSingle):
223 decConstBase = 'LoadImm'
224 basePrefix = 'MemoryImm'
225 nameFunc = staticmethod(loadImmClassName)
227 def loadRegClassName(post, add, writeback, size=4, sign=False, user=False):
228 return memClassName("LOAD_REG", post, add, writeback, size, sign, user)
230 class LoadReg(LoadRegInst, LoadSingle):
231 decConstBase = 'LoadReg'
232 basePrefix = 'MemoryReg'
233 nameFunc = staticmethod(loadRegClassName)
235 class LoadDouble(LoadInst):
236 def __init__(self, *args, **kargs):
237 super(LoadDouble, self).__init__(*args, **kargs)
239 # Build the default class name
240 self.Name = self.nameFunc(self.post, self.add, self.writeback)
243 # Add memory request flags where necessary
244 if self.flavor in ("exclusive", "acex"):
245 self.memFlags.append("Request::LLSC")
246 self.memFlags.append("ArmISA::TLB::AlignDoubleWord")
248 self.memFlags.append("ArmISA::TLB::AlignWord")
250 # Disambiguate the class name for different flavors of loads
251 if self.flavor != "normal":
252 self.Name = "%s_%s" % (self.name.upper(), self.Name)
254 if self.flavor in ("acquire", "acex"):
255 self.instFlags.extend(["IsMemBarrier",
260 # Address computation code
263 eaCode += self.offset
266 if self.flavor == "fp":
267 eaCode += vfpEnabledCheckCode
269 self.codeBlobs["ea_code"] = eaCode
271 # Code that actually handles the access
272 if self.flavor != "fp":
275 Dest = cSwap<uint32_t>(Mem_ud, cpsr.e);
276 Dest2 = cSwap<uint32_t>(Mem_ud >> 32, cpsr.e);
280 uint64_t swappedMem = cSwap(Mem_ud, ((CPSR)Cpsr).e);
281 FpDest_uw = (uint32_t)swappedMem;
282 FpDest2_uw = (uint32_t)(swappedMem >> 32);
285 self.codeBlobs["memacc_code"] = accCode
287 # Push it out to the output files
288 base = buildMemBase(self.basePrefix, self.post, self.writeback)
292 self.emitHelper(base, wbDecl, self.instFlags)
294 def loadDoubleImmClassName(post, add, writeback):
295 return memClassName("LOAD_IMMD", post, add, writeback, 4, False, False)
297 class LoadDoubleImm(LoadImmInst, LoadDouble):
298 decConstBase = 'LoadStoreDImm'
299 basePrefix = 'MemoryDImm'
300 nameFunc = staticmethod(loadDoubleImmClassName)
302 def loadDoubleRegClassName(post, add, writeback):
303 return memClassName("LOAD_REGD", post, add, writeback, 4, False, False)
305 class LoadDoubleReg(LoadRegInst, LoadDouble):
306 decConstBase = 'LoadDReg'
307 basePrefix = 'MemoryDReg'
308 nameFunc = staticmethod(loadDoubleRegClassName)
310 def buildLoads(mnem, size=4, sign=False, user=False):
311 LoadImm(mnem, True, True, True, size, sign, user).emit()
312 LoadReg(mnem, True, True, True, size, sign, user).emit()
313 LoadImm(mnem, True, False, True, size, sign, user).emit()
314 LoadReg(mnem, True, False, True, size, sign, user).emit()
315 LoadImm(mnem, False, True, True, size, sign, user).emit()
316 LoadReg(mnem, False, True, True, size, sign, user).emit()
317 LoadImm(mnem, False, False, True, size, sign, user).emit()
318 LoadReg(mnem, False, False, True, size, sign, user).emit()
319 LoadImm(mnem, False, True, False, size, sign, user).emit()
320 LoadReg(mnem, False, True, False, size, sign, user).emit()
321 LoadImm(mnem, False, False, False, size, sign, user).emit()
322 LoadReg(mnem, False, False, False, size, sign, user).emit()
324 def buildDoubleLoads(mnem):
325 LoadDoubleImm(mnem, True, True, True).emit()
326 LoadDoubleReg(mnem, True, True, True).emit()
327 LoadDoubleImm(mnem, True, False, True).emit()
328 LoadDoubleReg(mnem, True, False, True).emit()
329 LoadDoubleImm(mnem, False, True, True).emit()
330 LoadDoubleReg(mnem, False, True, True).emit()
331 LoadDoubleImm(mnem, False, False, True).emit()
332 LoadDoubleReg(mnem, False, False, True).emit()
333 LoadDoubleImm(mnem, False, True, False).emit()
334 LoadDoubleReg(mnem, False, True, False).emit()
335 LoadDoubleImm(mnem, False, False, False).emit()
336 LoadDoubleReg(mnem, False, False, False).emit()
338 def buildRfeLoads(mnem):
339 RfeInst(mnem, True, True, True).emit()
340 RfeInst(mnem, True, True, False).emit()
341 RfeInst(mnem, True, False, True).emit()
342 RfeInst(mnem, True, False, False).emit()
343 RfeInst(mnem, False, True, True).emit()
344 RfeInst(mnem, False, True, False).emit()
345 RfeInst(mnem, False, False, True).emit()
346 RfeInst(mnem, False, False, False).emit()
348 def buildPrefetches(mnem, type):
349 LoadReg(mnem, False, False, False, size=1, flavor=type).emit()
350 LoadImm(mnem, False, False, False, size=1, flavor=type).emit()
351 LoadReg(mnem, False, True, False, size=1, flavor=type).emit()
352 LoadImm(mnem, False, True, False, size=1, flavor=type).emit()
355 buildLoads("ldrt", user=True)
356 buildLoads("ldrb", size=1)
357 buildLoads("ldrbt", size=1, user=True)
358 buildLoads("ldrsb", size=1, sign=True)
359 buildLoads("ldrsbt", size=1, sign=True, user=True)
360 buildLoads("ldrh", size=2)
361 buildLoads("ldrht", size=2, user=True)
362 buildLoads("ldrsh", size=2, sign=True)
363 buildLoads("ldrsht", size=2, sign=True, user=True)
365 buildDoubleLoads("ldrd")
369 buildPrefetches("pld", "dprefetch")
370 buildPrefetches("pldw", "dprefetch")
371 buildPrefetches("pli", "iprefetch")
373 LoadImm("ldrex", False, True, False, size=4, flavor="exclusive").emit()
374 LoadImm("ldrexh", False, True, False, size=2, flavor="exclusive").emit()
375 LoadImm("ldrexb", False, True, False, size=1, flavor="exclusive").emit()
376 LoadDoubleImm("ldrexd", False, True, False, flavor="exclusive").emit()
378 LoadImm("lda", False, True, False, size=4, flavor="acquire").emit()
379 LoadImm("ldah", False, True, False, size=2, flavor="acquire").emit()
380 LoadImm("ldab", False, True, False, size=1, flavor="acquire").emit()
381 LoadImm("ldaex", False, True, False, size=4, flavor="acex").emit()
382 LoadImm("ldaexh", False, True, False, size=2, flavor="acex").emit()
383 LoadImm("ldaexb", False, True, False, size=1, flavor="acex").emit()
384 LoadDoubleImm("ldaexd", False, True, False, flavor="acex").emit()
386 LoadImm("vldr", False, True, False, size=4, flavor="fp").emit()
387 LoadImm("vldr", False, False, False, size=4, flavor="fp").emit()
388 LoadDoubleImm("vldr", False, True, False, flavor="fp").emit()
389 LoadDoubleImm("vldr", False, False, False, flavor="fp").emit()