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