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