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