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