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