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