ldr.isa revision 7336:52dc042584d6
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    def loadImmClassName(post, add, writeback, \
47                         size=4, sign=False, user=False):
48        return memClassName("LOAD_IMM", post, add, writeback,
49                            size, sign, user)
50
51    def loadRegClassName(post, add, writeback, \
52                         size=4, sign=False, user=False):
53        return memClassName("LOAD_REG", post, add, writeback,
54                            size, sign, user)
55
56    def loadDoubleImmClassName(post, add, writeback):
57        return memClassName("LOAD_IMMD", post, add, writeback, 4, False, False)
58
59    def loadDoubleRegClassName(post, add, writeback):
60        return memClassName("LOAD_REGD", post, add, writeback, 4, False, False)
61
62    def emitLoad(name, Name, imm, eaCode, accCode, \
63                 memFlags, instFlags, base, double=False):
64        global header_output, decoder_output, exec_output
65
66        (newHeader,
67         newDecoder,
68         newExec) = loadStoreBase(name, Name, imm,
69                                  eaCode, accCode, "",
70                                  memFlags, instFlags, double, False,
71                                  base, execTemplateBase = 'Load')
72
73        header_output += newHeader
74        decoder_output += newDecoder
75        exec_output += newExec
76
77    def buildImmLoad(mnem, post, add, writeback, \
78                     size=4, sign=False, user=False, \
79                     prefetch=False, ldrex=False, vldr=False):
80        name = mnem
81        Name = loadImmClassName(post, add, writeback, \
82                                size, sign, user)
83
84        if add:
85            op = " +"
86        else:
87            op = " -"
88
89        offset = op + " imm"
90        eaCode = "EA = Base"
91        if not post:
92            eaCode += offset
93        eaCode += ";"
94
95        memFlags = ["ArmISA::TLB::MustBeOne", "%d" % (size - 1)]
96        if prefetch:
97            Name = "%s_%s" % (mnem.upper(), Name)
98            memFlags.append("Request::PREFETCH")
99            accCode = '''
100            uint64_t temp = Mem%s;\n
101            temp = temp;
102            ''' % buildMemSuffix(sign, size)
103        elif vldr:
104            Name = "%s_%s" % (mnem.upper(), Name)
105            accCode = "FpDest.uw = cSwap(Mem%s, ((CPSR)Cpsr).e);\n" % \
106                buildMemSuffix(sign, size)
107        else:
108            if ldrex:
109                memFlags.append("Request::LLSC")
110                Name = "%s_%s" % (mnem.upper(), Name)
111            accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);" % \
112                buildMemSuffix(sign, size)
113
114        if not prefetch and not ldrex and not vldr:
115            memFlags.append("ArmISA::TLB::AllowUnaligned")
116
117        if writeback:
118            accCode += "Base = Base %s;\n" % offset
119        base = buildMemBase("MemoryImm", post, writeback)
120
121        emitLoad(name, Name, True, eaCode, accCode, memFlags, [], base)
122
123    def buildRfeLoad(mnem, post, add, writeback):
124        name = mnem
125        Name = "RFE_" + loadImmClassName(post, add, writeback, 8)
126
127        offset = 0
128        if post != add:
129            offset += 4
130        if not add:
131            offset -= 8
132
133        eaCode = "EA = Base + %d;" % offset
134
135        wbDiff = -8
136        if add:
137            wbDiff = 8
138        accCode = '''
139        CPSR cpsr = Cpsr;
140        NPC = cSwap<uint32_t>(Mem.ud, cpsr.e);
141        uint32_t newCpsr =
142            cpsrWriteByInstr(cpsr | CondCodes,
143                             cSwap<uint32_t>(Mem.ud >> 32, cpsr.e),
144                             0xF, true);
145        Cpsr = ~CondCodesMask & newCpsr;
146        CondCodes = CondCodesMask & newCpsr;
147        '''
148        if writeback:
149            accCode += "Base = Base + %s;\n" % wbDiff
150
151        global header_output, decoder_output, exec_output
152
153        (newHeader,
154         newDecoder,
155         newExec) = RfeBase(name, Name, eaCode, accCode,
156             ["ArmISA::TLB::AlignWord", "ArmISA::TLB::MustBeOne"], [])
157
158        header_output += newHeader
159        decoder_output += newDecoder
160        exec_output += newExec
161
162    def buildRegLoad(mnem, post, add, writeback, size=4, sign=False, \
163                     user=False, prefetch=False):
164        name = mnem
165        Name = loadRegClassName(post, add, writeback,
166                                size, sign, user)
167
168        if add:
169            op = " +"
170        else:
171            op = " -"
172
173        offset = op + " shift_rm_imm(Index, shiftAmt," + \
174                      " shiftType, CondCodes<29:>)"
175        eaCode = "EA = Base"
176        if not post:
177            eaCode += offset
178        eaCode += ";"
179
180        memFlags = ["%d" % (size - 1), "ArmISA::TLB::MustBeOne"]
181        if prefetch:
182            Name = "%s_%s" % (mnem.upper(), Name)
183            memFlags.append("Request::PREFETCH")
184            accCode = '''
185            uint64_t temp = Mem%s;\n
186            temp = temp;
187            ''' % buildMemSuffix(sign, size)
188        else:
189            accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);" % \
190                buildMemSuffix(sign, size)
191        if writeback:
192            accCode += "Base = Base %s;\n" % offset
193
194        if not prefetch:
195            memFlags.append("ArmISA::TLB::AllowUnaligned")
196
197        base = buildMemBase("MemoryReg", post, writeback)
198
199        emitLoad(name, Name, False, eaCode, accCode, \
200                 memFlags, [], base)
201
202    def buildDoubleImmLoad(mnem, post, add, writeback, \
203                           ldrex=False, vldr=False):
204        name = mnem
205        Name = loadDoubleImmClassName(post, add, writeback)
206
207        if add:
208            op = " +"
209        else:
210            op = " -"
211
212        offset = op + " imm"
213        eaCode = "EA = Base"
214        if not post:
215            eaCode += offset
216        eaCode += ";"
217
218        if not vldr:
219            accCode = '''
220            CPSR cpsr = Cpsr;
221            Dest = cSwap<uint32_t>(Mem.ud, cpsr.e);
222            Dest2 = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
223            '''
224        else:
225            accCode = '''
226            uint64_t swappedMem = cSwap(Mem.ud, ((CPSR)Cpsr).e);
227            FpDest.uw = (uint32_t)swappedMem;
228            FpDest2.uw = (uint32_t)(swappedMem >> 32);
229            '''
230        if ldrex:
231            memFlags = ["Request::LLSC"]
232        else:
233            memFlags = []
234        if ldrex or vldr:
235            Name = "%s_%s" % (mnem.upper(), Name)
236        if writeback:
237            accCode += "Base = Base %s;\n" % offset
238        base = buildMemBase("MemoryDImm", post, writeback)
239
240        memFlags.extend(["ArmISA::TLB::MustBeOne",
241                         "ArmISA::TLB::AlignWord"])
242
243        emitLoad(name, Name, True, eaCode, accCode, \
244                 memFlags, [], base, double=True)
245
246    def buildDoubleRegLoad(mnem, post, add, writeback):
247        name = mnem
248        Name = loadDoubleRegClassName(post, add, writeback)
249
250        if add:
251            op = " +"
252        else:
253            op = " -"
254
255        offset = op + " shift_rm_imm(Index, shiftAmt," + \
256                      " shiftType, CondCodes<29:>)"
257        eaCode = "EA = Base"
258        if not post:
259            eaCode += offset
260        eaCode += ";"
261
262        accCode = '''
263        CPSR cpsr = Cpsr;
264        Dest = cSwap<uint32_t>(Mem.ud, cpsr.e);
265        Dest2 = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
266        '''
267        if writeback:
268            accCode += "Base = Base %s;\n" % offset
269        base = buildMemBase("MemoryDReg", post, writeback)
270
271        emitLoad(name, Name, False, eaCode, accCode,
272                 ["ArmISA::TLB::MustBeOne", "ArmISA::TLB::AlignWord"],
273                 [], base, double=True)
274
275    def buildLoads(mnem, size=4, sign=False, user=False):
276        buildImmLoad(mnem, True, True, True, size, sign, user)
277        buildRegLoad(mnem, True, True, True, size, sign, user)
278        buildImmLoad(mnem, True, False, True, size, sign, user)
279        buildRegLoad(mnem, True, False, True, size, sign, user)
280        buildImmLoad(mnem, False, True, True, size, sign, user)
281        buildRegLoad(mnem, False, True, True, size, sign, user)
282        buildImmLoad(mnem, False, False, True, size, sign, user)
283        buildRegLoad(mnem, False, False, True, size, sign, user)
284        buildImmLoad(mnem, False, True, False, size, sign, user)
285        buildRegLoad(mnem, False, True, False, size, sign, user)
286        buildImmLoad(mnem, False, False, False, size, sign, user)
287        buildRegLoad(mnem, False, False, False, size, sign, user)
288
289    def buildDoubleLoads(mnem):
290        buildDoubleImmLoad(mnem, True, True, True)
291        buildDoubleRegLoad(mnem, True, True, True)
292        buildDoubleImmLoad(mnem, True, False, True)
293        buildDoubleRegLoad(mnem, True, False, True)
294        buildDoubleImmLoad(mnem, False, True, True)
295        buildDoubleRegLoad(mnem, False, True, True)
296        buildDoubleImmLoad(mnem, False, False, True)
297        buildDoubleRegLoad(mnem, False, False, True)
298        buildDoubleImmLoad(mnem, False, True, False)
299        buildDoubleRegLoad(mnem, False, True, False)
300        buildDoubleImmLoad(mnem, False, False, False)
301        buildDoubleRegLoad(mnem, False, False, False)
302
303    def buildRfeLoads(mnem):
304        buildRfeLoad(mnem, True, True, True)
305        buildRfeLoad(mnem, True, True, False)
306        buildRfeLoad(mnem, True, False, True)
307        buildRfeLoad(mnem, True, False, False)
308        buildRfeLoad(mnem, False, True, True)
309        buildRfeLoad(mnem, False, True, False)
310        buildRfeLoad(mnem, False, False, True)
311        buildRfeLoad(mnem, False, False, False)
312
313    def buildPrefetches(mnem):
314        buildRegLoad(mnem, False, False, False, size=1, prefetch=True)
315        buildImmLoad(mnem, False, False, False, size=1, prefetch=True)
316        buildRegLoad(mnem, False, True, False, size=1, prefetch=True)
317        buildImmLoad(mnem, False, True, False, size=1, prefetch=True)
318
319    buildLoads("ldr")
320    buildLoads("ldrt", user=True)
321    buildLoads("ldrb", size=1)
322    buildLoads("ldrbt", size=1, user=True)
323    buildLoads("ldrsb", size=1, sign=True)
324    buildLoads("ldrsbt", size=1, sign=True, user=True)
325    buildLoads("ldrh", size=2)
326    buildLoads("ldrht", size=2, user=True)
327    buildLoads("hdrsh", size=2, sign=True)
328    buildLoads("ldrsht", size=2, sign=True, user=True)
329
330    buildDoubleLoads("ldrd")
331
332    buildRfeLoads("rfe")
333
334    buildPrefetches("pld")
335    buildPrefetches("pldw")
336    buildPrefetches("pli")
337
338    buildImmLoad("ldrex", False, True, False, size=4, ldrex=True)
339    buildImmLoad("ldrexh", False, True, False, size=2, ldrex=True)
340    buildImmLoad("ldrexb", False, True, False, size=1, ldrex=True)
341    buildDoubleImmLoad("ldrexd", False, True, False, ldrex=True)
342
343    buildImmLoad("vldr", False, True, False, size=4, vldr=True)
344    buildImmLoad("vldr", False, False, False, size=4, vldr=True)
345    buildDoubleImmLoad("vldr", False, True, False, vldr=True)
346    buildDoubleImmLoad("vldr", False, False, False, vldr=True)
347}};
348