str.isa revision 8588
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, 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);'
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);
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);
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}};
385