macromem.isa revision 10474:799c8ee4ecba
1// -*- mode:c++ -*-
2
3// Copyright (c) 2010-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// Copyright (c) 2007-2008 The Florida State University
16// All rights reserved.
17//
18// Redistribution and use in source and binary forms, with or without
19// modification, are permitted provided that the following conditions are
20// met: redistributions of source code must retain the above copyright
21// notice, this list of conditions and the following disclaimer;
22// redistributions in binary form must reproduce the above copyright
23// notice, this list of conditions and the following disclaimer in the
24// documentation and/or other materials provided with the distribution;
25// neither the name of the copyright holders nor the names of its
26// contributors may be used to endorse or promote products derived from
27// this software without specific prior written permission.
28//
29// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40//
41// Authors: Stephen Hines
42//          Gabe Black
43
44////////////////////////////////////////////////////////////////////
45//
46// Load/store microops
47//
48
49let {{
50    microLdrUopCode = "IWRa = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
51    microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop',
52                                   'MicroMemOp',
53                                   {'memacc_code': microLdrUopCode,
54                                    'ea_code': 'EA = URb + (up ? imm : -imm);',
55                                    'predicate_test': predicateTest},
56                                   ['IsMicroop'])
57
58    microLdr2UopCode = '''
59                        uint64_t data = Mem_ud;
60                        Dest = cSwap((uint32_t) data, ((CPSR)Cpsr).e);
61                        Dest2 = cSwap((uint32_t) (data >> 32), ((CPSR)Cpsr).e);
62                        '''
63    microLdr2UopIop = InstObjParams('ldr2_uop', 'MicroLdr2Uop',
64                                   'MicroMemPairOp',
65                                   {'memacc_code': microLdr2UopCode,
66                                    'ea_code': 'EA = URb + (up ? imm : -imm);',
67                                    'predicate_test': predicateTest},
68                                   ['IsMicroop'])
69
70    microLdrFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
71    microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop',
72                                      'MicroMemOp',
73                                      {'memacc_code': microLdrFpUopCode,
74                                       'ea_code': vfpEnabledCheckCode +
75                                           'EA = URb + (up ? imm : -imm);',
76                                       'predicate_test': predicateTest},
77                                      ['IsMicroop'])
78
79    microLdrDBFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
80    microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop',
81                                      'MicroMemOp',
82                                      {'memacc_code': microLdrFpUopCode,
83                                       'ea_code': vfpEnabledCheckCode + '''
84                                        EA = URb + (up ? imm : -imm) +
85                                             (((CPSR)Cpsr).e ? 4 : 0);
86                                        ''',
87                                       'predicate_test': predicateTest},
88                                      ['IsMicroop'])
89
90    microLdrDTFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
91    microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop',
92                                      'MicroMemOp',
93                                      {'memacc_code': microLdrFpUopCode,
94                                       'ea_code': vfpEnabledCheckCode + '''
95                                        EA = URb + (up ? imm : -imm) -
96                                             (((CPSR)Cpsr).e ? 4 : 0);
97                                        ''',
98                                       'predicate_test': predicateTest},
99                                      ['IsMicroop'])
100
101    microRetUopCode = '''
102        CPSR old_cpsr = Cpsr;
103        SCTLR sctlr = Sctlr;
104
105        CPSR new_cpsr =
106            cpsrWriteByInstr(old_cpsr, Spsr, Scr, Nsacr, 0xF, true,
107                             sctlr.nmfi, xc->tcBase());
108        Cpsr = ~CondCodesMask & new_cpsr;
109        CondCodesNZ = new_cpsr.nz;
110        CondCodesC = new_cpsr.c;
111        CondCodesV = new_cpsr.v;
112        CondCodesGE = new_cpsr.ge;
113        IWNPC = cSwap(%s, old_cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
114        NextItState = ((((CPSR)Spsr).it2 << 2) & 0xFC)
115                | (((CPSR)Spsr).it1 & 0x3);
116        SevMailbox = 1;
117    '''
118
119    microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
120                                      'MicroMemOp',
121                                      {'memacc_code':
122                                          microRetUopCode % 'Mem_uw',
123                                       'ea_code':
124                                          'EA = URb + (up ? imm : -imm);',
125                                       'predicate_test': condPredicateTest},
126                                      ['IsMicroop','IsNonSpeculative',
127                                       'IsSerializeAfter'])
128
129    microStrUopCode = "Mem = cSwap(URa_uw, ((CPSR)Cpsr).e);"
130    microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
131                                   'MicroMemOp',
132                                   {'memacc_code': microStrUopCode,
133                                    'postacc_code': "",
134                                    'ea_code': 'EA = URb + (up ? imm : -imm);',
135                                    'predicate_test': predicateTest},
136                                   ['IsMicroop'])
137
138    microStrFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);"
139    microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop',
140                                     'MicroMemOp',
141                                     {'memacc_code': microStrFpUopCode,
142                                      'postacc_code': "",
143                                      'ea_code': vfpEnabledCheckCode +
144                                           'EA = URb + (up ? imm : -imm);',
145                                      'predicate_test': predicateTest},
146                                     ['IsMicroop'])
147
148    microStrDBFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);"
149    microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop',
150                                       'MicroMemOp',
151                                       {'memacc_code': microStrFpUopCode,
152                                        'postacc_code': "",
153                                        'ea_code': vfpEnabledCheckCode + '''
154                                         EA = URb + (up ? imm : -imm) +
155                                              (((CPSR)Cpsr).e ? 4 : 0);
156                                         ''',
157                                        'predicate_test': predicateTest},
158                                       ['IsMicroop'])
159
160    microStrDTFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);"
161    microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop',
162                                       'MicroMemOp',
163                                       {'memacc_code': microStrFpUopCode,
164                                        'postacc_code': "",
165                                        'ea_code': vfpEnabledCheckCode + '''
166                                         EA = URb + (up ? imm : -imm) -
167                                              (((CPSR)Cpsr).e ? 4 : 0);
168                                         ''',
169                                        'predicate_test': predicateTest},
170                                       ['IsMicroop'])
171
172    header_output = decoder_output = exec_output = ''
173
174    loadIops = (microLdrUopIop, microLdrRetUopIop,
175                microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop)
176    storeIops = (microStrUopIop, microStrFpUopIop,
177                 microStrDBFpUopIop, microStrDTFpUopIop)
178    for iop in loadIops + storeIops:
179        header_output += MicroMemDeclare.subst(iop)
180        decoder_output += MicroMemConstructor.subst(iop)
181    for iop in loadIops:
182        exec_output += LoadExecute.subst(iop) + \
183                       LoadInitiateAcc.subst(iop) + \
184                       LoadCompleteAcc.subst(iop)
185    for iop in storeIops:
186        exec_output += StoreExecute.subst(iop) + \
187                       StoreInitiateAcc.subst(iop) + \
188                       StoreCompleteAcc.subst(iop)
189
190    header_output += MicroMemPairDeclare.subst(microLdr2UopIop)
191    decoder_output += MicroMemPairConstructor.subst(microLdr2UopIop)
192    exec_output += LoadExecute.subst(microLdr2UopIop) + \
193                   LoadInitiateAcc.subst(microLdr2UopIop) + \
194                   LoadCompleteAcc.subst(microLdr2UopIop)
195}};
196
197let {{
198    exec_output = header_output = ''
199
200    eaCode = 'EA = XURa + imm;'
201
202    for size in (1, 2, 3, 4, 6, 8, 12, 16):
203        # Set up the memory access.
204        regs = (size + 3) // 4
205        subst = { "size" : size, "regs" : regs }
206        memDecl = '''
207        union MemUnion {
208            uint8_t bytes[%(size)d];
209            Element elements[%(size)d / sizeof(Element)];
210            uint32_t floatRegBits[%(regs)d];
211        };
212        ''' % subst
213
214        # Do endian conversion for all the elements.
215        convCode = '''
216            const unsigned eCount = sizeof(memUnion.elements) /
217                                    sizeof(memUnion.elements[0]);
218            if (((CPSR)Cpsr).e) {
219                for (unsigned i = 0; i < eCount; i++) {
220                    memUnion.elements[i] = gtobe(memUnion.elements[i]);
221                }
222            } else {
223                for (unsigned i = 0; i < eCount; i++) {
224                    memUnion.elements[i] = gtole(memUnion.elements[i]);
225                }
226            }
227        '''
228
229        # Offload everything into registers
230        regSetCode = ''
231        for reg in range(regs):
232            mask = ''
233            if reg == regs - 1:
234                mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size))
235            regSetCode += '''
236            FpDestP%(reg)d_uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s;
237            ''' % { "reg" : reg, "mask" : mask }
238
239        # Pull everything in from registers
240        regGetCode = ''
241        for reg in range(regs):
242            regGetCode += '''
243            memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d_uw);
244            ''' % { "reg" : reg }
245
246        loadMemAccCode = convCode + regSetCode
247        storeMemAccCode = regGetCode + convCode
248
249        loadIop = InstObjParams('ldrneon%(size)d_uop' % subst,
250                                'MicroLdrNeon%(size)dUop' % subst,
251                                'MicroNeonMemOp',
252                                { 'mem_decl' : memDecl,
253                                  'size' : size,
254                                  'memacc_code' : loadMemAccCode,
255                                  'ea_code' : simdEnabledCheckCode + eaCode,
256                                  'predicate_test' : predicateTest },
257                                [ 'IsMicroop', 'IsMemRef', 'IsLoad' ])
258        storeIop = InstObjParams('strneon%(size)d_uop' % subst,
259                                 'MicroStrNeon%(size)dUop' % subst,
260                                 'MicroNeonMemOp',
261                                 { 'mem_decl' : memDecl,
262                                   'size' : size,
263                                   'memacc_code' : storeMemAccCode,
264                                   'ea_code' : simdEnabledCheckCode + eaCode,
265                                   'predicate_test' : predicateTest },
266                                 [ 'IsMicroop', 'IsMemRef', 'IsStore' ])
267
268        exec_output += NeonLoadExecute.subst(loadIop) + \
269                       NeonLoadInitiateAcc.subst(loadIop) + \
270                       NeonLoadCompleteAcc.subst(loadIop) + \
271                       NeonStoreExecute.subst(storeIop) + \
272                       NeonStoreInitiateAcc.subst(storeIop) + \
273                       NeonStoreCompleteAcc.subst(storeIop)
274        header_output += MicroNeonMemDeclare.subst(loadIop) + \
275                         MicroNeonMemDeclare.subst(storeIop)
276}};
277
278let {{
279    exec_output = ''
280    for eSize, type in (1, 'uint8_t'), \
281                       (2, 'uint16_t'), \
282                       (4, 'uint32_t'), \
283                       (8, 'uint64_t'):
284        size = eSize
285        # An instruction handles no more than 16 bytes and no more than
286        # 4 elements, or the number of elements needed to fill 8 or 16 bytes.
287        sizes = set((16, 8))
288        for count in 1, 2, 3, 4:
289            size = count * eSize
290            if size <= 16:
291                sizes.add(size)
292        for size in sizes:
293            substDict = {
294                "class_name" : "MicroLdrNeon%dUop" % size,
295                "targs" : type
296            }
297            exec_output += MicroNeonMemExecDeclare.subst(substDict)
298            substDict["class_name"] = "MicroStrNeon%dUop" % size
299            exec_output += MicroNeonMemExecDeclare.subst(substDict)
300            size += eSize
301}};
302
303////////////////////////////////////////////////////////////////////
304//
305// Neon (de)interlacing microops
306//
307
308let {{
309    header_output = exec_output = ''
310    for dRegs in (2, 3, 4):
311        loadConv = ''
312        unloadConv = ''
313        for dReg in range(dRegs):
314            loadConv += '''
315                conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d_uw);
316                conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d_uw);
317            ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
318            unloadConv += '''
319                FpDestS%(dReg)dP0_uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]);
320                FpDestS%(dReg)dP1_uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]);
321            ''' % { "dReg" : dReg }
322        microDeintNeonCode = '''
323            const unsigned dRegs = %(dRegs)d;
324            const unsigned regs = 2 * dRegs;
325            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
326                                     sizeof(Element);
327            union convStruct {
328                FloatRegBits cRegs[regs];
329                Element elements[dRegs * perDReg];
330            } conv1, conv2;
331
332            %(loadConv)s
333
334            unsigned srcElem = 0;
335            for (unsigned destOffset = 0;
336                    destOffset < perDReg; destOffset++) {
337                for (unsigned dReg = 0; dReg < dRegs; dReg++) {
338                    conv2.elements[dReg * perDReg + destOffset] =
339                        conv1.elements[srcElem++];
340                }
341            }
342
343            %(unloadConv)s
344        ''' % { "dRegs" : dRegs,
345                "loadConv" : loadConv,
346                "unloadConv" : unloadConv }
347        microDeintNeonIop = \
348            InstObjParams('deintneon%duop' % (dRegs * 2),
349                          'MicroDeintNeon%dUop' % (dRegs * 2),
350                          'MicroNeonMixOp',
351                          { 'predicate_test': predicateTest,
352                            'code' : microDeintNeonCode },
353                            ['IsMicroop'])
354        header_output += MicroNeonMixDeclare.subst(microDeintNeonIop)
355        exec_output += MicroNeonMixExecute.subst(microDeintNeonIop)
356
357        loadConv = ''
358        unloadConv = ''
359        for dReg in range(dRegs):
360            loadConv += '''
361                conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0_uw);
362                conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1_uw);
363            ''' % { "dReg" : dReg }
364            unloadConv += '''
365                FpDestP%(sReg0)d_uw = gtoh(conv2.cRegs[%(sReg0)d]);
366                FpDestP%(sReg1)d_uw = gtoh(conv2.cRegs[%(sReg1)d]);
367            ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
368        microInterNeonCode = '''
369            const unsigned dRegs = %(dRegs)d;
370            const unsigned regs = 2 * dRegs;
371            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
372                                     sizeof(Element);
373            union convStruct {
374                FloatRegBits cRegs[regs];
375                Element elements[dRegs * perDReg];
376            } conv1, conv2;
377
378            %(loadConv)s
379
380            unsigned destElem = 0;
381            for (unsigned srcOffset = 0;
382                    srcOffset < perDReg; srcOffset++) {
383                for (unsigned dReg = 0; dReg < dRegs; dReg++) {
384                    conv2.elements[destElem++] =
385                        conv1.elements[dReg * perDReg + srcOffset];
386                }
387            }
388
389            %(unloadConv)s
390        ''' % { "dRegs" : dRegs,
391                "loadConv" : loadConv,
392                "unloadConv" : unloadConv }
393        microInterNeonIop = \
394            InstObjParams('interneon%duop' % (dRegs * 2),
395                          'MicroInterNeon%dUop' % (dRegs * 2),
396                          'MicroNeonMixOp',
397                          { 'predicate_test': predicateTest,
398                            'code' : microInterNeonCode },
399                            ['IsMicroop'])
400        header_output += MicroNeonMixDeclare.subst(microInterNeonIop)
401        exec_output += MicroNeonMixExecute.subst(microInterNeonIop)
402}};
403
404let {{
405    exec_output = ''
406    for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'):
407        for dRegs in (2, 3, 4):
408            Name = "MicroDeintNeon%dUop" % (dRegs * 2)
409            substDict = { "class_name" : Name, "targs" : type }
410            exec_output += MicroNeonExecDeclare.subst(substDict)
411            Name = "MicroInterNeon%dUop" % (dRegs * 2)
412            substDict = { "class_name" : Name, "targs" : type }
413            exec_output += MicroNeonExecDeclare.subst(substDict)
414}};
415
416////////////////////////////////////////////////////////////////////
417//
418// Neon microops to pack/unpack a single lane
419//
420
421let {{
422    header_output = exec_output = ''
423    for sRegs in 1, 2:
424        baseLoadRegs = ''
425        for reg in range(sRegs):
426            baseLoadRegs += '''
427                sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d_uw);
428                sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d_uw);
429            ''' % { "reg0" : (2 * reg + 0),
430                    "reg1" : (2 * reg + 1) }
431        for dRegs in range(sRegs, 5):
432            unloadRegs = ''
433            loadRegs = baseLoadRegs
434            for reg in range(dRegs):
435                loadRegs += '''
436                    destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0_uw);
437                    destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1_uw);
438                ''' % { "reg" : reg }
439                unloadRegs += '''
440                    FpDestS%(reg)dP0_uw = gtoh(destRegs[%(reg)d].fRegs[0]);
441                    FpDestS%(reg)dP1_uw = gtoh(destRegs[%(reg)d].fRegs[1]);
442                ''' % { "reg" : reg }
443            microUnpackNeonCode = '''
444            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
445                                     sizeof(Element);
446
447            union SourceRegs {
448                FloatRegBits fRegs[2 * %(sRegs)d];
449                Element elements[%(sRegs)d * perDReg];
450            } sourceRegs;
451
452            union DestReg {
453                FloatRegBits fRegs[2];
454                Element elements[perDReg];
455            } destRegs[%(dRegs)d];
456
457            %(loadRegs)s
458
459            for (unsigned i = 0; i < %(dRegs)d; i++) {
460                destRegs[i].elements[lane] = sourceRegs.elements[i];
461            }
462
463            %(unloadRegs)s
464            ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
465                    "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
466
467            microUnpackNeonIop = \
468                InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2),
469                              'MicroUnpackNeon%dto%dUop' %
470                                    (sRegs * 2, dRegs * 2),
471                              'MicroNeonMixLaneOp',
472                              { 'predicate_test': predicateTest,
473                                'code' : microUnpackNeonCode },
474                                ['IsMicroop'])
475            header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop)
476            exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop)
477
478    for sRegs in 1, 2:
479        loadRegs = ''
480        for reg in range(sRegs):
481            loadRegs += '''
482                sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d_uw);
483                sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d_uw);
484            ''' % { "reg0" : (2 * reg + 0),
485                    "reg1" : (2 * reg + 1) }
486        for dRegs in range(sRegs, 5):
487            unloadRegs = ''
488            for reg in range(dRegs):
489                unloadRegs += '''
490                    FpDestS%(reg)dP0_uw = gtoh(destRegs[%(reg)d].fRegs[0]);
491                    FpDestS%(reg)dP1_uw = gtoh(destRegs[%(reg)d].fRegs[1]);
492                ''' % { "reg" : reg }
493            microUnpackAllNeonCode = '''
494            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
495                                     sizeof(Element);
496
497            union SourceRegs {
498                FloatRegBits fRegs[2 * %(sRegs)d];
499                Element elements[%(sRegs)d * perDReg];
500            } sourceRegs;
501
502            union DestReg {
503                FloatRegBits fRegs[2];
504                Element elements[perDReg];
505            } destRegs[%(dRegs)d];
506
507            %(loadRegs)s
508
509            for (unsigned i = 0; i < %(dRegs)d; i++) {
510                for (unsigned j = 0; j < perDReg; j++)
511                    destRegs[i].elements[j] = sourceRegs.elements[i];
512            }
513
514            %(unloadRegs)s
515            ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
516                    "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
517
518            microUnpackAllNeonIop = \
519                InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2),
520                              'MicroUnpackAllNeon%dto%dUop' %
521                                    (sRegs * 2, dRegs * 2),
522                              'MicroNeonMixOp',
523                              { 'predicate_test': predicateTest,
524                                'code' : microUnpackAllNeonCode },
525                                ['IsMicroop'])
526            header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop)
527            exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop)
528
529    for dRegs in 1, 2:
530        unloadRegs = ''
531        for reg in range(dRegs):
532            unloadRegs += '''
533                FpDestP%(reg0)d_uw = gtoh(destRegs.fRegs[%(reg0)d]);
534                FpDestP%(reg1)d_uw = gtoh(destRegs.fRegs[%(reg1)d]);
535            ''' % { "reg0" : (2 * reg + 0),
536                    "reg1" : (2 * reg + 1) }
537        for sRegs in range(dRegs, 5):
538            loadRegs = ''
539            for reg in range(sRegs):
540                loadRegs += '''
541                    sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0_uw);
542                    sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1_uw);
543                ''' % { "reg" : reg }
544            microPackNeonCode = '''
545            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
546                                     sizeof(Element);
547
548            union SourceReg {
549                FloatRegBits fRegs[2];
550                Element elements[perDReg];
551            } sourceRegs[%(sRegs)d];
552
553            union DestRegs {
554                FloatRegBits fRegs[2 * %(dRegs)d];
555                Element elements[%(dRegs)d * perDReg];
556            } destRegs;
557
558            %(loadRegs)s
559
560            for (unsigned i = 0; i < %(sRegs)d; i++) {
561                destRegs.elements[i] = sourceRegs[i].elements[lane];
562            }
563            for (unsigned i = %(sRegs)d; i < %(dRegs)d * perDReg; ++i) {
564                destRegs.elements[i] = 0;
565            }
566
567            %(unloadRegs)s
568            ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
569                    "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
570
571            microPackNeonIop = \
572                InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2),
573                              'MicroPackNeon%dto%dUop' %
574                                    (sRegs * 2, dRegs * 2),
575                              'MicroNeonMixLaneOp',
576                              { 'predicate_test': predicateTest,
577                                'code' : microPackNeonCode },
578                                ['IsMicroop'])
579            header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop)
580            exec_output += MicroNeonMixExecute.subst(microPackNeonIop)
581}};
582
583let {{
584    exec_output = ''
585    for typeSize in (8, 16, 32):
586        for sRegs in 1, 2:
587            for dRegs in range(sRegs, min(sRegs * 64 / typeSize + 1, 5)):
588                for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop",
589                               "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop",
590                               "MicroPackNeon%(dRegs)dto%(sRegs)dUop"):
591                    Name = format % { "sRegs" : sRegs * 2,
592                                      "dRegs" : dRegs * 2 }
593                    substDict = { "class_name" : Name,
594                                  "targs" : "uint%d_t" % typeSize }
595                    exec_output += MicroNeonExecDeclare.subst(substDict)
596}};
597
598////////////////////////////////////////////////////////////////////
599//
600// Integer = Integer op Immediate microops
601//
602
603let {{
604    microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop',
605                                    'MicroIntImmOp',
606                                    {'code': 'URa = URb + imm;',
607                                     'predicate_test': predicateTest},
608                                    ['IsMicroop'])
609
610    microAddUopCode = '''
611        URa = URb + shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC);
612    '''
613
614    microAddXiUopIop = InstObjParams('addxi_uop', 'MicroAddXiUop',
615                                     'MicroIntImmXOp',
616                                     'XURa = XURb + imm;',
617                                     ['IsMicroop'])
618
619    microAddXiSpAlignUopIop = InstObjParams('addxi_uop', 'MicroAddXiSpAlignUop',
620                                            'MicroIntImmXOp', '''
621        if (isSP((IntRegIndex) urb) && bits(XURb, 3, 0) &&
622            SPAlignmentCheckEnabled(xc->tcBase())) {
623            return std::make_shared<SPAlignmentFault>();
624        }
625        XURa = XURb + imm;
626    ''', ['IsMicroop'])
627
628    microAddXERegUopIop = InstObjParams('addxr_uop', 'MicroAddXERegUop',
629                                        'MicroIntRegXOp',
630                                        'XURa = XURb + ' + \
631                                            'extendReg64(XURc, type, shiftAmt, 64);',
632                                        ['IsMicroop'])
633
634    microAddUopIop = InstObjParams('add_uop', 'MicroAddUop',
635                                   'MicroIntRegOp',
636                                   {'code': microAddUopCode,
637                                    'predicate_test': pickPredicate(microAddUopCode)},
638                                   ['IsMicroop'])
639
640    microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop',
641                                    'MicroIntImmOp',
642                                    {'code': 'URa = URb - imm;',
643                                     'predicate_test': predicateTest},
644                                    ['IsMicroop'])
645
646    microSubXiUopIop = InstObjParams('subxi_uop', 'MicroSubXiUop',
647                                     'MicroIntImmXOp',
648                                     'XURa = XURb - imm;',
649                                     ['IsMicroop'])
650
651    microSubUopCode = '''
652        URa = URb - shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC);
653    '''
654    microSubUopIop = InstObjParams('sub_uop', 'MicroSubUop',
655                                   'MicroIntRegOp',
656                                   {'code': microSubUopCode,
657                                    'predicate_test': pickPredicate(microSubUopCode)},
658                                   ['IsMicroop'])
659
660    microUopRegMovIop = InstObjParams('uopReg_uop', 'MicroUopRegMov',
661                                   'MicroIntMov',
662                                   {'code': 'IWRa = URb;',
663                                    'predicate_test': predicateTest},
664                                   ['IsMicroop'])
665
666    microUopRegMovRetIop = InstObjParams('movret_uop', 'MicroUopRegMovRet',
667                                      'MicroIntMov',
668                                     {'code': microRetUopCode % 'URb',
669                                      'predicate_test': predicateTest},
670                                     ['IsMicroop', 'IsNonSpeculative',
671                                      'IsSerializeAfter'])
672
673    setPCCPSRDecl = '''
674                    CPSR cpsrOrCondCodes = URc;
675                    SCTLR sctlr = Sctlr;
676                    pNPC = URa;
677                    CPSR new_cpsr =
678                    cpsrWriteByInstr(cpsrOrCondCodes, URb, Scr, Nsacr,
679                                     0xF, true, sctlr.nmfi, xc->tcBase());
680                    Cpsr = ~CondCodesMask & new_cpsr;
681                    NextThumb = new_cpsr.t;
682                    NextJazelle = new_cpsr.j;
683                    NextItState = ((((CPSR)URb).it2 << 2) & 0xFC)
684                                    | (((CPSR)URb).it1 & 0x3);
685                    CondCodesNZ = new_cpsr.nz;
686                    CondCodesC = new_cpsr.c;
687                    CondCodesV = new_cpsr.v;
688                    CondCodesGE = new_cpsr.ge;
689                    '''
690
691    microUopSetPCCPSRIop = InstObjParams('uopSet_uop', 'MicroUopSetPCCPSR',
692                                         'MicroSetPCCPSR',
693                                         {'code': setPCCPSRDecl,
694                                          'predicate_test': predicateTest},
695                                         ['IsMicroop'])
696
697    header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \
698                    MicroIntImmDeclare.subst(microAddXiUopIop) + \
699                    MicroIntImmDeclare.subst(microAddXiSpAlignUopIop) + \
700                    MicroIntImmDeclare.subst(microSubiUopIop) + \
701                    MicroIntImmDeclare.subst(microSubXiUopIop) + \
702                    MicroIntRegDeclare.subst(microAddUopIop) + \
703                    MicroIntRegDeclare.subst(microSubUopIop) + \
704                    MicroIntXERegDeclare.subst(microAddXERegUopIop) + \
705                    MicroIntMovDeclare.subst(microUopRegMovIop) + \
706                    MicroIntMovDeclare.subst(microUopRegMovRetIop) + \
707                    MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop)
708
709    decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \
710                     MicroIntImmXConstructor.subst(microAddXiUopIop) + \
711                     MicroIntImmXConstructor.subst(microAddXiSpAlignUopIop) + \
712                     MicroIntImmConstructor.subst(microSubiUopIop) + \
713                     MicroIntImmXConstructor.subst(microSubXiUopIop) + \
714                     MicroIntRegConstructor.subst(microAddUopIop) + \
715                     MicroIntRegConstructor.subst(microSubUopIop) + \
716                     MicroIntXERegConstructor.subst(microAddXERegUopIop) + \
717                     MicroIntMovConstructor.subst(microUopRegMovIop) + \
718                     MicroIntMovConstructor.subst(microUopRegMovRetIop) + \
719                     MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop)
720
721    exec_output = PredOpExecute.subst(microAddiUopIop) + \
722                  BasicExecute.subst(microAddXiUopIop) + \
723                  BasicExecute.subst(microAddXiSpAlignUopIop) + \
724                  PredOpExecute.subst(microSubiUopIop) + \
725                  BasicExecute.subst(microSubXiUopIop) + \
726                  PredOpExecute.subst(microAddUopIop) + \
727                  PredOpExecute.subst(microSubUopIop) + \
728                  BasicExecute.subst(microAddXERegUopIop) + \
729                  PredOpExecute.subst(microUopRegMovIop) + \
730                  PredOpExecute.subst(microUopRegMovRetIop) + \
731                  PredOpExecute.subst(microUopSetPCCPSRIop)
732
733}};
734
735let {{
736    iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", [])
737    header_output = MacroMemDeclare.subst(iop)
738    decoder_output = MacroMemConstructor.subst(iop)
739
740    iop = InstObjParams("ldpstp", "LdpStp", 'PairMemOp', "", [])
741    header_output += PairMemDeclare.subst(iop)
742    decoder_output += PairMemConstructor.subst(iop)
743
744    iopImm = InstObjParams("bigfpmemimm", "BigFpMemImm", "BigFpMemImmOp", "")
745    iopPre = InstObjParams("bigfpmempre", "BigFpMemPre", "BigFpMemPreOp", "")
746    iopPost = InstObjParams("bigfpmempost", "BigFpMemPost", "BigFpMemPostOp", "")
747    for iop in (iopImm, iopPre, iopPost):
748        header_output += BigFpMemImmDeclare.subst(iop)
749        decoder_output += BigFpMemImmConstructor.subst(iop)
750
751    iop = InstObjParams("bigfpmemreg", "BigFpMemReg", "BigFpMemRegOp", "")
752    header_output += BigFpMemRegDeclare.subst(iop)
753    decoder_output += BigFpMemRegConstructor.subst(iop)
754
755    iop = InstObjParams("bigfpmemlit", "BigFpMemLit", "BigFpMemLitOp", "")
756    header_output += BigFpMemLitDeclare.subst(iop)
757    decoder_output += BigFpMemLitConstructor.subst(iop)
758
759    iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", [])
760    header_output += VMemMultDeclare.subst(iop)
761    decoder_output += VMemMultConstructor.subst(iop)
762
763    iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", [])
764    header_output += VMemSingleDeclare.subst(iop)
765    decoder_output += VMemSingleConstructor.subst(iop)
766
767    iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", [])
768    header_output += VMemMultDeclare.subst(iop)
769    decoder_output += VMemMultConstructor.subst(iop)
770
771    iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", [])
772    header_output += VMemSingleDeclare.subst(iop)
773    decoder_output += VMemSingleConstructor.subst(iop)
774
775    vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", [])
776    header_output += MacroVFPMemDeclare.subst(vfpIop)
777    decoder_output += MacroVFPMemConstructor.subst(vfpIop)
778}};
779