ldr.isa revision 7593:aa32d1398dfd
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 LoadInst(LoadStoreInst):
47        execBase = 'Load'
48
49        def __init__(self, mnem, post, add, writeback,
50                     size=4, sign=False, user=False, flavor="normal"):
51            super(LoadInst, 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'):
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)
80
81            header_output += newHeader
82            decoder_output += newDecoder
83            exec_output += newExec
84
85    class RfeInst(LoadInst):
86        decConstBase = 'Rfe'
87
88        def __init__(self, mnem, post, add, writeback):
89            super(RfeInst, self).__init__(mnem, post, add, writeback)
90            self.Name = "RFE_" + loadImmClassName(post, add, writeback, 8)
91
92            self.memFlags.append("ArmISA::TLB::AlignWord")
93
94        def emit(self):
95            offset = 0
96            if self.post != self.add:
97                offset += 4
98            if not self.add:
99                offset -= 8
100            self.codeBlobs["ea_code"] = "EA = Base + %d;" % offset
101
102            wbDiff = -8
103            if self.add:
104                wbDiff = 8
105            accCode = '''
106            CPSR cpsr = Cpsr;
107            SCTLR sctlr = Sctlr;
108            NPC = cSwap<uint32_t>(Mem.ud, cpsr.e);
109            uint32_t newCpsr =
110                cpsrWriteByInstr(cpsr | CondCodes,
111                                 cSwap<uint32_t>(Mem.ud >> 32, cpsr.e),
112                                 0xF, true, sctlr.nmfi);
113            Cpsr = ~CondCodesMask & newCpsr;
114            CondCodes = CondCodesMask & newCpsr;
115            '''
116            if self.writeback:
117                accCode += "Base = Base + %s;\n" % wbDiff
118            self.codeBlobs["memacc_code"] = accCode
119
120            self.emitHelper('RfeOp')
121
122    class LoadImmInst(LoadInst):
123        def __init__(self, *args, **kargs):
124            super(LoadImmInst, self).__init__(*args, **kargs)
125            self.offset = self.op + " imm"
126
127    class LoadRegInst(LoadInst):
128        def __init__(self, *args, **kargs):
129            super(LoadRegInst, self).__init__(*args, **kargs)
130            self.offset = self.op + " shift_rm_imm(Index, shiftAmt," + \
131                                    " shiftType, CondCodes<29:>)"
132
133    class LoadSingle(LoadInst):
134        def __init__(self, *args, **kargs):
135            super(LoadSingle, self).__init__(*args, **kargs)
136
137            # Build the default class name
138            self.Name = self.nameFunc(self.post, self.add, self.writeback,
139                                      self.size, self.sign, self.user)
140
141            # Add memory request flags where necessary
142            self.memFlags.append("%d" % (self.size - 1))
143            if self.user:
144                self.memFlags.append("ArmISA::TLB::UserMode")
145
146            if self.flavor == "prefetch":
147                self.memFlags.append("Request::PREFETCH")
148            elif self.flavor == "exclusive":
149                self.memFlags.append("Request::LLSC")
150            elif self.flavor == "normal":
151                self.memFlags.append("ArmISA::TLB::AllowUnaligned")
152
153            # Disambiguate the class name for different flavors of loads
154            if self.flavor != "normal":
155                self.Name = "%s_%s" % (self.name.upper(), self.Name)
156
157        def emit(self):
158            # Address compuation code
159            eaCode = "EA = Base"
160            if not self.post:
161                eaCode += self.offset
162            eaCode += ";"
163            self.codeBlobs["ea_code"] = eaCode
164
165            # Code that actually handles the access
166            if self.flavor == "prefetch":
167                accCode = 'uint64_t temp = Mem%s; temp = temp;'
168            elif self.flavor == "fp":
169                accCode = "FpDest.uw = cSwap(Mem%s, ((CPSR)Cpsr).e);\n"
170            else:
171                accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);"
172            accCode = accCode % buildMemSuffix(self.sign, self.size)
173
174            if self.writeback:
175                accCode += "Base = Base %s;\n" % self.offset
176
177            self.codeBlobs["memacc_code"] = accCode
178
179            # Push it out to the output files
180            base = buildMemBase(self.basePrefix, self.post, self.writeback)
181            self.emitHelper(base)
182
183    def loadImmClassName(post, add, writeback, size=4, sign=False, user=False):
184        return memClassName("LOAD_IMM", post, add, writeback, size, sign, user)
185
186    class LoadImm(LoadImmInst, LoadSingle):
187        decConstBase = 'LoadStoreImm'
188        basePrefix = 'MemoryImm'
189        nameFunc = staticmethod(loadImmClassName)
190
191    def loadRegClassName(post, add, writeback, size=4, sign=False, user=False):
192        return memClassName("LOAD_REG", post, add, writeback, size, sign, user)
193
194    class LoadReg(LoadRegInst, LoadSingle):
195        decConstBase = 'LoadStoreReg'
196        basePrefix = 'MemoryReg'
197        nameFunc = staticmethod(loadRegClassName)
198
199    class LoadDouble(LoadInst):
200        def __init__(self, *args, **kargs):
201            super(LoadDouble, self).__init__(*args, **kargs)
202
203            # Build the default class name
204            self.Name = self.nameFunc(self.post, self.add, self.writeback)
205
206            # Add memory request flags where necessary
207            if self.flavor == "exclusive":
208                self.memFlags.append("Request::LLSC")
209                self.memFlags.append("ArmISA::TLB::AlignDoubleWord")
210            else:
211                self.memFlags.append("ArmISA::TLB::AlignWord")
212
213            # Disambiguate the class name for different flavors of loads
214            if self.flavor != "normal":
215                self.Name = "%s_%s" % (self.name.upper(), self.Name)
216
217        def emit(self):
218            # Address computation code
219            eaCode = "EA = Base"
220            if not self.post:
221                eaCode += self.offset
222            eaCode += ";"
223            self.codeBlobs["ea_code"] = eaCode
224
225            # Code that actually handles the access
226            if self.flavor != "fp":
227                accCode = '''
228                CPSR cpsr = Cpsr;
229                Dest = cSwap<uint32_t>(Mem.ud, cpsr.e);
230                Dest2 = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
231                '''
232            else:
233                accCode = '''
234                uint64_t swappedMem = cSwap(Mem.ud, ((CPSR)Cpsr).e);
235                FpDest.uw = (uint32_t)swappedMem;
236                FpDest2.uw = (uint32_t)(swappedMem >> 32);
237                '''
238
239            if self.writeback:
240                accCode += "Base = Base %s;\n" % self.offset
241
242            self.codeBlobs["memacc_code"] = accCode
243
244            # Push it out to the output files
245            base = buildMemBase(self.basePrefix, self.post, self.writeback)
246            self.emitHelper(base)
247
248    def loadDoubleImmClassName(post, add, writeback):
249        return memClassName("LOAD_IMMD", post, add, writeback, 4, False, False)
250
251    class LoadDoubleImm(LoadImmInst, LoadDouble):
252        decConstBase = 'LoadStoreDImm'
253        basePrefix = 'MemoryDImm'
254        nameFunc = staticmethod(loadDoubleImmClassName)
255
256    def loadDoubleRegClassName(post, add, writeback):
257        return memClassName("LOAD_REGD", post, add, writeback, 4, False, False)
258
259    class LoadDoubleReg(LoadRegInst, LoadDouble):
260        decConstBase = 'LoadStoreDReg'
261        basePrefix = 'MemoryDReg'
262        nameFunc = staticmethod(loadDoubleRegClassName)
263
264    def buildLoads(mnem, size=4, sign=False, user=False):
265        LoadImm(mnem, True, True, True, size, sign, user).emit()
266        LoadReg(mnem, True, True, True, size, sign, user).emit()
267        LoadImm(mnem, True, False, True, size, sign, user).emit()
268        LoadReg(mnem, True, False, True, size, sign, user).emit()
269        LoadImm(mnem, False, True, True, size, sign, user).emit()
270        LoadReg(mnem, False, True, True, size, sign, user).emit()
271        LoadImm(mnem, False, False, True, size, sign, user).emit()
272        LoadReg(mnem, False, False, True, size, sign, user).emit()
273        LoadImm(mnem, False, True, False, size, sign, user).emit()
274        LoadReg(mnem, False, True, False, size, sign, user).emit()
275        LoadImm(mnem, False, False, False, size, sign, user).emit()
276        LoadReg(mnem, False, False, False, size, sign, user).emit()
277
278    def buildDoubleLoads(mnem):
279        LoadDoubleImm(mnem, True, True, True).emit()
280        LoadDoubleReg(mnem, True, True, True).emit()
281        LoadDoubleImm(mnem, True, False, True).emit()
282        LoadDoubleReg(mnem, True, False, True).emit()
283        LoadDoubleImm(mnem, False, True, True).emit()
284        LoadDoubleReg(mnem, False, True, True).emit()
285        LoadDoubleImm(mnem, False, False, True).emit()
286        LoadDoubleReg(mnem, False, False, True).emit()
287        LoadDoubleImm(mnem, False, True, False).emit()
288        LoadDoubleReg(mnem, False, True, False).emit()
289        LoadDoubleImm(mnem, False, False, False).emit()
290        LoadDoubleReg(mnem, False, False, False).emit()
291
292    def buildRfeLoads(mnem):
293        RfeInst(mnem, True, True, True).emit()
294        RfeInst(mnem, True, True, False).emit()
295        RfeInst(mnem, True, False, True).emit()
296        RfeInst(mnem, True, False, False).emit()
297        RfeInst(mnem, False, True, True).emit()
298        RfeInst(mnem, False, True, False).emit()
299        RfeInst(mnem, False, False, True).emit()
300        RfeInst(mnem, False, False, False).emit()
301
302    def buildPrefetches(mnem):
303        LoadReg(mnem, False, False, False, size=1, flavor="prefetch").emit()
304        LoadImm(mnem, False, False, False, size=1, flavor="prefetch").emit()
305        LoadReg(mnem, False, True, False, size=1, flavor="prefetch").emit()
306        LoadImm(mnem, False, True, False, size=1, flavor="prefetch").emit()
307
308    buildLoads("ldr")
309    buildLoads("ldrt", user=True)
310    buildLoads("ldrb", size=1)
311    buildLoads("ldrbt", size=1, user=True)
312    buildLoads("ldrsb", size=1, sign=True)
313    buildLoads("ldrsbt", size=1, sign=True, user=True)
314    buildLoads("ldrh", size=2)
315    buildLoads("ldrht", size=2, user=True)
316    buildLoads("hdrsh", size=2, sign=True)
317    buildLoads("ldrsht", size=2, sign=True, user=True)
318
319    buildDoubleLoads("ldrd")
320
321    buildRfeLoads("rfe")
322
323    buildPrefetches("pld")
324    buildPrefetches("pldw")
325    buildPrefetches("pli")
326
327    LoadImm("ldrex", False, True, False, size=4, flavor="exclusive").emit()
328    LoadImm("ldrexh", False, True, False, size=2, flavor="exclusive").emit()
329    LoadImm("ldrexb", False, True, False, size=1, flavor="exclusive").emit()
330    LoadDoubleImm("ldrexd", False, True, False, flavor="exclusive").emit()
331
332    LoadImm("vldr", False, True, False, size=4, flavor="fp").emit()
333    LoadImm("vldr", False, False, False, size=4, flavor="fp").emit()
334    LoadDoubleImm("vldr", False, True, False, flavor="fp").emit()
335    LoadDoubleImm("vldr", False, False, False, flavor="fp").emit()
336}};
337