macromem.isa revision 8304
1// -*- mode:c++ -*- 2 3// Copyright (c) 2010 ARM Limited 4// All rights reserved 5// 6// The license below extends only to copyright in the software and shall 7// not be construed as granting a license to any other intellectual 8// property including but not limited to intellectual property relating 9// to a hardware implementation of the functionality of the software 10// licensed hereunder. You may use the software subject to the license 11// terms below provided that you ensure that this notice is replicated 12// unmodified and in its entirety in all distributions of the software, 13// modified or unmodified, in source code or in binary form. 14// 15// Copyright (c) 2007-2008 The Florida State University 16// All rights reserved. 17// 18// Redistribution and use in source and binary forms, with or without 19// modification, are permitted provided that the following conditions are 20// met: redistributions of source code must retain the above copyright 21// notice, this list of conditions and the following disclaimer; 22// redistributions in binary form must reproduce the above copyright 23// notice, this list of conditions and the following disclaimer in the 24// documentation and/or other materials provided with the distribution; 25// neither the name of the copyright holders nor the names of its 26// contributors may be used to endorse or promote products derived from 27// this software without specific prior written permission. 28// 29// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40// 41// Authors: Stephen Hines 42// Gabe Black 43 44//////////////////////////////////////////////////////////////////// 45// 46// Load/store microops 47// 48 49let {{ 50 microLdrUopCode = "IWRa = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 51 microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop', 52 'MicroMemOp', 53 {'memacc_code': microLdrUopCode, 54 'ea_code': 'EA = URb + (up ? imm : -imm);', 55 'predicate_test': predicateTest}, 56 ['IsMicroop']) 57 58 microLdrFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 59 microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop', 60 'MicroMemOp', 61 {'memacc_code': microLdrFpUopCode, 62 'ea_code': vfpEnabledCheckCode + 63 'EA = URb + (up ? imm : -imm);', 64 'predicate_test': predicateTest}, 65 ['IsMicroop']) 66 67 microLdrDBFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 68 microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop', 69 'MicroMemOp', 70 {'memacc_code': microLdrFpUopCode, 71 'ea_code': vfpEnabledCheckCode + ''' 72 EA = URb + (up ? imm : -imm) + 73 (((CPSR)Cpsr).e ? 4 : 0); 74 ''', 75 'predicate_test': predicateTest}, 76 ['IsMicroop']) 77 78 microLdrDTFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 79 microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop', 80 'MicroMemOp', 81 {'memacc_code': microLdrFpUopCode, 82 'ea_code': vfpEnabledCheckCode + ''' 83 EA = URb + (up ? imm : -imm) - 84 (((CPSR)Cpsr).e ? 4 : 0); 85 ''', 86 'predicate_test': predicateTest}, 87 ['IsMicroop']) 88 89 microRetUopCode = ''' 90 CPSR old_cpsr = Cpsr; 91 SCTLR sctlr = Sctlr; 92 93 CPSR new_cpsr = 94 cpsrWriteByInstr(old_cpsr, Spsr, 0xF, true, sctlr.nmfi); 95 Cpsr = ~CondCodesMask & new_cpsr; 96 CondCodesNZ = new_cpsr.nz; 97 CondCodesC = new_cpsr.c; 98 CondCodesV = new_cpsr.v; 99 CondCodesGE = new_cpsr.ge; 100 IWNPC = cSwap(%s, old_cpsr.e) | ((Spsr & 0x20) ? 1 : 0); 101 NextItState = ((((CPSR)Spsr).it2 << 2) & 0xFC) 102 | (((CPSR)Spsr).it1 & 0x3); 103 SevMailbox = 1; 104 ''' 105 106 microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', 107 'MicroMemOp', 108 {'memacc_code': 109 microRetUopCode % 'Mem.uw', 110 'ea_code': 111 'EA = URb + (up ? imm : -imm);', 112 'predicate_test': condPredicateTest}, 113 ['IsMicroop','IsNonSpeculative', 114 'IsSerializeAfter']) 115 116 microStrUopCode = "Mem = cSwap(URa.uw, ((CPSR)Cpsr).e);" 117 microStrUopIop = InstObjParams('str_uop', 'MicroStrUop', 118 'MicroMemOp', 119 {'memacc_code': microStrUopCode, 120 'postacc_code': "", 121 'ea_code': 'EA = URb + (up ? imm : -imm);', 122 'predicate_test': predicateTest}, 123 ['IsMicroop']) 124 125 microStrFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 126 microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop', 127 'MicroMemOp', 128 {'memacc_code': microStrFpUopCode, 129 'postacc_code': "", 130 'ea_code': vfpEnabledCheckCode + 131 'EA = URb + (up ? imm : -imm);', 132 'predicate_test': predicateTest}, 133 ['IsMicroop']) 134 135 microStrDBFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 136 microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop', 137 'MicroMemOp', 138 {'memacc_code': microStrFpUopCode, 139 'postacc_code': "", 140 'ea_code': vfpEnabledCheckCode + ''' 141 EA = URb + (up ? imm : -imm) + 142 (((CPSR)Cpsr).e ? 4 : 0); 143 ''', 144 'predicate_test': predicateTest}, 145 ['IsMicroop']) 146 147 microStrDTFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 148 microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop', 149 'MicroMemOp', 150 {'memacc_code': microStrFpUopCode, 151 'postacc_code': "", 152 'ea_code': vfpEnabledCheckCode + ''' 153 EA = URb + (up ? imm : -imm) - 154 (((CPSR)Cpsr).e ? 4 : 0); 155 ''', 156 'predicate_test': predicateTest}, 157 ['IsMicroop']) 158 159 header_output = decoder_output = exec_output = '' 160 161 loadIops = (microLdrUopIop, microLdrRetUopIop, 162 microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop) 163 storeIops = (microStrUopIop, microStrFpUopIop, 164 microStrDBFpUopIop, microStrDTFpUopIop) 165 for iop in loadIops + storeIops: 166 header_output += MicroMemDeclare.subst(iop) 167 decoder_output += MicroMemConstructor.subst(iop) 168 for iop in loadIops: 169 exec_output += LoadExecute.subst(iop) + \ 170 LoadInitiateAcc.subst(iop) + \ 171 LoadCompleteAcc.subst(iop) 172 for iop in storeIops: 173 exec_output += StoreExecute.subst(iop) + \ 174 StoreInitiateAcc.subst(iop) + \ 175 StoreCompleteAcc.subst(iop) 176}}; 177 178let {{ 179 exec_output = header_output = '' 180 181 eaCode = 'EA = URa + imm;' 182 183 for size in (1, 2, 3, 4, 6, 8, 12, 16): 184 # Set up the memory access. 185 regs = (size + 3) // 4 186 subst = { "size" : size, "regs" : regs } 187 memDecl = ''' 188 union MemUnion { 189 uint8_t bytes[%(size)d]; 190 Element elements[%(size)d / sizeof(Element)]; 191 uint32_t floatRegBits[%(regs)d]; 192 }; 193 ''' % subst 194 195 # Do endian conversion for all the elements. 196 convCode = ''' 197 const unsigned eCount = sizeof(memUnion.elements) / 198 sizeof(memUnion.elements[0]); 199 if (((CPSR)Cpsr).e) { 200 for (unsigned i = 0; i < eCount; i++) { 201 memUnion.elements[i] = gtobe(memUnion.elements[i]); 202 } 203 } else { 204 for (unsigned i = 0; i < eCount; i++) { 205 memUnion.elements[i] = gtole(memUnion.elements[i]); 206 } 207 } 208 ''' 209 210 # Offload everything into registers 211 regSetCode = '' 212 for reg in range(regs): 213 mask = '' 214 if reg == regs - 1: 215 mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size)) 216 regSetCode += ''' 217 FpDestP%(reg)d.uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s; 218 ''' % { "reg" : reg, "mask" : mask } 219 220 # Pull everything in from registers 221 regGetCode = '' 222 for reg in range(regs): 223 regGetCode += ''' 224 memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d.uw); 225 ''' % { "reg" : reg } 226 227 loadMemAccCode = convCode + regSetCode 228 storeMemAccCode = regGetCode + convCode 229 230 loadIop = InstObjParams('ldrneon%(size)d_uop' % subst, 231 'MicroLdrNeon%(size)dUop' % subst, 232 'MicroNeonMemOp', 233 { 'mem_decl' : memDecl, 234 'size' : size, 235 'memacc_code' : loadMemAccCode, 236 'ea_code' : simdEnabledCheckCode + eaCode, 237 'predicate_test' : predicateTest }, 238 [ 'IsMicroop', 'IsMemRef', 'IsLoad' ]) 239 storeIop = InstObjParams('strneon%(size)d_uop' % subst, 240 'MicroStrNeon%(size)dUop' % subst, 241 'MicroNeonMemOp', 242 { 'mem_decl' : memDecl, 243 'size' : size, 244 'memacc_code' : storeMemAccCode, 245 'ea_code' : simdEnabledCheckCode + eaCode, 246 'predicate_test' : predicateTest }, 247 [ 'IsMicroop', 'IsMemRef', 'IsStore' ]) 248 249 exec_output += NeonLoadExecute.subst(loadIop) + \ 250 NeonLoadInitiateAcc.subst(loadIop) + \ 251 NeonLoadCompleteAcc.subst(loadIop) + \ 252 NeonStoreExecute.subst(storeIop) + \ 253 NeonStoreInitiateAcc.subst(storeIop) + \ 254 NeonStoreCompleteAcc.subst(storeIop) 255 header_output += MicroNeonMemDeclare.subst(loadIop) + \ 256 MicroNeonMemDeclare.subst(storeIop) 257}}; 258 259let {{ 260 exec_output = '' 261 for eSize, type in (1, 'uint8_t'), \ 262 (2, 'uint16_t'), \ 263 (4, 'uint32_t'), \ 264 (8, 'uint64_t'): 265 size = eSize 266 # An instruction handles no more than 16 bytes and no more than 267 # 4 elements, or the number of elements needed to fill 8 or 16 bytes. 268 sizes = set((16, 8)) 269 for count in 1, 2, 3, 4: 270 size = count * eSize 271 if size <= 16: 272 sizes.add(size) 273 for size in sizes: 274 substDict = { 275 "class_name" : "MicroLdrNeon%dUop" % size, 276 "targs" : type 277 } 278 exec_output += MicroNeonMemExecDeclare.subst(substDict) 279 substDict["class_name"] = "MicroStrNeon%dUop" % size 280 exec_output += MicroNeonMemExecDeclare.subst(substDict) 281 size += eSize 282}}; 283 284//////////////////////////////////////////////////////////////////// 285// 286// Neon (de)interlacing microops 287// 288 289let {{ 290 header_output = exec_output = '' 291 for dRegs in (2, 3, 4): 292 loadConv = '' 293 unloadConv = '' 294 for dReg in range(dRegs): 295 loadConv += ''' 296 conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d.uw); 297 conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d.uw); 298 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 299 unloadConv += ''' 300 FpDestS%(dReg)dP0.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]); 301 FpDestS%(dReg)dP1.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]); 302 ''' % { "dReg" : dReg } 303 microDeintNeonCode = ''' 304 const unsigned dRegs = %(dRegs)d; 305 const unsigned regs = 2 * dRegs; 306 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 307 sizeof(Element); 308 union convStruct { 309 FloatRegBits cRegs[regs]; 310 Element elements[dRegs * perDReg]; 311 } conv1, conv2; 312 313 %(loadConv)s 314 315 unsigned srcElem = 0; 316 for (unsigned destOffset = 0; 317 destOffset < perDReg; destOffset++) { 318 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 319 conv2.elements[dReg * perDReg + destOffset] = 320 conv1.elements[srcElem++]; 321 } 322 } 323 324 %(unloadConv)s 325 ''' % { "dRegs" : dRegs, 326 "loadConv" : loadConv, 327 "unloadConv" : unloadConv } 328 microDeintNeonIop = \ 329 InstObjParams('deintneon%duop' % (dRegs * 2), 330 'MicroDeintNeon%dUop' % (dRegs * 2), 331 'MicroNeonMixOp', 332 { 'predicate_test': predicateTest, 333 'code' : microDeintNeonCode }, 334 ['IsMicroop']) 335 header_output += MicroNeonMixDeclare.subst(microDeintNeonIop) 336 exec_output += MicroNeonMixExecute.subst(microDeintNeonIop) 337 338 loadConv = '' 339 unloadConv = '' 340 for dReg in range(dRegs): 341 loadConv += ''' 342 conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0.uw); 343 conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1.uw); 344 ''' % { "dReg" : dReg } 345 unloadConv += ''' 346 FpDestP%(sReg0)d.uw = gtoh(conv2.cRegs[%(sReg0)d]); 347 FpDestP%(sReg1)d.uw = gtoh(conv2.cRegs[%(sReg1)d]); 348 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 349 microInterNeonCode = ''' 350 const unsigned dRegs = %(dRegs)d; 351 const unsigned regs = 2 * dRegs; 352 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 353 sizeof(Element); 354 union convStruct { 355 FloatRegBits cRegs[regs]; 356 Element elements[dRegs * perDReg]; 357 } conv1, conv2; 358 359 %(loadConv)s 360 361 unsigned destElem = 0; 362 for (unsigned srcOffset = 0; 363 srcOffset < perDReg; srcOffset++) { 364 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 365 conv2.elements[destElem++] = 366 conv1.elements[dReg * perDReg + srcOffset]; 367 } 368 } 369 370 %(unloadConv)s 371 ''' % { "dRegs" : dRegs, 372 "loadConv" : loadConv, 373 "unloadConv" : unloadConv } 374 microInterNeonIop = \ 375 InstObjParams('interneon%duop' % (dRegs * 2), 376 'MicroInterNeon%dUop' % (dRegs * 2), 377 'MicroNeonMixOp', 378 { 'predicate_test': predicateTest, 379 'code' : microInterNeonCode }, 380 ['IsMicroop']) 381 header_output += MicroNeonMixDeclare.subst(microInterNeonIop) 382 exec_output += MicroNeonMixExecute.subst(microInterNeonIop) 383}}; 384 385let {{ 386 exec_output = '' 387 for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'): 388 for dRegs in (2, 3, 4): 389 Name = "MicroDeintNeon%dUop" % (dRegs * 2) 390 substDict = { "class_name" : Name, "targs" : type } 391 exec_output += MicroNeonExecDeclare.subst(substDict) 392 Name = "MicroInterNeon%dUop" % (dRegs * 2) 393 substDict = { "class_name" : Name, "targs" : type } 394 exec_output += MicroNeonExecDeclare.subst(substDict) 395}}; 396 397//////////////////////////////////////////////////////////////////// 398// 399// Neon microops to pack/unpack a single lane 400// 401 402let {{ 403 header_output = exec_output = '' 404 for sRegs in 1, 2: 405 baseLoadRegs = '' 406 for reg in range(sRegs): 407 baseLoadRegs += ''' 408 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 409 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 410 ''' % { "reg0" : (2 * reg + 0), 411 "reg1" : (2 * reg + 1) } 412 for dRegs in range(sRegs, 5): 413 unloadRegs = '' 414 loadRegs = baseLoadRegs 415 for reg in range(dRegs): 416 loadRegs += ''' 417 destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0.uw); 418 destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1.uw); 419 ''' % { "reg" : reg } 420 unloadRegs += ''' 421 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 422 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 423 ''' % { "reg" : reg } 424 microUnpackNeonCode = ''' 425 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 426 sizeof(Element); 427 428 union SourceRegs { 429 FloatRegBits fRegs[2 * %(sRegs)d]; 430 Element elements[%(sRegs)d * perDReg]; 431 } sourceRegs; 432 433 union DestReg { 434 FloatRegBits fRegs[2]; 435 Element elements[perDReg]; 436 } destRegs[%(dRegs)d]; 437 438 %(loadRegs)s 439 440 for (unsigned i = 0; i < %(dRegs)d; i++) { 441 destRegs[i].elements[lane] = sourceRegs.elements[i]; 442 } 443 444 %(unloadRegs)s 445 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 446 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 447 448 microUnpackNeonIop = \ 449 InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2), 450 'MicroUnpackNeon%dto%dUop' % 451 (sRegs * 2, dRegs * 2), 452 'MicroNeonMixLaneOp', 453 { 'predicate_test': predicateTest, 454 'code' : microUnpackNeonCode }, 455 ['IsMicroop']) 456 header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop) 457 exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop) 458 459 for sRegs in 1, 2: 460 loadRegs = '' 461 for reg in range(sRegs): 462 loadRegs += ''' 463 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 464 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 465 ''' % { "reg0" : (2 * reg + 0), 466 "reg1" : (2 * reg + 1) } 467 for dRegs in range(sRegs, 5): 468 unloadRegs = '' 469 for reg in range(dRegs): 470 unloadRegs += ''' 471 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 472 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 473 ''' % { "reg" : reg } 474 microUnpackAllNeonCode = ''' 475 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 476 sizeof(Element); 477 478 union SourceRegs { 479 FloatRegBits fRegs[2 * %(sRegs)d]; 480 Element elements[%(sRegs)d * perDReg]; 481 } sourceRegs; 482 483 union DestReg { 484 FloatRegBits fRegs[2]; 485 Element elements[perDReg]; 486 } destRegs[%(dRegs)d]; 487 488 %(loadRegs)s 489 490 for (unsigned i = 0; i < %(dRegs)d; i++) { 491 for (unsigned j = 0; j < perDReg; j++) 492 destRegs[i].elements[j] = sourceRegs.elements[i]; 493 } 494 495 %(unloadRegs)s 496 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 497 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 498 499 microUnpackAllNeonIop = \ 500 InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2), 501 'MicroUnpackAllNeon%dto%dUop' % 502 (sRegs * 2, dRegs * 2), 503 'MicroNeonMixOp', 504 { 'predicate_test': predicateTest, 505 'code' : microUnpackAllNeonCode }, 506 ['IsMicroop']) 507 header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop) 508 exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop) 509 510 for dRegs in 1, 2: 511 unloadRegs = '' 512 for reg in range(dRegs): 513 unloadRegs += ''' 514 FpDestP%(reg0)d.uw = gtoh(destRegs.fRegs[%(reg0)d]); 515 FpDestP%(reg1)d.uw = gtoh(destRegs.fRegs[%(reg1)d]); 516 ''' % { "reg0" : (2 * reg + 0), 517 "reg1" : (2 * reg + 1) } 518 for sRegs in range(dRegs, 5): 519 loadRegs = '' 520 for reg in range(sRegs): 521 loadRegs += ''' 522 sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0.uw); 523 sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1.uw); 524 ''' % { "reg" : reg } 525 microPackNeonCode = ''' 526 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 527 sizeof(Element); 528 529 union SourceReg { 530 FloatRegBits fRegs[2]; 531 Element elements[perDReg]; 532 } sourceRegs[%(sRegs)d]; 533 534 union DestRegs { 535 FloatRegBits fRegs[2 * %(dRegs)d]; 536 Element elements[%(dRegs)d * perDReg]; 537 } destRegs; 538 539 %(loadRegs)s 540 541 for (unsigned i = 0; i < %(sRegs)d; i++) { 542 destRegs.elements[i] = sourceRegs[i].elements[lane]; 543 } 544 545 %(unloadRegs)s 546 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 547 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 548 549 microPackNeonIop = \ 550 InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2), 551 'MicroPackNeon%dto%dUop' % 552 (sRegs * 2, dRegs * 2), 553 'MicroNeonMixLaneOp', 554 { 'predicate_test': predicateTest, 555 'code' : microPackNeonCode }, 556 ['IsMicroop']) 557 header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop) 558 exec_output += MicroNeonMixExecute.subst(microPackNeonIop) 559}}; 560 561let {{ 562 exec_output = '' 563 for type in ('uint8_t', 'uint16_t', 'uint32_t'): 564 for sRegs in 1, 2: 565 for dRegs in range(sRegs, 5): 566 for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop", 567 "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop", 568 "MicroPackNeon%(dRegs)dto%(sRegs)dUop"): 569 Name = format % { "sRegs" : sRegs * 2, 570 "dRegs" : dRegs * 2 } 571 substDict = { "class_name" : Name, "targs" : type } 572 exec_output += MicroNeonExecDeclare.subst(substDict) 573}}; 574 575//////////////////////////////////////////////////////////////////// 576// 577// Integer = Integer op Immediate microops 578// 579 580let {{ 581 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop', 582 'MicroIntImmOp', 583 {'code': 'URa = URb + imm;', 584 'predicate_test': predicateTest}, 585 ['IsMicroop']) 586 587 microAddUopCode = ''' 588 URa = URb + shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC); 589 ''' 590 591 microAddUopIop = InstObjParams('add_uop', 'MicroAddUop', 592 'MicroIntRegOp', 593 {'code': microAddUopCode, 594 'predicate_test': pickPredicate(microAddUopCode)}, 595 ['IsMicroop']) 596 597 microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop', 598 'MicroIntImmOp', 599 {'code': 'URa = URb - imm;', 600 'predicate_test': predicateTest}, 601 ['IsMicroop']) 602 603 microSubUopCode = ''' 604 URa = URb - shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC); 605 ''' 606 microSubUopIop = InstObjParams('sub_uop', 'MicroSubUop', 607 'MicroIntRegOp', 608 {'code': microSubUopCode, 609 'predicate_test': pickPredicate(microSubUopCode)}, 610 ['IsMicroop']) 611 612 microUopRegMovIop = InstObjParams('uopReg_uop', 'MicroUopRegMov', 613 'MicroIntMov', 614 {'code': 'IWRa = URb;', 615 'predicate_test': predicateTest}, 616 ['IsMicroop']) 617 618 microUopRegMovRetIop = InstObjParams('movret_uop', 'MicroUopRegMovRet', 619 'MicroIntMov', 620 {'code': microRetUopCode % 'URb', 621 'predicate_test': predicateTest}, 622 ['IsMicroop', 'IsNonSpeculative', 623 'IsSerializeAfter']) 624 625 setPCCPSRDecl = ''' 626 CPSR cpsrOrCondCodes = URc; 627 SCTLR sctlr = Sctlr; 628 pNPC = URa; 629 CPSR new_cpsr = 630 cpsrWriteByInstr(cpsrOrCondCodes, URb, 631 0xF, true, sctlr.nmfi); 632 Cpsr = ~CondCodesMask & new_cpsr; 633 NextThumb = new_cpsr.t; 634 NextJazelle = new_cpsr.j; 635 NextItState = ((((CPSR)URb).it2 << 2) & 0xFC) 636 | (((CPSR)URb).it1 & 0x3); 637 CondCodesNZ = new_cpsr.nz; 638 CondCodesC = new_cpsr.c; 639 CondCodesV = new_cpsr.v; 640 CondCodesGE = new_cpsr.ge; 641 ''' 642 643 microUopSetPCCPSRIop = InstObjParams('uopSet_uop', 'MicroUopSetPCCPSR', 644 'MicroSetPCCPSR', 645 {'code': setPCCPSRDecl, 646 'predicate_test': predicateTest}, 647 ['IsMicroop']) 648 649 header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \ 650 MicroIntImmDeclare.subst(microSubiUopIop) + \ 651 MicroIntRegDeclare.subst(microAddUopIop) + \ 652 MicroIntRegDeclare.subst(microSubUopIop) + \ 653 MicroIntMovDeclare.subst(microUopRegMovIop) + \ 654 MicroIntMovDeclare.subst(microUopRegMovRetIop) + \ 655 MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop) 656 657 decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \ 658 MicroIntImmConstructor.subst(microSubiUopIop) + \ 659 MicroIntRegConstructor.subst(microAddUopIop) + \ 660 MicroIntRegConstructor.subst(microSubUopIop) + \ 661 MicroIntMovConstructor.subst(microUopRegMovIop) + \ 662 MicroIntMovConstructor.subst(microUopRegMovRetIop) + \ 663 MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop) 664 665 exec_output = PredOpExecute.subst(microAddiUopIop) + \ 666 PredOpExecute.subst(microSubiUopIop) + \ 667 PredOpExecute.subst(microAddUopIop) + \ 668 PredOpExecute.subst(microSubUopIop) + \ 669 PredOpExecute.subst(microUopRegMovIop) + \ 670 PredOpExecute.subst(microUopRegMovRetIop) + \ 671 PredOpExecute.subst(microUopSetPCCPSRIop) 672 673}}; 674 675let {{ 676 iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", []) 677 header_output = MacroMemDeclare.subst(iop) 678 decoder_output = MacroMemConstructor.subst(iop) 679 680 iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", []) 681 header_output += VMemMultDeclare.subst(iop) 682 decoder_output += VMemMultConstructor.subst(iop) 683 684 iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", []) 685 header_output += VMemSingleDeclare.subst(iop) 686 decoder_output += VMemSingleConstructor.subst(iop) 687 688 iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", []) 689 header_output += VMemMultDeclare.subst(iop) 690 decoder_output += VMemMultConstructor.subst(iop) 691 692 iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", []) 693 header_output += VMemSingleDeclare.subst(iop) 694 decoder_output += VMemSingleConstructor.subst(iop) 695 696 vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", []) 697 header_output += MacroVFPMemDeclare.subst(vfpIop) 698 decoder_output += MacroVFPMemConstructor.subst(vfpIop) 699}}; 700