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