ldr64.isa revision 10346
1// -*- mode:c++ -*-
2
3// Copyright (c) 2011-2014 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 LoadInst64(LoadStoreInst):
47        execBase = 'Load64'
48        micro = False
49
50        def __init__(self, mnem, Name, size=4, sign=False, user=False,
51                     literal=False, flavor="normal", top=False):
52            super(LoadInst64, self).__init__()
53
54            self.name = mnem
55            self.Name = Name
56            self.size = size
57            self.sign = sign
58            self.user = user
59            self.literal = literal
60            self.flavor = flavor
61            self.top = top
62
63            self.memFlags = ["ArmISA::TLB::MustBeOne"]
64            self.instFlags = []
65            self.codeBlobs = {"postacc_code" : ""}
66
67            # Add memory request flags where necessary
68            if self.user:
69                self.memFlags.append("ArmISA::TLB::UserMode")
70
71            if self.flavor == "dprefetch":
72                self.memFlags.append("Request::PREFETCH")
73                self.instFlags = ['IsDataPrefetch']
74            elif self.flavor == "iprefetch":
75                self.memFlags.append("Request::PREFETCH")
76                self.instFlags = ['IsInstPrefetch']
77            if self.micro:
78                self.instFlags.append("IsMicroop")
79
80            if self.flavor in ("acexp", "exp"):
81                # For exclusive pair ops alignment check is based on total size
82                self.memFlags.append("%d" % int(math.log(self.size, 2) + 1))
83            elif not (self.size == 16 and self.top):
84                # Only the first microop should perform alignment checking.
85                self.memFlags.append("%d" % int(math.log(self.size, 2)))
86
87            if self.flavor not in ("acquire", "acex", "exclusive",
88                                   "acexp", "exp"):
89                self.memFlags.append("ArmISA::TLB::AllowUnaligned")
90
91            if self.flavor in ("acquire", "acex", "acexp"):
92                self.instFlags.extend(["IsMemBarrier",
93                                       "IsWriteBarrier",
94                                       "IsReadBarrier"])
95            if self.flavor in ("acex", "exclusive", "exp", "acexp"):
96                self.memFlags.append("Request::LLSC")
97
98        def buildEACode(self):
99            # Address computation code
100            eaCode = ""
101            if self.flavor == "fp":
102                eaCode += vfp64EnabledCheckCode
103
104            if self.literal:
105                eaCode += "EA = RawPC"
106            else:
107                eaCode += SPAlignmentCheckCode + "EA = XBase"
108
109            if self.size == 16:
110                if self.top:
111                    eaCode += " + (isBigEndian64(xc->tcBase()) ? 0 : 8)"
112                else:
113                    eaCode += " + (isBigEndian64(xc->tcBase()) ? 8 : 0)"
114            if not self.post:
115                eaCode += self.offset
116            eaCode += ";"
117
118            self.codeBlobs["ea_code"] = eaCode
119
120        def emitHelper(self, base='Memory64', wbDecl=None):
121            global header_output, decoder_output, exec_output
122
123            # If this is a microop itself, don't allow anything that would
124            # require further microcoding.
125            if self.micro:
126                assert not wbDecl
127
128            fa_code = None
129            if not self.micro and self.flavor in ("normal", "widen", "acquire"):
130                fa_code = '''
131                    fault->annotate(ArmFault::SAS, %s);
132                    fault->annotate(ArmFault::SSE, %s);
133                    fault->annotate(ArmFault::SRT, dest);
134                    fault->annotate(ArmFault::SF, %s);
135                    fault->annotate(ArmFault::AR, %s);
136                ''' % ("0" if self.size == 1 else
137                       "1" if self.size == 2 else
138                       "2" if self.size == 4 else "3",
139                       "true" if self.sign else "false",
140                       "true" if (self.size == 8 or
141                                  self.flavor == "widen") else "false",
142                       "true" if self.flavor == "acquire" else "false")
143
144            (newHeader, newDecoder, newExec) = \
145                self.fillTemplates(self.name, self.Name, self.codeBlobs,
146                                   self.memFlags, self.instFlags,
147                                   base, wbDecl, faCode=fa_code)
148
149            header_output += newHeader
150            decoder_output += newDecoder
151            exec_output += newExec
152
153    class LoadImmInst64(LoadInst64):
154        def __init__(self, *args, **kargs):
155            super(LoadImmInst64, self).__init__(*args, **kargs)
156            self.offset = " + imm"
157
158            self.wbDecl = "MicroAddXiUop(machInst, base, base, imm);"
159
160    class LoadRegInst64(LoadInst64):
161        def __init__(self, *args, **kargs):
162            super(LoadRegInst64, self).__init__(*args, **kargs)
163            self.offset = " + extendReg64(XOffset, type, shiftAmt, 64)"
164
165            self.wbDecl = \
166                "MicroAddXERegUop(machInst, base, base, " + \
167                "                 offset, type, shiftAmt);"
168
169    class LoadRawRegInst64(LoadInst64):
170        def __init__(self, *args, **kargs):
171            super(LoadRawRegInst64, self).__init__(*args, **kargs)
172            self.offset = ""
173
174    class LoadSingle64(LoadInst64):
175        def emit(self):
176            self.buildEACode()
177
178            # Code that actually handles the access
179            if self.flavor in ("dprefetch", "iprefetch"):
180                accCode = 'uint64_t temp M5_VAR_USED = Mem%s;'
181            elif self.flavor == "fp":
182                if self.size in (1, 2, 4):
183                    accCode = '''
184                        AA64FpDestP0_uw = cSwap(Mem%s,
185                                                isBigEndian64(xc->tcBase()));
186                        AA64FpDestP1_uw = 0;
187                        AA64FpDestP2_uw = 0;
188                        AA64FpDestP3_uw = 0;
189                    '''
190                elif self.size == 8:
191                    accCode = '''
192                        uint64_t data = cSwap(Mem%s,
193                                              isBigEndian64(xc->tcBase()));
194                        AA64FpDestP0_uw = (uint32_t)data;
195                        AA64FpDestP1_uw = (data >> 32);
196                        AA64FpDestP2_uw = 0;
197                        AA64FpDestP3_uw = 0;
198                    '''
199                elif self.size == 16:
200                    accCode = '''
201                    Twin64_t data = cSwap(Mem%s,
202                                          isBigEndian64(xc->tcBase()));
203
204
205                    AA64FpDestP0_uw = (uint32_t)data.a;
206                    AA64FpDestP1_uw = (data.a >> 32);
207                    AA64FpDestP2_uw = (uint32_t)data.b;
208                    AA64FpDestP3_uw = (data.b >> 32);
209                    '''
210            elif self.flavor == "widen" or self.size == 8:
211                accCode = "XDest = cSwap(Mem%s, isBigEndian64(xc->tcBase()));"
212            else:
213                accCode = "WDest = cSwap(Mem%s, isBigEndian64(xc->tcBase()));"
214
215            accCode = accCode % buildMemSuffix(self.sign, self.size)
216
217            self.codeBlobs["memacc_code"] = accCode
218
219            # Push it out to the output files
220            wbDecl = None
221            if self.writeback and not self.micro:
222                wbDecl = self.wbDecl
223            self.emitHelper(self.base, wbDecl)
224
225    class LoadDouble64(LoadInst64):
226        def emit(self):
227            self.buildEACode()
228
229            # Code that actually handles the access
230            if self.flavor == "fp":
231                if self.size == 4:
232                    accCode = '''
233                        uint64_t data = cSwap(Mem_ud, isBigEndian64(xc->tcBase()));
234                        AA64FpDestP0_uw = (uint32_t)data;
235                        AA64FpDestP1_uw = 0;
236                        AA64FpDestP2_uw = 0;
237                        AA64FpDestP3_uw = 0;
238                        AA64FpDest2P0_uw = (data >> 32);
239                        AA64FpDest2P1_uw = 0;
240                        AA64FpDest2P2_uw = 0;
241                        AA64FpDest2P3_uw = 0;
242                    '''
243                elif self.size == 8:
244                    accCode = '''
245                        AA64FpDestP0_uw = (uint32_t)Mem_tud.a;
246                        AA64FpDestP1_uw = (uint32_t)(Mem_tud.a >> 32);
247                        AA64FpDestP2_uw = 0;
248                        AA64FpDestP3_uw = 0;
249                        AA64FpDest2P0_uw = (uint32_t)Mem_tud.b;
250                        AA64FpDest2P1_uw = (uint32_t)(Mem_tud.b >> 32);
251                        AA64FpDest2P2_uw = 0;
252                        AA64FpDest2P3_uw = 0;
253                    '''
254            else:
255                if self.sign:
256                    if self.size == 4:
257                        accCode = '''
258                            uint64_t data = cSwap(Mem_ud,
259                                                  isBigEndian64(xc->tcBase()));
260                            XDest = sext<32>((uint32_t)data);
261                            XDest2 = sext<32>(data >> 32);
262                        '''
263                    elif self.size == 8:
264                        accCode = '''
265                            XDest = Mem_tud.a;
266                            XDest2 = Mem_tud.b;
267                        '''
268                else:
269                    if self.size == 4:
270                        accCode = '''
271                            uint64_t data = cSwap(Mem_ud,
272                                                  isBigEndian64(xc->tcBase()));
273                            XDest = (uint32_t)data;
274                            XDest2 = data >> 32;
275                        '''
276                    elif self.size == 8:
277                        accCode = '''
278                            XDest = Mem_tud.a;
279                            XDest2 = Mem_tud.b;
280                        '''
281            self.codeBlobs["memacc_code"] = accCode
282
283            # Push it out to the output files
284            wbDecl = None
285            if self.writeback and not self.micro:
286                wbDecl = self.wbDecl
287            self.emitHelper(self.base, wbDecl)
288
289    class LoadImm64(LoadImmInst64, LoadSingle64):
290        decConstBase = 'LoadStoreImm64'
291        base = 'ArmISA::MemoryImm64'
292        writeback = False
293        post = False
294
295    class LoadPre64(LoadImmInst64, LoadSingle64):
296        decConstBase = 'LoadStoreImm64'
297        base = 'ArmISA::MemoryPreIndex64'
298        writeback = True
299        post = False
300
301    class LoadPost64(LoadImmInst64, LoadSingle64):
302        decConstBase = 'LoadStoreImm64'
303        base = 'ArmISA::MemoryPostIndex64'
304        writeback = True
305        post = True
306
307    class LoadReg64(LoadRegInst64, LoadSingle64):
308        decConstBase = 'LoadStoreReg64'
309        base = 'ArmISA::MemoryReg64'
310        writeback = False
311        post = False
312
313    class LoadRaw64(LoadRawRegInst64, LoadSingle64):
314        decConstBase = 'LoadStoreRaw64'
315        base = 'ArmISA::MemoryRaw64'
316        writeback = False
317        post = False
318
319    class LoadEx64(LoadRawRegInst64, LoadSingle64):
320        decConstBase = 'LoadStoreEx64'
321        base = 'ArmISA::MemoryEx64'
322        writeback = False
323        post = False
324
325    class LoadLit64(LoadImmInst64, LoadSingle64):
326        decConstBase = 'LoadStoreLit64'
327        base = 'ArmISA::MemoryLiteral64'
328        writeback = False
329        post = False
330
331    def buildLoads64(mnem, NameBase, size, sign, flavor="normal"):
332        LoadImm64(mnem, NameBase + "_IMM", size, sign, flavor=flavor).emit()
333        LoadPre64(mnem, NameBase + "_PRE", size, sign, flavor=flavor).emit()
334        LoadPost64(mnem, NameBase + "_POST", size, sign, flavor=flavor).emit()
335        LoadReg64(mnem, NameBase + "_REG", size, sign, flavor=flavor).emit()
336
337    buildLoads64("ldrb", "LDRB64", 1, False)
338    buildLoads64("ldrsb", "LDRSBW64", 1, True)
339    buildLoads64("ldrsb", "LDRSBX64", 1, True, flavor="widen")
340    buildLoads64("ldrh", "LDRH64", 2, False)
341    buildLoads64("ldrsh", "LDRSHW64", 2, True)
342    buildLoads64("ldrsh", "LDRSHX64", 2, True, flavor="widen")
343    buildLoads64("ldrsw", "LDRSW64", 4, True, flavor="widen")
344    buildLoads64("ldr", "LDRW64", 4, False)
345    buildLoads64("ldr", "LDRX64", 8, False)
346    buildLoads64("ldr", "LDRBFP64", 1, False, flavor="fp")
347    buildLoads64("ldr", "LDRHFP64", 2, False, flavor="fp")
348    buildLoads64("ldr", "LDRSFP64", 4, False, flavor="fp")
349    buildLoads64("ldr", "LDRDFP64", 8, False, flavor="fp")
350
351    LoadImm64("prfm", "PRFM64_IMM", 8, flavor="dprefetch").emit()
352    LoadReg64("prfm", "PRFM64_REG", 8, flavor="dprefetch").emit()
353    LoadLit64("prfm", "PRFM64_LIT", 8, literal=True, flavor="dprefetch").emit()
354    LoadImm64("prfum", "PRFUM64_IMM", 8, flavor="dprefetch").emit()
355
356    LoadImm64("ldurb", "LDURB64_IMM", 1, False).emit()
357    LoadImm64("ldursb", "LDURSBW64_IMM", 1, True).emit()
358    LoadImm64("ldursb", "LDURSBX64_IMM", 1, True, flavor="widen").emit()
359    LoadImm64("ldurh", "LDURH64_IMM", 2, False).emit()
360    LoadImm64("ldursh", "LDURSHW64_IMM", 2, True).emit()
361    LoadImm64("ldursh", "LDURSHX64_IMM", 2, True, flavor="widen").emit()
362    LoadImm64("ldursw", "LDURSW64_IMM", 4, True, flavor="widen").emit()
363    LoadImm64("ldur", "LDURW64_IMM", 4, False).emit()
364    LoadImm64("ldur", "LDURX64_IMM", 8, False).emit()
365    LoadImm64("ldur", "LDURBFP64_IMM", 1, flavor="fp").emit()
366    LoadImm64("ldur", "LDURHFP64_IMM", 2, flavor="fp").emit()
367    LoadImm64("ldur", "LDURSFP64_IMM", 4, flavor="fp").emit()
368    LoadImm64("ldur", "LDURDFP64_IMM", 8, flavor="fp").emit()
369
370    LoadImm64("ldtrb", "LDTRB64_IMM", 1, False, True).emit()
371    LoadImm64("ldtrsb", "LDTRSBW64_IMM", 1, True, True).emit()
372    LoadImm64("ldtrsb", "LDTRSBX64_IMM", 1, True, True, flavor="widen").emit()
373    LoadImm64("ldtrh", "LDTRH64_IMM", 2, False, True).emit()
374    LoadImm64("ldtrsh", "LDTRSHW64_IMM", 2, True, True).emit()
375    LoadImm64("ldtrsh", "LDTRSHX64_IMM", 2, True, True, flavor="widen").emit()
376    LoadImm64("ldtrsw", "LDTRSW64_IMM", 4, True, flavor="widen").emit()
377    LoadImm64("ldtr", "LDTRW64_IMM", 4, False, True).emit()
378    LoadImm64("ldtr", "LDTRX64_IMM", 8, False, True).emit()
379
380    LoadLit64("ldrsw", "LDRSWL64_LIT", 4, True, \
381              literal=True, flavor="widen").emit()
382    LoadLit64("ldr", "LDRWL64_LIT", 4, False, literal=True).emit()
383    LoadLit64("ldr", "LDRXL64_LIT", 8, False, literal=True).emit()
384    LoadLit64("ldr", "LDRSFP64_LIT", 4, literal=True, flavor="fp").emit()
385    LoadLit64("ldr", "LDRDFP64_LIT", 8, literal=True, flavor="fp").emit()
386
387    LoadRaw64("ldar", "LDARX64", 8, flavor="acquire").emit()
388    LoadRaw64("ldar", "LDARW64", 4, flavor="acquire").emit()
389    LoadRaw64("ldarh", "LDARH64", 2, flavor="acquire").emit()
390    LoadRaw64("ldarb", "LDARB64", 1, flavor="acquire").emit()
391
392    LoadEx64("ldaxr", "LDAXRX64", 8, flavor="acex").emit()
393    LoadEx64("ldaxr", "LDAXRW64", 4, flavor="acex").emit()
394    LoadEx64("ldaxrh", "LDAXRH64", 2, flavor="acex").emit()
395    LoadEx64("ldaxrb", "LDAXRB64", 1, flavor="acex").emit()
396
397    LoadEx64("ldxr", "LDXRX64", 8, flavor="exclusive").emit()
398    LoadEx64("ldxr", "LDXRW64", 4, flavor="exclusive").emit()
399    LoadEx64("ldxrh", "LDXRH64", 2, flavor="exclusive").emit()
400    LoadEx64("ldxrb", "LDXRB64", 1, flavor="exclusive").emit()
401
402    class LoadImmU64(LoadImm64):
403        decConstBase = 'LoadStoreImmU64'
404        micro = True
405
406    class LoadImmDU64(LoadImmInst64, LoadDouble64):
407        decConstBase = 'LoadStoreImmDU64'
408        base = 'ArmISA::MemoryDImm64'
409        micro = True
410        post = False
411        writeback = False
412
413    class LoadImmDouble64(LoadImmInst64, LoadDouble64):
414        decConstBase = 'LoadStoreImmDU64'
415        base = 'ArmISA::MemoryDImm64'
416        micro = False
417        post = False
418        writeback = False
419
420    class LoadRegU64(LoadReg64):
421        decConstBase = 'LoadStoreRegU64'
422        micro = True
423
424    class LoadLitU64(LoadLit64):
425        decConstBase = 'LoadStoreLitU64'
426        micro = True
427
428    LoadImmDU64("ldp_uop", "MicroLdPairUop", 8).emit()
429    LoadImmDU64("ldp_fp8_uop", "MicroLdPairFp8Uop", 8, flavor="fp").emit()
430    LoadImmU64("ldfp16_uop", "MicroLdFp16Uop", 16, flavor="fp").emit()
431    LoadReg64("ldfp16reg_uop", "MicroLdFp16RegUop", 16, flavor="fp").emit()
432
433    LoadImmDouble64("ldaxp", "LDAXPW64", 4, flavor="acexp").emit()
434    LoadImmDouble64("ldaxp", "LDAXPX64", 8, flavor="acexp").emit()
435    LoadImmDouble64("ldxp", "LDXPW64", 4, flavor="exp").emit()
436    LoadImmDouble64("ldxp", "LDXPX64", 8, flavor="exp").emit()
437
438    LoadImmU64("ldrxi_uop", "MicroLdrXImmUop", 8).emit()
439    LoadRegU64("ldrxr_uop", "MicroLdrXRegUop", 8).emit()
440    LoadLitU64("ldrxl_uop", "MicroLdrXLitUop", 8, literal=True).emit()
441    LoadImmU64("ldrfpxi_uop", "MicroLdrFpXImmUop", 8, flavor="fp").emit()
442    LoadRegU64("ldrfpxr_uop", "MicroLdrFpXRegUop", 8, flavor="fp").emit()
443    LoadLitU64("ldrfpxl_uop", "MicroLdrFpXLitUop", 8, literal=True,
444               flavor="fp").emit()
445    LoadLitU64("ldfp16_lit__uop", "MicroLdFp16LitUop",
446               16, literal=True, flavor="fp").emit()
447    LoadImmDU64("ldrduxi_uop", "MicroLdrDUXImmUop", 4, sign=False).emit()
448    LoadImmDU64("ldrdsxi_uop", "MicroLdrDSXImmUop", 4, sign=True).emit()
449    LoadImmDU64("ldrdfpxi_uop", "MicroLdrDFpXImmUop", 4, flavor="fp").emit()
450}};
451