macromem.isa revision 12134
12SN/A// -*- mode:c++ -*-
21762SN/A
32SN/A// Copyright (c) 2010-2014 ARM Limited
42SN/A// All rights reserved
52SN/A//
62SN/A// The license below extends only to copyright in the software and shall
72SN/A// not be construed as granting a license to any other intellectual
82SN/A// property including but not limited to intellectual property relating
92SN/A// to a hardware implementation of the functionality of the software
102SN/A// licensed hereunder.  You may use the software subject to the license
112SN/A// terms below provided that you ensure that this notice is replicated
122SN/A// unmodified and in its entirety in all distributions of the software,
132SN/A// modified or unmodified, in source code or in binary form.
142SN/A//
152SN/A// Copyright (c) 2007-2008 The Florida State University
162SN/A// All rights reserved.
172SN/A//
182SN/A// Redistribution and use in source and binary forms, with or without
192SN/A// modification, are permitted provided that the following conditions are
202SN/A// met: redistributions of source code must retain the above copyright
212SN/A// notice, this list of conditions and the following disclaimer;
222SN/A// redistributions in binary form must reproduce the above copyright
232SN/A// notice, this list of conditions and the following disclaimer in the
242SN/A// documentation and/or other materials provided with the distribution;
252SN/A// neither the name of the copyright holders nor the names of its
262SN/A// contributors may be used to endorse or promote products derived from
272665Ssaidi@eecs.umich.edu// 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
302SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
312SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32360SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33360SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
342SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
352SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
362SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
382SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
392SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
401858SN/A//
411858SN/A// Authors: Stephen Hines
421858SN/A//          Gabe Black
432SN/A
444117Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////
45180SN/A//
462SN/A// Load/store microops
472378SN/A//
484111Sgblack@eecs.umich.edu
4956SN/Alet {{
502SN/A    microLdrUopCode = "IWRa = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
515154Sgblack@eecs.umich.edu    microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop',
525154Sgblack@eecs.umich.edu                                   'MicroMemOp',
535154Sgblack@eecs.umich.edu                                   {'memacc_code': microLdrUopCode,
545154Sgblack@eecs.umich.edu                                    'ea_code': 'EA = URb + (up ? imm : -imm);',
555154Sgblack@eecs.umich.edu                                    'predicate_test': predicateTest},
565154Sgblack@eecs.umich.edu                                   ['IsMicroop'])
572680Sktlim@umich.edu
582401SN/A    microLdr2UopCode = '''
593971Sgblack@eecs.umich.edu                        uint64_t data = Mem_ud;
603971Sgblack@eecs.umich.edu                        Dest = cSwap((uint32_t) data, ((CPSR)Cpsr).e);
613971Sgblack@eecs.umich.edu                        IWDest2 = cSwap((uint32_t) (data >> 32),
623971Sgblack@eecs.umich.edu                                        ((CPSR)Cpsr).e);
632378SN/A                        '''
642SN/A    microLdr2UopIop = InstObjParams('ldr2_uop', 'MicroLdr2Uop',
652SN/A                                   'MicroMemPairOp',
662SN/A                                   {'memacc_code': microLdr2UopCode,
672SN/A                                    'ea_code': 'EA = URb + (up ? imm : -imm);',
682378SN/A                                    'predicate_test': predicateTest},
692378SN/A                                   ['IsMicroop'])
702378SN/A
712378SN/A    microLdrFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
722680Sktlim@umich.edu    microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop',
732SN/A                                      'MicroMemOp',
742SN/A                                      {'memacc_code': microLdrFpUopCode,
752SN/A                                       'ea_code': vfpEnabledCheckCode +
762SN/A                                           'EA = URb + (up ? imm : -imm);',
772680Sktlim@umich.edu                                       'predicate_test': predicateTest},
782680Sktlim@umich.edu                                      ['IsMicroop'])
79180SN/A
803971Sgblack@eecs.umich.edu    microLdrDBFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
813971Sgblack@eecs.umich.edu    microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop',
823971Sgblack@eecs.umich.edu                                      'MicroMemOp',
833971Sgblack@eecs.umich.edu                                      {'memacc_code': microLdrFpUopCode,
843971Sgblack@eecs.umich.edu                                       'ea_code': vfpEnabledCheckCode + '''
85180SN/A                                        EA = URb + (up ? imm : -imm) +
862680Sktlim@umich.edu                                             (((CPSR)Cpsr).e ? 4 : 0);
872SN/A                                        ''',
882SN/A                                       'predicate_test': predicateTest},
892SN/A                                      ['IsMicroop'])
902SN/A
912SN/A    microLdrDTFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
922680Sktlim@umich.edu    microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop',
932SN/A                                      'MicroMemOp',
942680Sktlim@umich.edu                                      {'memacc_code': microLdrFpUopCode,
952SN/A                                       'ea_code': vfpEnabledCheckCode + '''
962378SN/A                                        EA = URb + (up ? imm : -imm) -
972SN/A                                             (((CPSR)Cpsr).e ? 4 : 0);
982SN/A                                        ''',
992SN/A                                       'predicate_test': predicateTest},
1002SN/A                                      ['IsMicroop'])
1012SN/A
1022SN/A    microRetUopCode = '''
1032SN/A        CPSR old_cpsr = Cpsr;
1042SN/A        SCTLR sctlr = Sctlr;
1052SN/A
1062SN/A        CPSR new_cpsr =
1072SN/A            cpsrWriteByInstr(old_cpsr, Spsr, Scr, Nsacr, 0xF, true,
1085154Sgblack@eecs.umich.edu                             sctlr.nmfi, xc->tcBase());
1095154Sgblack@eecs.umich.edu        Cpsr = ~CondCodesMask & new_cpsr;
1105154Sgblack@eecs.umich.edu        CondCodesNZ = new_cpsr.nz;
1112SN/A        CondCodesC = new_cpsr.c;
1122SN/A        CondCodesV = new_cpsr.v;
1132SN/A        CondCodesGE = new_cpsr.ge;
114360SN/A        IWNPC = cSwap(%s, old_cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
1151408SN/A        NextItState = ((((CPSR)Spsr).it2 << 2) & 0xFC)
1161408SN/A                | (((CPSR)Spsr).it1 & 0x3);
117360SN/A        SevMailbox = 1;
1181514SN/A    '''
1191514SN/A
1201514SN/A    microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
1211514SN/A                                      'MicroMemOp',
1222SN/A                                      {'memacc_code':
1232SN/A                                          microRetUopCode % 'Mem_uw',
124729SN/A                                       'ea_code':
1252SN/A                                          'EA = URb + (up ? imm : -imm);',
1262SN/A                                       'predicate_test': condPredicateTest},
1272SN/A                                      ['IsMicroop','IsNonSpeculative',
1282SN/A                                       'IsSerializeAfter', 'IsSquashAfter'])
1295154Sgblack@eecs.umich.edu
1302SN/A    microStrUopCode = "Mem = cSwap(URa_uw, ((CPSR)Cpsr).e);"
1311395SN/A    microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
1321395SN/A                                   'MicroMemOp',
1332SN/A                                   {'memacc_code': microStrUopCode,
1342SN/A                                    'postacc_code': "",
1352378SN/A                                    'ea_code': 'EA = URb + (up ? imm : -imm);',
1362401SN/A                                    'predicate_test': predicateTest},
1372378SN/A                                   ['IsMicroop'])
1382378SN/A
1392378SN/A    microStrFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);"
1402SN/A    microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop',
1414997Sgblack@eecs.umich.edu                                     'MicroMemOp',
1424997Sgblack@eecs.umich.edu                                     {'memacc_code': microStrFpUopCode,
1434997Sgblack@eecs.umich.edu                                      'postacc_code': "",
1444997Sgblack@eecs.umich.edu                                      'ea_code': vfpEnabledCheckCode +
1452SN/A                                           'EA = URb + (up ? imm : -imm);',
1462SN/A                                      'predicate_test': predicateTest},
1471970SN/A                                     ['IsMicroop'])
1482SN/A
1492SN/A    microStrDBFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);"
1502SN/A    microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop',
1512SN/A                                       'MicroMemOp',
1522SN/A                                       {'memacc_code': microStrFpUopCode,
1532SN/A                                        'postacc_code': "",
1542SN/A                                        'ea_code': vfpEnabledCheckCode + '''
1552SN/A                                         EA = URb + (up ? imm : -imm) +
1562SN/A                                              (((CPSR)Cpsr).e ? 4 : 0);
1572SN/A                                         ''',
1582680Sktlim@umich.edu                                        'predicate_test': predicateTest},
1592680Sktlim@umich.edu                                       ['IsMicroop'])
1602680Sktlim@umich.edu
161180SN/A    microStrDTFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);"
162180SN/A    microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop',
1632680Sktlim@umich.edu                                       'MicroMemOp',
1642SN/A                                       {'memacc_code': microStrFpUopCode,
1652SN/A                                        'postacc_code': "",
1662SN/A                                        'ea_code': vfpEnabledCheckCode + '''
1672SN/A                                         EA = URb + (up ? imm : -imm) -
1682SN/A                                              (((CPSR)Cpsr).e ? 4 : 0);
1691970SN/A                                         ''',
1701970SN/A                                        'predicate_test': predicateTest},
1711970SN/A                                       ['IsMicroop'])
1721970SN/A
1732SN/A    header_output = decoder_output = exec_output = ''
1742SN/A
1752SN/A    loadIops = (microLdrUopIop, microLdrRetUopIop,
1762SN/A                microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop)
1772680Sktlim@umich.edu    storeIops = (microStrUopIop, microStrFpUopIop,
1783311Ssaidi@eecs.umich.edu                 microStrDBFpUopIop, microStrDTFpUopIop)
1794434Ssaidi@eecs.umich.edu    for iop in loadIops + storeIops:
1804434Ssaidi@eecs.umich.edu        header_output += MicroMemDeclare.subst(iop)
1814434Ssaidi@eecs.umich.edu        decoder_output += MicroMemConstructor.subst(iop)
1824434Ssaidi@eecs.umich.edu    for iop in loadIops:
1833311Ssaidi@eecs.umich.edu        exec_output += LoadExecute.subst(iop) + \
1843311Ssaidi@eecs.umich.edu                       LoadInitiateAcc.subst(iop) + \
1852SN/A                       LoadCompleteAcc.subst(iop)
1862SN/A    for iop in storeIops:
1872SN/A        exec_output += StoreExecute.subst(iop) + \
1882SN/A                       StoreInitiateAcc.subst(iop) + \
1892SN/A                       StoreCompleteAcc.subst(iop)
190360SN/A
1912SN/A    header_output += MicroMemPairDeclare.subst(microLdr2UopIop)
1922SN/A    decoder_output += MicroMemPairConstructor.subst(microLdr2UopIop)
193360SN/A    exec_output += LoadExecute.subst(microLdr2UopIop) + \
1942378SN/A                   LoadInitiateAcc.subst(microLdr2UopIop) + \
1952378SN/A                   LoadCompleteAcc.subst(microLdr2UopIop)
1962378SN/A}};
1973669Sbinkertn@umich.edu
1982378SN/Alet {{
1995154Sgblack@eecs.umich.edu    exec_output = header_output = ''
2002SN/A
2012561SN/A    eaCode = 'EA = XURa + imm;'
2022378SN/A
2033114Sgblack@eecs.umich.edu    for size in (1, 2, 3, 4, 6, 8, 12, 16):
2043114Sgblack@eecs.umich.edu        # Set up the memory access.
2053114Sgblack@eecs.umich.edu        regs = (size + 3) // 4
2063114Sgblack@eecs.umich.edu        subst = { "size" : size, "regs" : regs }
2073114Sgblack@eecs.umich.edu        memDecl = '''
2083114Sgblack@eecs.umich.edu        union MemUnion {
2093114Sgblack@eecs.umich.edu            uint8_t bytes[%(size)d];
2103114Sgblack@eecs.umich.edu            Element elements[%(size)d / sizeof(Element)];
2113114Sgblack@eecs.umich.edu            uint32_t floatRegBits[%(regs)d];
2123114Sgblack@eecs.umich.edu        };
213360SN/A        ''' % subst
2143114Sgblack@eecs.umich.edu
2154793Sgblack@eecs.umich.edu        # Do endian conversion for all the elements.
2164793Sgblack@eecs.umich.edu        convCode = '''
2174793Sgblack@eecs.umich.edu            const unsigned eCount = sizeof(memUnion.elements) /
2184793Sgblack@eecs.umich.edu                                    sizeof(memUnion.elements[0]);
2194793Sgblack@eecs.umich.edu            if (((CPSR)Cpsr).e) {
2204793Sgblack@eecs.umich.edu                for (unsigned i = 0; i < eCount; i++) {
2214793Sgblack@eecs.umich.edu                    memUnion.elements[i] = gtobe(memUnion.elements[i]);
2224793Sgblack@eecs.umich.edu                }
2234793Sgblack@eecs.umich.edu            } else {
2244793Sgblack@eecs.umich.edu                for (unsigned i = 0; i < eCount; i++) {
2254793Sgblack@eecs.umich.edu                    memUnion.elements[i] = gtole(memUnion.elements[i]);
2264793Sgblack@eecs.umich.edu                }
2274793Sgblack@eecs.umich.edu            }
2284793Sgblack@eecs.umich.edu        '''
2294793Sgblack@eecs.umich.edu
2304793Sgblack@eecs.umich.edu        # Offload everything into registers
2314793Sgblack@eecs.umich.edu        regSetCode = ''
2324793Sgblack@eecs.umich.edu        for reg in range(regs):
2334793Sgblack@eecs.umich.edu            mask = ''
2344793Sgblack@eecs.umich.edu            if reg == regs - 1:
2354793Sgblack@eecs.umich.edu                mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size))
2364793Sgblack@eecs.umich.edu            regSetCode += '''
2374793Sgblack@eecs.umich.edu            FpDestP%(reg)d_uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s;
2384793Sgblack@eecs.umich.edu            ''' % { "reg" : reg, "mask" : mask }
2394793Sgblack@eecs.umich.edu
2404793Sgblack@eecs.umich.edu        # Pull everything in from registers
2413114Sgblack@eecs.umich.edu        regGetCode = ''
2423114Sgblack@eecs.umich.edu        for reg in range(regs):
2433114Sgblack@eecs.umich.edu            regGetCode += '''
2443114Sgblack@eecs.umich.edu            memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d_uw);
2453114Sgblack@eecs.umich.edu            ''' % { "reg" : reg }
2463114Sgblack@eecs.umich.edu
2473114Sgblack@eecs.umich.edu        loadMemAccCode = convCode + regSetCode
2483669Sbinkertn@umich.edu        storeMemAccCode = regGetCode + convCode
2493669Sbinkertn@umich.edu
2503669Sbinkertn@umich.edu        loadIop = InstObjParams('ldrneon%(size)d_uop' % subst,
2513669Sbinkertn@umich.edu                                'MicroLdrNeon%(size)dUop' % subst,
2523669Sbinkertn@umich.edu                                'MicroNeonMemOp',
2533669Sbinkertn@umich.edu                                { 'mem_decl' : memDecl,
2543669Sbinkertn@umich.edu                                  'size' : size,
2553669Sbinkertn@umich.edu                                  'memacc_code' : loadMemAccCode,
2563669Sbinkertn@umich.edu                                  'ea_code' : simdEnabledCheckCode + eaCode,
2573669Sbinkertn@umich.edu                                  'predicate_test' : predicateTest },
2583669Sbinkertn@umich.edu                                [ 'IsMicroop', 'IsMemRef', 'IsLoad' ])
2593669Sbinkertn@umich.edu        storeIop = InstObjParams('strneon%(size)d_uop' % subst,
2603669Sbinkertn@umich.edu                                 'MicroStrNeon%(size)dUop' % subst,
2613669Sbinkertn@umich.edu                                 'MicroNeonMemOp',
2622680Sktlim@umich.edu                                 { 'mem_decl' : memDecl,
2632093SN/A                                   'size' : size,
2642462SN/A                                   'memacc_code' : storeMemAccCode,
2652715Sstever@eecs.umich.edu                                   'ea_code' : simdEnabledCheckCode + eaCode,
2662715Sstever@eecs.umich.edu                                   'predicate_test' : predicateTest },
2672715Sstever@eecs.umich.edu                                 [ 'IsMicroop', 'IsMemRef', 'IsStore' ])
2682715Sstever@eecs.umich.edu
2695154Sgblack@eecs.umich.edu        exec_output += NeonLoadExecute.subst(loadIop) + \
2702SN/A                       NeonLoadInitiateAcc.subst(loadIop) + \
2712SN/A                       NeonLoadCompleteAcc.subst(loadIop) + \
272360SN/A                       NeonStoreExecute.subst(storeIop) + \
2732SN/A                       NeonStoreInitiateAcc.subst(storeIop) + \
2742SN/A                       NeonStoreCompleteAcc.subst(storeIop)
275360SN/A        header_output += MicroNeonMemDeclare.subst(loadIop) + \
276                         MicroNeonMemDeclare.subst(storeIop)
277}};
278
279let {{
280    exec_output = ''
281    for eSize, type in (1, 'uint8_t'), \
282                       (2, 'uint16_t'), \
283                       (4, 'uint32_t'), \
284                       (8, 'uint64_t'):
285        size = eSize
286        # An instruction handles no more than 16 bytes and no more than
287        # 4 elements, or the number of elements needed to fill 8 or 16 bytes.
288        sizes = set((16, 8))
289        for count in 1, 2, 3, 4:
290            size = count * eSize
291            if size <= 16:
292                sizes.add(size)
293        for size in sizes:
294            substDict = {
295                "class_name" : "MicroLdrNeon%dUop" % size,
296                "targs" : type
297            }
298            exec_output += MicroNeonMemExecDeclare.subst(substDict)
299            substDict["class_name"] = "MicroStrNeon%dUop" % size
300            exec_output += MicroNeonMemExecDeclare.subst(substDict)
301            size += eSize
302}};
303
304////////////////////////////////////////////////////////////////////
305//
306// Neon (de)interlacing microops
307//
308
309let {{
310    header_output = exec_output = ''
311    for dRegs in (2, 3, 4):
312        loadConv = ''
313        unloadConv = ''
314        for dReg in range(dRegs):
315            loadConv += '''
316                conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d_uw);
317                conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d_uw);
318            ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
319            unloadConv += '''
320                FpDestS%(dReg)dP0_uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]);
321                FpDestS%(dReg)dP1_uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]);
322            ''' % { "dReg" : dReg }
323        microDeintNeonCode = '''
324            const unsigned dRegs = %(dRegs)d;
325            const unsigned regs = 2 * dRegs;
326            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
327                                     sizeof(Element);
328            union convStruct {
329                FloatRegBits cRegs[regs];
330                Element elements[dRegs * perDReg];
331            } conv1, conv2;
332
333            %(loadConv)s
334
335            unsigned srcElem = 0;
336            for (unsigned destOffset = 0;
337                    destOffset < perDReg; destOffset++) {
338                for (unsigned dReg = 0; dReg < dRegs; dReg++) {
339                    conv2.elements[dReg * perDReg + destOffset] =
340                        conv1.elements[srcElem++];
341                }
342            }
343
344            %(unloadConv)s
345        ''' % { "dRegs" : dRegs,
346                "loadConv" : loadConv,
347                "unloadConv" : unloadConv }
348        microDeintNeonIop = \
349            InstObjParams('deintneon%duop' % (dRegs * 2),
350                          'MicroDeintNeon%dUop' % (dRegs * 2),
351                          'MicroNeonMixOp',
352                          { 'predicate_test': predicateTest,
353                            'code' : microDeintNeonCode },
354                            ['IsMicroop'])
355        header_output += MicroNeonMixDeclare.subst(microDeintNeonIop)
356        exec_output += MicroNeonMixExecute.subst(microDeintNeonIop)
357
358        loadConv = ''
359        unloadConv = ''
360        for dReg in range(dRegs):
361            loadConv += '''
362                conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0_uw);
363                conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1_uw);
364            ''' % { "dReg" : dReg }
365            unloadConv += '''
366                FpDestP%(sReg0)d_uw = gtoh(conv2.cRegs[%(sReg0)d]);
367                FpDestP%(sReg1)d_uw = gtoh(conv2.cRegs[%(sReg1)d]);
368            ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
369        microInterNeonCode = '''
370            const unsigned dRegs = %(dRegs)d;
371            const unsigned regs = 2 * dRegs;
372            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
373                                     sizeof(Element);
374            union convStruct {
375                FloatRegBits cRegs[regs];
376                Element elements[dRegs * perDReg];
377            } conv1, conv2;
378
379            %(loadConv)s
380
381            unsigned destElem = 0;
382            for (unsigned srcOffset = 0;
383                    srcOffset < perDReg; srcOffset++) {
384                for (unsigned dReg = 0; dReg < dRegs; dReg++) {
385                    conv2.elements[destElem++] =
386                        conv1.elements[dReg * perDReg + srcOffset];
387                }
388            }
389
390            %(unloadConv)s
391        ''' % { "dRegs" : dRegs,
392                "loadConv" : loadConv,
393                "unloadConv" : unloadConv }
394        microInterNeonIop = \
395            InstObjParams('interneon%duop' % (dRegs * 2),
396                          'MicroInterNeon%dUop' % (dRegs * 2),
397                          'MicroNeonMixOp',
398                          { 'predicate_test': predicateTest,
399                            'code' : microInterNeonCode },
400                            ['IsMicroop'])
401        header_output += MicroNeonMixDeclare.subst(microInterNeonIop)
402        exec_output += MicroNeonMixExecute.subst(microInterNeonIop)
403}};
404
405let {{
406    exec_output = ''
407    for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'):
408        for dRegs in (2, 3, 4):
409            Name = "MicroDeintNeon%dUop" % (dRegs * 2)
410            substDict = { "class_name" : Name, "targs" : type }
411            exec_output += MicroNeonExecDeclare.subst(substDict)
412            Name = "MicroInterNeon%dUop" % (dRegs * 2)
413            substDict = { "class_name" : Name, "targs" : type }
414            exec_output += MicroNeonExecDeclare.subst(substDict)
415}};
416
417////////////////////////////////////////////////////////////////////
418//
419// Neon microops to pack/unpack a single lane
420//
421
422let {{
423    header_output = exec_output = ''
424    for sRegs in 1, 2:
425        baseLoadRegs = ''
426        for reg in range(sRegs):
427            baseLoadRegs += '''
428                sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d_uw);
429                sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d_uw);
430            ''' % { "reg0" : (2 * reg + 0),
431                    "reg1" : (2 * reg + 1) }
432        for dRegs in range(sRegs, 5):
433            unloadRegs = ''
434            loadRegs = baseLoadRegs
435            for reg in range(dRegs):
436                loadRegs += '''
437                    destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0_uw);
438                    destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1_uw);
439                ''' % { "reg" : reg }
440                unloadRegs += '''
441                    FpDestS%(reg)dP0_uw = gtoh(destRegs[%(reg)d].fRegs[0]);
442                    FpDestS%(reg)dP1_uw = gtoh(destRegs[%(reg)d].fRegs[1]);
443                ''' % { "reg" : reg }
444            microUnpackNeonCode = '''
445            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
446                                     sizeof(Element);
447
448            union SourceRegs {
449                FloatRegBits fRegs[2 * %(sRegs)d];
450                Element elements[%(sRegs)d * perDReg];
451            } sourceRegs;
452
453            union DestReg {
454                FloatRegBits fRegs[2];
455                Element elements[perDReg];
456            } destRegs[%(dRegs)d];
457
458            %(loadRegs)s
459
460            for (unsigned i = 0; i < %(dRegs)d; i++) {
461                destRegs[i].elements[lane] = sourceRegs.elements[i];
462            }
463
464            %(unloadRegs)s
465            ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
466                    "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
467
468            microUnpackNeonIop = \
469                InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2),
470                              'MicroUnpackNeon%dto%dUop' %
471                                    (sRegs * 2, dRegs * 2),
472                              'MicroNeonMixLaneOp',
473                              { 'predicate_test': predicateTest,
474                                'code' : microUnpackNeonCode },
475                                ['IsMicroop'])
476            header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop)
477            exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop)
478
479    for sRegs in 1, 2:
480        loadRegs = ''
481        for reg in range(sRegs):
482            loadRegs += '''
483                sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d_uw);
484                sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d_uw);
485            ''' % { "reg0" : (2 * reg + 0),
486                    "reg1" : (2 * reg + 1) }
487        for dRegs in range(sRegs, 5):
488            unloadRegs = ''
489            for reg in range(dRegs):
490                unloadRegs += '''
491                    FpDestS%(reg)dP0_uw = gtoh(destRegs[%(reg)d].fRegs[0]);
492                    FpDestS%(reg)dP1_uw = gtoh(destRegs[%(reg)d].fRegs[1]);
493                ''' % { "reg" : reg }
494            microUnpackAllNeonCode = '''
495            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
496                                     sizeof(Element);
497
498            union SourceRegs {
499                FloatRegBits fRegs[2 * %(sRegs)d];
500                Element elements[%(sRegs)d * perDReg];
501            } sourceRegs;
502
503            union DestReg {
504                FloatRegBits fRegs[2];
505                Element elements[perDReg];
506            } destRegs[%(dRegs)d];
507
508            %(loadRegs)s
509
510            for (unsigned i = 0; i < %(dRegs)d; i++) {
511                for (unsigned j = 0; j < perDReg; j++)
512                    destRegs[i].elements[j] = sourceRegs.elements[i];
513            }
514
515            %(unloadRegs)s
516            ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
517                    "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
518
519            microUnpackAllNeonIop = \
520                InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2),
521                              'MicroUnpackAllNeon%dto%dUop' %
522                                    (sRegs * 2, dRegs * 2),
523                              'MicroNeonMixOp',
524                              { 'predicate_test': predicateTest,
525                                'code' : microUnpackAllNeonCode },
526                                ['IsMicroop'])
527            header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop)
528            exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop)
529
530    for dRegs in 1, 2:
531        unloadRegs = ''
532        for reg in range(dRegs):
533            unloadRegs += '''
534                FpDestP%(reg0)d_uw = gtoh(destRegs.fRegs[%(reg0)d]);
535                FpDestP%(reg1)d_uw = gtoh(destRegs.fRegs[%(reg1)d]);
536            ''' % { "reg0" : (2 * reg + 0),
537                    "reg1" : (2 * reg + 1) }
538        for sRegs in range(dRegs, 5):
539            loadRegs = ''
540            for reg in range(sRegs):
541                loadRegs += '''
542                    sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0_uw);
543                    sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1_uw);
544                ''' % { "reg" : reg }
545            microPackNeonCode = '''
546            const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
547                                     sizeof(Element);
548
549            union SourceReg {
550                FloatRegBits fRegs[2];
551                Element elements[perDReg];
552            } sourceRegs[%(sRegs)d];
553
554            union DestRegs {
555                FloatRegBits fRegs[2 * %(dRegs)d];
556                Element elements[%(dRegs)d * perDReg];
557            } destRegs;
558
559            %(loadRegs)s
560
561            for (unsigned i = 0; i < %(sRegs)d; i++) {
562                destRegs.elements[i] = sourceRegs[i].elements[lane];
563            }
564            for (unsigned i = %(sRegs)d; i < %(dRegs)d * perDReg; ++i) {
565                destRegs.elements[i] = 0;
566            }
567
568            %(unloadRegs)s
569            ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
570                    "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
571
572            microPackNeonIop = \
573                InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2),
574                              'MicroPackNeon%dto%dUop' %
575                                    (sRegs * 2, dRegs * 2),
576                              'MicroNeonMixLaneOp',
577                              { 'predicate_test': predicateTest,
578                                'code' : microPackNeonCode },
579                                ['IsMicroop'])
580            header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop)
581            exec_output += MicroNeonMixExecute.subst(microPackNeonIop)
582}};
583
584let {{
585    exec_output = ''
586    for typeSize in (8, 16, 32):
587        for sRegs in 1, 2:
588            for dRegs in range(sRegs, min(sRegs * 64 / typeSize + 1, 5)):
589                for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop",
590                               "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop",
591                               "MicroPackNeon%(dRegs)dto%(sRegs)dUop"):
592                    Name = format % { "sRegs" : sRegs * 2,
593                                      "dRegs" : dRegs * 2 }
594                    substDict = { "class_name" : Name,
595                                  "targs" : "uint%d_t" % typeSize }
596                    exec_output += MicroNeonExecDeclare.subst(substDict)
597}};
598
599////////////////////////////////////////////////////////////////////
600//
601// Integer = Integer op Immediate microops
602//
603
604let {{
605    microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop',
606                                    'MicroIntImmOp',
607                                    {'code': 'URa = URb + imm;',
608                                     'predicate_test': predicateTest},
609                                    ['IsMicroop'])
610
611    microAddUopCode = '''
612        URa = URb + shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC);
613    '''
614
615    microAddXiUopIop = InstObjParams('addxi_uop', 'MicroAddXiUop',
616                                     'MicroIntImmXOp',
617                                     'XURa = XURb + imm;',
618                                     ['IsMicroop'])
619
620    microAddXiSpAlignUopIop = InstObjParams('addxi_uop', 'MicroAddXiSpAlignUop',
621                                            'MicroIntImmXOp', '''
622        if (isSP((IntRegIndex) urb) && bits(XURb, 3, 0) &&
623            SPAlignmentCheckEnabled(xc->tcBase())) {
624            return std::make_shared<SPAlignmentFault>();
625        }
626        XURa = XURb + imm;
627    ''', ['IsMicroop'])
628
629    microAddXERegUopIop = InstObjParams('addxr_uop', 'MicroAddXERegUop',
630                                        'MicroIntRegXOp',
631                                        'XURa = XURb + ' + \
632                                            'extendReg64(XURc, type, shiftAmt, 64);',
633                                        ['IsMicroop'])
634
635    microAddUopIop = InstObjParams('add_uop', 'MicroAddUop',
636                                   'MicroIntRegOp',
637                                   {'code': microAddUopCode,
638                                    'predicate_test': pickPredicate(microAddUopCode)},
639                                   ['IsMicroop'])
640
641    microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop',
642                                    'MicroIntImmOp',
643                                    {'code': 'URa = URb - imm;',
644                                     'predicate_test': predicateTest},
645                                    ['IsMicroop'])
646
647    microSubXiUopIop = InstObjParams('subxi_uop', 'MicroSubXiUop',
648                                     'MicroIntImmXOp',
649                                     'XURa = XURb - imm;',
650                                     ['IsMicroop'])
651
652    microSubUopCode = '''
653        URa = URb - shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC);
654    '''
655    microSubUopIop = InstObjParams('sub_uop', 'MicroSubUop',
656                                   'MicroIntRegOp',
657                                   {'code': microSubUopCode,
658                                    'predicate_test': pickPredicate(microSubUopCode)},
659                                   ['IsMicroop'])
660
661    microUopRegMovIop = InstObjParams('uopReg_uop', 'MicroUopRegMov',
662                                   'MicroIntMov',
663                                   {'code': 'IWRa = URb;',
664                                    'predicate_test': predicateTest},
665                                   ['IsMicroop'])
666
667    microUopRegMovRetIop = InstObjParams('movret_uop', 'MicroUopRegMovRet',
668                                      'MicroIntMov',
669                                     {'code': microRetUopCode % 'URb',
670                                      'predicate_test': predicateTest},
671                                     ['IsMicroop', 'IsNonSpeculative',
672                                      'IsSerializeAfter', 'IsSquashAfter'])
673
674    setPCCPSRDecl = '''
675                    CPSR cpsrOrCondCodes = URc;
676                    SCTLR sctlr = Sctlr;
677                    pNPC = URa;
678                    CPSR new_cpsr =
679                    cpsrWriteByInstr(cpsrOrCondCodes, URb, Scr, Nsacr,
680                                     0xF, true, sctlr.nmfi, xc->tcBase());
681                    Cpsr = ~CondCodesMask & new_cpsr;
682                    NextThumb = new_cpsr.t;
683                    NextJazelle = new_cpsr.j;
684                    NextItState = ((((CPSR)URb).it2 << 2) & 0xFC)
685                                    | (((CPSR)URb).it1 & 0x3);
686                    CondCodesNZ = new_cpsr.nz;
687                    CondCodesC = new_cpsr.c;
688                    CondCodesV = new_cpsr.v;
689                    CondCodesGE = new_cpsr.ge;
690                    '''
691
692    microUopSetPCCPSRIop = InstObjParams('uopSet_uop', 'MicroUopSetPCCPSR',
693                                         'MicroSetPCCPSR',
694                                         {'code': setPCCPSRDecl,
695                                          'predicate_test': predicateTest},
696                                         ['IsMicroop'])
697
698    header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \
699                    MicroIntImmDeclare.subst(microAddXiUopIop) + \
700                    MicroIntImmDeclare.subst(microAddXiSpAlignUopIop) + \
701                    MicroIntImmDeclare.subst(microSubiUopIop) + \
702                    MicroIntImmDeclare.subst(microSubXiUopIop) + \
703                    MicroIntRegDeclare.subst(microAddUopIop) + \
704                    MicroIntRegDeclare.subst(microSubUopIop) + \
705                    MicroIntXERegDeclare.subst(microAddXERegUopIop) + \
706                    MicroIntMovDeclare.subst(microUopRegMovIop) + \
707                    MicroIntMovDeclare.subst(microUopRegMovRetIop) + \
708                    MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop)
709
710    decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \
711                     MicroIntImmXConstructor.subst(microAddXiUopIop) + \
712                     MicroIntImmXConstructor.subst(microAddXiSpAlignUopIop) + \
713                     MicroIntImmConstructor.subst(microSubiUopIop) + \
714                     MicroIntImmXConstructor.subst(microSubXiUopIop) + \
715                     MicroIntRegConstructor.subst(microAddUopIop) + \
716                     MicroIntRegConstructor.subst(microSubUopIop) + \
717                     MicroIntXERegConstructor.subst(microAddXERegUopIop) + \
718                     MicroIntMovConstructor.subst(microUopRegMovIop) + \
719                     MicroIntMovConstructor.subst(microUopRegMovRetIop) + \
720                     MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop)
721
722    exec_output = PredOpExecute.subst(microAddiUopIop) + \
723                  BasicExecute.subst(microAddXiUopIop) + \
724                  BasicExecute.subst(microAddXiSpAlignUopIop) + \
725                  PredOpExecute.subst(microSubiUopIop) + \
726                  BasicExecute.subst(microSubXiUopIop) + \
727                  PredOpExecute.subst(microAddUopIop) + \
728                  PredOpExecute.subst(microSubUopIop) + \
729                  BasicExecute.subst(microAddXERegUopIop) + \
730                  PredOpExecute.subst(microUopRegMovIop) + \
731                  PredOpExecute.subst(microUopRegMovRetIop) + \
732                  PredOpExecute.subst(microUopSetPCCPSRIop)
733
734}};
735
736let {{
737    iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", [])
738    header_output = MacroMemDeclare.subst(iop)
739    decoder_output = MacroMemConstructor.subst(iop)
740
741    iop = InstObjParams("ldpstp", "LdpStp", 'PairMemOp', "", [])
742    header_output += PairMemDeclare.subst(iop)
743    decoder_output += PairMemConstructor.subst(iop)
744
745    iopImm = InstObjParams("bigfpmemimm", "BigFpMemImm", "BigFpMemImmOp", "")
746    iopPre = InstObjParams("bigfpmempre", "BigFpMemPre", "BigFpMemPreOp", "")
747    iopPost = InstObjParams("bigfpmempost", "BigFpMemPost", "BigFpMemPostOp", "")
748    for iop in (iopImm, iopPre, iopPost):
749        header_output += BigFpMemImmDeclare.subst(iop)
750        decoder_output += BigFpMemImmConstructor.subst(iop)
751
752    iop = InstObjParams("bigfpmemreg", "BigFpMemReg", "BigFpMemRegOp", "")
753    header_output += BigFpMemRegDeclare.subst(iop)
754    decoder_output += BigFpMemRegConstructor.subst(iop)
755
756    iop = InstObjParams("bigfpmemlit", "BigFpMemLit", "BigFpMemLitOp", "")
757    header_output += BigFpMemLitDeclare.subst(iop)
758    decoder_output += BigFpMemLitConstructor.subst(iop)
759
760    iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", [])
761    header_output += VMemMultDeclare.subst(iop)
762    decoder_output += VMemMultConstructor.subst(iop)
763
764    iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", [])
765    header_output += VMemSingleDeclare.subst(iop)
766    decoder_output += VMemSingleConstructor.subst(iop)
767
768    iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", [])
769    header_output += VMemMultDeclare.subst(iop)
770    decoder_output += VMemMultConstructor.subst(iop)
771
772    iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", [])
773    header_output += VMemSingleDeclare.subst(iop)
774    decoder_output += VMemSingleConstructor.subst(iop)
775
776    vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", [])
777    header_output += MacroVFPMemDeclare.subst(vfpIop)
778    decoder_output += MacroVFPMemConstructor.subst(vfpIop)
779}};
780