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