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