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