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