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