macromem.isa revision 8205
12068SN/A// -*- mode:c++ -*-
22068SN/A
32068SN/A// Copyright (c) 2010 ARM Limited
42068SN/A// All rights reserved
52068SN/A//
62068SN/A// The license below extends only to copyright in the software and shall
72068SN/A// not be construed as granting a license to any other intellectual
82068SN/A// property including but not limited to intellectual property relating
92068SN/A// to a hardware implementation of the functionality of the software
102068SN/A// licensed hereunder.  You may use the software subject to the license
112068SN/A// terms below provided that you ensure that this notice is replicated
122068SN/A// unmodified and in its entirety in all distributions of the software,
132068SN/A// modified or unmodified, in source code or in binary form.
142068SN/A//
152068SN/A// Copyright (c) 2007-2008 The Florida State University
162068SN/A// All rights reserved.
172068SN/A//
182068SN/A// Redistribution and use in source and binary forms, with or without
192068SN/A// modification, are permitted provided that the following conditions are
202068SN/A// met: redistributions of source code must retain the above copyright
212068SN/A// notice, this list of conditions and the following disclaimer;
222068SN/A// redistributions in binary form must reproduce the above copyright
232068SN/A// notice, this list of conditions and the following disclaimer in the
242068SN/A// documentation and/or other materials provided with the distribution;
252068SN/A// neither the name of the copyright holders nor the names of its
262068SN/A// contributors may be used to endorse or promote products derived from
272068SN/A// this software without specific prior written permission.
282665Ssaidi@eecs.umich.edu//
292665Ssaidi@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
302068SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
312649Ssaidi@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
322649Ssaidi@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
332649Ssaidi@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
342649Ssaidi@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
352649Ssaidi@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
362068SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372068SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
382068SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
392068SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402068SN/A//
412068SN/A// Authors: Stephen Hines
422068SN/A//          Gabe Black
432068SN/A
442068SN/A////////////////////////////////////////////////////////////////////
452068SN/A//
462227SN/A// Load/store microops
472068SN/A//
482068SN/A
492068SN/Alet {{
502068SN/A    microLdrUopCode = "IWRa = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
512068SN/A    microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop',
522068SN/A                                   'MicroMemOp',
532068SN/A                                   {'memacc_code': microLdrUopCode,
542068SN/A                                    'ea_code': 'EA = URb + (up ? imm : -imm);',
552068SN/A                                    'predicate_test': predicateTest},
562068SN/A                                   ['IsMicroop'])
572068SN/A
582068SN/A    microLdrFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
592068SN/A    microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop',
602068SN/A                                      'MicroMemOp',
612068SN/A                                      {'memacc_code': microLdrFpUopCode,
622068SN/A                                       'ea_code': vfpEnabledCheckCode +
632068SN/A                                           'EA = URb + (up ? imm : -imm);',
642068SN/A                                       'predicate_test': predicateTest},
652068SN/A                                      ['IsMicroop'])
662068SN/A
672068SN/A    microLdrDBFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
682068SN/A    microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop',
692068SN/A                                      'MicroMemOp',
702068SN/A                                      {'memacc_code': microLdrFpUopCode,
713953Sstever@eecs.umich.edu                                       'ea_code': vfpEnabledCheckCode + '''
722068SN/A                                        EA = URb + (up ? imm : -imm) +
732068SN/A                                             (((CPSR)Cpsr).e ? 4 : 0);
742068SN/A                                        ''',
752068SN/A                                       'predicate_test': predicateTest},
762068SN/A                                      ['IsMicroop'])
772068SN/A
782068SN/A    microLdrDTFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
792068SN/A    microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop',
802068SN/A                                      'MicroMemOp',
812068SN/A                                      {'memacc_code': microLdrFpUopCode,
822068SN/A                                       'ea_code': vfpEnabledCheckCode + '''
832068SN/A                                        EA = URb + (up ? imm : -imm) -
842068SN/A                                             (((CPSR)Cpsr).e ? 4 : 0);
852068SN/A                                        ''',
862068SN/A                                       'predicate_test': predicateTest},
877799Sgblack@eecs.umich.edu                                      ['IsMicroop'])
887799Sgblack@eecs.umich.edu
897799Sgblack@eecs.umich.edu    microRetUopCode = '''
907799Sgblack@eecs.umich.edu        CPSR cpsr = Cpsr;
912068SN/A        SCTLR sctlr = Sctlr;
922068SN/A        uint32_t newCpsr =
932227SN/A            cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi);
942068SN/A        Cpsr = ~CondCodesMask & newCpsr;
952068SN/A        CondCodes = CondCodesMask & newCpsr;
962068SN/A        IWNPC = cSwap(%s, cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
972068SN/A        NextItState = ((((CPSR)Spsr).it2 << 2) & 0xFC)
982068SN/A                | (((CPSR)Spsr).it1 & 0x3);
992068SN/A    '''
1002068SN/A
1012068SN/A    microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
1022068SN/A                                      'MicroMemOp',
1032227SN/A                                      {'memacc_code':
1042068SN/A                                          microRetUopCode % 'Mem.uw',
1052068SN/A                                       'ea_code':
1062068SN/A                                          'EA = URb + (up ? imm : -imm);',
1072068SN/A                                       'predicate_test': condPredicateTest},
1082068SN/A                                      ['IsMicroop','IsNonSpeculative',
1092068SN/A                                       'IsSerializeAfter'])
1102068SN/A
1112068SN/A    microStrUopCode = "Mem = cSwap(URa.uw, ((CPSR)Cpsr).e);"
1122068SN/A    microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
1132068SN/A                                   'MicroMemOp',
1142068SN/A                                   {'memacc_code': microStrUopCode,
1152068SN/A                                    'postacc_code': "",
1162068SN/A                                    'ea_code': 'EA = URb + (up ? imm : -imm);',
1172068SN/A                                    'predicate_test': predicateTest},
1182068SN/A                                   ['IsMicroop'])
1192068SN/A
1202068SN/A    microStrFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);"
1212068SN/A    microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop',
1222068SN/A                                     'MicroMemOp',
1232068SN/A                                     {'memacc_code': microStrFpUopCode,
1242068SN/A                                      'postacc_code': "",
1252068SN/A                                      'ea_code': vfpEnabledCheckCode +
1262068SN/A                                           'EA = URb + (up ? imm : -imm);',
1272068SN/A                                      'predicate_test': predicateTest},
1282068SN/A                                     ['IsMicroop'])
1292068SN/A
1302068SN/A    microStrDBFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);"
1312068SN/A    microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop',
1322068SN/A                                       'MicroMemOp',
1332068SN/A                                       {'memacc_code': microStrFpUopCode,
1343953Sstever@eecs.umich.edu                                        'postacc_code': "",
1352068SN/A                                        'ea_code': vfpEnabledCheckCode + '''
1362068SN/A                                         EA = URb + (up ? imm : -imm) +
1372068SN/A                                              (((CPSR)Cpsr).e ? 4 : 0);
1382068SN/A                                         ''',
1392068SN/A                                        'predicate_test': predicateTest},
1402068SN/A                                       ['IsMicroop'])
1412068SN/A
1422068SN/A    microStrDTFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);"
1432068SN/A    microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop',
1442068SN/A                                       'MicroMemOp',
1452068SN/A                                       {'memacc_code': microStrFpUopCode,
1462068SN/A                                        'postacc_code': "",
1472068SN/A                                        'ea_code': vfpEnabledCheckCode + '''
1482068SN/A                                         EA = URb + (up ? imm : -imm) -
1492068SN/A                                              (((CPSR)Cpsr).e ? 4 : 0);
1502068SN/A                                         ''',
1512068SN/A                                        'predicate_test': predicateTest},
1522068SN/A                                       ['IsMicroop'])
1532068SN/A
1542068SN/A    header_output = decoder_output = exec_output = ''
1552068SN/A
1562068SN/A    loadIops = (microLdrUopIop, microLdrRetUopIop,
1572068SN/A                microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop)
1586181Sksewell@umich.edu    storeIops = (microStrUopIop, microStrFpUopIop,
1592068SN/A                 microStrDBFpUopIop, microStrDTFpUopIop)
1602068SN/A    for iop in loadIops + storeIops:
1612068SN/A        header_output += MicroMemDeclare.subst(iop)
1622068SN/A        decoder_output += MicroMemConstructor.subst(iop)
1632068SN/A    for iop in loadIops:
1642068SN/A        exec_output += LoadExecute.subst(iop) + \
1652068SN/A                       LoadInitiateAcc.subst(iop) + \
1662068SN/A                       LoadCompleteAcc.subst(iop)
1672068SN/A    for iop in storeIops:
1682227SN/A        exec_output += StoreExecute.subst(iop) + \
1696181Sksewell@umich.edu                       StoreInitiateAcc.subst(iop) + \
1706181Sksewell@umich.edu                       StoreCompleteAcc.subst(iop)
1712068SN/A}};
1725736Snate@binkert.org
1735736Snate@binkert.orglet {{
1745736Snate@binkert.org    exec_output = header_output = ''
1755736Snate@binkert.org
1766076Sgblack@eecs.umich.edu    eaCode = 'EA = URa + imm;'
1772068SN/A
1782068SN/A    for size in (1, 2, 3, 4, 6, 8, 12, 16):
1792068SN/A        # Set up the memory access.
1802068SN/A        regs = (size + 3) // 4
1812068SN/A        subst = { "size" : size, "regs" : regs }
1822068SN/A        memDecl = '''
1832068SN/A        union MemUnion {
1842068SN/A            uint8_t bytes[%(size)d];
1852068SN/A            Element elements[%(size)d / sizeof(Element)];
1862068SN/A            uint32_t floatRegBits[%(regs)d];
1872068SN/A        };
1882068SN/A        ''' % subst
1892068SN/A
1902068SN/A        # Do endian conversion for all the elements.
1912068SN/A        convCode = '''
1922068SN/A            const unsigned eCount = sizeof(memUnion.elements) /
1932068SN/A                                    sizeof(memUnion.elements[0]);
1942068SN/A            if (((CPSR)Cpsr).e) {
1952068SN/A                for (unsigned i = 0; i < eCount; i++) {
1962068SN/A                    memUnion.elements[i] = gtobe(memUnion.elements[i]);
1972068SN/A                }
1982068SN/A            } else {
1992068SN/A                for (unsigned i = 0; i < eCount; i++) {
2002069SN/A                    memUnion.elements[i] = gtole(memUnion.elements[i]);
2012068SN/A                }
2022068SN/A            }
2032075SN/A        '''
2042075SN/A
2052069SN/A        # Offload everything into registers
2062069SN/A        regSetCode = ''
2072069SN/A        for reg in range(regs):
2082069SN/A            mask = ''
2092069SN/A            if reg == regs - 1:
2102069SN/A                mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size))
2112075SN/A            regSetCode += '''
2122075SN/A            FpDestP%(reg)d.uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s;
2132068SN/A            ''' % { "reg" : reg, "mask" : mask }
2142068SN/A
2152068SN/A        # Pull everything in from registers
2162075SN/A        regGetCode = ''
2172075SN/A        for reg in range(regs):
2182068SN/A            regGetCode += '''
2192068SN/A            memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d.uw);
2202075SN/A            ''' % { "reg" : reg }
2212075SN/A
2222068SN/A        loadMemAccCode = convCode + regSetCode
2232068SN/A        storeMemAccCode = regGetCode + convCode
2242068SN/A
2252068SN/A        loadIop = InstObjParams('ldrneon%(size)d_uop' % subst,
2262068SN/A                                'MicroLdrNeon%(size)dUop' % subst,
2272068SN/A                                'MicroNeonMemOp',
2282068SN/A                                { 'mem_decl' : memDecl,
2292068SN/A                                  'size' : size,
2302068SN/A                                  'memacc_code' : loadMemAccCode,
2312068SN/A                                  'ea_code' : simdEnabledCheckCode + eaCode,
2322068SN/A                                  'predicate_test' : predicateTest },
2332068SN/A                                [ 'IsMicroop', 'IsMemRef', 'IsLoad' ])
2342068SN/A        storeIop = InstObjParams('strneon%(size)d_uop' % subst,
2352068SN/A                                 'MicroStrNeon%(size)dUop' % subst,
2362227SN/A                                 'MicroNeonMemOp',
2372068SN/A                                 { 'mem_decl' : memDecl,
2382068SN/A                                   'size' : size,
2392068SN/A                                   'memacc_code' : storeMemAccCode,
2402068SN/A                                   'ea_code' : simdEnabledCheckCode + eaCode,
2412068SN/A                                   'predicate_test' : predicateTest },
2422068SN/A                                 [ 'IsMicroop', 'IsMemRef', 'IsStore' ])
2432068SN/A
2442068SN/A        exec_output += NeonLoadExecute.subst(loadIop) + \
2452068SN/A                       NeonLoadInitiateAcc.subst(loadIop) + \
2462068SN/A                       NeonLoadCompleteAcc.subst(loadIop) + \
2472068SN/A                       NeonStoreExecute.subst(storeIop) + \
2482068SN/A                       NeonStoreInitiateAcc.subst(storeIop) + \
2492068SN/A                       NeonStoreCompleteAcc.subst(storeIop)
2502068SN/A        header_output += MicroNeonMemDeclare.subst(loadIop) + \
2512068SN/A                         MicroNeonMemDeclare.subst(storeIop)
2522068SN/A}};
2532068SN/A
2542068SN/Alet {{
2552068SN/A    exec_output = ''
2562068SN/A    for eSize, type in (1, 'uint8_t'), \
2572068SN/A                       (2, 'uint16_t'), \
2582068SN/A                       (4, 'uint32_t'), \
2592068SN/A                       (8, 'uint64_t'):
2602068SN/A        size = eSize
2612068SN/A        # An instruction handles no more than 16 bytes and no more than
2622068SN/A        # 4 elements, or the number of elements needed to fill 8 or 16 bytes.
2632068SN/A        sizes = set((16, 8))
2642292SN/A        for count in 1, 2, 3, 4:
2652292SN/A            size = count * eSize
2662292SN/A            if size <= 16:
2673953Sstever@eecs.umich.edu                sizes.add(size)
2682068SN/A        for size in sizes:
2692068SN/A            substDict = {
2702068SN/A                "class_name" : "MicroLdrNeon%dUop" % size,
2712068SN/A                "targs" : type
2722068SN/A            }
2732068SN/A            exec_output += MicroNeonMemExecDeclare.subst(substDict)
2742068SN/A            substDict["class_name"] = "MicroStrNeon%dUop" % size
275            exec_output += MicroNeonMemExecDeclare.subst(substDict)
276            size += eSize
277}};
278
279////////////////////////////////////////////////////////////////////
280//
281// Neon (de)interlacing microops
282//
283
284let {{
285    header_output = exec_output = ''
286    for dRegs in (2, 3, 4):
287        loadConv = ''
288        unloadConv = ''
289        for dReg in range(dRegs):
290            loadConv += '''
291                conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d.uw);
292                conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d.uw);
293            ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
294            unloadConv += '''
295                FpDestS%(dReg)dP0.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]);
296                FpDestS%(dReg)dP1.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]);
297            ''' % { "dReg" : dReg }
298        microDeintNeonCode = '''
299            const unsigned dRegs = %(dRegs)d;
300            const unsigned regs = 2 * dRegs;
301            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
302                                     sizeof(Element);
303            union convStruct {
304                FloatRegBits cRegs[regs];
305                Element elements[dRegs * perDReg];
306            } conv1, conv2;
307
308            %(loadConv)s
309
310            unsigned srcElem = 0;
311            for (unsigned destOffset = 0;
312                    destOffset < perDReg; destOffset++) {
313                for (unsigned dReg = 0; dReg < dRegs; dReg++) {
314                    conv2.elements[dReg * perDReg + destOffset] =
315                        conv1.elements[srcElem++];
316                }
317            }
318
319            %(unloadConv)s
320        ''' % { "dRegs" : dRegs,
321                "loadConv" : loadConv,
322                "unloadConv" : unloadConv }
323        microDeintNeonIop = \
324            InstObjParams('deintneon%duop' % (dRegs * 2),
325                          'MicroDeintNeon%dUop' % (dRegs * 2),
326                          'MicroNeonMixOp',
327                          { 'predicate_test': predicateTest,
328                            'code' : microDeintNeonCode },
329                            ['IsMicroop'])
330        header_output += MicroNeonMixDeclare.subst(microDeintNeonIop)
331        exec_output += MicroNeonMixExecute.subst(microDeintNeonIop)
332
333        loadConv = ''
334        unloadConv = ''
335        for dReg in range(dRegs):
336            loadConv += '''
337                conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0.uw);
338                conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1.uw);
339            ''' % { "dReg" : dReg }
340            unloadConv += '''
341                FpDestP%(sReg0)d.uw = gtoh(conv2.cRegs[%(sReg0)d]);
342                FpDestP%(sReg1)d.uw = gtoh(conv2.cRegs[%(sReg1)d]);
343            ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
344        microInterNeonCode = '''
345            const unsigned dRegs = %(dRegs)d;
346            const unsigned regs = 2 * dRegs;
347            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
348                                     sizeof(Element);
349            union convStruct {
350                FloatRegBits cRegs[regs];
351                Element elements[dRegs * perDReg];
352            } conv1, conv2;
353
354            %(loadConv)s
355
356            unsigned destElem = 0;
357            for (unsigned srcOffset = 0;
358                    srcOffset < perDReg; srcOffset++) {
359                for (unsigned dReg = 0; dReg < dRegs; dReg++) {
360                    conv2.elements[destElem++] =
361                        conv1.elements[dReg * perDReg + srcOffset];
362                }
363            }
364
365            %(unloadConv)s
366        ''' % { "dRegs" : dRegs,
367                "loadConv" : loadConv,
368                "unloadConv" : unloadConv }
369        microInterNeonIop = \
370            InstObjParams('interneon%duop' % (dRegs * 2),
371                          'MicroInterNeon%dUop' % (dRegs * 2),
372                          'MicroNeonMixOp',
373                          { 'predicate_test': predicateTest,
374                            'code' : microInterNeonCode },
375                            ['IsMicroop'])
376        header_output += MicroNeonMixDeclare.subst(microInterNeonIop)
377        exec_output += MicroNeonMixExecute.subst(microInterNeonIop)
378}};
379
380let {{
381    exec_output = ''
382    for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'):
383        for dRegs in (2, 3, 4):
384            Name = "MicroDeintNeon%dUop" % (dRegs * 2)
385            substDict = { "class_name" : Name, "targs" : type }
386            exec_output += MicroNeonExecDeclare.subst(substDict)
387            Name = "MicroInterNeon%dUop" % (dRegs * 2)
388            substDict = { "class_name" : Name, "targs" : type }
389            exec_output += MicroNeonExecDeclare.subst(substDict)
390}};
391
392////////////////////////////////////////////////////////////////////
393//
394// Neon microops to pack/unpack a single lane
395//
396
397let {{
398    header_output = exec_output = ''
399    for sRegs in 1, 2:
400        baseLoadRegs = ''
401        for reg in range(sRegs):
402            baseLoadRegs += '''
403                sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw);
404                sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw);
405            ''' % { "reg0" : (2 * reg + 0),
406                    "reg1" : (2 * reg + 1) }
407        for dRegs in range(sRegs, 5):
408            unloadRegs = ''
409            loadRegs = baseLoadRegs
410            for reg in range(dRegs):
411                loadRegs += '''
412                    destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0.uw);
413                    destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1.uw);
414                ''' % { "reg" : reg }
415                unloadRegs += '''
416                    FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]);
417                    FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]);
418                ''' % { "reg" : reg }
419            microUnpackNeonCode = '''
420            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
421                                     sizeof(Element);
422
423            union SourceRegs {
424                FloatRegBits fRegs[2 * %(sRegs)d];
425                Element elements[%(sRegs)d * perDReg];
426            } sourceRegs;
427
428            union DestReg {
429                FloatRegBits fRegs[2];
430                Element elements[perDReg];
431            } destRegs[%(dRegs)d];
432
433            %(loadRegs)s
434
435            for (unsigned i = 0; i < %(dRegs)d; i++) {
436                destRegs[i].elements[lane] = sourceRegs.elements[i];
437            }
438
439            %(unloadRegs)s
440            ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
441                    "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
442
443            microUnpackNeonIop = \
444                InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2),
445                              'MicroUnpackNeon%dto%dUop' %
446                                    (sRegs * 2, dRegs * 2),
447                              'MicroNeonMixLaneOp',
448                              { 'predicate_test': predicateTest,
449                                'code' : microUnpackNeonCode },
450                                ['IsMicroop'])
451            header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop)
452            exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop)
453
454    for sRegs in 1, 2:
455        loadRegs = ''
456        for reg in range(sRegs):
457            loadRegs += '''
458                sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw);
459                sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw);
460            ''' % { "reg0" : (2 * reg + 0),
461                    "reg1" : (2 * reg + 1) }
462        for dRegs in range(sRegs, 5):
463            unloadRegs = ''
464            for reg in range(dRegs):
465                unloadRegs += '''
466                    FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]);
467                    FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]);
468                ''' % { "reg" : reg }
469            microUnpackAllNeonCode = '''
470            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
471                                     sizeof(Element);
472
473            union SourceRegs {
474                FloatRegBits fRegs[2 * %(sRegs)d];
475                Element elements[%(sRegs)d * perDReg];
476            } sourceRegs;
477
478            union DestReg {
479                FloatRegBits fRegs[2];
480                Element elements[perDReg];
481            } destRegs[%(dRegs)d];
482
483            %(loadRegs)s
484
485            for (unsigned i = 0; i < %(dRegs)d; i++) {
486                for (unsigned j = 0; j < perDReg; j++)
487                    destRegs[i].elements[j] = sourceRegs.elements[i];
488            }
489
490            %(unloadRegs)s
491            ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
492                    "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
493
494            microUnpackAllNeonIop = \
495                InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2),
496                              'MicroUnpackAllNeon%dto%dUop' %
497                                    (sRegs * 2, dRegs * 2),
498                              'MicroNeonMixOp',
499                              { 'predicate_test': predicateTest,
500                                'code' : microUnpackAllNeonCode },
501                                ['IsMicroop'])
502            header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop)
503            exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop)
504
505    for dRegs in 1, 2:
506        unloadRegs = ''
507        for reg in range(dRegs):
508            unloadRegs += '''
509                FpDestP%(reg0)d.uw = gtoh(destRegs.fRegs[%(reg0)d]);
510                FpDestP%(reg1)d.uw = gtoh(destRegs.fRegs[%(reg1)d]);
511            ''' % { "reg0" : (2 * reg + 0),
512                    "reg1" : (2 * reg + 1) }
513        for sRegs in range(dRegs, 5):
514            loadRegs = ''
515            for reg in range(sRegs):
516                loadRegs += '''
517                    sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0.uw);
518                    sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1.uw);
519                ''' % { "reg" : reg }
520            microPackNeonCode = '''
521            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
522                                     sizeof(Element);
523
524            union SourceReg {
525                FloatRegBits fRegs[2];
526                Element elements[perDReg];
527            } sourceRegs[%(sRegs)d];
528
529            union DestRegs {
530                FloatRegBits fRegs[2 * %(dRegs)d];
531                Element elements[%(dRegs)d * perDReg];
532            } destRegs;
533
534            %(loadRegs)s
535
536            for (unsigned i = 0; i < %(sRegs)d; i++) {
537                destRegs.elements[i] = sourceRegs[i].elements[lane];
538            }
539
540            %(unloadRegs)s
541            ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
542                    "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
543
544            microPackNeonIop = \
545                InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2),
546                              'MicroPackNeon%dto%dUop' %
547                                    (sRegs * 2, dRegs * 2),
548                              'MicroNeonMixLaneOp',
549                              { 'predicate_test': predicateTest,
550                                'code' : microPackNeonCode },
551                                ['IsMicroop'])
552            header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop)
553            exec_output += MicroNeonMixExecute.subst(microPackNeonIop)
554}};
555
556let {{
557    exec_output = ''
558    for type in ('uint8_t', 'uint16_t', 'uint32_t'):
559        for sRegs in 1, 2:
560            for dRegs in range(sRegs, 5):
561                for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop",
562                               "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop",
563                               "MicroPackNeon%(dRegs)dto%(sRegs)dUop"):
564                    Name = format % { "sRegs" : sRegs * 2,
565                                      "dRegs" : dRegs * 2 }
566                    substDict = { "class_name" : Name, "targs" : type }
567                    exec_output += MicroNeonExecDeclare.subst(substDict)
568}};
569
570////////////////////////////////////////////////////////////////////
571//
572// Integer = Integer op Immediate microops
573//
574
575let {{
576    microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop',
577                                    'MicroIntImmOp',
578                                    {'code': 'URa = URb + imm;',
579                                     'predicate_test': predicateTest},
580                                    ['IsMicroop'])
581
582    microAddUopIop = InstObjParams('add_uop', 'MicroAddUop',
583                                   'MicroIntRegOp',
584                                   {'code':
585                                    '''URa = URb + shift_rm_imm(URc, shiftAmt,
586                                                              shiftType,
587                                                              CondCodes<29:>);
588                                    ''',
589                                    'predicate_test': predicateTest},
590                                   ['IsMicroop'])
591
592    microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop',
593                                    'MicroIntImmOp',
594                                    {'code': 'URa = URb - imm;',
595                                     'predicate_test': predicateTest},
596                                    ['IsMicroop'])
597
598    microSubUopIop = InstObjParams('sub_uop', 'MicroSubUop',
599                                   'MicroIntRegOp',
600                                   {'code':
601                                    '''URa = URb - shift_rm_imm(URc, shiftAmt,
602                                                              shiftType,
603                                                              CondCodes<29:>);
604                                    ''',
605                                    'predicate_test': predicateTest},
606                                   ['IsMicroop'])
607
608    microUopRegMovIop = InstObjParams('uopReg_uop', 'MicroUopRegMov',
609                                   'MicroIntMov',
610                                   {'code': 'IWRa = URb;',
611                                    'predicate_test': predicateTest},
612                                   ['IsMicroop'])
613
614    microUopRegMovRetIop = InstObjParams('movret_uop', 'MicroUopRegMovRet',
615                                      'MicroIntMov',
616                                     {'code': microRetUopCode % 'URb',
617                                      'predicate_test': predicateTest},
618                                     ['IsMicroop', 'IsNonSpeculative',
619                                      'IsSerializeAfter'])
620
621    setPCCPSRDecl = '''
622                    CPSR cpsrOrCondCodes = URc;
623                    SCTLR sctlr = Sctlr;
624                    pNPC = URa;
625                    uint32_t newCpsr =
626                    cpsrWriteByInstr(cpsrOrCondCodes, URb,
627                                     0xF, true, sctlr.nmfi);
628                    Cpsr = ~CondCodesMask & newCpsr;
629                    NextThumb = ((CPSR)newCpsr).t;
630                    NextJazelle = ((CPSR)newCpsr).j;
631                    NextItState = ((((CPSR)URb).it2 << 2) & 0xFC)
632                                    | (((CPSR)URb).it1 & 0x3);
633                    CondCodes = CondCodesMask & newCpsr;
634                    '''
635
636    microUopSetPCCPSRIop = InstObjParams('uopSet_uop', 'MicroUopSetPCCPSR',
637                                         'MicroSetPCCPSR',
638                                         {'code': setPCCPSRDecl,
639                                          'predicate_test': predicateTest},
640                                         ['IsMicroop'])
641
642    header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \
643                    MicroIntImmDeclare.subst(microSubiUopIop) + \
644                    MicroIntRegDeclare.subst(microAddUopIop) + \
645                    MicroIntRegDeclare.subst(microSubUopIop) + \
646                    MicroIntMovDeclare.subst(microUopRegMovIop) + \
647                    MicroIntMovDeclare.subst(microUopRegMovRetIop) + \
648                    MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop)
649
650    decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \
651                     MicroIntImmConstructor.subst(microSubiUopIop) + \
652                     MicroIntRegConstructor.subst(microAddUopIop) + \
653                     MicroIntRegConstructor.subst(microSubUopIop) + \
654                     MicroIntMovConstructor.subst(microUopRegMovIop) + \
655                     MicroIntMovConstructor.subst(microUopRegMovRetIop) + \
656                     MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop)
657
658    exec_output = PredOpExecute.subst(microAddiUopIop) + \
659                  PredOpExecute.subst(microSubiUopIop) + \
660                  PredOpExecute.subst(microAddUopIop) + \
661                  PredOpExecute.subst(microSubUopIop) + \
662                  PredOpExecute.subst(microUopRegMovIop) + \
663                  PredOpExecute.subst(microUopRegMovRetIop) + \
664                  PredOpExecute.subst(microUopSetPCCPSRIop)
665
666}};
667
668let {{
669    iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", [])
670    header_output = MacroMemDeclare.subst(iop)
671    decoder_output = MacroMemConstructor.subst(iop)
672
673    iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", [])
674    header_output += VMemMultDeclare.subst(iop)
675    decoder_output += VMemMultConstructor.subst(iop)
676
677    iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", [])
678    header_output += VMemSingleDeclare.subst(iop)
679    decoder_output += VMemSingleConstructor.subst(iop)
680
681    iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", [])
682    header_output += VMemMultDeclare.subst(iop)
683    decoder_output += VMemMultConstructor.subst(iop)
684
685    iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", [])
686    header_output += VMemSingleDeclare.subst(iop)
687    decoder_output += VMemSingleConstructor.subst(iop)
688
689    vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", [])
690    header_output += MacroVFPMemDeclare.subst(vfpIop)
691    decoder_output += MacroVFPMemConstructor.subst(vfpIop)
692}};
693