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 StoreInst(LoadStoreInst):
47 execBase = 'Store'
48
49 def __init__(self, mnem, post, add, writeback, size=4,
50 sign=False, user=False, flavor="normal",
51 instFlags = []):
52 super(StoreInst, 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.instFlags = instFlags
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):
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, self.instFlags, base, wbDecl)
81
82 header_output += newHeader
83 decoder_output += newDecoder
84 exec_output += newExec
85
86 class SrsInst(LoadStoreInst):
87 execBase = 'Store'
88 decConstBase = 'Srs'
89
90 def __init__(self, mnem, post, add, writeback):
91 super(SrsInst, self).__init__()
92 self.name = mnem
93 self.post = post
94 self.add = add
95 self.writeback = writeback
96
97 self.Name = "SRS_" + storeImmClassName(post, add, writeback, 8)
98
99 def emit(self):
100 offset = 0
101 if self.post != self.add:
102 offset += 4
103 if not self.add:
104 offset -= 8
105
106 eaCode = "EA = SpMode + %d;" % offset
107
108 wbDiff = -8
109 if self.add:
110 wbDiff = 8
111 accCode = '''
112 CPSR cpsr = Cpsr;
113 Mem.ud = (uint64_t)cSwap(LR.uw, cpsr.e) |
114 ((uint64_t)cSwap(Spsr.uw, cpsr.e) << 32);
113 Mem_ud = (uint64_t)cSwap(LR_uw, cpsr.e) |
114 ((uint64_t)cSwap(Spsr_uw, cpsr.e) << 32);
115 '''
116
117 global header_output, decoder_output, exec_output
118
119 codeBlobs = { "ea_code": eaCode,
120 "memacc_code": accCode,
121 "postacc_code": "" }
122 codeBlobs["predicate_test"] = pickPredicate(codeBlobs)
123
124 wbDecl = None
125 if self.writeback:
126 wbDecl = '''MicroAddiUop(machInst,
127 intRegInMode((OperatingMode)regMode, INTREG_SP),
128 intRegInMode((OperatingMode)regMode, INTREG_SP),
129 %d);''' % wbDiff
130
131 (newHeader,
132 newDecoder,
133 newExec) = self.fillTemplates(self.name, self.Name, codeBlobs,
134 ["ArmISA::TLB::AlignWord", "ArmISA::TLB::MustBeOne"], [],
135 'SrsOp', wbDecl)
136
137 header_output += newHeader
138 decoder_output += newDecoder
139 exec_output += newExec
140
141 class StoreImmInst(StoreInst):
142 def __init__(self, *args, **kargs):
143 super(StoreImmInst, self).__init__(*args, **kargs)
144 self.offset = self.op + " imm"
145
146 if self.add:
147 self.wbDecl = "MicroAddiUop(machInst, base, base, imm);"
148 else:
149 self.wbDecl = "MicroSubiUop(machInst, base, base, imm);"
150
151 class StoreRegInst(StoreInst):
152 def __init__(self, *args, **kargs):
153 super(StoreRegInst, self).__init__(*args, **kargs)
154 self.offset = self.op + " shift_rm_imm(Index, shiftAmt," + \
155 " shiftType, OptShiftRmCondCodesC)"
156 if self.add:
157 self.wbDecl = '''
158 MicroAddUop(machInst, base, base, index, shiftAmt, shiftType);
159 '''
160 else:
161 self.wbDecl = '''
162 MicroSubUop(machInst, base, base, index, shiftAmt, shiftType);
163 '''
164
165 class StoreSingle(StoreInst):
166 def __init__(self, *args, **kargs):
167 super(StoreSingle, self).__init__(*args, **kargs)
168
169 # Build the default class name
170 self.Name = self.nameFunc(self.post, self.add, self.writeback,
171 self.size, self.sign, self.user)
172
173 # Add memory request flags where necessary
174 self.memFlags.append("%d" % (self.size - 1))
175 if self.user:
176 self.memFlags.append("ArmISA::TLB::UserMode")
177
178 if self.flavor == "exclusive":
179 self.memFlags.append("Request::LLSC")
180 elif self.flavor != "fp":
181 self.memFlags.append("ArmISA::TLB::AllowUnaligned")
182
183 # Disambiguate the class name for different flavors of stores
184 if self.flavor != "normal":
185 self.Name = "%s_%s" % (self.name.upper(), self.Name)
186
187 def emit(self):
188 # Address computation
189 eaCode = "EA = Base"
190 if not self.post:
191 eaCode += self.offset
192 eaCode += ";"
193
194 if self.flavor == "fp":
195 eaCode += vfpEnabledCheckCode
196
197 self.codeBlobs["ea_code"] = eaCode
198
199 # Code that actually handles the access
200 if self.flavor == "fp":
201 accCode = 'Mem%(suffix)s = cSwap(FpDest.uw, ((CPSR)Cpsr).e);'
201 accCode = 'Mem%(suffix)s = cSwap(FpDest_uw, ((CPSR)Cpsr).e);'
202 else:
203 accCode = \
204 'Mem%(suffix)s = cSwap(Dest%(suffix)s, ((CPSR)Cpsr).e);'
205 accCode = accCode % \
206 { "suffix" : buildMemSuffix(self.sign, self.size) }
207
208 self.codeBlobs["memacc_code"] = accCode
209
210 # Push it out to the output files
211 base = buildMemBase(self.basePrefix, self.post, self.writeback)
212 wbDecl = None
213 if self.writeback:
214 wbDecl = self.wbDecl
215 self.emitHelper(base, wbDecl)
216
217 def storeImmClassName(post, add, writeback, size=4, sign=False, user=False):
218 return memClassName("STORE_IMM", post, add, writeback, size, sign, user)
219
220 class StoreImmEx(StoreImmInst, StoreSingle):
221 execBase = 'StoreEx'
222 decConstBase = 'StoreExImm'
223 basePrefix = 'MemoryExImm'
224 nameFunc = staticmethod(storeImmClassName)
225
226 def __init__(self, *args, **kargs):
227 super(StoreImmEx, self).__init__(*args, **kargs)
228 self.codeBlobs["postacc_code"] = "Result = !writeResult;"
229
230 class StoreImm(StoreImmInst, StoreSingle):
231 decConstBase = 'LoadStoreImm'
232 basePrefix = 'MemoryImm'
233 nameFunc = staticmethod(storeImmClassName)
234
235 def storeRegClassName(post, add, writeback, size=4, sign=False, user=False):
236 return memClassName("STORE_REG", post, add, writeback, size, sign, user)
237
238 class StoreReg(StoreRegInst, StoreSingle):
239 decConstBase = 'StoreReg'
240 basePrefix = 'MemoryReg'
241 nameFunc = staticmethod(storeRegClassName)
242
243 class StoreDouble(StoreInst):
244 def __init__(self, *args, **kargs):
245 super(StoreDouble, self).__init__(*args, **kargs)
246
247 # Build the default class name
248 self.Name = self.nameFunc(self.post, self.add, self.writeback)
249
250 # Add memory request flags where necessary
251 if self.flavor == "exclusive":
252 self.memFlags.append("Request::LLSC")
253 self.memFlags.append("ArmISA::TLB::AlignDoubleWord")
254 else:
255 self.memFlags.append("ArmISA::TLB::AlignWord")
256
257 # Disambiguate the class name for different flavors of stores
258 if self.flavor != "normal":
259 self.Name = "%s_%s" % (self.name.upper(), self.Name)
260
261 def emit(self):
262 # Address computation code
263 eaCode = "EA = Base"
264 if not self.post:
265 eaCode += self.offset
266 eaCode += ";"
267
268 if self.flavor == "fp":
269 eaCode += vfpEnabledCheckCode
270
271 self.codeBlobs["ea_code"] = eaCode
272
273 # Code that actually handles the access
274 if self.flavor == "fp":
275 accCode = '''
276 uint64_t swappedMem = (uint64_t)FpDest.uw |
277 ((uint64_t)FpDest2.uw << 32);
278 Mem.ud = cSwap(swappedMem, ((CPSR)Cpsr).e);
276 uint64_t swappedMem = (uint64_t)FpDest_uw |
277 ((uint64_t)FpDest2_uw << 32);
278 Mem_ud = cSwap(swappedMem, ((CPSR)Cpsr).e);
279 '''
280 else:
281 accCode = '''
282 CPSR cpsr = Cpsr;
283 Mem.ud = (uint64_t)cSwap(Dest.uw, cpsr.e) |
284 ((uint64_t)cSwap(Dest2.uw, cpsr.e) << 32);
283 Mem_ud = (uint64_t)cSwap(Dest_uw, cpsr.e) |
284 ((uint64_t)cSwap(Dest2_uw, cpsr.e) << 32);
285 '''
286
287 self.codeBlobs["memacc_code"] = accCode
288
289 # Push it out to the output files
290 base = buildMemBase(self.basePrefix, self.post, self.writeback)
291 wbDecl = None
292 if self.writeback:
293 wbDecl = self.wbDecl
294 self.emitHelper(base, wbDecl)
295
296 def storeDoubleImmClassName(post, add, writeback):
297 return memClassName("STORE_IMMD", post, add, writeback, 4, False, False)
298
299 class StoreDoubleImmEx(StoreImmInst, StoreDouble):
300 execBase = 'StoreEx'
301 decConstBase = 'StoreExDImm'
302 basePrefix = 'MemoryExDImm'
303 nameFunc = staticmethod(storeDoubleImmClassName)
304
305 def __init__(self, *args, **kargs):
306 super(StoreDoubleImmEx, self).__init__(*args, **kargs)
307 self.codeBlobs["postacc_code"] = "Result = !writeResult;"
308
309 class StoreDoubleImm(StoreImmInst, StoreDouble):
310 decConstBase = 'LoadStoreDImm'
311 basePrefix = 'MemoryDImm'
312 nameFunc = staticmethod(storeDoubleImmClassName)
313
314 def storeDoubleRegClassName(post, add, writeback):
315 return memClassName("STORE_REGD", post, add, writeback, 4, False, False)
316
317 class StoreDoubleReg(StoreRegInst, StoreDouble):
318 decConstBase = 'StoreDReg'
319 basePrefix = 'MemoryDReg'
320 nameFunc = staticmethod(storeDoubleRegClassName)
321
322 def buildStores(mnem, size=4, sign=False, user=False):
323 StoreImm(mnem, True, True, True, size, sign, user).emit()
324 StoreReg(mnem, True, True, True, size, sign, user).emit()
325 StoreImm(mnem, True, False, True, size, sign, user).emit()
326 StoreReg(mnem, True, False, True, size, sign, user).emit()
327 StoreImm(mnem, False, True, True, size, sign, user).emit()
328 StoreReg(mnem, False, True, True, size, sign, user).emit()
329 StoreImm(mnem, False, False, True, size, sign, user).emit()
330 StoreReg(mnem, False, False, True, size, sign, user).emit()
331 StoreImm(mnem, False, True, False, size, sign, user).emit()
332 StoreReg(mnem, False, True, False, size, sign, user).emit()
333 StoreImm(mnem, False, False, False, size, sign, user).emit()
334 StoreReg(mnem, False, False, False, size, sign, user).emit()
335
336 def buildDoubleStores(mnem):
337 StoreDoubleImm(mnem, True, True, True).emit()
338 StoreDoubleReg(mnem, True, True, True).emit()
339 StoreDoubleImm(mnem, True, False, True).emit()
340 StoreDoubleReg(mnem, True, False, True).emit()
341 StoreDoubleImm(mnem, False, True, True).emit()
342 StoreDoubleReg(mnem, False, True, True).emit()
343 StoreDoubleImm(mnem, False, False, True).emit()
344 StoreDoubleReg(mnem, False, False, True).emit()
345 StoreDoubleImm(mnem, False, True, False).emit()
346 StoreDoubleReg(mnem, False, True, False).emit()
347 StoreDoubleImm(mnem, False, False, False).emit()
348 StoreDoubleReg(mnem, False, False, False).emit()
349
350 def buildSrsStores(mnem):
351 SrsInst(mnem, True, True, True).emit()
352 SrsInst(mnem, True, True, False).emit()
353 SrsInst(mnem, True, False, True).emit()
354 SrsInst(mnem, True, False, False).emit()
355 SrsInst(mnem, False, True, True).emit()
356 SrsInst(mnem, False, True, False).emit()
357 SrsInst(mnem, False, False, True).emit()
358 SrsInst(mnem, False, False, False).emit()
359
360 buildStores("str")
361 buildStores("strt", user=True)
362 buildStores("strb", size=1)
363 buildStores("strbt", size=1, user=True)
364 buildStores("strh", size=2)
365 buildStores("strht", size=2, user=True)
366
367 buildSrsStores("srs")
368
369 buildDoubleStores("strd")
370
371 StoreImmEx("strex", False, True, False, size=4, flavor="exclusive",
372 instFlags = ['IsStoreConditional']).emit()
373 StoreImmEx("strexh", False, True, False, size=2, flavor="exclusive",
374 instFlags = ['IsStoreConditional']).emit()
375 StoreImmEx("strexb", False, True, False, size=1, flavor="exclusive",
376 instFlags = ['IsStoreConditional']).emit()
377 StoreDoubleImmEx("strexd", False, True, False, flavor="exclusive",
378 instFlags = ['IsStoreConditional']).emit()
379
380 StoreImm("vstr", False, True, False, size=4, flavor="fp").emit()
381 StoreImm("vstr", False, False, False, size=4, flavor="fp").emit()
382 StoreDoubleImm("vstr", False, True, False, flavor="fp").emit()
383 StoreDoubleImm("vstr", False, False, False, flavor="fp").emit()
384}};