ldr.isa revision 7590:27dbb92bbad5
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::AlignWord")
210
211            # Disambiguate the class name for different flavors of loads
212            if self.flavor != "normal":
213                self.Name = "%s_%s" % (self.name.upper(), self.Name)
214
215        def emit(self):
216            # Address computation code
217            eaCode = "EA = Base"
218            if not self.post:
219                eaCode += self.offset
220            eaCode += ";"
221            self.codeBlobs["ea_code"] = eaCode
222
223            # Code that actually handles the access
224            if self.flavor != "fp":
225                accCode = '''
226                CPSR cpsr = Cpsr;
227                Dest = cSwap<uint32_t>(Mem.ud, cpsr.e);
228                Dest2 = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
229                '''
230            else:
231                accCode = '''
232                uint64_t swappedMem = cSwap(Mem.ud, ((CPSR)Cpsr).e);
233                FpDest.uw = (uint32_t)swappedMem;
234                FpDest2.uw = (uint32_t)(swappedMem >> 32);
235                '''
236
237            if self.writeback:
238                accCode += "Base = Base %s;\n" % self.offset
239
240            self.codeBlobs["memacc_code"] = accCode
241
242            # Push it out to the output files
243            base = buildMemBase(self.basePrefix, self.post, self.writeback)
244            self.emitHelper(base)
245
246    def loadDoubleImmClassName(post, add, writeback):
247        return memClassName("LOAD_IMMD", post, add, writeback, 4, False, False)
248
249    class LoadDoubleImm(LoadImmInst, LoadDouble):
250        decConstBase = 'LoadStoreDImm'
251        basePrefix = 'MemoryDImm'
252        nameFunc = staticmethod(loadDoubleImmClassName)
253
254    def loadDoubleRegClassName(post, add, writeback):
255        return memClassName("LOAD_REGD", post, add, writeback, 4, False, False)
256
257    class LoadDoubleReg(LoadRegInst, LoadDouble):
258        decConstBase = 'LoadStoreDReg'
259        basePrefix = 'MemoryDReg'
260        nameFunc = staticmethod(loadDoubleRegClassName)
261
262    def buildLoads(mnem, size=4, sign=False, user=False):
263        LoadImm(mnem, True, True, True, size, sign, user).emit()
264        LoadReg(mnem, True, True, True, size, sign, user).emit()
265        LoadImm(mnem, True, False, True, size, sign, user).emit()
266        LoadReg(mnem, True, False, True, size, sign, user).emit()
267        LoadImm(mnem, False, True, True, size, sign, user).emit()
268        LoadReg(mnem, False, True, True, size, sign, user).emit()
269        LoadImm(mnem, False, False, True, size, sign, user).emit()
270        LoadReg(mnem, False, False, True, size, sign, user).emit()
271        LoadImm(mnem, False, True, False, size, sign, user).emit()
272        LoadReg(mnem, False, True, False, size, sign, user).emit()
273        LoadImm(mnem, False, False, False, size, sign, user).emit()
274        LoadReg(mnem, False, False, False, size, sign, user).emit()
275
276    def buildDoubleLoads(mnem):
277        LoadDoubleImm(mnem, True, True, True).emit()
278        LoadDoubleReg(mnem, True, True, True).emit()
279        LoadDoubleImm(mnem, True, False, True).emit()
280        LoadDoubleReg(mnem, True, False, True).emit()
281        LoadDoubleImm(mnem, False, True, True).emit()
282        LoadDoubleReg(mnem, False, True, True).emit()
283        LoadDoubleImm(mnem, False, False, True).emit()
284        LoadDoubleReg(mnem, False, False, True).emit()
285        LoadDoubleImm(mnem, False, True, False).emit()
286        LoadDoubleReg(mnem, False, True, False).emit()
287        LoadDoubleImm(mnem, False, False, False).emit()
288        LoadDoubleReg(mnem, False, False, False).emit()
289
290    def buildRfeLoads(mnem):
291        RfeInst(mnem, True, True, True).emit()
292        RfeInst(mnem, True, True, False).emit()
293        RfeInst(mnem, True, False, True).emit()
294        RfeInst(mnem, True, False, False).emit()
295        RfeInst(mnem, False, True, True).emit()
296        RfeInst(mnem, False, True, False).emit()
297        RfeInst(mnem, False, False, True).emit()
298        RfeInst(mnem, False, False, False).emit()
299
300    def buildPrefetches(mnem):
301        LoadReg(mnem, False, False, False, size=1, flavor="prefetch").emit()
302        LoadImm(mnem, False, False, False, size=1, flavor="prefetch").emit()
303        LoadReg(mnem, False, True, False, size=1, flavor="prefetch").emit()
304        LoadImm(mnem, False, True, False, size=1, flavor="prefetch").emit()
305
306    buildLoads("ldr")
307    buildLoads("ldrt", user=True)
308    buildLoads("ldrb", size=1)
309    buildLoads("ldrbt", size=1, user=True)
310    buildLoads("ldrsb", size=1, sign=True)
311    buildLoads("ldrsbt", size=1, sign=True, user=True)
312    buildLoads("ldrh", size=2)
313    buildLoads("ldrht", size=2, user=True)
314    buildLoads("hdrsh", size=2, sign=True)
315    buildLoads("ldrsht", size=2, sign=True, user=True)
316
317    buildDoubleLoads("ldrd")
318
319    buildRfeLoads("rfe")
320
321    buildPrefetches("pld")
322    buildPrefetches("pldw")
323    buildPrefetches("pli")
324
325    LoadImm("ldrex", False, True, False, size=4, flavor="exclusive").emit()
326    LoadImm("ldrexh", False, True, False, size=2, flavor="exclusive").emit()
327    LoadImm("ldrexb", False, True, False, size=1, flavor="exclusive").emit()
328    LoadDoubleImm("ldrexd", False, True, False, flavor="exclusive").emit()
329
330    LoadImm("vldr", False, True, False, size=4, flavor="fp").emit()
331    LoadImm("vldr", False, False, False, size=4, flavor="fp").emit()
332    LoadDoubleImm("vldr", False, True, False, flavor="fp").emit()
333    LoadDoubleImm("vldr", False, False, False, flavor="fp").emit()
334}};
335