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