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