str.isa revision 13588:fb25d9448acc
1// -*- mode:c++ -*-
2
3// Copyright (c) 2010-2011,2017 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, opModeToEL(currOpMode(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 == "exclusive":
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            # Disambiguate the class name for different flavors of stores
193            if self.flavor != "normal":
194                self.Name = "%s_%s" % (self.name.upper(), self.Name)
195
196        def emit(self):
197            # Address computation
198            eaCode = "EA = Base"
199            if not self.post:
200                eaCode += self.offset
201            eaCode += ";"
202
203            if self.flavor == "fp":
204                eaCode += vfpEnabledCheckCode
205
206            self.codeBlobs["ea_code"] = eaCode
207
208            # Code that actually handles the access
209            if self.flavor == "fp":
210                accCode = 'Mem%(suffix)s = cSwap(FpDest_uw, ((CPSR)Cpsr).e);'
211            else:
212                accCode = \
213                    'Mem%(suffix)s = cSwap(Dest%(suffix)s, ((CPSR)Cpsr).e);'
214            accCode = accCode % \
215                { "suffix" : buildMemSuffix(self.sign, self.size) }
216
217            self.codeBlobs["memacc_code"] = accCode
218
219            # Push it out to the output files
220            base = buildMemBase(self.basePrefix, self.post, self.writeback)
221            wbDecl = None
222            if self.writeback:
223                wbDecl = self.wbDecl
224            self.emitHelper(base, wbDecl)
225
226    def storeImmClassName(post, add, writeback, size=4, sign=False, user=False):
227        return memClassName("STORE_IMM", post, add, writeback, size, sign, user)
228
229    class StoreImmEx(StoreImmInst, StoreSingle):
230        execBase = 'StoreEx'
231        decConstBase = 'StoreExImm'
232        basePrefix = 'MemoryExImm'
233        nameFunc = staticmethod(storeImmClassName)
234
235        def __init__(self, *args, **kargs):
236            super(StoreImmEx, self).__init__(*args, **kargs)
237            self.codeBlobs["postacc_code"] = \
238                  "Result = !writeResult; SevMailbox = 1; LLSCLock = 0;"
239
240    class StoreImm(StoreImmInst, StoreSingle):
241        decConstBase = 'LoadStoreImm'
242        basePrefix = 'MemoryImm'
243        nameFunc = staticmethod(storeImmClassName)
244
245    def storeRegClassName(post, add, writeback, size=4, sign=False, user=False):
246        return memClassName("STORE_REG", post, add, writeback, size, sign, user)
247
248    class StoreReg(StoreRegInst, StoreSingle):
249        decConstBase = 'StoreReg'
250        basePrefix = 'MemoryReg'
251        nameFunc = staticmethod(storeRegClassName)
252
253    class StoreDouble(StoreInst):
254        def __init__(self, *args, **kargs):
255            super(StoreDouble, self).__init__(*args, **kargs)
256
257            # Build the default class name
258            self.Name = self.nameFunc(self.post, self.add, self.writeback)
259
260            # Add memory request flags where necessary
261            if self.flavor == "exclusive":
262                self.instFlags.append("IsStoreConditional")
263                self.memFlags.append("Request::LLSC")
264                self.memFlags.append("ArmISA::TLB::AlignDoubleWord")
265            else:
266                self.memFlags.append("ArmISA::TLB::AlignWord")
267
268            # Disambiguate the class name for different flavors of stores
269            if self.flavor != "normal":
270                self.Name = "%s_%s" % (self.name.upper(), self.Name)
271
272        def emit(self):
273            # Address computation code
274            eaCode = "EA = Base"
275            if not self.post:
276                eaCode += self.offset
277            eaCode += ";"
278
279            if self.flavor == "fp":
280                eaCode += vfpEnabledCheckCode
281
282            self.codeBlobs["ea_code"] = eaCode
283
284            # Code that actually handles the access
285            if self.flavor == "fp":
286                accCode = '''
287                uint64_t swappedMem  = (uint64_t)FpDest_uw |
288                                       ((uint64_t)FpDest2_uw << 32);
289                Mem_ud = cSwap(swappedMem, ((CPSR)Cpsr).e);
290                '''
291            else:
292                accCode = '''
293                CPSR cpsr = Cpsr;
294                Mem_ud = (uint64_t)cSwap(Dest_uw, cpsr.e) |
295                         ((uint64_t)cSwap(Dest2_uw, cpsr.e) << 32);
296                '''
297
298            self.codeBlobs["memacc_code"] = accCode
299
300            # Push it out to the output files
301            base = buildMemBase(self.basePrefix, self.post, self.writeback)
302            wbDecl = None
303            if self.writeback:
304                wbDecl = self.wbDecl
305            self.emitHelper(base, wbDecl)
306
307    def storeDoubleImmClassName(post, add, writeback):
308        return memClassName("STORE_IMMD", post, add, writeback, 4, False, False)
309
310    class StoreDoubleImmEx(StoreImmInst, StoreDouble):
311        execBase = 'StoreEx'
312        decConstBase = 'StoreExDImm'
313        basePrefix = 'MemoryExDImm'
314        nameFunc = staticmethod(storeDoubleImmClassName)
315
316        def __init__(self, *args, **kargs):
317            super(StoreDoubleImmEx, self).__init__(*args, **kargs)
318            self.codeBlobs["postacc_code"] = \
319                  "Result = !writeResult; SevMailbox = 1; LLSCLock = 0;"
320
321    class StoreDoubleImm(StoreImmInst, StoreDouble):
322        decConstBase = 'LoadStoreDImm'
323        basePrefix = 'MemoryDImm'
324        nameFunc = staticmethod(storeDoubleImmClassName)
325
326    def storeDoubleRegClassName(post, add, writeback):
327        return memClassName("STORE_REGD", post, add, writeback, 4, False, False)
328
329    class StoreDoubleReg(StoreRegInst, StoreDouble):
330        decConstBase = 'StoreDReg'
331        basePrefix = 'MemoryDReg'
332        nameFunc = staticmethod(storeDoubleRegClassName)
333
334    def buildStores(mnem, size=4, sign=False, user=False):
335        StoreImm(mnem, True, True, True, size, sign, user).emit()
336        StoreReg(mnem, True, True, True, size, sign, user).emit()
337        StoreImm(mnem, True, False, True, size, sign, user).emit()
338        StoreReg(mnem, True, False, True, size, sign, user).emit()
339        StoreImm(mnem, False, True, True, size, sign, user).emit()
340        StoreReg(mnem, False, True, True, size, sign, user).emit()
341        StoreImm(mnem, False, False, True, size, sign, user).emit()
342        StoreReg(mnem, False, False, True, size, sign, user).emit()
343        StoreImm(mnem, False, True, False, size, sign, user).emit()
344        StoreReg(mnem, False, True, False, size, sign, user).emit()
345        StoreImm(mnem, False, False, False, size, sign, user).emit()
346        StoreReg(mnem, False, False, False, size, sign, user).emit()
347
348    def buildDoubleStores(mnem):
349        StoreDoubleImm(mnem, True, True, True).emit()
350        StoreDoubleReg(mnem, True, True, True).emit()
351        StoreDoubleImm(mnem, True, False, True).emit()
352        StoreDoubleReg(mnem, True, False, True).emit()
353        StoreDoubleImm(mnem, False, True, True).emit()
354        StoreDoubleReg(mnem, False, True, True).emit()
355        StoreDoubleImm(mnem, False, False, True).emit()
356        StoreDoubleReg(mnem, False, False, True).emit()
357        StoreDoubleImm(mnem, False, True, False).emit()
358        StoreDoubleReg(mnem, False, True, False).emit()
359        StoreDoubleImm(mnem, False, False, False).emit()
360        StoreDoubleReg(mnem, False, False, False).emit()
361
362    def buildSrsStores(mnem):
363        SrsInst(mnem, True, True, True).emit()
364        SrsInst(mnem, True, True, False).emit()
365        SrsInst(mnem, True, False, True).emit()
366        SrsInst(mnem, True, False, False).emit()
367        SrsInst(mnem, False, True, True).emit()
368        SrsInst(mnem, False, True, False).emit()
369        SrsInst(mnem, False, False, True).emit()
370        SrsInst(mnem, False, False, False).emit()
371
372    buildStores("str")
373    buildStores("strt", user=True)
374    buildStores("strb", size=1)
375    buildStores("strbt", size=1, user=True)
376    buildStores("strh", size=2)
377    buildStores("strht", size=2, user=True)
378
379    buildSrsStores("srs")
380
381    buildDoubleStores("strd")
382
383    StoreImmEx("strex", False, True, False, size=4,
384               flavor="exclusive").emit()
385    StoreImmEx("strexh", False, True, False, size=2,
386               flavor="exclusive").emit()
387    StoreImmEx("strexb", False, True, False, size=1,
388               flavor="exclusive").emit()
389    StoreDoubleImmEx("strexd", False, True, False,
390                     flavor="exclusive").emit()
391
392    StoreImm("vstr", False, True, False, size=4, flavor="fp").emit()
393    StoreImm("vstr", False, False, False, size=4, flavor="fp").emit()
394    StoreDoubleImm("vstr", False, True, False, flavor="fp").emit()
395    StoreDoubleImm("vstr", False, False, False, flavor="fp").emit()
396}};
397