ldr.isa revision 10869:43b5dd939a49
1// -*- mode:c++ -*-
2
3// Copyright (c) 2010-2011 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    import math
42
43    header_output = ""
44    decoder_output = ""
45    exec_output = ""
46
47    class LoadInst(LoadStoreInst):
48        execBase = 'Load'
49
50        def __init__(self, mnem, post, add, writeback,
51                     size=4, sign=False, user=False, flavor="normal"):
52            super(LoadInst, self).__init__()
53
54            self.name = mnem
55            self.post = post
56            self.add = add
57            self.writeback = writeback
58            self.size = size
59            self.sign = sign
60            self.user = user
61            self.flavor = flavor
62            self.rasPop = False
63
64            if self.add:
65                self.op = " +"
66            else:
67                self.op = " -"
68
69            self.memFlags = ["ArmISA::TLB::MustBeOne"]
70            self.codeBlobs = {"postacc_code" : ""}
71
72        def emitHelper(self, base = 'Memory', wbDecl = None, instFlags = [], pcDecl = None):
73
74            global header_output, decoder_output, exec_output
75
76            codeBlobs = self.codeBlobs
77            codeBlobs["predicate_test"] = pickPredicate(codeBlobs)
78            (newHeader,
79             newDecoder,
80             newExec) = self.fillTemplates(self.name, self.Name, codeBlobs,
81                                           self.memFlags, instFlags, base,
82                                           wbDecl, pcDecl, self.rasPop,
83                                           self.size, self.sign)
84
85            header_output += newHeader
86            decoder_output += newDecoder
87            exec_output += newExec
88
89    class RfeInst(LoadInst):
90        decConstBase = 'Rfe'
91
92        def __init__(self, mnem, post, add, writeback):
93            super(RfeInst, self).__init__(mnem, post, add, writeback)
94            self.Name = "RFE_" + loadImmClassName(post, add, writeback, 8)
95
96            self.memFlags.append("ArmISA::TLB::AlignWord")
97
98        def emit(self):
99            offset = 0
100            if self.post != self.add:
101                offset += 4
102            if not self.add:
103                offset -= 8
104            self.codeBlobs["ea_code"] = "EA = Base + %d;" % offset
105
106            wbDiff = -8
107            if self.add:
108                wbDiff = 8
109            accCode = '''
110            CPSR cpsr = Cpsr;
111            cpsr.nz = CondCodesNZ;
112            cpsr.c = CondCodesC;
113            cpsr.v = CondCodesV;
114            cpsr.ge = CondCodesGE;
115            URc = cpsr;
116            URa = cSwap<uint32_t>(Mem_ud, cpsr.e);
117            URb = cSwap<uint32_t>(Mem_ud >> 32, cpsr.e);
118            '''
119            self.codeBlobs["memacc_code"] = accCode
120
121            wbDecl = None
122            pcDecl = "MicroUopSetPCCPSR(machInst, INTREG_UREG0, INTREG_UREG1, INTREG_UREG2);"
123
124            if self.writeback:
125                wbDecl = "MicroAddiUop(machInst, base, base, %d);" % wbDiff
126            self.emitHelper('RfeOp', wbDecl, ["IsSerializeAfter", "IsNonSpeculative"], pcDecl)
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            if self.add and self.post and self.writeback and not self.sign and \
139               not self.user and self.size == 4:
140                self.rasPop = True
141
142    class LoadRegInst(LoadInst):
143        def __init__(self, *args, **kargs):
144            super(LoadRegInst, self).__init__(*args, **kargs)
145            self.offset = self.op + " shift_rm_imm(Index, shiftAmt," + \
146                                    " shiftType, OptShiftRmCondCodesC)"
147            if self.add:
148                 self.wbDecl = '''
149                     MicroAddUop(machInst, base, base, wbIndexReg, shiftAmt, shiftType);
150                 '''
151            else:
152                 self.wbDecl = '''
153                     MicroSubUop(machInst, base, base, wbIndexReg, shiftAmt, shiftType);
154                 '''
155
156    class LoadSingle(LoadInst):
157        def __init__(self, *args, **kargs):
158            super(LoadSingle, self).__init__(*args, **kargs)
159
160            # Build the default class name
161            self.Name = self.nameFunc(self.post, self.add, self.writeback,
162                                      self.size, self.sign, self.user)
163
164            # Add memory request flags where necessary
165            self.memFlags.append("%d" % int(math.log(self.size, 2)))
166            if self.user:
167                self.memFlags.append("ArmISA::TLB::UserMode")
168
169            self.instFlags = []
170            if self.flavor == "dprefetch":
171                self.memFlags.append("Request::PREFETCH")
172                self.instFlags = ['IsDataPrefetch']
173            elif self.flavor == "iprefetch":
174                self.memFlags.append("Request::PREFETCH")
175                self.instFlags = ['IsInstPrefetch']
176            elif self.flavor == "exclusive":
177                self.memFlags.append("Request::LLSC")
178            elif self.flavor == "normal":
179                self.memFlags.append("ArmISA::TLB::AllowUnaligned")
180
181            # Disambiguate the class name for different flavors of loads
182            if self.flavor != "normal":
183                self.Name = "%s_%s" % (self.name.upper(), self.Name)
184
185        def emit(self):
186            # Address compuation code
187            eaCode = "EA = Base"
188            if not self.post:
189                eaCode += self.offset
190            eaCode += ";"
191
192            if self.flavor == "fp":
193                eaCode += vfpEnabledCheckCode
194
195            self.codeBlobs["ea_code"] = eaCode
196
197            # Code that actually handles the access
198            if self.flavor == "dprefetch" or self.flavor == "iprefetch":
199                accCode = 'uint64_t temp = Mem%s; temp = temp;'
200            elif self.flavor == "fp":
201                accCode = "FpDest_uw = cSwap(Mem%s, ((CPSR)Cpsr).e);\n"
202            else:
203                accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);"
204            accCode = accCode % buildMemSuffix(self.sign, self.size)
205
206            self.codeBlobs["memacc_code"] = accCode
207
208            # Push it out to the output files
209            base = buildMemBase(self.basePrefix, self.post, self.writeback)
210            wbDecl = None
211            if self.writeback:
212                wbDecl = self.wbDecl
213            self.emitHelper(base, wbDecl, self.instFlags)
214
215    def loadImmClassName(post, add, writeback, size=4, sign=False, user=False):
216        return memClassName("LOAD_IMM", post, add, writeback, size, sign, user)
217
218    class LoadImm(LoadImmInst, LoadSingle):
219        decConstBase = 'LoadImm'
220        basePrefix = 'MemoryImm'
221        nameFunc = staticmethod(loadImmClassName)
222
223    def loadRegClassName(post, add, writeback, size=4, sign=False, user=False):
224        return memClassName("LOAD_REG", post, add, writeback, size, sign, user)
225
226    class LoadReg(LoadRegInst, LoadSingle):
227        decConstBase = 'LoadReg'
228        basePrefix = 'MemoryReg'
229        nameFunc = staticmethod(loadRegClassName)
230
231    class LoadDouble(LoadInst):
232        def __init__(self, *args, **kargs):
233            super(LoadDouble, self).__init__(*args, **kargs)
234
235            # Build the default class name
236            self.Name = self.nameFunc(self.post, self.add, self.writeback)
237
238            # Add memory request flags where necessary
239            if self.flavor == "exclusive":
240                self.memFlags.append("Request::LLSC")
241                self.memFlags.append("ArmISA::TLB::AlignDoubleWord")
242            else:
243                self.memFlags.append("ArmISA::TLB::AlignWord")
244
245            # Disambiguate the class name for different flavors of loads
246            if self.flavor != "normal":
247                self.Name = "%s_%s" % (self.name.upper(), self.Name)
248
249        def emit(self):
250            # Address computation code
251            eaCode = "EA = Base"
252            if not self.post:
253                eaCode += self.offset
254            eaCode += ";"
255
256            if self.flavor == "fp":
257                eaCode += vfpEnabledCheckCode
258
259            self.codeBlobs["ea_code"] = eaCode
260
261            # Code that actually handles the access
262            if self.flavor != "fp":
263                accCode = '''
264                CPSR cpsr = Cpsr;
265                Dest = cSwap<uint32_t>(Mem_ud, cpsr.e);
266                Dest2 = cSwap<uint32_t>(Mem_ud >> 32, cpsr.e);
267                '''
268            else:
269                accCode = '''
270                uint64_t swappedMem = cSwap(Mem_ud, ((CPSR)Cpsr).e);
271                FpDest_uw = (uint32_t)swappedMem;
272                FpDest2_uw = (uint32_t)(swappedMem >> 32);
273                '''
274
275            self.codeBlobs["memacc_code"] = accCode
276
277            # Push it out to the output files
278            base = buildMemBase(self.basePrefix, self.post, self.writeback)
279            wbDecl = None
280            if self.writeback:
281                wbDecl = self.wbDecl
282            self.emitHelper(base, wbDecl)
283
284    def loadDoubleImmClassName(post, add, writeback):
285        return memClassName("LOAD_IMMD", post, add, writeback, 4, False, False)
286
287    class LoadDoubleImm(LoadImmInst, LoadDouble):
288        decConstBase = 'LoadStoreDImm'
289        basePrefix = 'MemoryDImm'
290        nameFunc = staticmethod(loadDoubleImmClassName)
291
292    def loadDoubleRegClassName(post, add, writeback):
293        return memClassName("LOAD_REGD", post, add, writeback, 4, False, False)
294
295    class LoadDoubleReg(LoadRegInst, LoadDouble):
296        decConstBase = 'LoadDReg'
297        basePrefix = 'MemoryDReg'
298        nameFunc = staticmethod(loadDoubleRegClassName)
299
300    def buildLoads(mnem, size=4, sign=False, user=False):
301        LoadImm(mnem, True, True, True, size, sign, user).emit()
302        LoadReg(mnem, True, True, True, size, sign, user).emit()
303        LoadImm(mnem, True, False, True, size, sign, user).emit()
304        LoadReg(mnem, True, False, True, size, sign, user).emit()
305        LoadImm(mnem, False, True, True, size, sign, user).emit()
306        LoadReg(mnem, False, True, True, size, sign, user).emit()
307        LoadImm(mnem, False, False, True, size, sign, user).emit()
308        LoadReg(mnem, False, False, True, size, sign, user).emit()
309        LoadImm(mnem, False, True, False, size, sign, user).emit()
310        LoadReg(mnem, False, True, False, size, sign, user).emit()
311        LoadImm(mnem, False, False, False, size, sign, user).emit()
312        LoadReg(mnem, False, False, False, size, sign, user).emit()
313
314    def buildDoubleLoads(mnem):
315        LoadDoubleImm(mnem, True, True, True).emit()
316        LoadDoubleReg(mnem, True, True, True).emit()
317        LoadDoubleImm(mnem, True, False, True).emit()
318        LoadDoubleReg(mnem, True, False, True).emit()
319        LoadDoubleImm(mnem, False, True, True).emit()
320        LoadDoubleReg(mnem, False, True, True).emit()
321        LoadDoubleImm(mnem, False, False, True).emit()
322        LoadDoubleReg(mnem, False, False, True).emit()
323        LoadDoubleImm(mnem, False, True, False).emit()
324        LoadDoubleReg(mnem, False, True, False).emit()
325        LoadDoubleImm(mnem, False, False, False).emit()
326        LoadDoubleReg(mnem, False, False, False).emit()
327
328    def buildRfeLoads(mnem):
329        RfeInst(mnem, True, True, True).emit()
330        RfeInst(mnem, True, True, False).emit()
331        RfeInst(mnem, True, False, True).emit()
332        RfeInst(mnem, True, False, False).emit()
333        RfeInst(mnem, False, True, True).emit()
334        RfeInst(mnem, False, True, False).emit()
335        RfeInst(mnem, False, False, True).emit()
336        RfeInst(mnem, False, False, False).emit()
337
338    def buildPrefetches(mnem, type):
339        LoadReg(mnem, False, False, False, size=1, flavor=type).emit()
340        LoadImm(mnem, False, False, False, size=1, flavor=type).emit()
341        LoadReg(mnem, False, True, False, size=1, flavor=type).emit()
342        LoadImm(mnem, False, True, False, size=1, flavor=type).emit()
343
344    buildLoads("ldr")
345    buildLoads("ldrt", user=True)
346    buildLoads("ldrb", size=1)
347    buildLoads("ldrbt", size=1, user=True)
348    buildLoads("ldrsb", size=1, sign=True)
349    buildLoads("ldrsbt", size=1, sign=True, user=True)
350    buildLoads("ldrh", size=2)
351    buildLoads("ldrht", size=2, user=True)
352    buildLoads("ldrsh", size=2, sign=True)
353    buildLoads("ldrsht", size=2, sign=True, user=True)
354
355    buildDoubleLoads("ldrd")
356
357    buildRfeLoads("rfe")
358
359    buildPrefetches("pld", "dprefetch")
360    buildPrefetches("pldw", "dprefetch")
361    buildPrefetches("pli", "iprefetch")
362
363    LoadImm("ldrex", False, True, False, size=4, flavor="exclusive").emit()
364    LoadImm("ldrexh", False, True, False, size=2, flavor="exclusive").emit()
365    LoadImm("ldrexb", False, True, False, size=1, flavor="exclusive").emit()
366    LoadDoubleImm("ldrexd", False, True, False, flavor="exclusive").emit()
367
368    LoadImm("vldr", False, True, False, size=4, flavor="fp").emit()
369    LoadImm("vldr", False, False, False, size=4, flavor="fp").emit()
370    LoadDoubleImm("vldr", False, True, False, flavor="fp").emit()
371    LoadDoubleImm("vldr", False, False, False, flavor="fp").emit()
372}};
373