ldr.isa revision 7644:62873d5c2bfc
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
164            if self.flavor == "fp":
165                eaCode += vfpEnabledCheckCode
166
167            self.codeBlobs["ea_code"] = eaCode
168
169            # Code that actually handles the access
170            if self.flavor == "prefetch":
171                accCode = 'uint64_t temp = Mem%s; temp = temp;'
172            elif self.flavor == "fp":
173                accCode = "FpDest.uw = cSwap(Mem%s, ((CPSR)Cpsr).e);\n"
174            else:
175                accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);"
176            accCode = accCode % buildMemSuffix(self.sign, self.size)
177
178            if self.writeback:
179                accCode += "Base = Base %s;\n" % self.offset
180
181            self.codeBlobs["memacc_code"] = accCode
182
183            # Push it out to the output files
184            base = buildMemBase(self.basePrefix, self.post, self.writeback)
185            self.emitHelper(base)
186
187    def loadImmClassName(post, add, writeback, size=4, sign=False, user=False):
188        return memClassName("LOAD_IMM", post, add, writeback, size, sign, user)
189
190    class LoadImm(LoadImmInst, LoadSingle):
191        decConstBase = 'LoadStoreImm'
192        basePrefix = 'MemoryImm'
193        nameFunc = staticmethod(loadImmClassName)
194
195    def loadRegClassName(post, add, writeback, size=4, sign=False, user=False):
196        return memClassName("LOAD_REG", post, add, writeback, size, sign, user)
197
198    class LoadReg(LoadRegInst, LoadSingle):
199        decConstBase = 'LoadStoreReg'
200        basePrefix = 'MemoryReg'
201        nameFunc = staticmethod(loadRegClassName)
202
203    class LoadDouble(LoadInst):
204        def __init__(self, *args, **kargs):
205            super(LoadDouble, self).__init__(*args, **kargs)
206
207            # Build the default class name
208            self.Name = self.nameFunc(self.post, self.add, self.writeback)
209
210            # Add memory request flags where necessary
211            if self.flavor == "exclusive":
212                self.memFlags.append("Request::LLSC")
213                self.memFlags.append("ArmISA::TLB::AlignDoubleWord")
214            else:
215                self.memFlags.append("ArmISA::TLB::AlignWord")
216
217            # Disambiguate the class name for different flavors of loads
218            if self.flavor != "normal":
219                self.Name = "%s_%s" % (self.name.upper(), self.Name)
220
221        def emit(self):
222            # Address computation code
223            eaCode = "EA = Base"
224            if not self.post:
225                eaCode += self.offset
226            eaCode += ";"
227
228            if self.flavor == "fp":
229                eaCode += vfpEnabledCheckCode
230
231            self.codeBlobs["ea_code"] = eaCode
232
233            # Code that actually handles the access
234            if self.flavor != "fp":
235                accCode = '''
236                CPSR cpsr = Cpsr;
237                Dest = cSwap<uint32_t>(Mem.ud, cpsr.e);
238                Dest2 = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
239                '''
240            else:
241                accCode = '''
242                uint64_t swappedMem = cSwap(Mem.ud, ((CPSR)Cpsr).e);
243                FpDest.uw = (uint32_t)swappedMem;
244                FpDest2.uw = (uint32_t)(swappedMem >> 32);
245                '''
246
247            if self.writeback:
248                accCode += "Base = Base %s;\n" % self.offset
249
250            self.codeBlobs["memacc_code"] = accCode
251
252            # Push it out to the output files
253            base = buildMemBase(self.basePrefix, self.post, self.writeback)
254            self.emitHelper(base)
255
256    def loadDoubleImmClassName(post, add, writeback):
257        return memClassName("LOAD_IMMD", post, add, writeback, 4, False, False)
258
259    class LoadDoubleImm(LoadImmInst, LoadDouble):
260        decConstBase = 'LoadStoreDImm'
261        basePrefix = 'MemoryDImm'
262        nameFunc = staticmethod(loadDoubleImmClassName)
263
264    def loadDoubleRegClassName(post, add, writeback):
265        return memClassName("LOAD_REGD", post, add, writeback, 4, False, False)
266
267    class LoadDoubleReg(LoadRegInst, LoadDouble):
268        decConstBase = 'LoadStoreDReg'
269        basePrefix = 'MemoryDReg'
270        nameFunc = staticmethod(loadDoubleRegClassName)
271
272    def buildLoads(mnem, size=4, sign=False, user=False):
273        LoadImm(mnem, True, True, True, size, sign, user).emit()
274        LoadReg(mnem, True, True, True, size, sign, user).emit()
275        LoadImm(mnem, True, False, True, size, sign, user).emit()
276        LoadReg(mnem, True, False, True, size, sign, user).emit()
277        LoadImm(mnem, False, True, True, size, sign, user).emit()
278        LoadReg(mnem, False, True, True, size, sign, user).emit()
279        LoadImm(mnem, False, False, True, size, sign, user).emit()
280        LoadReg(mnem, False, False, True, size, sign, user).emit()
281        LoadImm(mnem, False, True, False, size, sign, user).emit()
282        LoadReg(mnem, False, True, False, size, sign, user).emit()
283        LoadImm(mnem, False, False, False, size, sign, user).emit()
284        LoadReg(mnem, False, False, False, size, sign, user).emit()
285
286    def buildDoubleLoads(mnem):
287        LoadDoubleImm(mnem, True, True, True).emit()
288        LoadDoubleReg(mnem, True, True, True).emit()
289        LoadDoubleImm(mnem, True, False, True).emit()
290        LoadDoubleReg(mnem, True, False, True).emit()
291        LoadDoubleImm(mnem, False, True, True).emit()
292        LoadDoubleReg(mnem, False, True, True).emit()
293        LoadDoubleImm(mnem, False, False, True).emit()
294        LoadDoubleReg(mnem, False, False, True).emit()
295        LoadDoubleImm(mnem, False, True, False).emit()
296        LoadDoubleReg(mnem, False, True, False).emit()
297        LoadDoubleImm(mnem, False, False, False).emit()
298        LoadDoubleReg(mnem, False, False, False).emit()
299
300    def buildRfeLoads(mnem):
301        RfeInst(mnem, True, True, True).emit()
302        RfeInst(mnem, True, True, False).emit()
303        RfeInst(mnem, True, False, True).emit()
304        RfeInst(mnem, True, False, False).emit()
305        RfeInst(mnem, False, True, True).emit()
306        RfeInst(mnem, False, True, False).emit()
307        RfeInst(mnem, False, False, True).emit()
308        RfeInst(mnem, False, False, False).emit()
309
310    def buildPrefetches(mnem):
311        LoadReg(mnem, False, False, False, size=1, flavor="prefetch").emit()
312        LoadImm(mnem, False, False, False, size=1, flavor="prefetch").emit()
313        LoadReg(mnem, False, True, False, size=1, flavor="prefetch").emit()
314        LoadImm(mnem, False, True, False, size=1, flavor="prefetch").emit()
315
316    buildLoads("ldr")
317    buildLoads("ldrt", user=True)
318    buildLoads("ldrb", size=1)
319    buildLoads("ldrbt", size=1, user=True)
320    buildLoads("ldrsb", size=1, sign=True)
321    buildLoads("ldrsbt", size=1, sign=True, user=True)
322    buildLoads("ldrh", size=2)
323    buildLoads("ldrht", size=2, user=True)
324    buildLoads("hdrsh", size=2, sign=True)
325    buildLoads("ldrsht", size=2, sign=True, user=True)
326
327    buildDoubleLoads("ldrd")
328
329    buildRfeLoads("rfe")
330
331    buildPrefetches("pld")
332    buildPrefetches("pldw")
333    buildPrefetches("pli")
334
335    LoadImm("ldrex", False, True, False, size=4, flavor="exclusive").emit()
336    LoadImm("ldrexh", False, True, False, size=2, flavor="exclusive").emit()
337    LoadImm("ldrexb", False, True, False, size=1, flavor="exclusive").emit()
338    LoadDoubleImm("ldrexd", False, True, False, flavor="exclusive").emit()
339
340    LoadImm("vldr", False, True, False, size=4, flavor="fp").emit()
341    LoadImm("vldr", False, False, False, size=4, flavor="fp").emit()
342    LoadDoubleImm("vldr", False, True, False, flavor="fp").emit()
343    LoadDoubleImm("vldr", False, False, False, flavor="fp").emit()
344}};
345