macromem.isa revision 13544
110259SAndrew.Bardsley@arm.com// -*- mode:c++ -*- 210259SAndrew.Bardsley@arm.com 310259SAndrew.Bardsley@arm.com// Copyright (c) 2010-2014 ARM Limited 410259SAndrew.Bardsley@arm.com// All rights reserved 510259SAndrew.Bardsley@arm.com// 610259SAndrew.Bardsley@arm.com// The license below extends only to copyright in the software and shall 710259SAndrew.Bardsley@arm.com// not be construed as granting a license to any other intellectual 810259SAndrew.Bardsley@arm.com// property including but not limited to intellectual property relating 910259SAndrew.Bardsley@arm.com// to a hardware implementation of the functionality of the software 1010259SAndrew.Bardsley@arm.com// licensed hereunder. You may use the software subject to the license 1110259SAndrew.Bardsley@arm.com// terms below provided that you ensure that this notice is replicated 1210259SAndrew.Bardsley@arm.com// unmodified and in its entirety in all distributions of the software, 1310259SAndrew.Bardsley@arm.com// modified or unmodified, in source code or in binary form. 1410259SAndrew.Bardsley@arm.com// 1510259SAndrew.Bardsley@arm.com// Copyright (c) 2007-2008 The Florida State University 1610259SAndrew.Bardsley@arm.com// All rights reserved. 1710259SAndrew.Bardsley@arm.com// 1810259SAndrew.Bardsley@arm.com// Redistribution and use in source and binary forms, with or without 1910259SAndrew.Bardsley@arm.com// modification, are permitted provided that the following conditions are 2010259SAndrew.Bardsley@arm.com// met: redistributions of source code must retain the above copyright 2110259SAndrew.Bardsley@arm.com// notice, this list of conditions and the following disclaimer; 2210259SAndrew.Bardsley@arm.com// redistributions in binary form must reproduce the above copyright 2310259SAndrew.Bardsley@arm.com// notice, this list of conditions and the following disclaimer in the 2410259SAndrew.Bardsley@arm.com// documentation and/or other materials provided with the distribution; 2510259SAndrew.Bardsley@arm.com// neither the name of the copyright holders nor the names of its 2610259SAndrew.Bardsley@arm.com// contributors may be used to endorse or promote products derived from 2710259SAndrew.Bardsley@arm.com// this software without specific prior written permission. 2810259SAndrew.Bardsley@arm.com// 2910259SAndrew.Bardsley@arm.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3010259SAndrew.Bardsley@arm.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3110259SAndrew.Bardsley@arm.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3210259SAndrew.Bardsley@arm.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3310259SAndrew.Bardsley@arm.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3410259SAndrew.Bardsley@arm.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3510259SAndrew.Bardsley@arm.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3610259SAndrew.Bardsley@arm.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3710259SAndrew.Bardsley@arm.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3810259SAndrew.Bardsley@arm.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3910259SAndrew.Bardsley@arm.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4010259SAndrew.Bardsley@arm.com// 4110259SAndrew.Bardsley@arm.com// Authors: Stephen Hines 4210259SAndrew.Bardsley@arm.com// Gabe Black 4310259SAndrew.Bardsley@arm.com 4410259SAndrew.Bardsley@arm.com//////////////////////////////////////////////////////////////////// 4510259SAndrew.Bardsley@arm.com// 4610259SAndrew.Bardsley@arm.com// Load/store microops 4710259SAndrew.Bardsley@arm.com// 4810259SAndrew.Bardsley@arm.com 4910259SAndrew.Bardsley@arm.comlet {{ 5010259SAndrew.Bardsley@arm.com microLdrUopCode = "IWRa = cSwap(Mem_uw, ((CPSR)Cpsr).e);" 5110259SAndrew.Bardsley@arm.com microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop', 5210259SAndrew.Bardsley@arm.com 'MicroMemOp', 5310259SAndrew.Bardsley@arm.com {'memacc_code': microLdrUopCode, 5410259SAndrew.Bardsley@arm.com 'ea_code': 'EA = URb + (up ? imm : -imm);', 5510259SAndrew.Bardsley@arm.com 'predicate_test': predicateTest}, 5610259SAndrew.Bardsley@arm.com ['IsMicroop']) 5710259SAndrew.Bardsley@arm.com 5810259SAndrew.Bardsley@arm.com microLdr2UopCode = ''' 5910259SAndrew.Bardsley@arm.com uint64_t data = Mem_ud; 6010259SAndrew.Bardsley@arm.com Dest = cSwap((uint32_t) data, ((CPSR)Cpsr).e); 6110259SAndrew.Bardsley@arm.com IWDest2 = cSwap((uint32_t) (data >> 32), 6210259SAndrew.Bardsley@arm.com ((CPSR)Cpsr).e); 6310259SAndrew.Bardsley@arm.com ''' 6410259SAndrew.Bardsley@arm.com microLdr2UopIop = InstObjParams('ldr2_uop', 'MicroLdr2Uop', 6510259SAndrew.Bardsley@arm.com 'MicroMemPairOp', 6610259SAndrew.Bardsley@arm.com {'memacc_code': microLdr2UopCode, 6710259SAndrew.Bardsley@arm.com 'ea_code': 'EA = URb + (up ? imm : -imm);', 6810259SAndrew.Bardsley@arm.com 'predicate_test': predicateTest}, 6910259SAndrew.Bardsley@arm.com ['IsMicroop']) 7010259SAndrew.Bardsley@arm.com 7110259SAndrew.Bardsley@arm.com microLdrFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);" 7210259SAndrew.Bardsley@arm.com microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop', 7310259SAndrew.Bardsley@arm.com 'MicroMemOp', 7410259SAndrew.Bardsley@arm.com {'memacc_code': microLdrFpUopCode, 7510259SAndrew.Bardsley@arm.com 'ea_code': vfpEnabledCheckCode + 7610259SAndrew.Bardsley@arm.com 'EA = URb + (up ? imm : -imm);', 7710259SAndrew.Bardsley@arm.com 'predicate_test': predicateTest}, 7810259SAndrew.Bardsley@arm.com ['IsMicroop']) 7910259SAndrew.Bardsley@arm.com 8010259SAndrew.Bardsley@arm.com microLdrDBFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);" 8110259SAndrew.Bardsley@arm.com microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop', 8210259SAndrew.Bardsley@arm.com 'MicroMemOp', 8310259SAndrew.Bardsley@arm.com {'memacc_code': microLdrFpUopCode, 8410259SAndrew.Bardsley@arm.com 'ea_code': vfpEnabledCheckCode + ''' 8510259SAndrew.Bardsley@arm.com EA = URb + (up ? imm : -imm) + 8610259SAndrew.Bardsley@arm.com (((CPSR)Cpsr).e ? 4 : 0); 8710259SAndrew.Bardsley@arm.com ''', 8810259SAndrew.Bardsley@arm.com 'predicate_test': predicateTest}, 8910259SAndrew.Bardsley@arm.com ['IsMicroop']) 9010259SAndrew.Bardsley@arm.com 9110259SAndrew.Bardsley@arm.com microLdrDTFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);" 9210259SAndrew.Bardsley@arm.com microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop', 9310259SAndrew.Bardsley@arm.com 'MicroMemOp', 9410259SAndrew.Bardsley@arm.com {'memacc_code': microLdrFpUopCode, 9510259SAndrew.Bardsley@arm.com 'ea_code': vfpEnabledCheckCode + ''' 9610259SAndrew.Bardsley@arm.com EA = URb + (up ? imm : -imm) - 9710259SAndrew.Bardsley@arm.com (((CPSR)Cpsr).e ? 4 : 0); 9810259SAndrew.Bardsley@arm.com ''', 9910259SAndrew.Bardsley@arm.com 'predicate_test': predicateTest}, 10010259SAndrew.Bardsley@arm.com ['IsMicroop']) 10110259SAndrew.Bardsley@arm.com 10210259SAndrew.Bardsley@arm.com microRetUopCode = ''' 10310259SAndrew.Bardsley@arm.com CPSR old_cpsr = Cpsr; 10410259SAndrew.Bardsley@arm.com SCTLR sctlr = Sctlr; 10510259SAndrew.Bardsley@arm.com 10610259SAndrew.Bardsley@arm.com CPSR new_cpsr = 10710259SAndrew.Bardsley@arm.com cpsrWriteByInstr(old_cpsr, Spsr, Scr, Nsacr, 0xF, true, 10810259SAndrew.Bardsley@arm.com sctlr.nmfi, xc->tcBase()); 10910259SAndrew.Bardsley@arm.com Cpsr = ~CondCodesMask & new_cpsr; 11010259SAndrew.Bardsley@arm.com CondCodesNZ = new_cpsr.nz; 11110259SAndrew.Bardsley@arm.com CondCodesC = new_cpsr.c; 11210259SAndrew.Bardsley@arm.com CondCodesV = new_cpsr.v; 11310259SAndrew.Bardsley@arm.com CondCodesGE = new_cpsr.ge; 11410259SAndrew.Bardsley@arm.com IWNPC = cSwap(%s, old_cpsr.e) | ((Spsr & 0x20) ? 1 : 0); 11510259SAndrew.Bardsley@arm.com NextItState = ((((CPSR)Spsr).it2 << 2) & 0xFC) 11610259SAndrew.Bardsley@arm.com | (((CPSR)Spsr).it1 & 0x3); 11710259SAndrew.Bardsley@arm.com SevMailbox = 1; 11810259SAndrew.Bardsley@arm.com ''' 11910259SAndrew.Bardsley@arm.com 12010259SAndrew.Bardsley@arm.com microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', 12110259SAndrew.Bardsley@arm.com 'MicroMemOp', 12210259SAndrew.Bardsley@arm.com {'memacc_code': 12310259SAndrew.Bardsley@arm.com microRetUopCode % 'Mem_uw', 12410259SAndrew.Bardsley@arm.com 'ea_code': 12510259SAndrew.Bardsley@arm.com 'EA = URb + (up ? imm : -imm);', 12610259SAndrew.Bardsley@arm.com 'predicate_test': condPredicateTest}, 12710259SAndrew.Bardsley@arm.com ['IsMicroop','IsNonSpeculative', 12810259SAndrew.Bardsley@arm.com 'IsSerializeAfter', 'IsSquashAfter']) 12910259SAndrew.Bardsley@arm.com 13010259SAndrew.Bardsley@arm.com microStrUopCode = "Mem = cSwap(URa_uw, ((CPSR)Cpsr).e);" 13110259SAndrew.Bardsley@arm.com microStrUopIop = InstObjParams('str_uop', 'MicroStrUop', 13210259SAndrew.Bardsley@arm.com 'MicroMemOp', 13310259SAndrew.Bardsley@arm.com {'memacc_code': microStrUopCode, 13410259SAndrew.Bardsley@arm.com 'postacc_code': "", 13510259SAndrew.Bardsley@arm.com 'ea_code': 'EA = URb + (up ? imm : -imm);', 13610259SAndrew.Bardsley@arm.com 'predicate_test': predicateTest}, 13710259SAndrew.Bardsley@arm.com ['IsMicroop']) 13810259SAndrew.Bardsley@arm.com 13910259SAndrew.Bardsley@arm.com microStrFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);" 14010259SAndrew.Bardsley@arm.com microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop', 14110259SAndrew.Bardsley@arm.com 'MicroMemOp', 14210259SAndrew.Bardsley@arm.com {'memacc_code': microStrFpUopCode, 14310259SAndrew.Bardsley@arm.com 'postacc_code': "", 14410259SAndrew.Bardsley@arm.com 'ea_code': vfpEnabledCheckCode + 14510259SAndrew.Bardsley@arm.com 'EA = URb + (up ? imm : -imm);', 14610259SAndrew.Bardsley@arm.com 'predicate_test': predicateTest}, 14710259SAndrew.Bardsley@arm.com ['IsMicroop']) 14810259SAndrew.Bardsley@arm.com 14910259SAndrew.Bardsley@arm.com microStrDBFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);" 15010259SAndrew.Bardsley@arm.com microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop', 15110259SAndrew.Bardsley@arm.com 'MicroMemOp', 15210259SAndrew.Bardsley@arm.com {'memacc_code': microStrFpUopCode, 15310259SAndrew.Bardsley@arm.com 'postacc_code': "", 15410259SAndrew.Bardsley@arm.com 'ea_code': vfpEnabledCheckCode + ''' 15510259SAndrew.Bardsley@arm.com EA = URb + (up ? imm : -imm) + 15610259SAndrew.Bardsley@arm.com (((CPSR)Cpsr).e ? 4 : 0); 15710259SAndrew.Bardsley@arm.com ''', 15810259SAndrew.Bardsley@arm.com 'predicate_test': predicateTest}, 15910259SAndrew.Bardsley@arm.com ['IsMicroop']) 16010259SAndrew.Bardsley@arm.com 16110259SAndrew.Bardsley@arm.com microStrDTFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);" 16210259SAndrew.Bardsley@arm.com microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop', 16310259SAndrew.Bardsley@arm.com 'MicroMemOp', 16410259SAndrew.Bardsley@arm.com {'memacc_code': microStrFpUopCode, 16510259SAndrew.Bardsley@arm.com 'postacc_code': "", 16610259SAndrew.Bardsley@arm.com 'ea_code': vfpEnabledCheckCode + ''' 16710259SAndrew.Bardsley@arm.com EA = URb + (up ? imm : -imm) - 16810259SAndrew.Bardsley@arm.com (((CPSR)Cpsr).e ? 4 : 0); 16910259SAndrew.Bardsley@arm.com ''', 17010259SAndrew.Bardsley@arm.com 'predicate_test': predicateTest}, 17110259SAndrew.Bardsley@arm.com ['IsMicroop']) 17210259SAndrew.Bardsley@arm.com 17310259SAndrew.Bardsley@arm.com header_output = decoder_output = exec_output = '' 17410259SAndrew.Bardsley@arm.com 17510259SAndrew.Bardsley@arm.com loadIops = (microLdrUopIop, microLdrRetUopIop, 17610259SAndrew.Bardsley@arm.com microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop) 17710259SAndrew.Bardsley@arm.com storeIops = (microStrUopIop, microStrFpUopIop, 17810259SAndrew.Bardsley@arm.com microStrDBFpUopIop, microStrDTFpUopIop) 17910259SAndrew.Bardsley@arm.com for iop in loadIops + storeIops: 18010259SAndrew.Bardsley@arm.com header_output += MicroMemDeclare.subst(iop) 18110259SAndrew.Bardsley@arm.com decoder_output += MicroMemConstructor.subst(iop) 18210259SAndrew.Bardsley@arm.com for iop in loadIops: 18310259SAndrew.Bardsley@arm.com exec_output += LoadExecute.subst(iop) + \ 18410259SAndrew.Bardsley@arm.com LoadInitiateAcc.subst(iop) + \ 18510259SAndrew.Bardsley@arm.com LoadCompleteAcc.subst(iop) 18610259SAndrew.Bardsley@arm.com for iop in storeIops: 18710259SAndrew.Bardsley@arm.com exec_output += StoreExecute.subst(iop) + \ 18810259SAndrew.Bardsley@arm.com StoreInitiateAcc.subst(iop) + \ 18910259SAndrew.Bardsley@arm.com StoreCompleteAcc.subst(iop) 19010259SAndrew.Bardsley@arm.com 19110259SAndrew.Bardsley@arm.com header_output += MicroMemPairDeclare.subst(microLdr2UopIop) 19210259SAndrew.Bardsley@arm.com decoder_output += MicroMemPairConstructor.subst(microLdr2UopIop) 19310259SAndrew.Bardsley@arm.com exec_output += LoadExecute.subst(microLdr2UopIop) + \ 19410259SAndrew.Bardsley@arm.com LoadInitiateAcc.subst(microLdr2UopIop) + \ 19510259SAndrew.Bardsley@arm.com LoadCompleteAcc.subst(microLdr2UopIop) 19610259SAndrew.Bardsley@arm.com}}; 19710259SAndrew.Bardsley@arm.com 19810259SAndrew.Bardsley@arm.comlet {{ 19910259SAndrew.Bardsley@arm.com exec_output = header_output = '' 20010259SAndrew.Bardsley@arm.com 20110259SAndrew.Bardsley@arm.com eaCode = 'EA = XURa + imm;' 20210259SAndrew.Bardsley@arm.com 20310259SAndrew.Bardsley@arm.com for size in (1, 2, 3, 4, 6, 8, 12, 16): 20410259SAndrew.Bardsley@arm.com # Set up the memory access. 20513954Sgiacomo.gabrielli@arm.com regs = (size + 3) // 4 20613954Sgiacomo.gabrielli@arm.com subst = { "size" : size, "regs" : regs } 20713954Sgiacomo.gabrielli@arm.com memDecl = ''' 20813954Sgiacomo.gabrielli@arm.com union MemUnion { 20913954Sgiacomo.gabrielli@arm.com uint8_t bytes[%(size)d]; 21013954Sgiacomo.gabrielli@arm.com Element elements[%(size)d / sizeof(Element)]; 21113954Sgiacomo.gabrielli@arm.com uint32_t floatRegBits[%(regs)d]; 21210259SAndrew.Bardsley@arm.com }; 21310259SAndrew.Bardsley@arm.com ''' % subst 21410259SAndrew.Bardsley@arm.com 21510259SAndrew.Bardsley@arm.com # Do endian conversion for all the elements. 21610259SAndrew.Bardsley@arm.com convCode = ''' 21710259SAndrew.Bardsley@arm.com const unsigned eCount = sizeof(memUnion.elements) / 21810259SAndrew.Bardsley@arm.com sizeof(memUnion.elements[0]); 21910259SAndrew.Bardsley@arm.com if (((CPSR)Cpsr).e) { 22010259SAndrew.Bardsley@arm.com for (unsigned i = 0; i < eCount; i++) { 22110259SAndrew.Bardsley@arm.com memUnion.elements[i] = gtobe(memUnion.elements[i]); 22210259SAndrew.Bardsley@arm.com } 22310259SAndrew.Bardsley@arm.com } else { 22410259SAndrew.Bardsley@arm.com for (unsigned i = 0; i < eCount; i++) { 22510259SAndrew.Bardsley@arm.com memUnion.elements[i] = gtole(memUnion.elements[i]); 22610259SAndrew.Bardsley@arm.com } 22710259SAndrew.Bardsley@arm.com } 22810259SAndrew.Bardsley@arm.com ''' 22912104Snathanael.premillieu@arm.com 23010259SAndrew.Bardsley@arm.com # Offload everything into registers 23110259SAndrew.Bardsley@arm.com regSetCode = '' 23210259SAndrew.Bardsley@arm.com for reg in range(regs): 23310259SAndrew.Bardsley@arm.com mask = '' 23410259SAndrew.Bardsley@arm.com if reg == regs - 1: 23510259SAndrew.Bardsley@arm.com mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size)) 23610259SAndrew.Bardsley@arm.com regSetCode += ''' 23713954Sgiacomo.gabrielli@arm.com FpDestP%(reg)d_uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s; 23810259SAndrew.Bardsley@arm.com ''' % { "reg" : reg, "mask" : mask } 23912420Sgabeblack@google.com 24010259SAndrew.Bardsley@arm.com # Pull everything in from registers 24110259SAndrew.Bardsley@arm.com regGetCode = '' 24210259SAndrew.Bardsley@arm.com for reg in range(regs): 24310259SAndrew.Bardsley@arm.com regGetCode += ''' 24410259SAndrew.Bardsley@arm.com memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d_uw); 24510259SAndrew.Bardsley@arm.com ''' % { "reg" : reg } 24610259SAndrew.Bardsley@arm.com 24710259SAndrew.Bardsley@arm.com loadMemAccCode = convCode + regSetCode 24810259SAndrew.Bardsley@arm.com storeMemAccCode = regGetCode + convCode 24910259SAndrew.Bardsley@arm.com 25010259SAndrew.Bardsley@arm.com loadIop = InstObjParams('ldrneon%(size)d_uop' % subst, 25110259SAndrew.Bardsley@arm.com 'MicroLdrNeon%(size)dUop' % subst, 25210259SAndrew.Bardsley@arm.com 'MicroNeonMemOp', 25310259SAndrew.Bardsley@arm.com { 'mem_decl' : memDecl, 25410259SAndrew.Bardsley@arm.com 'size' : size, 25510259SAndrew.Bardsley@arm.com 'memacc_code' : loadMemAccCode, 25610259SAndrew.Bardsley@arm.com 'ea_code' : simdEnabledCheckCode + eaCode, 25710259SAndrew.Bardsley@arm.com 'predicate_test' : predicateTest }, 25810259SAndrew.Bardsley@arm.com [ 'IsMicroop', 'IsMemRef', 'IsLoad' ]) 25910259SAndrew.Bardsley@arm.com storeIop = InstObjParams('strneon%(size)d_uop' % subst, 26010259SAndrew.Bardsley@arm.com 'MicroStrNeon%(size)dUop' % subst, 26110259SAndrew.Bardsley@arm.com 'MicroNeonMemOp', 26210259SAndrew.Bardsley@arm.com { 'mem_decl' : memDecl, 26310259SAndrew.Bardsley@arm.com 'size' : size, 26410259SAndrew.Bardsley@arm.com 'memacc_code' : storeMemAccCode, 26510259SAndrew.Bardsley@arm.com 'ea_code' : simdEnabledCheckCode + eaCode, 26610259SAndrew.Bardsley@arm.com 'predicate_test' : predicateTest }, 26710259SAndrew.Bardsley@arm.com [ 'IsMicroop', 'IsMemRef', 'IsStore' ]) 26810259SAndrew.Bardsley@arm.com 26910259SAndrew.Bardsley@arm.com exec_output += NeonLoadExecute.subst(loadIop) + \ 27010259SAndrew.Bardsley@arm.com NeonLoadInitiateAcc.subst(loadIop) + \ 27110259SAndrew.Bardsley@arm.com NeonLoadCompleteAcc.subst(loadIop) + \ 27210259SAndrew.Bardsley@arm.com NeonStoreExecute.subst(storeIop) + \ 27310259SAndrew.Bardsley@arm.com NeonStoreInitiateAcc.subst(storeIop) + \ 27410259SAndrew.Bardsley@arm.com NeonStoreCompleteAcc.subst(storeIop) 27510259SAndrew.Bardsley@arm.com header_output += MicroNeonMemDeclare.subst(loadIop) + \ 27613954Sgiacomo.gabrielli@arm.com MicroNeonMemDeclare.subst(storeIop) 27713954Sgiacomo.gabrielli@arm.com}}; 27813954Sgiacomo.gabrielli@arm.com 27913954Sgiacomo.gabrielli@arm.comlet {{ 28013954Sgiacomo.gabrielli@arm.com exec_output = '' 28113954Sgiacomo.gabrielli@arm.com for eSize, type in (1, 'uint8_t'), \ 28213954Sgiacomo.gabrielli@arm.com (2, 'uint16_t'), \ 28313954Sgiacomo.gabrielli@arm.com (4, 'uint32_t'), \ 28410259SAndrew.Bardsley@arm.com (8, 'uint64_t'): 28510259SAndrew.Bardsley@arm.com size = eSize 28610259SAndrew.Bardsley@arm.com # An instruction handles no more than 16 bytes and no more than 28710259SAndrew.Bardsley@arm.com # 4 elements, or the number of elements needed to fill 8 or 16 bytes. 28810259SAndrew.Bardsley@arm.com sizes = set((16, 8)) 28910259SAndrew.Bardsley@arm.com for count in 1, 2, 3, 4: 29010259SAndrew.Bardsley@arm.com size = count * eSize 29110259SAndrew.Bardsley@arm.com if size <= 16: 29210259SAndrew.Bardsley@arm.com 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 = 327 (2 * sizeof(uint32_t)) / sizeof(Element); 328 union convStruct { 329 uint32_t 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 = 373 (2 * sizeof(uint32_t)) / sizeof(Element); 374 union convStruct { 375 uint32_t 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(uint32_t)) / sizeof(Element); 446 447 union SourceRegs { 448 uint32_t fRegs[2 * %(sRegs)d]; 449 Element elements[%(sRegs)d * perDReg]; 450 } sourceRegs; 451 452 union DestReg { 453 uint32_t fRegs[2]; 454 Element elements[perDReg]; 455 } destRegs[%(dRegs)d]; 456 457 %(loadRegs)s 458 459 for (unsigned i = 0; i < %(dRegs)d; i++) { 460 destRegs[i].elements[lane] = sourceRegs.elements[i]; 461 } 462 463 %(unloadRegs)s 464 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 465 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 466 467 microUnpackNeonIop = \ 468 InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2), 469 'MicroUnpackNeon%dto%dUop' % 470 (sRegs * 2, dRegs * 2), 471 'MicroNeonMixLaneOp', 472 { 'predicate_test': predicateTest, 473 'code' : microUnpackNeonCode }, 474 ['IsMicroop']) 475 header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop) 476 exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop) 477 478 for sRegs in 1, 2: 479 loadRegs = '' 480 for reg in range(sRegs): 481 loadRegs += ''' 482 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d_uw); 483 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d_uw); 484 ''' % { "reg0" : (2 * reg + 0), 485 "reg1" : (2 * reg + 1) } 486 for dRegs in range(sRegs, 5): 487 unloadRegs = '' 488 for reg in range(dRegs): 489 unloadRegs += ''' 490 FpDestS%(reg)dP0_uw = gtoh(destRegs[%(reg)d].fRegs[0]); 491 FpDestS%(reg)dP1_uw = gtoh(destRegs[%(reg)d].fRegs[1]); 492 ''' % { "reg" : reg } 493 microUnpackAllNeonCode = ''' 494 const unsigned perDReg = (2 * sizeof(uint32_t)) / sizeof(Element); 495 496 union SourceRegs { 497 uint32_t fRegs[2 * %(sRegs)d]; 498 Element elements[%(sRegs)d * perDReg]; 499 } sourceRegs; 500 501 union DestReg { 502 uint32_t fRegs[2]; 503 Element elements[perDReg]; 504 } destRegs[%(dRegs)d]; 505 506 %(loadRegs)s 507 508 for (unsigned i = 0; i < %(dRegs)d; i++) { 509 for (unsigned j = 0; j < perDReg; j++) 510 destRegs[i].elements[j] = sourceRegs.elements[i]; 511 } 512 513 %(unloadRegs)s 514 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 515 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 516 517 microUnpackAllNeonIop = \ 518 InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2), 519 'MicroUnpackAllNeon%dto%dUop' % 520 (sRegs * 2, dRegs * 2), 521 'MicroNeonMixOp', 522 { 'predicate_test': predicateTest, 523 'code' : microUnpackAllNeonCode }, 524 ['IsMicroop']) 525 header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop) 526 exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop) 527 528 for dRegs in 1, 2: 529 unloadRegs = '' 530 for reg in range(dRegs): 531 unloadRegs += ''' 532 FpDestP%(reg0)d_uw = gtoh(destRegs.fRegs[%(reg0)d]); 533 FpDestP%(reg1)d_uw = gtoh(destRegs.fRegs[%(reg1)d]); 534 ''' % { "reg0" : (2 * reg + 0), 535 "reg1" : (2 * reg + 1) } 536 for sRegs in range(dRegs, 5): 537 loadRegs = '' 538 for reg in range(sRegs): 539 loadRegs += ''' 540 sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0_uw); 541 sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1_uw); 542 ''' % { "reg" : reg } 543 microPackNeonCode = ''' 544 const unsigned perDReg = 545 (2 * sizeof(uint32_t)) / sizeof(Element); 546 547 union SourceReg { 548 uint32_t fRegs[2]; 549 Element elements[perDReg]; 550 } sourceRegs[%(sRegs)d]; 551 552 union DestRegs { 553 uint32_t fRegs[2 * %(dRegs)d]; 554 Element elements[%(dRegs)d * perDReg]; 555 } destRegs; 556 557 %(loadRegs)s 558 559 for (unsigned i = 0; i < %(sRegs)d; i++) { 560 destRegs.elements[i] = sourceRegs[i].elements[lane]; 561 } 562 for (unsigned i = %(sRegs)d; i < %(dRegs)d * perDReg; ++i) { 563 destRegs.elements[i] = 0; 564 } 565 566 %(unloadRegs)s 567 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 568 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 569 570 microPackNeonIop = \ 571 InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2), 572 'MicroPackNeon%dto%dUop' % 573 (sRegs * 2, dRegs * 2), 574 'MicroNeonMixLaneOp', 575 { 'predicate_test': predicateTest, 576 'code' : microPackNeonCode }, 577 ['IsMicroop']) 578 header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop) 579 exec_output += MicroNeonMixExecute.subst(microPackNeonIop) 580}}; 581 582let {{ 583 exec_output = '' 584 for typeSize in (8, 16, 32): 585 for sRegs in 1, 2: 586 for dRegs in range(sRegs, min(sRegs * 64 / typeSize + 1, 5)): 587 for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop", 588 "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop", 589 "MicroPackNeon%(dRegs)dto%(sRegs)dUop"): 590 Name = format % { "sRegs" : sRegs * 2, 591 "dRegs" : dRegs * 2 } 592 substDict = { "class_name" : Name, 593 "targs" : "uint%d_t" % typeSize } 594 exec_output += MicroNeonExecDeclare.subst(substDict) 595}}; 596 597//////////////////////////////////////////////////////////////////// 598// 599// Integer = Integer op Immediate microops 600// 601 602let {{ 603 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop', 604 'MicroIntImmOp', 605 {'code': 'URa = URb + imm;', 606 'predicate_test': predicateTest}, 607 ['IsMicroop']) 608 609 microAddUopCode = ''' 610 URa = URb + shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC); 611 ''' 612 613 microAddXiUopIop = InstObjParams('addxi_uop', 'MicroAddXiUop', 614 'MicroIntImmXOp', 615 'XURa = XURb + imm;', 616 ['IsMicroop']) 617 618 microAddXiSpAlignUopIop = InstObjParams('addxi_uop', 'MicroAddXiSpAlignUop', 619 'MicroIntImmXOp', ''' 620 if (isSP((IntRegIndex) urb) && bits(XURb, 3, 0) && 621 SPAlignmentCheckEnabled(xc->tcBase())) { 622 return std::make_shared<SPAlignmentFault>(); 623 } 624 XURa = XURb + imm; 625 ''', ['IsMicroop']) 626 627 microAddXERegUopIop = InstObjParams('addxr_uop', 'MicroAddXERegUop', 628 'MicroIntRegXOp', 629 'XURa = XURb + ' + \ 630 'extendReg64(XURc, type, shiftAmt, 64);', 631 ['IsMicroop']) 632 633 microAddUopIop = InstObjParams('add_uop', 'MicroAddUop', 634 'MicroIntRegOp', 635 {'code': microAddUopCode, 636 'predicate_test': pickPredicate(microAddUopCode)}, 637 ['IsMicroop']) 638 639 microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop', 640 'MicroIntImmOp', 641 {'code': 'URa = URb - imm;', 642 'predicate_test': predicateTest}, 643 ['IsMicroop']) 644 645 microSubXiUopIop = InstObjParams('subxi_uop', 'MicroSubXiUop', 646 'MicroIntImmXOp', 647 'XURa = XURb - imm;', 648 ['IsMicroop']) 649 650 microSubUopCode = ''' 651 URa = URb - shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC); 652 ''' 653 microSubUopIop = InstObjParams('sub_uop', 'MicroSubUop', 654 'MicroIntRegOp', 655 {'code': microSubUopCode, 656 'predicate_test': pickPredicate(microSubUopCode)}, 657 ['IsMicroop']) 658 659 microUopRegMovIop = InstObjParams('uopReg_uop', 'MicroUopRegMov', 660 'MicroIntMov', 661 {'code': 'IWRa = URb;', 662 'predicate_test': predicateTest}, 663 ['IsMicroop']) 664 665 microUopRegMovRetIop = InstObjParams('movret_uop', 'MicroUopRegMovRet', 666 'MicroIntMov', 667 {'code': microRetUopCode % 'URb', 668 'predicate_test': predicateTest}, 669 ['IsMicroop', 'IsNonSpeculative', 670 'IsSerializeAfter', 'IsSquashAfter']) 671 672 setPCCPSRDecl = ''' 673 CPSR cpsrOrCondCodes = URc; 674 SCTLR sctlr = Sctlr; 675 pNPC = URa; 676 CPSR new_cpsr = 677 cpsrWriteByInstr(cpsrOrCondCodes, URb, Scr, Nsacr, 678 0xF, true, sctlr.nmfi, xc->tcBase()); 679 Cpsr = ~CondCodesMask & new_cpsr; 680 NextThumb = new_cpsr.t; 681 NextJazelle = new_cpsr.j; 682 NextItState = ((((CPSR)URb).it2 << 2) & 0xFC) 683 | (((CPSR)URb).it1 & 0x3); 684 CondCodesNZ = new_cpsr.nz; 685 CondCodesC = new_cpsr.c; 686 CondCodesV = new_cpsr.v; 687 CondCodesGE = new_cpsr.ge; 688 ''' 689 690 microUopSetPCCPSRIop = InstObjParams('uopSet_uop', 'MicroUopSetPCCPSR', 691 'MicroSetPCCPSR', 692 {'code': setPCCPSRDecl, 693 'predicate_test': predicateTest}, 694 ['IsMicroop']) 695 696 header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \ 697 MicroIntImmDeclare.subst(microAddXiUopIop) + \ 698 MicroIntImmDeclare.subst(microAddXiSpAlignUopIop) + \ 699 MicroIntImmDeclare.subst(microSubiUopIop) + \ 700 MicroIntImmDeclare.subst(microSubXiUopIop) + \ 701 MicroIntRegDeclare.subst(microAddUopIop) + \ 702 MicroIntRegDeclare.subst(microSubUopIop) + \ 703 MicroIntXERegDeclare.subst(microAddXERegUopIop) + \ 704 MicroIntMovDeclare.subst(microUopRegMovIop) + \ 705 MicroIntMovDeclare.subst(microUopRegMovRetIop) + \ 706 MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop) 707 708 decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \ 709 MicroIntImmXConstructor.subst(microAddXiUopIop) + \ 710 MicroIntImmXConstructor.subst(microAddXiSpAlignUopIop) + \ 711 MicroIntImmConstructor.subst(microSubiUopIop) + \ 712 MicroIntImmXConstructor.subst(microSubXiUopIop) + \ 713 MicroIntRegConstructor.subst(microAddUopIop) + \ 714 MicroIntRegConstructor.subst(microSubUopIop) + \ 715 MicroIntXERegConstructor.subst(microAddXERegUopIop) + \ 716 MicroIntMovConstructor.subst(microUopRegMovIop) + \ 717 MicroIntMovConstructor.subst(microUopRegMovRetIop) + \ 718 MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop) 719 720 exec_output = PredOpExecute.subst(microAddiUopIop) + \ 721 BasicExecute.subst(microAddXiUopIop) + \ 722 BasicExecute.subst(microAddXiSpAlignUopIop) + \ 723 PredOpExecute.subst(microSubiUopIop) + \ 724 BasicExecute.subst(microSubXiUopIop) + \ 725 PredOpExecute.subst(microAddUopIop) + \ 726 PredOpExecute.subst(microSubUopIop) + \ 727 BasicExecute.subst(microAddXERegUopIop) + \ 728 PredOpExecute.subst(microUopRegMovIop) + \ 729 PredOpExecute.subst(microUopRegMovRetIop) + \ 730 PredOpExecute.subst(microUopSetPCCPSRIop) 731 732}}; 733 734let {{ 735 iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", []) 736 header_output = MacroMemDeclare.subst(iop) 737 decoder_output = MacroMemConstructor.subst(iop) 738 739 iop = InstObjParams("ldpstp", "LdpStp", 'PairMemOp', "", []) 740 header_output += PairMemDeclare.subst(iop) 741 decoder_output += PairMemConstructor.subst(iop) 742 743 iopImm = InstObjParams("bigfpmemimm", "BigFpMemImm", "BigFpMemImmOp", "") 744 iopPre = InstObjParams("bigfpmempre", "BigFpMemPre", "BigFpMemPreOp", "") 745 iopPost = InstObjParams("bigfpmempost", "BigFpMemPost", "BigFpMemPostOp", "") 746 for iop in (iopImm, iopPre, iopPost): 747 header_output += BigFpMemImmDeclare.subst(iop) 748 decoder_output += BigFpMemImmConstructor.subst(iop) 749 750 iop = InstObjParams("bigfpmemreg", "BigFpMemReg", "BigFpMemRegOp", "") 751 header_output += BigFpMemRegDeclare.subst(iop) 752 decoder_output += BigFpMemRegConstructor.subst(iop) 753 754 iop = InstObjParams("bigfpmemlit", "BigFpMemLit", "BigFpMemLitOp", "") 755 header_output += BigFpMemLitDeclare.subst(iop) 756 decoder_output += BigFpMemLitConstructor.subst(iop) 757 758 iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", []) 759 header_output += VMemMultDeclare.subst(iop) 760 decoder_output += VMemMultConstructor.subst(iop) 761 762 iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", []) 763 header_output += VMemSingleDeclare.subst(iop) 764 decoder_output += VMemSingleConstructor.subst(iop) 765 766 iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", []) 767 header_output += VMemMultDeclare.subst(iop) 768 decoder_output += VMemMultConstructor.subst(iop) 769 770 iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", []) 771 header_output += VMemSingleDeclare.subst(iop) 772 decoder_output += VMemSingleConstructor.subst(iop) 773 774 vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", []) 775 header_output += MacroVFPMemDeclare.subst(vfpIop) 776 decoder_output += MacroVFPMemConstructor.subst(vfpIop) 777}}; 778