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