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