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