macromem.isa revision 7639
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// 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 = Rb + (up ? imm : -imm);',
55                                    'predicate_test': predicateTest},
56                                   ['IsMicroop'])
57
58    microLdrFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
59    microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop',
60                                      'MicroMemOp',
61                                      {'memacc_code': microLdrFpUopCode,
62                                       'ea_code':
63                                           'EA = Rb + (up ? imm : -imm);',
64                                       'predicate_test': predicateTest},
65                                      ['IsMicroop'])
66
67    microLdrDBFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
68    microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop',
69                                      'MicroMemOp',
70                                      {'memacc_code': microLdrFpUopCode,
71                                       'ea_code': '''
72                                        EA = Rb + (up ? imm : -imm) +
73                                             (((CPSR)Cpsr).e ? 4 : 0);
74                                        ''',
75                                       'predicate_test': predicateTest},
76                                      ['IsMicroop'])
77
78    microLdrDTFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
79    microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop',
80                                      'MicroMemOp',
81                                      {'memacc_code': microLdrFpUopCode,
82                                       'ea_code': '''
83                                        EA = Rb + (up ? imm : -imm) -
84                                             (((CPSR)Cpsr).e ? 4 : 0);
85                                        ''',
86                                       'predicate_test': predicateTest},
87                                      ['IsMicroop'])
88
89    microLdrRetUopCode = '''
90        CPSR cpsr = Cpsr;
91        SCTLR sctlr = Sctlr;
92        uint32_t newCpsr =
93            cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi);
94        Cpsr = ~CondCodesMask & newCpsr;
95        CondCodes = CondCodesMask & newCpsr;
96        IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
97    '''
98    microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
99                                      'MicroMemOp',
100                                      {'memacc_code': microLdrRetUopCode,
101                                       'ea_code':
102                                          'EA = Rb + (up ? imm : -imm);',
103                                       'predicate_test': condPredicateTest},
104                                      ['IsMicroop'])
105
106    microStrUopCode = "Mem = cSwap(Ra.uw, ((CPSR)Cpsr).e);"
107    microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
108                                   'MicroMemOp',
109                                   {'memacc_code': microStrUopCode,
110                                    'postacc_code': "",
111                                    'ea_code': 'EA = Rb + (up ? imm : -imm);',
112                                    'predicate_test': predicateTest},
113                                   ['IsMicroop'])
114
115    microStrFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);"
116    microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop',
117                                     'MicroMemOp',
118                                     {'memacc_code': microStrFpUopCode,
119                                      'postacc_code': "",
120                                      'ea_code': 'EA = Rb + (up ? imm : -imm);',
121                                      'predicate_test': predicateTest},
122                                     ['IsMicroop'])
123
124    microStrDBFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);"
125    microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop',
126                                       'MicroMemOp',
127                                       {'memacc_code': microStrFpUopCode,
128                                        'postacc_code': "",
129                                        'ea_code': '''
130                                         EA = Rb + (up ? imm : -imm) +
131                                              (((CPSR)Cpsr).e ? 4 : 0);
132                                         ''',
133                                        'predicate_test': predicateTest},
134                                       ['IsMicroop'])
135
136    microStrDTFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);"
137    microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop',
138                                       'MicroMemOp',
139                                       {'memacc_code': microStrFpUopCode,
140                                        'postacc_code': "",
141                                        'ea_code': '''
142                                         EA = Rb + (up ? imm : -imm) -
143                                              (((CPSR)Cpsr).e ? 4 : 0);
144                                         ''',
145                                        'predicate_test': predicateTest},
146                                       ['IsMicroop'])
147
148    header_output = decoder_output = exec_output = ''
149
150    loadIops = (microLdrUopIop, microLdrRetUopIop,
151                microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop)
152    storeIops = (microStrUopIop, microStrFpUopIop,
153                 microStrDBFpUopIop, microStrDTFpUopIop)
154    for iop in loadIops + storeIops:
155        header_output += MicroMemDeclare.subst(iop)
156        decoder_output += MicroMemConstructor.subst(iop)
157    for iop in loadIops:
158        exec_output += LoadExecute.subst(iop) + \
159                       LoadInitiateAcc.subst(iop) + \
160                       LoadCompleteAcc.subst(iop)
161    for iop in storeIops:
162        exec_output += StoreExecute.subst(iop) + \
163                       StoreInitiateAcc.subst(iop) + \
164                       StoreCompleteAcc.subst(iop)
165}};
166
167let {{
168    exec_output = header_output = ''
169
170    eaCode = 'EA = Ra + imm;'
171
172    for size in (1, 2, 3, 4, 6, 8, 12, 16):
173        # Set up the memory access.
174        regs = (size + 3) // 4
175        subst = { "size" : size, "regs" : regs }
176        memDecl = '''
177        union MemUnion {
178            uint8_t bytes[%(size)d];
179            Element elements[%(size)d / sizeof(Element)];
180            uint32_t floatRegBits[%(regs)d];
181        };
182        ''' % subst
183
184        # Do endian conversion for all the elements.
185        convCode = '''
186            const unsigned eCount = sizeof(memUnion.elements) /
187                                    sizeof(memUnion.elements[0]);
188            if (((CPSR)Cpsr).e) {
189                for (unsigned i = 0; i < eCount; i++) {
190                    memUnion.elements[i] = gtobe(memUnion.elements[i]);
191                }
192            } else {
193                for (unsigned i = 0; i < eCount; i++) {
194                    memUnion.elements[i] = gtole(memUnion.elements[i]);
195                }
196            }
197        '''
198
199        # Offload everything into registers
200        regSetCode = ''
201        for reg in range(regs):
202            mask = ''
203            if reg == regs - 1:
204                mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size))
205            regSetCode += '''
206            FpDestP%(reg)d.uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s;
207            ''' % { "reg" : reg, "mask" : mask }
208
209        # Pull everything in from registers
210        regGetCode = ''
211        for reg in range(regs):
212            regGetCode += '''
213            memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d.uw);
214            ''' % { "reg" : reg }
215
216        loadMemAccCode = convCode + regSetCode
217        storeMemAccCode = regGetCode + convCode
218
219        loadIop = InstObjParams('ldrneon%(size)d_uop' % subst,
220                                'MicroLdrNeon%(size)dUop' % subst,
221                                'MicroNeonMemOp',
222                                { 'mem_decl' : memDecl,
223                                  'size' : size,
224                                  'memacc_code' : loadMemAccCode,
225                                  'ea_code' : eaCode,
226                                  'predicate_test' : predicateTest },
227                                [ 'IsMicroop', 'IsMemRef', 'IsLoad' ])
228        storeIop = InstObjParams('strneon%(size)d_uop' % subst,
229                                 'MicroStrNeon%(size)dUop' % subst,
230                                 'MicroNeonMemOp',
231                                 { 'mem_decl' : memDecl,
232                                   'size' : size,
233                                   'memacc_code' : storeMemAccCode,
234                                   'ea_code' : eaCode,
235                                   'predicate_test' : predicateTest },
236                                 [ 'IsMicroop', 'IsMemRef', 'IsStore' ])
237
238        exec_output += NeonLoadExecute.subst(loadIop) + \
239                       NeonLoadInitiateAcc.subst(loadIop) + \
240                       NeonLoadCompleteAcc.subst(loadIop) + \
241                       NeonStoreExecute.subst(storeIop) + \
242                       NeonStoreInitiateAcc.subst(storeIop) + \
243                       NeonStoreCompleteAcc.subst(storeIop)
244        header_output += MicroNeonMemDeclare.subst(loadIop) + \
245                         MicroNeonMemDeclare.subst(storeIop)
246}};
247
248let {{
249    exec_output = ''
250    for eSize, type in (1, 'uint8_t'), \
251                       (2, 'uint16_t'), \
252                       (4, 'uint32_t'), \
253                       (8, 'uint64_t'):
254        size = eSize
255        # An instruction handles no more than 16 bytes and no more than
256        # 4 elements, or the number of elements needed to fill 8 or 16 bytes.
257        sizes = set((16, 8))
258        for count in 1, 2, 3, 4:
259            size = count * eSize
260            if size <= 16:
261                sizes.add(size)
262        for size in sizes:
263            substDict = {
264                "class_name" : "MicroLdrNeon%dUop" % size,
265                "targs" : type
266            }
267            exec_output += MicroNeonMemExecDeclare.subst(substDict)
268            substDict["class_name"] = "MicroStrNeon%dUop" % size
269            exec_output += MicroNeonMemExecDeclare.subst(substDict)
270            size += eSize
271}};
272
273////////////////////////////////////////////////////////////////////
274//
275// Neon (de)interlacing microops
276//
277
278let {{
279    header_output = exec_output = ''
280    for dRegs in (2, 3, 4):
281        loadConv = ''
282        unloadConv = ''
283        for dReg in range(dRegs):
284            loadConv += '''
285                conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d.uw);
286                conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d.uw);
287            ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
288            unloadConv += '''
289                FpDestS%(dReg)dP0.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]);
290                FpDestS%(dReg)dP1.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]);
291            ''' % { "dReg" : dReg }
292        microDeintNeonCode = '''
293            const unsigned dRegs = %(dRegs)d;
294            const unsigned regs = 2 * dRegs;
295            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
296                                     sizeof(Element);
297            union convStruct {
298                FloatRegBits cRegs[regs];
299                Element elements[dRegs * perDReg];
300            } conv1, conv2;
301
302            %(loadConv)s
303
304            unsigned srcElem = 0;
305            for (unsigned destOffset = 0;
306                    destOffset < perDReg; destOffset++) {
307                for (unsigned dReg = 0; dReg < dRegs; dReg++) {
308                    conv2.elements[dReg * perDReg + destOffset] =
309                        conv1.elements[srcElem++];
310                }
311            }
312
313            %(unloadConv)s
314        ''' % { "dRegs" : dRegs,
315                "loadConv" : loadConv,
316                "unloadConv" : unloadConv }
317        microDeintNeonIop = \
318            InstObjParams('deintneon%duop' % (dRegs * 2),
319                          'MicroDeintNeon%dUop' % (dRegs * 2),
320                          'MicroNeonMixOp',
321                          { 'predicate_test': predicateTest,
322                            'code' : microDeintNeonCode },
323                            ['IsMicroop'])
324        header_output += MicroNeonMixDeclare.subst(microDeintNeonIop)
325        exec_output += MicroNeonMixExecute.subst(microDeintNeonIop)
326
327        loadConv = ''
328        unloadConv = ''
329        for dReg in range(dRegs):
330            loadConv += '''
331                conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0.uw);
332                conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1.uw);
333            ''' % { "dReg" : dReg }
334            unloadConv += '''
335                FpDestP%(sReg0)d.uw = gtoh(conv2.cRegs[%(sReg0)d]);
336                FpDestP%(sReg1)d.uw = gtoh(conv2.cRegs[%(sReg1)d]);
337            ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
338        microInterNeonCode = '''
339            const unsigned dRegs = %(dRegs)d;
340            const unsigned regs = 2 * dRegs;
341            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
342                                     sizeof(Element);
343            union convStruct {
344                FloatRegBits cRegs[regs];
345                Element elements[dRegs * perDReg];
346            } conv1, conv2;
347
348            %(loadConv)s
349
350            unsigned destElem = 0;
351            for (unsigned srcOffset = 0;
352                    srcOffset < perDReg; srcOffset++) {
353                for (unsigned dReg = 0; dReg < dRegs; dReg++) {
354                    conv2.elements[destElem++] =
355                        conv1.elements[dReg * perDReg + srcOffset];
356                }
357            }
358
359            %(unloadConv)s
360        ''' % { "dRegs" : dRegs,
361                "loadConv" : loadConv,
362                "unloadConv" : unloadConv }
363        microInterNeonIop = \
364            InstObjParams('interneon%duop' % (dRegs * 2),
365                          'MicroInterNeon%dUop' % (dRegs * 2),
366                          'MicroNeonMixOp',
367                          { 'predicate_test': predicateTest,
368                            'code' : microInterNeonCode },
369                            ['IsMicroop'])
370        header_output += MicroNeonMixDeclare.subst(microInterNeonIop)
371        exec_output += MicroNeonMixExecute.subst(microInterNeonIop)
372}};
373
374let {{
375    exec_output = ''
376    for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'):
377        for dRegs in (2, 3, 4):
378            Name = "MicroDeintNeon%dUop" % (dRegs * 2)
379            substDict = { "class_name" : Name, "targs" : type }
380            exec_output += MicroNeonExecDeclare.subst(substDict)
381            Name = "MicroInterNeon%dUop" % (dRegs * 2)
382            substDict = { "class_name" : Name, "targs" : type }
383            exec_output += MicroNeonExecDeclare.subst(substDict)
384}};
385
386////////////////////////////////////////////////////////////////////
387//
388// Neon microops to pack/unpack a single lane
389//
390
391let {{
392    header_output = exec_output = ''
393    for sRegs in 1, 2:
394        baseLoadRegs = ''
395        for reg in range(sRegs):
396            baseLoadRegs += '''
397                sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw);
398                sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw);
399            ''' % { "reg0" : (2 * reg + 0),
400                    "reg1" : (2 * reg + 1) }
401        for dRegs in range(sRegs, 5):
402            unloadRegs = ''
403            loadRegs = baseLoadRegs
404            for reg in range(dRegs):
405                loadRegs += '''
406                    destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0.uw);
407                    destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1.uw);
408                ''' % { "reg" : reg }
409                unloadRegs += '''
410                    FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]);
411                    FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]);
412                ''' % { "reg" : reg }
413            microUnpackNeonCode = '''
414            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
415                                     sizeof(Element);
416
417            union SourceRegs {
418                FloatRegBits fRegs[2 * %(sRegs)d];
419                Element elements[%(sRegs)d * perDReg];
420            } sourceRegs;
421
422            union DestReg {
423                FloatRegBits fRegs[2];
424                Element elements[perDReg];
425            } destRegs[%(dRegs)d];
426
427            %(loadRegs)s
428
429            for (unsigned i = 0; i < %(dRegs)d; i++) {
430                destRegs[i].elements[lane] = sourceRegs.elements[i];
431            }
432
433            %(unloadRegs)s
434            ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
435                    "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
436
437            microUnpackNeonIop = \
438                InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2),
439                              'MicroUnpackNeon%dto%dUop' %
440                                    (sRegs * 2, dRegs * 2),
441                              'MicroNeonMixLaneOp',
442                              { 'predicate_test': predicateTest,
443                                'code' : microUnpackNeonCode },
444                                ['IsMicroop'])
445            header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop)
446            exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop)
447
448    for sRegs in 1, 2:
449        loadRegs = ''
450        for reg in range(sRegs):
451            loadRegs += '''
452                sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw);
453                sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw);
454            ''' % { "reg0" : (2 * reg + 0),
455                    "reg1" : (2 * reg + 1) }
456        for dRegs in range(sRegs, 5):
457            unloadRegs = ''
458            for reg in range(dRegs):
459                unloadRegs += '''
460                    FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]);
461                    FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]);
462                ''' % { "reg" : reg }
463            microUnpackAllNeonCode = '''
464            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
465                                     sizeof(Element);
466
467            union SourceRegs {
468                FloatRegBits fRegs[2 * %(sRegs)d];
469                Element elements[%(sRegs)d * perDReg];
470            } sourceRegs;
471
472            union DestReg {
473                FloatRegBits fRegs[2];
474                Element elements[perDReg];
475            } destRegs[%(dRegs)d];
476
477            %(loadRegs)s
478
479            for (unsigned i = 0; i < %(dRegs)d; i++) {
480                for (unsigned j = 0; j < perDReg; j++)
481                    destRegs[i].elements[j] = sourceRegs.elements[i];
482            }
483
484            %(unloadRegs)s
485            ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
486                    "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
487
488            microUnpackAllNeonIop = \
489                InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2),
490                              'MicroUnpackAllNeon%dto%dUop' %
491                                    (sRegs * 2, dRegs * 2),
492                              'MicroNeonMixOp',
493                              { 'predicate_test': predicateTest,
494                                'code' : microUnpackAllNeonCode },
495                                ['IsMicroop'])
496            header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop)
497            exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop)
498
499    for dRegs in 1, 2:
500        unloadRegs = ''
501        for reg in range(dRegs):
502            unloadRegs += '''
503                FpDestP%(reg0)d.uw = gtoh(destRegs.fRegs[%(reg0)d]);
504                FpDestP%(reg1)d.uw = gtoh(destRegs.fRegs[%(reg1)d]);
505            ''' % { "reg0" : (2 * reg + 0),
506                    "reg1" : (2 * reg + 1) }
507        for sRegs in range(dRegs, 5):
508            loadRegs = ''
509            for reg in range(sRegs):
510                loadRegs += '''
511                    sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0.uw);
512                    sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1.uw);
513                ''' % { "reg" : reg }
514            microPackNeonCode = '''
515            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
516                                     sizeof(Element);
517
518            union SourceReg {
519                FloatRegBits fRegs[2];
520                Element elements[perDReg];
521            } sourceRegs[%(sRegs)d];
522
523            union DestRegs {
524                FloatRegBits fRegs[2 * %(dRegs)d];
525                Element elements[%(dRegs)d * perDReg];
526            } destRegs;
527
528            %(loadRegs)s
529
530            for (unsigned i = 0; i < %(sRegs)d; i++) {
531                destRegs.elements[i] = sourceRegs[i].elements[lane];
532            }
533
534            %(unloadRegs)s
535            ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
536                    "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
537
538            microPackNeonIop = \
539                InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2),
540                              'MicroPackNeon%dto%dUop' %
541                                    (sRegs * 2, dRegs * 2),
542                              'MicroNeonMixLaneOp',
543                              { 'predicate_test': predicateTest,
544                                'code' : microPackNeonCode },
545                                ['IsMicroop'])
546            header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop)
547            exec_output += MicroNeonMixExecute.subst(microPackNeonIop)
548}};
549
550let {{
551    exec_output = ''
552    for type in ('uint8_t', 'uint16_t', 'uint32_t'):
553        for sRegs in 1, 2:
554            for dRegs in range(sRegs, 5):
555                for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop",
556                               "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop",
557                               "MicroPackNeon%(dRegs)dto%(sRegs)dUop"):
558                    Name = format % { "sRegs" : sRegs * 2,
559                                      "dRegs" : dRegs * 2 }
560                    substDict = { "class_name" : Name, "targs" : type }
561                    exec_output += MicroNeonExecDeclare.subst(substDict)
562}};
563
564////////////////////////////////////////////////////////////////////
565//
566// Integer = Integer op Immediate microops
567//
568
569let {{
570    microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop',
571                                    'MicroIntImmOp',
572                                    {'code': 'Ra = Rb + imm;',
573                                     'predicate_test': predicateTest},
574                                    ['IsMicroop'])
575
576    microAddUopIop = InstObjParams('add_uop', 'MicroAddUop',
577                                   'MicroIntOp',
578                                   {'code': 'Ra = Rb + Rc;',
579                                    'predicate_test': predicateTest},
580                                   ['IsMicroop'])
581
582    microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop',
583                                    'MicroIntImmOp',
584                                    {'code': 'Ra = Rb - imm;',
585                                     'predicate_test': predicateTest},
586                                    ['IsMicroop'])
587
588    header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \
589                    MicroIntImmDeclare.subst(microSubiUopIop) + \
590                    MicroIntDeclare.subst(microAddUopIop)
591    decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \
592                     MicroIntImmConstructor.subst(microSubiUopIop) + \
593                     MicroIntConstructor.subst(microAddUopIop)
594    exec_output = PredOpExecute.subst(microAddiUopIop) + \
595                  PredOpExecute.subst(microSubiUopIop) + \
596                  PredOpExecute.subst(microAddUopIop)
597}};
598
599let {{
600    iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", [])
601    header_output = MacroMemDeclare.subst(iop)
602    decoder_output = MacroMemConstructor.subst(iop)
603
604    iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", [])
605    header_output += VMemMultDeclare.subst(iop)
606    decoder_output += VMemMultConstructor.subst(iop)
607
608    iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", [])
609    header_output += VMemSingleDeclare.subst(iop)
610    decoder_output += VMemSingleConstructor.subst(iop)
611
612    iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", [])
613    header_output += VMemMultDeclare.subst(iop)
614    decoder_output += VMemMultConstructor.subst(iop)
615
616    iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", [])
617    header_output += VMemSingleDeclare.subst(iop)
618    decoder_output += VMemSingleConstructor.subst(iop)
619
620    vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", [])
621    header_output += MacroVFPMemDeclare.subst(vfpIop)
622    decoder_output += MacroVFPMemConstructor.subst(vfpIop)
623}};
624