149 replaceBits(regs, reg, 0); 150 reg_idx = force_user ? intRegInMode(MODE_USER, reg) : reg; 151 152 if (load) { 153 if (writeback && reg_idx == INTREG_PC) { 154 // If this instruction changes the PC and performs a 155 // writeback, ensure the pc load/branch is the last uop. 156 // Load into a temp reg here. 157 *uop = new MicroLdrUop(machInst, INTREG_UREG1, 158 copy_base ? INTREG_UREG0 : rn, up, addr); 159 } else if (reg_idx == INTREG_PC && exception_ret) { 160 // Special handling for exception return 161 *uop = new MicroLdrRetUop(machInst, reg_idx, 162 copy_base ? INTREG_UREG0 : rn, up, addr); 163 } else { 164 // standard single load uop 165 *uop = new MicroLdrUop(machInst, reg_idx, 166 copy_base ? INTREG_UREG0 : rn, up, addr); 167 } 168 169 // Loading pc as last operation? Set appropriate flags. 170 if (!writeback && reg_idx == INTREG_PC) { 171 (*uop)->setFlag(StaticInst::IsControl); 172 (*uop)->setFlag(StaticInst::IsIndirectControl); 173 174 if (!(condCode == COND_AL || condCode == COND_UC)) 175 (*uop)->setFlag(StaticInst::IsCondControl); 176 else 177 (*uop)->setFlag(StaticInst::IsUncondControl); 178 } 179 } else { 180 *uop = new MicroStrUop(machInst, reg_idx, rn, up, addr); 181 } 182 183 if (up) addr += 4; 184 else addr -= 4; 185 --mem_ops; 186 } 187 188 // Load/store micro-op generated, go to next uop 189 ++uop; 190 } 191 192 if (writeback && ones) { 193 // Perform writeback uop operation 194 if (up) 195 *uop++ = new MicroAddiUop(machInst, rn, rn, ones * 4); 196 else 197 *uop++ = new MicroSubiUop(machInst, rn, rn, ones * 4); 198 199 // Write PC after address writeback? 200 if (pc_temp) { 201 if (exception_ret) { 202 *uop = new MicroUopRegMovRet(machInst, 0, INTREG_UREG1); 203 } else { 204 *uop = new MicroUopRegMov(machInst, INTREG_PC, INTREG_UREG1); 205 } 206 (*uop)->setFlag(StaticInst::IsControl); 207 (*uop)->setFlag(StaticInst::IsIndirectControl); 208 209 if (!(condCode == COND_AL || condCode == COND_UC)) 210 (*uop)->setFlag(StaticInst::IsCondControl); 211 else 212 (*uop)->setFlag(StaticInst::IsUncondControl); 213 214 if (rn == INTREG_SP) 215 (*uop)->setFlag(StaticInst::IsReturn); 216 217 ++uop; 218 } 219 } 220 221 --uop; 222 (*uop)->setLastMicroop(); 223 microOps[0]->setFirstMicroop(); 224 225 /* Take the control flags from the last microop for the macroop */ 226 if ((*uop)->isControl()) 227 setFlag(StaticInst::IsControl); 228 if ((*uop)->isCondCtrl()) 229 setFlag(StaticInst::IsCondControl); 230 if ((*uop)->isUncondCtrl()) 231 setFlag(StaticInst::IsUncondControl); 232 if ((*uop)->isIndirectCtrl()) 233 setFlag(StaticInst::IsIndirectControl); 234 if ((*uop)->isReturn()) 235 setFlag(StaticInst::IsReturn); 236 237 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) { 238 (*uop)->setDelayedCommit(); 239 } 240} 241 242PairMemOp::PairMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, 243 uint32_t size, bool fp, bool load, bool noAlloc, 244 bool signExt, bool exclusive, bool acrel, 245 int64_t imm, AddrMode mode, 246 IntRegIndex rn, IntRegIndex rt, IntRegIndex rt2) : 247 PredMacroOp(mnem, machInst, __opClass) 248{ 249 bool post = (mode == AddrMd_PostIndex); 250 bool writeback = (mode != AddrMd_Offset); 251 252 if (load) { 253 // Use integer rounding to round up loads of size 4 254 numMicroops = (post ? 0 : 1) + ((size + 4) / 8) + (writeback ? 1 : 0); 255 } else { 256 numMicroops = (post ? 0 : 1) + (size / 4) + (writeback ? 1 : 0); 257 } 258 microOps = new StaticInstPtr[numMicroops]; 259 260 StaticInstPtr *uop = microOps; 261 262 rn = makeSP(rn); 263 264 if (!post) { 265 *uop++ = new MicroAddXiSpAlignUop(machInst, INTREG_UREG0, rn, 266 post ? 0 : imm); 267 } 268 269 if (fp) { 270 if (size == 16) { 271 if (load) { 272 *uop++ = new MicroLdFp16Uop(machInst, rt, 273 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 274 *uop++ = new MicroLdFp16Uop(machInst, rt2, 275 post ? rn : INTREG_UREG0, 16, noAlloc, exclusive, acrel); 276 } else { 277 *uop++ = new MicroStrQBFpXImmUop(machInst, rt, 278 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 279 *uop++ = new MicroStrQTFpXImmUop(machInst, rt, 280 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 281 *uop++ = new MicroStrQBFpXImmUop(machInst, rt2, 282 post ? rn : INTREG_UREG0, 16, noAlloc, exclusive, acrel); 283 *uop++ = new MicroStrQTFpXImmUop(machInst, rt2, 284 post ? rn : INTREG_UREG0, 16, noAlloc, exclusive, acrel); 285 } 286 } else if (size == 8) { 287 if (load) { 288 *uop++ = new MicroLdPairFp8Uop(machInst, rt, rt2, 289 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 290 } else { 291 *uop++ = new MicroStrFpXImmUop(machInst, rt, 292 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 293 *uop++ = new MicroStrFpXImmUop(machInst, rt2, 294 post ? rn : INTREG_UREG0, 8, noAlloc, exclusive, acrel); 295 } 296 } else if (size == 4) { 297 if (load) { 298 *uop++ = new MicroLdrDFpXImmUop(machInst, rt, rt2, 299 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 300 } else { 301 *uop++ = new MicroStrDFpXImmUop(machInst, rt, rt2, 302 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 303 } 304 } 305 } else { 306 if (size == 8) { 307 if (load) { 308 *uop++ = new MicroLdPairUop(machInst, rt, rt2, 309 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 310 } else { 311 *uop++ = new MicroStrXImmUop(machInst, rt, post ? rn : INTREG_UREG0, 312 0, noAlloc, exclusive, acrel); 313 *uop++ = new MicroStrXImmUop(machInst, rt2, post ? rn : INTREG_UREG0, 314 size, noAlloc, exclusive, acrel); 315 } 316 } else if (size == 4) { 317 if (load) { 318 if (signExt) { 319 *uop++ = new MicroLdrDSXImmUop(machInst, rt, rt2, 320 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 321 } else { 322 *uop++ = new MicroLdrDUXImmUop(machInst, rt, rt2, 323 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 324 } 325 } else { 326 *uop++ = new MicroStrDXImmUop(machInst, rt, rt2, 327 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 328 } 329 } 330 } 331 332 if (writeback) { 333 *uop++ = new MicroAddXiUop(machInst, rn, post ? rn : INTREG_UREG0, 334 post ? imm : 0); 335 } 336 337 assert(uop == µOps[numMicroops]); 338 (*--uop)->setLastMicroop(); 339 microOps[0]->setFirstMicroop(); 340 341 for (StaticInstPtr *curUop = microOps; 342 !(*curUop)->isLastMicroop(); curUop++) { 343 (*curUop)->setDelayedCommit(); 344 } 345} 346 347BigFpMemImmOp::BigFpMemImmOp(const char *mnem, ExtMachInst machInst, 348 OpClass __opClass, bool load, IntRegIndex dest, 349 IntRegIndex base, int64_t imm) : 350 PredMacroOp(mnem, machInst, __opClass) 351{ 352 numMicroops = load ? 1 : 2; 353 microOps = new StaticInstPtr[numMicroops]; 354 355 StaticInstPtr *uop = microOps; 356 357 if (load) { 358 *uop = new MicroLdFp16Uop(machInst, dest, base, imm); 359 } else { 360 *uop = new MicroStrQBFpXImmUop(machInst, dest, base, imm); 361 (*uop)->setDelayedCommit(); 362 *++uop = new MicroStrQTFpXImmUop(machInst, dest, base, imm); 363 } 364 (*uop)->setLastMicroop(); 365 microOps[0]->setFirstMicroop(); 366} 367 368BigFpMemPostOp::BigFpMemPostOp(const char *mnem, ExtMachInst machInst, 369 OpClass __opClass, bool load, IntRegIndex dest, 370 IntRegIndex base, int64_t imm) : 371 PredMacroOp(mnem, machInst, __opClass) 372{ 373 numMicroops = load ? 2 : 3; 374 microOps = new StaticInstPtr[numMicroops]; 375 376 StaticInstPtr *uop = microOps; 377 378 if (load) { 379 *uop++ = new MicroLdFp16Uop(machInst, dest, base, 0); 380 } else { 381 *uop++= new MicroStrQBFpXImmUop(machInst, dest, base, 0); 382 *uop++ = new MicroStrQTFpXImmUop(machInst, dest, base, 0); 383 } 384 *uop = new MicroAddXiUop(machInst, base, base, imm); 385 (*uop)->setLastMicroop(); 386 microOps[0]->setFirstMicroop(); 387 388 for (StaticInstPtr *curUop = microOps; 389 !(*curUop)->isLastMicroop(); curUop++) { 390 (*curUop)->setDelayedCommit(); 391 } 392} 393 394BigFpMemPreOp::BigFpMemPreOp(const char *mnem, ExtMachInst machInst, 395 OpClass __opClass, bool load, IntRegIndex dest, 396 IntRegIndex base, int64_t imm) : 397 PredMacroOp(mnem, machInst, __opClass) 398{ 399 numMicroops = load ? 2 : 3; 400 microOps = new StaticInstPtr[numMicroops]; 401 402 StaticInstPtr *uop = microOps; 403 404 if (load) { 405 *uop++ = new MicroLdFp16Uop(machInst, dest, base, imm); 406 } else { 407 *uop++ = new MicroStrQBFpXImmUop(machInst, dest, base, imm); 408 *uop++ = new MicroStrQTFpXImmUop(machInst, dest, base, imm); 409 } 410 *uop = new MicroAddXiUop(machInst, base, base, imm); 411 (*uop)->setLastMicroop(); 412 microOps[0]->setFirstMicroop(); 413 414 for (StaticInstPtr *curUop = microOps; 415 !(*curUop)->isLastMicroop(); curUop++) { 416 (*curUop)->setDelayedCommit(); 417 } 418} 419 420BigFpMemRegOp::BigFpMemRegOp(const char *mnem, ExtMachInst machInst, 421 OpClass __opClass, bool load, IntRegIndex dest, 422 IntRegIndex base, IntRegIndex offset, 423 ArmExtendType type, int64_t imm) : 424 PredMacroOp(mnem, machInst, __opClass) 425{ 426 numMicroops = load ? 1 : 2; 427 microOps = new StaticInstPtr[numMicroops]; 428 429 StaticInstPtr *uop = microOps; 430 431 if (load) { 432 *uop = new MicroLdFp16RegUop(machInst, dest, base, 433 offset, type, imm); 434 } else { 435 *uop = new MicroStrQBFpXRegUop(machInst, dest, base, 436 offset, type, imm); 437 (*uop)->setDelayedCommit(); 438 *++uop = new MicroStrQTFpXRegUop(machInst, dest, base, 439 offset, type, imm); 440 } 441 442 (*uop)->setLastMicroop(); 443 microOps[0]->setFirstMicroop(); 444} 445 446BigFpMemLitOp::BigFpMemLitOp(const char *mnem, ExtMachInst machInst, 447 OpClass __opClass, IntRegIndex dest, 448 int64_t imm) : 449 PredMacroOp(mnem, machInst, __opClass) 450{ 451 numMicroops = 1; 452 microOps = new StaticInstPtr[numMicroops]; 453 454 microOps[0] = new MicroLdFp16LitUop(machInst, dest, imm); 455 microOps[0]->setLastMicroop(); 456 microOps[0]->setFirstMicroop(); 457} 458 459VldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, 460 unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, 461 unsigned inc, uint32_t size, uint32_t align, RegIndex rm) : 462 PredMacroOp(mnem, machInst, __opClass) 463{ 464 assert(regs > 0 && regs <= 4); 465 assert(regs % elems == 0); 466 467 numMicroops = (regs > 2) ? 2 : 1; 468 bool wb = (rm != 15); 469 bool deinterleave = (elems > 1); 470 471 if (wb) numMicroops++; 472 if (deinterleave) numMicroops += (regs / elems); 473 microOps = new StaticInstPtr[numMicroops]; 474 475 RegIndex rMid = deinterleave ? NumFloatV7ArchRegs : vd * 2; 476 477 uint32_t noAlign = TLB::MustBeOne; 478 479 unsigned uopIdx = 0; 480 switch (regs) { 481 case 4: 482 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 483 size, machInst, rMid, rn, 0, align); 484 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 485 size, machInst, rMid + 4, rn, 16, noAlign); 486 break; 487 case 3: 488 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 489 size, machInst, rMid, rn, 0, align); 490 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>( 491 size, machInst, rMid + 4, rn, 16, noAlign); 492 break; 493 case 2: 494 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 495 size, machInst, rMid, rn, 0, align); 496 break; 497 case 1: 498 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>( 499 size, machInst, rMid, rn, 0, align); 500 break; 501 default: 502 // Unknown number of registers 503 microOps[uopIdx++] = new Unknown(machInst); 504 } 505 if (wb) { 506 if (rm != 15 && rm != 13) { 507 microOps[uopIdx++] = 508 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); 509 } else { 510 microOps[uopIdx++] = 511 new MicroAddiUop(machInst, rn, rn, regs * 8); 512 } 513 } 514 if (deinterleave) { 515 switch (elems) { 516 case 4: 517 assert(regs == 4); 518 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon8Uop>( 519 size, machInst, vd * 2, rMid, inc * 2); 520 break; 521 case 3: 522 assert(regs == 3); 523 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon6Uop>( 524 size, machInst, vd * 2, rMid, inc * 2); 525 break; 526 case 2: 527 assert(regs == 4 || regs == 2); 528 if (regs == 4) { 529 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>( 530 size, machInst, vd * 2, rMid, inc * 2); 531 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>( 532 size, machInst, vd * 2 + 2, rMid + 4, inc * 2); 533 } else { 534 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>( 535 size, machInst, vd * 2, rMid, inc * 2); 536 } 537 break; 538 default: 539 // Bad number of elements to deinterleave 540 microOps[uopIdx++] = new Unknown(machInst); 541 } 542 } 543 assert(uopIdx == numMicroops); 544 545 for (unsigned i = 0; i < numMicroops - 1; i++) { 546 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 547 assert(uopPtr); 548 uopPtr->setDelayedCommit(); 549 } 550 microOps[0]->setFirstMicroop(); 551 microOps[numMicroops - 1]->setLastMicroop(); 552} 553 554VldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst, 555 OpClass __opClass, bool all, unsigned elems, 556 RegIndex rn, RegIndex vd, unsigned regs, 557 unsigned inc, uint32_t size, uint32_t align, 558 RegIndex rm, unsigned lane) : 559 PredMacroOp(mnem, machInst, __opClass) 560{ 561 assert(regs > 0 && regs <= 4); 562 assert(regs % elems == 0); 563 564 unsigned eBytes = (1 << size); 565 unsigned loadSize = eBytes * elems; 566 unsigned loadRegs M5_VAR_USED = (loadSize + sizeof(FloatRegBits) - 1) / 567 sizeof(FloatRegBits); 568 569 assert(loadRegs > 0 && loadRegs <= 4); 570 571 numMicroops = 1; 572 bool wb = (rm != 15); 573 574 if (wb) numMicroops++; 575 numMicroops += (regs / elems); 576 microOps = new StaticInstPtr[numMicroops]; 577 578 RegIndex ufp0 = NumFloatV7ArchRegs; 579 580 unsigned uopIdx = 0; 581 switch (loadSize) { 582 case 1: 583 microOps[uopIdx++] = new MicroLdrNeon1Uop<uint8_t>( 584 machInst, ufp0, rn, 0, align); 585 break; 586 case 2: 587 if (eBytes == 2) { 588 microOps[uopIdx++] = new MicroLdrNeon2Uop<uint16_t>( 589 machInst, ufp0, rn, 0, align); 590 } else { 591 microOps[uopIdx++] = new MicroLdrNeon2Uop<uint8_t>( 592 machInst, ufp0, rn, 0, align); 593 } 594 break; 595 case 3: 596 microOps[uopIdx++] = new MicroLdrNeon3Uop<uint8_t>( 597 machInst, ufp0, rn, 0, align); 598 break; 599 case 4: 600 switch (eBytes) { 601 case 1: 602 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint8_t>( 603 machInst, ufp0, rn, 0, align); 604 break; 605 case 2: 606 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint16_t>( 607 machInst, ufp0, rn, 0, align); 608 break; 609 case 4: 610 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint32_t>( 611 machInst, ufp0, rn, 0, align); 612 break; 613 } 614 break; 615 case 6: 616 microOps[uopIdx++] = new MicroLdrNeon6Uop<uint16_t>( 617 machInst, ufp0, rn, 0, align); 618 break; 619 case 8: 620 switch (eBytes) { 621 case 2: 622 microOps[uopIdx++] = new MicroLdrNeon8Uop<uint16_t>( 623 machInst, ufp0, rn, 0, align); 624 break; 625 case 4: 626 microOps[uopIdx++] = new MicroLdrNeon8Uop<uint32_t>( 627 machInst, ufp0, rn, 0, align); 628 break; 629 } 630 break; 631 case 12: 632 microOps[uopIdx++] = new MicroLdrNeon12Uop<uint32_t>( 633 machInst, ufp0, rn, 0, align); 634 break; 635 case 16: 636 microOps[uopIdx++] = new MicroLdrNeon16Uop<uint32_t>( 637 machInst, ufp0, rn, 0, align); 638 break; 639 default: 640 // Unrecognized load size 641 microOps[uopIdx++] = new Unknown(machInst); 642 } 643 if (wb) { 644 if (rm != 15 && rm != 13) { 645 microOps[uopIdx++] = 646 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); 647 } else { 648 microOps[uopIdx++] = 649 new MicroAddiUop(machInst, rn, rn, loadSize); 650 } 651 } 652 switch (elems) { 653 case 4: 654 assert(regs == 4); 655 switch (size) { 656 case 0: 657 if (all) { 658 microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint8_t>( 659 machInst, vd * 2, ufp0, inc * 2); 660 } else { 661 microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint8_t>( 662 machInst, vd * 2, ufp0, inc * 2, lane); 663 } 664 break; 665 case 1: 666 if (all) { 667 microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint16_t>( 668 machInst, vd * 2, ufp0, inc * 2); 669 } else { 670 microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint16_t>( 671 machInst, vd * 2, ufp0, inc * 2, lane); 672 } 673 break; 674 case 2: 675 if (all) { 676 microOps[uopIdx++] = new MicroUnpackAllNeon4to8Uop<uint32_t>( 677 machInst, vd * 2, ufp0, inc * 2); 678 } else { 679 microOps[uopIdx++] = new MicroUnpackNeon4to8Uop<uint32_t>( 680 machInst, vd * 2, ufp0, inc * 2, lane); 681 } 682 break; 683 default: 684 // Bad size 685 microOps[uopIdx++] = new Unknown(machInst); 686 break; 687 } 688 break; 689 case 3: 690 assert(regs == 3); 691 switch (size) { 692 case 0: 693 if (all) { 694 microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint8_t>( 695 machInst, vd * 2, ufp0, inc * 2); 696 } else { 697 microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint8_t>( 698 machInst, vd * 2, ufp0, inc * 2, lane); 699 } 700 break; 701 case 1: 702 if (all) { 703 microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint16_t>( 704 machInst, vd * 2, ufp0, inc * 2); 705 } else { 706 microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint16_t>( 707 machInst, vd * 2, ufp0, inc * 2, lane); 708 } 709 break; 710 case 2: 711 if (all) { 712 microOps[uopIdx++] = new MicroUnpackAllNeon4to6Uop<uint32_t>( 713 machInst, vd * 2, ufp0, inc * 2); 714 } else { 715 microOps[uopIdx++] = new MicroUnpackNeon4to6Uop<uint32_t>( 716 machInst, vd * 2, ufp0, inc * 2, lane); 717 } 718 break; 719 default: 720 // Bad size 721 microOps[uopIdx++] = new Unknown(machInst); 722 break; 723 } 724 break; 725 case 2: 726 assert(regs == 2); 727 assert(loadRegs <= 2); 728 switch (size) { 729 case 0: 730 if (all) { 731 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint8_t>( 732 machInst, vd * 2, ufp0, inc * 2); 733 } else { 734 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint8_t>( 735 machInst, vd * 2, ufp0, inc * 2, lane); 736 } 737 break; 738 case 1: 739 if (all) { 740 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint16_t>( 741 machInst, vd * 2, ufp0, inc * 2); 742 } else { 743 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint16_t>( 744 machInst, vd * 2, ufp0, inc * 2, lane); 745 } 746 break; 747 case 2: 748 if (all) { 749 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint32_t>( 750 machInst, vd * 2, ufp0, inc * 2); 751 } else { 752 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint32_t>( 753 machInst, vd * 2, ufp0, inc * 2, lane); 754 } 755 break; 756 default: 757 // Bad size 758 microOps[uopIdx++] = new Unknown(machInst); 759 break; 760 } 761 break; 762 case 1: 763 assert(regs == 1 || (all && regs == 2)); 764 assert(loadRegs <= 2); 765 for (unsigned offset = 0; offset < regs; offset++) { 766 switch (size) { 767 case 0: 768 if (all) { 769 microOps[uopIdx++] = 770 new MicroUnpackAllNeon2to2Uop<uint8_t>( 771 machInst, (vd + offset) * 2, ufp0, inc * 2); 772 } else { 773 microOps[uopIdx++] = 774 new MicroUnpackNeon2to2Uop<uint8_t>( 775 machInst, (vd + offset) * 2, ufp0, inc * 2, lane); 776 } 777 break; 778 case 1: 779 if (all) { 780 microOps[uopIdx++] = 781 new MicroUnpackAllNeon2to2Uop<uint16_t>( 782 machInst, (vd + offset) * 2, ufp0, inc * 2); 783 } else { 784 microOps[uopIdx++] = 785 new MicroUnpackNeon2to2Uop<uint16_t>( 786 machInst, (vd + offset) * 2, ufp0, inc * 2, lane); 787 } 788 break; 789 case 2: 790 if (all) { 791 microOps[uopIdx++] = 792 new MicroUnpackAllNeon2to2Uop<uint32_t>( 793 machInst, (vd + offset) * 2, ufp0, inc * 2); 794 } else { 795 microOps[uopIdx++] = 796 new MicroUnpackNeon2to2Uop<uint32_t>( 797 machInst, (vd + offset) * 2, ufp0, inc * 2, lane); 798 } 799 break; 800 default: 801 // Bad size 802 microOps[uopIdx++] = new Unknown(machInst); 803 break; 804 } 805 } 806 break; 807 default: 808 // Bad number of elements to unpack 809 microOps[uopIdx++] = new Unknown(machInst); 810 } 811 assert(uopIdx == numMicroops); 812 813 for (unsigned i = 0; i < numMicroops - 1; i++) { 814 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 815 assert(uopPtr); 816 uopPtr->setDelayedCommit(); 817 } 818 microOps[0]->setFirstMicroop(); 819 microOps[numMicroops - 1]->setLastMicroop(); 820} 821 822VstMultOp::VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, 823 unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, 824 unsigned inc, uint32_t size, uint32_t align, RegIndex rm) : 825 PredMacroOp(mnem, machInst, __opClass) 826{ 827 assert(regs > 0 && regs <= 4); 828 assert(regs % elems == 0); 829 830 numMicroops = (regs > 2) ? 2 : 1; 831 bool wb = (rm != 15); 832 bool interleave = (elems > 1); 833 834 if (wb) numMicroops++; 835 if (interleave) numMicroops += (regs / elems); 836 microOps = new StaticInstPtr[numMicroops]; 837 838 uint32_t noAlign = TLB::MustBeOne; 839 840 RegIndex rMid = interleave ? NumFloatV7ArchRegs : vd * 2; 841 842 unsigned uopIdx = 0; 843 if (interleave) { 844 switch (elems) { 845 case 4: 846 assert(regs == 4); 847 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon8Uop>( 848 size, machInst, rMid, vd * 2, inc * 2); 849 break; 850 case 3: 851 assert(regs == 3); 852 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon6Uop>( 853 size, machInst, rMid, vd * 2, inc * 2); 854 break; 855 case 2: 856 assert(regs == 4 || regs == 2); 857 if (regs == 4) { 858 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>( 859 size, machInst, rMid, vd * 2, inc * 2); 860 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>( 861 size, machInst, rMid + 4, vd * 2 + 2, inc * 2); 862 } else { 863 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>( 864 size, machInst, rMid, vd * 2, inc * 2); 865 } 866 break; 867 default: 868 // Bad number of elements to interleave 869 microOps[uopIdx++] = new Unknown(machInst); 870 } 871 } 872 switch (regs) { 873 case 4: 874 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 875 size, machInst, rMid, rn, 0, align); 876 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 877 size, machInst, rMid + 4, rn, 16, noAlign); 878 break; 879 case 3: 880 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 881 size, machInst, rMid, rn, 0, align); 882 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>( 883 size, machInst, rMid + 4, rn, 16, noAlign); 884 break; 885 case 2: 886 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 887 size, machInst, rMid, rn, 0, align); 888 break; 889 case 1: 890 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>( 891 size, machInst, rMid, rn, 0, align); 892 break; 893 default: 894 // Unknown number of registers 895 microOps[uopIdx++] = new Unknown(machInst); 896 } 897 if (wb) { 898 if (rm != 15 && rm != 13) { 899 microOps[uopIdx++] = 900 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); 901 } else { 902 microOps[uopIdx++] = 903 new MicroAddiUop(machInst, rn, rn, regs * 8); 904 } 905 } 906 assert(uopIdx == numMicroops); 907 908 for (unsigned i = 0; i < numMicroops - 1; i++) { 909 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 910 assert(uopPtr); 911 uopPtr->setDelayedCommit(); 912 } 913 microOps[0]->setFirstMicroop(); 914 microOps[numMicroops - 1]->setLastMicroop(); 915} 916 917VstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst, 918 OpClass __opClass, bool all, unsigned elems, 919 RegIndex rn, RegIndex vd, unsigned regs, 920 unsigned inc, uint32_t size, uint32_t align, 921 RegIndex rm, unsigned lane) : 922 PredMacroOp(mnem, machInst, __opClass) 923{ 924 assert(!all); 925 assert(regs > 0 && regs <= 4); 926 assert(regs % elems == 0); 927 928 unsigned eBytes = (1 << size); 929 unsigned storeSize = eBytes * elems; 930 unsigned storeRegs M5_VAR_USED = (storeSize + sizeof(FloatRegBits) - 1) / 931 sizeof(FloatRegBits); 932 933 assert(storeRegs > 0 && storeRegs <= 4); 934 935 numMicroops = 1; 936 bool wb = (rm != 15); 937 938 if (wb) numMicroops++; 939 numMicroops += (regs / elems); 940 microOps = new StaticInstPtr[numMicroops]; 941 942 RegIndex ufp0 = NumFloatV7ArchRegs; 943 944 unsigned uopIdx = 0; 945 switch (elems) { 946 case 4: 947 assert(regs == 4); 948 switch (size) { 949 case 0: 950 microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint8_t>( 951 machInst, ufp0, vd * 2, inc * 2, lane); 952 break; 953 case 1: 954 microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint16_t>( 955 machInst, ufp0, vd * 2, inc * 2, lane); 956 break; 957 case 2: 958 microOps[uopIdx++] = new MicroPackNeon8to4Uop<uint32_t>( 959 machInst, ufp0, vd * 2, inc * 2, lane); 960 break; 961 default: 962 // Bad size 963 microOps[uopIdx++] = new Unknown(machInst); 964 break; 965 } 966 break; 967 case 3: 968 assert(regs == 3); 969 switch (size) { 970 case 0: 971 microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint8_t>( 972 machInst, ufp0, vd * 2, inc * 2, lane); 973 break; 974 case 1: 975 microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint16_t>( 976 machInst, ufp0, vd * 2, inc * 2, lane); 977 break; 978 case 2: 979 microOps[uopIdx++] = new MicroPackNeon6to4Uop<uint32_t>( 980 machInst, ufp0, vd * 2, inc * 2, lane); 981 break; 982 default: 983 // Bad size 984 microOps[uopIdx++] = new Unknown(machInst); 985 break; 986 } 987 break; 988 case 2: 989 assert(regs == 2); 990 assert(storeRegs <= 2); 991 switch (size) { 992 case 0: 993 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint8_t>( 994 machInst, ufp0, vd * 2, inc * 2, lane); 995 break; 996 case 1: 997 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint16_t>( 998 machInst, ufp0, vd * 2, inc * 2, lane); 999 break; 1000 case 2: 1001 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint32_t>( 1002 machInst, ufp0, vd * 2, inc * 2, lane); 1003 break; 1004 default: 1005 // Bad size 1006 microOps[uopIdx++] = new Unknown(machInst); 1007 break; 1008 } 1009 break; 1010 case 1: 1011 assert(regs == 1 || (all && regs == 2)); 1012 assert(storeRegs <= 2); 1013 for (unsigned offset = 0; offset < regs; offset++) { 1014 switch (size) { 1015 case 0: 1016 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint8_t>( 1017 machInst, ufp0, (vd + offset) * 2, inc * 2, lane); 1018 break; 1019 case 1: 1020 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint16_t>( 1021 machInst, ufp0, (vd + offset) * 2, inc * 2, lane); 1022 break; 1023 case 2: 1024 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint32_t>( 1025 machInst, ufp0, (vd + offset) * 2, inc * 2, lane); 1026 break; 1027 default: 1028 // Bad size 1029 microOps[uopIdx++] = new Unknown(machInst); 1030 break; 1031 } 1032 } 1033 break; 1034 default: 1035 // Bad number of elements to unpack 1036 microOps[uopIdx++] = new Unknown(machInst); 1037 } 1038 switch (storeSize) { 1039 case 1: 1040 microOps[uopIdx++] = new MicroStrNeon1Uop<uint8_t>( 1041 machInst, ufp0, rn, 0, align); 1042 break; 1043 case 2: 1044 if (eBytes == 2) { 1045 microOps[uopIdx++] = new MicroStrNeon2Uop<uint16_t>( 1046 machInst, ufp0, rn, 0, align); 1047 } else { 1048 microOps[uopIdx++] = new MicroStrNeon2Uop<uint8_t>( 1049 machInst, ufp0, rn, 0, align); 1050 } 1051 break; 1052 case 3: 1053 microOps[uopIdx++] = new MicroStrNeon3Uop<uint8_t>( 1054 machInst, ufp0, rn, 0, align); 1055 break; 1056 case 4: 1057 switch (eBytes) { 1058 case 1: 1059 microOps[uopIdx++] = new MicroStrNeon4Uop<uint8_t>( 1060 machInst, ufp0, rn, 0, align); 1061 break; 1062 case 2: 1063 microOps[uopIdx++] = new MicroStrNeon4Uop<uint16_t>( 1064 machInst, ufp0, rn, 0, align); 1065 break; 1066 case 4: 1067 microOps[uopIdx++] = new MicroStrNeon4Uop<uint32_t>( 1068 machInst, ufp0, rn, 0, align); 1069 break; 1070 } 1071 break; 1072 case 6: 1073 microOps[uopIdx++] = new MicroStrNeon6Uop<uint16_t>( 1074 machInst, ufp0, rn, 0, align); 1075 break; 1076 case 8: 1077 switch (eBytes) { 1078 case 2: 1079 microOps[uopIdx++] = new MicroStrNeon8Uop<uint16_t>( 1080 machInst, ufp0, rn, 0, align); 1081 break; 1082 case 4: 1083 microOps[uopIdx++] = new MicroStrNeon8Uop<uint32_t>( 1084 machInst, ufp0, rn, 0, align); 1085 break; 1086 } 1087 break; 1088 case 12: 1089 microOps[uopIdx++] = new MicroStrNeon12Uop<uint32_t>( 1090 machInst, ufp0, rn, 0, align); 1091 break; 1092 case 16: 1093 microOps[uopIdx++] = new MicroStrNeon16Uop<uint32_t>( 1094 machInst, ufp0, rn, 0, align); 1095 break; 1096 default: 1097 // Bad store size 1098 microOps[uopIdx++] = new Unknown(machInst); 1099 } 1100 if (wb) { 1101 if (rm != 15 && rm != 13) { 1102 microOps[uopIdx++] = 1103 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); 1104 } else { 1105 microOps[uopIdx++] = 1106 new MicroAddiUop(machInst, rn, rn, storeSize); 1107 } 1108 } 1109 assert(uopIdx == numMicroops); 1110 1111 for (unsigned i = 0; i < numMicroops - 1; i++) { 1112 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 1113 assert(uopPtr); 1114 uopPtr->setDelayedCommit(); 1115 } 1116 microOps[0]->setFirstMicroop(); 1117 microOps[numMicroops - 1]->setLastMicroop(); 1118} 1119 1120VldMultOp64::VldMultOp64(const char *mnem, ExtMachInst machInst, 1121 OpClass __opClass, RegIndex rn, RegIndex vd, 1122 RegIndex rm, uint8_t eSize, uint8_t dataSize, 1123 uint8_t numStructElems, uint8_t numRegs, bool wb) : 1124 PredMacroOp(mnem, machInst, __opClass) 1125{ 1126 RegIndex vx = NumFloatV8ArchRegs / 4; 1127 RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn); 1128 bool baseIsSP = isSP((IntRegIndex) rnsp); 1129 1130 numMicroops = wb ? 1 : 0; 1131 1132 int totNumBytes = numRegs * dataSize / 8; 1133 assert(totNumBytes <= 64); 1134 1135 // The guiding principle here is that no more than 16 bytes can be 1136 // transferred at a time 1137 int numMemMicroops = totNumBytes / 16; 1138 int residuum = totNumBytes % 16; 1139 if (residuum) 1140 ++numMemMicroops; 1141 numMicroops += numMemMicroops; 1142 1143 int numMarshalMicroops = numRegs / 2 + (numRegs % 2 ? 1 : 0); 1144 numMicroops += numMarshalMicroops; 1145 1146 microOps = new StaticInstPtr[numMicroops]; 1147 unsigned uopIdx = 0; 1148 uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize | 1149 TLB::AllowUnaligned; 1150 1151 int i = 0;
| 149 replaceBits(regs, reg, 0); 150 reg_idx = force_user ? intRegInMode(MODE_USER, reg) : reg; 151 152 if (load) { 153 if (writeback && reg_idx == INTREG_PC) { 154 // If this instruction changes the PC and performs a 155 // writeback, ensure the pc load/branch is the last uop. 156 // Load into a temp reg here. 157 *uop = new MicroLdrUop(machInst, INTREG_UREG1, 158 copy_base ? INTREG_UREG0 : rn, up, addr); 159 } else if (reg_idx == INTREG_PC && exception_ret) { 160 // Special handling for exception return 161 *uop = new MicroLdrRetUop(machInst, reg_idx, 162 copy_base ? INTREG_UREG0 : rn, up, addr); 163 } else { 164 // standard single load uop 165 *uop = new MicroLdrUop(machInst, reg_idx, 166 copy_base ? INTREG_UREG0 : rn, up, addr); 167 } 168 169 // Loading pc as last operation? Set appropriate flags. 170 if (!writeback && reg_idx == INTREG_PC) { 171 (*uop)->setFlag(StaticInst::IsControl); 172 (*uop)->setFlag(StaticInst::IsIndirectControl); 173 174 if (!(condCode == COND_AL || condCode == COND_UC)) 175 (*uop)->setFlag(StaticInst::IsCondControl); 176 else 177 (*uop)->setFlag(StaticInst::IsUncondControl); 178 } 179 } else { 180 *uop = new MicroStrUop(machInst, reg_idx, rn, up, addr); 181 } 182 183 if (up) addr += 4; 184 else addr -= 4; 185 --mem_ops; 186 } 187 188 // Load/store micro-op generated, go to next uop 189 ++uop; 190 } 191 192 if (writeback && ones) { 193 // Perform writeback uop operation 194 if (up) 195 *uop++ = new MicroAddiUop(machInst, rn, rn, ones * 4); 196 else 197 *uop++ = new MicroSubiUop(machInst, rn, rn, ones * 4); 198 199 // Write PC after address writeback? 200 if (pc_temp) { 201 if (exception_ret) { 202 *uop = new MicroUopRegMovRet(machInst, 0, INTREG_UREG1); 203 } else { 204 *uop = new MicroUopRegMov(machInst, INTREG_PC, INTREG_UREG1); 205 } 206 (*uop)->setFlag(StaticInst::IsControl); 207 (*uop)->setFlag(StaticInst::IsIndirectControl); 208 209 if (!(condCode == COND_AL || condCode == COND_UC)) 210 (*uop)->setFlag(StaticInst::IsCondControl); 211 else 212 (*uop)->setFlag(StaticInst::IsUncondControl); 213 214 if (rn == INTREG_SP) 215 (*uop)->setFlag(StaticInst::IsReturn); 216 217 ++uop; 218 } 219 } 220 221 --uop; 222 (*uop)->setLastMicroop(); 223 microOps[0]->setFirstMicroop(); 224 225 /* Take the control flags from the last microop for the macroop */ 226 if ((*uop)->isControl()) 227 setFlag(StaticInst::IsControl); 228 if ((*uop)->isCondCtrl()) 229 setFlag(StaticInst::IsCondControl); 230 if ((*uop)->isUncondCtrl()) 231 setFlag(StaticInst::IsUncondControl); 232 if ((*uop)->isIndirectCtrl()) 233 setFlag(StaticInst::IsIndirectControl); 234 if ((*uop)->isReturn()) 235 setFlag(StaticInst::IsReturn); 236 237 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) { 238 (*uop)->setDelayedCommit(); 239 } 240} 241 242PairMemOp::PairMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, 243 uint32_t size, bool fp, bool load, bool noAlloc, 244 bool signExt, bool exclusive, bool acrel, 245 int64_t imm, AddrMode mode, 246 IntRegIndex rn, IntRegIndex rt, IntRegIndex rt2) : 247 PredMacroOp(mnem, machInst, __opClass) 248{ 249 bool post = (mode == AddrMd_PostIndex); 250 bool writeback = (mode != AddrMd_Offset); 251 252 if (load) { 253 // Use integer rounding to round up loads of size 4 254 numMicroops = (post ? 0 : 1) + ((size + 4) / 8) + (writeback ? 1 : 0); 255 } else { 256 numMicroops = (post ? 0 : 1) + (size / 4) + (writeback ? 1 : 0); 257 } 258 microOps = new StaticInstPtr[numMicroops]; 259 260 StaticInstPtr *uop = microOps; 261 262 rn = makeSP(rn); 263 264 if (!post) { 265 *uop++ = new MicroAddXiSpAlignUop(machInst, INTREG_UREG0, rn, 266 post ? 0 : imm); 267 } 268 269 if (fp) { 270 if (size == 16) { 271 if (load) { 272 *uop++ = new MicroLdFp16Uop(machInst, rt, 273 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 274 *uop++ = new MicroLdFp16Uop(machInst, rt2, 275 post ? rn : INTREG_UREG0, 16, noAlloc, exclusive, acrel); 276 } else { 277 *uop++ = new MicroStrQBFpXImmUop(machInst, rt, 278 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 279 *uop++ = new MicroStrQTFpXImmUop(machInst, rt, 280 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 281 *uop++ = new MicroStrQBFpXImmUop(machInst, rt2, 282 post ? rn : INTREG_UREG0, 16, noAlloc, exclusive, acrel); 283 *uop++ = new MicroStrQTFpXImmUop(machInst, rt2, 284 post ? rn : INTREG_UREG0, 16, noAlloc, exclusive, acrel); 285 } 286 } else if (size == 8) { 287 if (load) { 288 *uop++ = new MicroLdPairFp8Uop(machInst, rt, rt2, 289 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 290 } else { 291 *uop++ = new MicroStrFpXImmUop(machInst, rt, 292 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 293 *uop++ = new MicroStrFpXImmUop(machInst, rt2, 294 post ? rn : INTREG_UREG0, 8, noAlloc, exclusive, acrel); 295 } 296 } else if (size == 4) { 297 if (load) { 298 *uop++ = new MicroLdrDFpXImmUop(machInst, rt, rt2, 299 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 300 } else { 301 *uop++ = new MicroStrDFpXImmUop(machInst, rt, rt2, 302 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 303 } 304 } 305 } else { 306 if (size == 8) { 307 if (load) { 308 *uop++ = new MicroLdPairUop(machInst, rt, rt2, 309 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 310 } else { 311 *uop++ = new MicroStrXImmUop(machInst, rt, post ? rn : INTREG_UREG0, 312 0, noAlloc, exclusive, acrel); 313 *uop++ = new MicroStrXImmUop(machInst, rt2, post ? rn : INTREG_UREG0, 314 size, noAlloc, exclusive, acrel); 315 } 316 } else if (size == 4) { 317 if (load) { 318 if (signExt) { 319 *uop++ = new MicroLdrDSXImmUop(machInst, rt, rt2, 320 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 321 } else { 322 *uop++ = new MicroLdrDUXImmUop(machInst, rt, rt2, 323 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 324 } 325 } else { 326 *uop++ = new MicroStrDXImmUop(machInst, rt, rt2, 327 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 328 } 329 } 330 } 331 332 if (writeback) { 333 *uop++ = new MicroAddXiUop(machInst, rn, post ? rn : INTREG_UREG0, 334 post ? imm : 0); 335 } 336 337 assert(uop == µOps[numMicroops]); 338 (*--uop)->setLastMicroop(); 339 microOps[0]->setFirstMicroop(); 340 341 for (StaticInstPtr *curUop = microOps; 342 !(*curUop)->isLastMicroop(); curUop++) { 343 (*curUop)->setDelayedCommit(); 344 } 345} 346 347BigFpMemImmOp::BigFpMemImmOp(const char *mnem, ExtMachInst machInst, 348 OpClass __opClass, bool load, IntRegIndex dest, 349 IntRegIndex base, int64_t imm) : 350 PredMacroOp(mnem, machInst, __opClass) 351{ 352 numMicroops = load ? 1 : 2; 353 microOps = new StaticInstPtr[numMicroops]; 354 355 StaticInstPtr *uop = microOps; 356 357 if (load) { 358 *uop = new MicroLdFp16Uop(machInst, dest, base, imm); 359 } else { 360 *uop = new MicroStrQBFpXImmUop(machInst, dest, base, imm); 361 (*uop)->setDelayedCommit(); 362 *++uop = new MicroStrQTFpXImmUop(machInst, dest, base, imm); 363 } 364 (*uop)->setLastMicroop(); 365 microOps[0]->setFirstMicroop(); 366} 367 368BigFpMemPostOp::BigFpMemPostOp(const char *mnem, ExtMachInst machInst, 369 OpClass __opClass, bool load, IntRegIndex dest, 370 IntRegIndex base, int64_t imm) : 371 PredMacroOp(mnem, machInst, __opClass) 372{ 373 numMicroops = load ? 2 : 3; 374 microOps = new StaticInstPtr[numMicroops]; 375 376 StaticInstPtr *uop = microOps; 377 378 if (load) { 379 *uop++ = new MicroLdFp16Uop(machInst, dest, base, 0); 380 } else { 381 *uop++= new MicroStrQBFpXImmUop(machInst, dest, base, 0); 382 *uop++ = new MicroStrQTFpXImmUop(machInst, dest, base, 0); 383 } 384 *uop = new MicroAddXiUop(machInst, base, base, imm); 385 (*uop)->setLastMicroop(); 386 microOps[0]->setFirstMicroop(); 387 388 for (StaticInstPtr *curUop = microOps; 389 !(*curUop)->isLastMicroop(); curUop++) { 390 (*curUop)->setDelayedCommit(); 391 } 392} 393 394BigFpMemPreOp::BigFpMemPreOp(const char *mnem, ExtMachInst machInst, 395 OpClass __opClass, bool load, IntRegIndex dest, 396 IntRegIndex base, int64_t imm) : 397 PredMacroOp(mnem, machInst, __opClass) 398{ 399 numMicroops = load ? 2 : 3; 400 microOps = new StaticInstPtr[numMicroops]; 401 402 StaticInstPtr *uop = microOps; 403 404 if (load) { 405 *uop++ = new MicroLdFp16Uop(machInst, dest, base, imm); 406 } else { 407 *uop++ = new MicroStrQBFpXImmUop(machInst, dest, base, imm); 408 *uop++ = new MicroStrQTFpXImmUop(machInst, dest, base, imm); 409 } 410 *uop = new MicroAddXiUop(machInst, base, base, imm); 411 (*uop)->setLastMicroop(); 412 microOps[0]->setFirstMicroop(); 413 414 for (StaticInstPtr *curUop = microOps; 415 !(*curUop)->isLastMicroop(); curUop++) { 416 (*curUop)->setDelayedCommit(); 417 } 418} 419 420BigFpMemRegOp::BigFpMemRegOp(const char *mnem, ExtMachInst machInst, 421 OpClass __opClass, bool load, IntRegIndex dest, 422 IntRegIndex base, IntRegIndex offset, 423 ArmExtendType type, int64_t imm) : 424 PredMacroOp(mnem, machInst, __opClass) 425{ 426 numMicroops = load ? 1 : 2; 427 microOps = new StaticInstPtr[numMicroops]; 428 429 StaticInstPtr *uop = microOps; 430 431 if (load) { 432 *uop = new MicroLdFp16RegUop(machInst, dest, base, 433 offset, type, imm); 434 } else { 435 *uop = new MicroStrQBFpXRegUop(machInst, dest, base, 436 offset, type, imm); 437 (*uop)->setDelayedCommit(); 438 *++uop = new MicroStrQTFpXRegUop(machInst, dest, base, 439 offset, type, imm); 440 } 441 442 (*uop)->setLastMicroop(); 443 microOps[0]->setFirstMicroop(); 444} 445 446BigFpMemLitOp::BigFpMemLitOp(const char *mnem, ExtMachInst machInst, 447 OpClass __opClass, IntRegIndex dest, 448 int64_t imm) : 449 PredMacroOp(mnem, machInst, __opClass) 450{ 451 numMicroops = 1; 452 microOps = new StaticInstPtr[numMicroops]; 453 454 microOps[0] = new MicroLdFp16LitUop(machInst, dest, imm); 455 microOps[0]->setLastMicroop(); 456 microOps[0]->setFirstMicroop(); 457} 458 459VldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, 460 unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, 461 unsigned inc, uint32_t size, uint32_t align, RegIndex rm) : 462 PredMacroOp(mnem, machInst, __opClass) 463{ 464 assert(regs > 0 && regs <= 4); 465 assert(regs % elems == 0); 466 467 numMicroops = (regs > 2) ? 2 : 1; 468 bool wb = (rm != 15); 469 bool deinterleave = (elems > 1); 470 471 if (wb) numMicroops++; 472 if (deinterleave) numMicroops += (regs / elems); 473 microOps = new StaticInstPtr[numMicroops]; 474 475 RegIndex rMid = deinterleave ? NumFloatV7ArchRegs : vd * 2; 476 477 uint32_t noAlign = TLB::MustBeOne; 478 479 unsigned uopIdx = 0; 480 switch (regs) { 481 case 4: 482 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 483 size, machInst, rMid, rn, 0, align); 484 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 485 size, machInst, rMid + 4, rn, 16, noAlign); 486 break; 487 case 3: 488 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 489 size, machInst, rMid, rn, 0, align); 490 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>( 491 size, machInst, rMid + 4, rn, 16, noAlign); 492 break; 493 case 2: 494 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 495 size, machInst, rMid, rn, 0, align); 496 break; 497 case 1: 498 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>( 499 size, machInst, rMid, rn, 0, align); 500 break; 501 default: 502 // Unknown number of registers 503 microOps[uopIdx++] = new Unknown(machInst); 504 } 505 if (wb) { 506 if (rm != 15 && rm != 13) { 507 microOps[uopIdx++] = 508 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); 509 } else { 510 microOps[uopIdx++] = 511 new MicroAddiUop(machInst, rn, rn, regs * 8); 512 } 513 } 514 if (deinterleave) { 515 switch (elems) { 516 case 4: 517 assert(regs == 4); 518 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon8Uop>( 519 size, machInst, vd * 2, rMid, inc * 2); 520 break; 521 case 3: 522 assert(regs == 3); 523 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon6Uop>( 524 size, machInst, vd * 2, rMid, inc * 2); 525 break; 526 case 2: 527 assert(regs == 4 || regs == 2); 528 if (regs == 4) { 529 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>( 530 size, machInst, vd * 2, rMid, inc * 2); 531 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>( 532 size, machInst, vd * 2 + 2, rMid + 4, inc * 2); 533 } else { 534 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>( 535 size, machInst, vd * 2, rMid, inc * 2); 536 } 537 break; 538 default: 539 // Bad number of elements to deinterleave 540 microOps[uopIdx++] = new Unknown(machInst); 541 } 542 } 543 assert(uopIdx == numMicroops); 544 545 for (unsigned i = 0; i < numMicroops - 1; i++) { 546 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 547 assert(uopPtr); 548 uopPtr->setDelayedCommit(); 549 } 550 microOps[0]->setFirstMicroop(); 551 microOps[numMicroops - 1]->setLastMicroop(); 552} 553 554VldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst, 555 OpClass __opClass, bool all, unsigned elems, 556 RegIndex rn, RegIndex vd, unsigned regs, 557 unsigned inc, uint32_t size, uint32_t align, 558 RegIndex rm, unsigned lane) : 559 PredMacroOp(mnem, machInst, __opClass) 560{ 561 assert(regs > 0 && regs <= 4); 562 assert(regs % elems == 0); 563 564 unsigned eBytes = (1 << size); 565 unsigned loadSize = eBytes * elems; 566 unsigned loadRegs M5_VAR_USED = (loadSize + sizeof(FloatRegBits) - 1) / 567 sizeof(FloatRegBits); 568 569 assert(loadRegs > 0 && loadRegs <= 4); 570 571 numMicroops = 1; 572 bool wb = (rm != 15); 573 574 if (wb) numMicroops++; 575 numMicroops += (regs / elems); 576 microOps = new StaticInstPtr[numMicroops]; 577 578 RegIndex ufp0 = NumFloatV7ArchRegs; 579 580 unsigned uopIdx = 0; 581 switch (loadSize) { 582 case 1: 583 microOps[uopIdx++] = new MicroLdrNeon1Uop<uint8_t>( 584 machInst, ufp0, rn, 0, align); 585 break; 586 case 2: 587 if (eBytes == 2) { 588 microOps[uopIdx++] = new MicroLdrNeon2Uop<uint16_t>( 589 machInst, ufp0, rn, 0, align); 590 } else { 591 microOps[uopIdx++] = new MicroLdrNeon2Uop<uint8_t>( 592 machInst, ufp0, rn, 0, align); 593 } 594 break; 595 case 3: 596 microOps[uopIdx++] = new MicroLdrNeon3Uop<uint8_t>( 597 machInst, ufp0, rn, 0, align); 598 break; 599 case 4: 600 switch (eBytes) { 601 case 1: 602 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint8_t>( 603 machInst, ufp0, rn, 0, align); 604 break; 605 case 2: 606 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint16_t>( 607 machInst, ufp0, rn, 0, align); 608 break; 609 case 4: 610 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint32_t>( 611 machInst, ufp0, rn, 0, align); 612 break; 613 } 614 break; 615 case 6: 616 microOps[uopIdx++] = new MicroLdrNeon6Uop<uint16_t>( 617 machInst, ufp0, rn, 0, align); 618 break; 619 case 8: 620 switch (eBytes) { 621 case 2: 622 microOps[uopIdx++] = new MicroLdrNeon8Uop<uint16_t>( 623 machInst, ufp0, rn, 0, align); 624 break; 625 case 4: 626 microOps[uopIdx++] = new MicroLdrNeon8Uop<uint32_t>( 627 machInst, ufp0, rn, 0, align); 628 break; 629 } 630 break; 631 case 12: 632 microOps[uopIdx++] = new MicroLdrNeon12Uop<uint32_t>( 633 machInst, ufp0, rn, 0, align); 634 break; 635 case 16: 636 microOps[uopIdx++] = new MicroLdrNeon16Uop<uint32_t>( 637 machInst, ufp0, rn, 0, align); 638 break; 639 default: 640 // Unrecognized load size 641 microOps[uopIdx++] = new Unknown(machInst); 642 } 643 if (wb) { 644 if (rm != 15 && rm != 13) { 645 microOps[uopIdx++] = 646 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); 647 } else { 648 microOps[uopIdx++] = 649 new MicroAddiUop(machInst, rn, rn, loadSize); 650 } 651 } 652 switch (elems) { 653 case 4: 654 assert(regs == 4); 655 switch (size) { 656 case 0: 657 if (all) { 658 microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint8_t>( 659 machInst, vd * 2, ufp0, inc * 2); 660 } else { 661 microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint8_t>( 662 machInst, vd * 2, ufp0, inc * 2, lane); 663 } 664 break; 665 case 1: 666 if (all) { 667 microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint16_t>( 668 machInst, vd * 2, ufp0, inc * 2); 669 } else { 670 microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint16_t>( 671 machInst, vd * 2, ufp0, inc * 2, lane); 672 } 673 break; 674 case 2: 675 if (all) { 676 microOps[uopIdx++] = new MicroUnpackAllNeon4to8Uop<uint32_t>( 677 machInst, vd * 2, ufp0, inc * 2); 678 } else { 679 microOps[uopIdx++] = new MicroUnpackNeon4to8Uop<uint32_t>( 680 machInst, vd * 2, ufp0, inc * 2, lane); 681 } 682 break; 683 default: 684 // Bad size 685 microOps[uopIdx++] = new Unknown(machInst); 686 break; 687 } 688 break; 689 case 3: 690 assert(regs == 3); 691 switch (size) { 692 case 0: 693 if (all) { 694 microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint8_t>( 695 machInst, vd * 2, ufp0, inc * 2); 696 } else { 697 microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint8_t>( 698 machInst, vd * 2, ufp0, inc * 2, lane); 699 } 700 break; 701 case 1: 702 if (all) { 703 microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint16_t>( 704 machInst, vd * 2, ufp0, inc * 2); 705 } else { 706 microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint16_t>( 707 machInst, vd * 2, ufp0, inc * 2, lane); 708 } 709 break; 710 case 2: 711 if (all) { 712 microOps[uopIdx++] = new MicroUnpackAllNeon4to6Uop<uint32_t>( 713 machInst, vd * 2, ufp0, inc * 2); 714 } else { 715 microOps[uopIdx++] = new MicroUnpackNeon4to6Uop<uint32_t>( 716 machInst, vd * 2, ufp0, inc * 2, lane); 717 } 718 break; 719 default: 720 // Bad size 721 microOps[uopIdx++] = new Unknown(machInst); 722 break; 723 } 724 break; 725 case 2: 726 assert(regs == 2); 727 assert(loadRegs <= 2); 728 switch (size) { 729 case 0: 730 if (all) { 731 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint8_t>( 732 machInst, vd * 2, ufp0, inc * 2); 733 } else { 734 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint8_t>( 735 machInst, vd * 2, ufp0, inc * 2, lane); 736 } 737 break; 738 case 1: 739 if (all) { 740 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint16_t>( 741 machInst, vd * 2, ufp0, inc * 2); 742 } else { 743 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint16_t>( 744 machInst, vd * 2, ufp0, inc * 2, lane); 745 } 746 break; 747 case 2: 748 if (all) { 749 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint32_t>( 750 machInst, vd * 2, ufp0, inc * 2); 751 } else { 752 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint32_t>( 753 machInst, vd * 2, ufp0, inc * 2, lane); 754 } 755 break; 756 default: 757 // Bad size 758 microOps[uopIdx++] = new Unknown(machInst); 759 break; 760 } 761 break; 762 case 1: 763 assert(regs == 1 || (all && regs == 2)); 764 assert(loadRegs <= 2); 765 for (unsigned offset = 0; offset < regs; offset++) { 766 switch (size) { 767 case 0: 768 if (all) { 769 microOps[uopIdx++] = 770 new MicroUnpackAllNeon2to2Uop<uint8_t>( 771 machInst, (vd + offset) * 2, ufp0, inc * 2); 772 } else { 773 microOps[uopIdx++] = 774 new MicroUnpackNeon2to2Uop<uint8_t>( 775 machInst, (vd + offset) * 2, ufp0, inc * 2, lane); 776 } 777 break; 778 case 1: 779 if (all) { 780 microOps[uopIdx++] = 781 new MicroUnpackAllNeon2to2Uop<uint16_t>( 782 machInst, (vd + offset) * 2, ufp0, inc * 2); 783 } else { 784 microOps[uopIdx++] = 785 new MicroUnpackNeon2to2Uop<uint16_t>( 786 machInst, (vd + offset) * 2, ufp0, inc * 2, lane); 787 } 788 break; 789 case 2: 790 if (all) { 791 microOps[uopIdx++] = 792 new MicroUnpackAllNeon2to2Uop<uint32_t>( 793 machInst, (vd + offset) * 2, ufp0, inc * 2); 794 } else { 795 microOps[uopIdx++] = 796 new MicroUnpackNeon2to2Uop<uint32_t>( 797 machInst, (vd + offset) * 2, ufp0, inc * 2, lane); 798 } 799 break; 800 default: 801 // Bad size 802 microOps[uopIdx++] = new Unknown(machInst); 803 break; 804 } 805 } 806 break; 807 default: 808 // Bad number of elements to unpack 809 microOps[uopIdx++] = new Unknown(machInst); 810 } 811 assert(uopIdx == numMicroops); 812 813 for (unsigned i = 0; i < numMicroops - 1; i++) { 814 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 815 assert(uopPtr); 816 uopPtr->setDelayedCommit(); 817 } 818 microOps[0]->setFirstMicroop(); 819 microOps[numMicroops - 1]->setLastMicroop(); 820} 821 822VstMultOp::VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, 823 unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, 824 unsigned inc, uint32_t size, uint32_t align, RegIndex rm) : 825 PredMacroOp(mnem, machInst, __opClass) 826{ 827 assert(regs > 0 && regs <= 4); 828 assert(regs % elems == 0); 829 830 numMicroops = (regs > 2) ? 2 : 1; 831 bool wb = (rm != 15); 832 bool interleave = (elems > 1); 833 834 if (wb) numMicroops++; 835 if (interleave) numMicroops += (regs / elems); 836 microOps = new StaticInstPtr[numMicroops]; 837 838 uint32_t noAlign = TLB::MustBeOne; 839 840 RegIndex rMid = interleave ? NumFloatV7ArchRegs : vd * 2; 841 842 unsigned uopIdx = 0; 843 if (interleave) { 844 switch (elems) { 845 case 4: 846 assert(regs == 4); 847 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon8Uop>( 848 size, machInst, rMid, vd * 2, inc * 2); 849 break; 850 case 3: 851 assert(regs == 3); 852 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon6Uop>( 853 size, machInst, rMid, vd * 2, inc * 2); 854 break; 855 case 2: 856 assert(regs == 4 || regs == 2); 857 if (regs == 4) { 858 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>( 859 size, machInst, rMid, vd * 2, inc * 2); 860 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>( 861 size, machInst, rMid + 4, vd * 2 + 2, inc * 2); 862 } else { 863 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>( 864 size, machInst, rMid, vd * 2, inc * 2); 865 } 866 break; 867 default: 868 // Bad number of elements to interleave 869 microOps[uopIdx++] = new Unknown(machInst); 870 } 871 } 872 switch (regs) { 873 case 4: 874 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 875 size, machInst, rMid, rn, 0, align); 876 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 877 size, machInst, rMid + 4, rn, 16, noAlign); 878 break; 879 case 3: 880 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 881 size, machInst, rMid, rn, 0, align); 882 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>( 883 size, machInst, rMid + 4, rn, 16, noAlign); 884 break; 885 case 2: 886 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 887 size, machInst, rMid, rn, 0, align); 888 break; 889 case 1: 890 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>( 891 size, machInst, rMid, rn, 0, align); 892 break; 893 default: 894 // Unknown number of registers 895 microOps[uopIdx++] = new Unknown(machInst); 896 } 897 if (wb) { 898 if (rm != 15 && rm != 13) { 899 microOps[uopIdx++] = 900 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); 901 } else { 902 microOps[uopIdx++] = 903 new MicroAddiUop(machInst, rn, rn, regs * 8); 904 } 905 } 906 assert(uopIdx == numMicroops); 907 908 for (unsigned i = 0; i < numMicroops - 1; i++) { 909 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 910 assert(uopPtr); 911 uopPtr->setDelayedCommit(); 912 } 913 microOps[0]->setFirstMicroop(); 914 microOps[numMicroops - 1]->setLastMicroop(); 915} 916 917VstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst, 918 OpClass __opClass, bool all, unsigned elems, 919 RegIndex rn, RegIndex vd, unsigned regs, 920 unsigned inc, uint32_t size, uint32_t align, 921 RegIndex rm, unsigned lane) : 922 PredMacroOp(mnem, machInst, __opClass) 923{ 924 assert(!all); 925 assert(regs > 0 && regs <= 4); 926 assert(regs % elems == 0); 927 928 unsigned eBytes = (1 << size); 929 unsigned storeSize = eBytes * elems; 930 unsigned storeRegs M5_VAR_USED = (storeSize + sizeof(FloatRegBits) - 1) / 931 sizeof(FloatRegBits); 932 933 assert(storeRegs > 0 && storeRegs <= 4); 934 935 numMicroops = 1; 936 bool wb = (rm != 15); 937 938 if (wb) numMicroops++; 939 numMicroops += (regs / elems); 940 microOps = new StaticInstPtr[numMicroops]; 941 942 RegIndex ufp0 = NumFloatV7ArchRegs; 943 944 unsigned uopIdx = 0; 945 switch (elems) { 946 case 4: 947 assert(regs == 4); 948 switch (size) { 949 case 0: 950 microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint8_t>( 951 machInst, ufp0, vd * 2, inc * 2, lane); 952 break; 953 case 1: 954 microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint16_t>( 955 machInst, ufp0, vd * 2, inc * 2, lane); 956 break; 957 case 2: 958 microOps[uopIdx++] = new MicroPackNeon8to4Uop<uint32_t>( 959 machInst, ufp0, vd * 2, inc * 2, lane); 960 break; 961 default: 962 // Bad size 963 microOps[uopIdx++] = new Unknown(machInst); 964 break; 965 } 966 break; 967 case 3: 968 assert(regs == 3); 969 switch (size) { 970 case 0: 971 microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint8_t>( 972 machInst, ufp0, vd * 2, inc * 2, lane); 973 break; 974 case 1: 975 microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint16_t>( 976 machInst, ufp0, vd * 2, inc * 2, lane); 977 break; 978 case 2: 979 microOps[uopIdx++] = new MicroPackNeon6to4Uop<uint32_t>( 980 machInst, ufp0, vd * 2, inc * 2, lane); 981 break; 982 default: 983 // Bad size 984 microOps[uopIdx++] = new Unknown(machInst); 985 break; 986 } 987 break; 988 case 2: 989 assert(regs == 2); 990 assert(storeRegs <= 2); 991 switch (size) { 992 case 0: 993 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint8_t>( 994 machInst, ufp0, vd * 2, inc * 2, lane); 995 break; 996 case 1: 997 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint16_t>( 998 machInst, ufp0, vd * 2, inc * 2, lane); 999 break; 1000 case 2: 1001 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint32_t>( 1002 machInst, ufp0, vd * 2, inc * 2, lane); 1003 break; 1004 default: 1005 // Bad size 1006 microOps[uopIdx++] = new Unknown(machInst); 1007 break; 1008 } 1009 break; 1010 case 1: 1011 assert(regs == 1 || (all && regs == 2)); 1012 assert(storeRegs <= 2); 1013 for (unsigned offset = 0; offset < regs; offset++) { 1014 switch (size) { 1015 case 0: 1016 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint8_t>( 1017 machInst, ufp0, (vd + offset) * 2, inc * 2, lane); 1018 break; 1019 case 1: 1020 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint16_t>( 1021 machInst, ufp0, (vd + offset) * 2, inc * 2, lane); 1022 break; 1023 case 2: 1024 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint32_t>( 1025 machInst, ufp0, (vd + offset) * 2, inc * 2, lane); 1026 break; 1027 default: 1028 // Bad size 1029 microOps[uopIdx++] = new Unknown(machInst); 1030 break; 1031 } 1032 } 1033 break; 1034 default: 1035 // Bad number of elements to unpack 1036 microOps[uopIdx++] = new Unknown(machInst); 1037 } 1038 switch (storeSize) { 1039 case 1: 1040 microOps[uopIdx++] = new MicroStrNeon1Uop<uint8_t>( 1041 machInst, ufp0, rn, 0, align); 1042 break; 1043 case 2: 1044 if (eBytes == 2) { 1045 microOps[uopIdx++] = new MicroStrNeon2Uop<uint16_t>( 1046 machInst, ufp0, rn, 0, align); 1047 } else { 1048 microOps[uopIdx++] = new MicroStrNeon2Uop<uint8_t>( 1049 machInst, ufp0, rn, 0, align); 1050 } 1051 break; 1052 case 3: 1053 microOps[uopIdx++] = new MicroStrNeon3Uop<uint8_t>( 1054 machInst, ufp0, rn, 0, align); 1055 break; 1056 case 4: 1057 switch (eBytes) { 1058 case 1: 1059 microOps[uopIdx++] = new MicroStrNeon4Uop<uint8_t>( 1060 machInst, ufp0, rn, 0, align); 1061 break; 1062 case 2: 1063 microOps[uopIdx++] = new MicroStrNeon4Uop<uint16_t>( 1064 machInst, ufp0, rn, 0, align); 1065 break; 1066 case 4: 1067 microOps[uopIdx++] = new MicroStrNeon4Uop<uint32_t>( 1068 machInst, ufp0, rn, 0, align); 1069 break; 1070 } 1071 break; 1072 case 6: 1073 microOps[uopIdx++] = new MicroStrNeon6Uop<uint16_t>( 1074 machInst, ufp0, rn, 0, align); 1075 break; 1076 case 8: 1077 switch (eBytes) { 1078 case 2: 1079 microOps[uopIdx++] = new MicroStrNeon8Uop<uint16_t>( 1080 machInst, ufp0, rn, 0, align); 1081 break; 1082 case 4: 1083 microOps[uopIdx++] = new MicroStrNeon8Uop<uint32_t>( 1084 machInst, ufp0, rn, 0, align); 1085 break; 1086 } 1087 break; 1088 case 12: 1089 microOps[uopIdx++] = new MicroStrNeon12Uop<uint32_t>( 1090 machInst, ufp0, rn, 0, align); 1091 break; 1092 case 16: 1093 microOps[uopIdx++] = new MicroStrNeon16Uop<uint32_t>( 1094 machInst, ufp0, rn, 0, align); 1095 break; 1096 default: 1097 // Bad store size 1098 microOps[uopIdx++] = new Unknown(machInst); 1099 } 1100 if (wb) { 1101 if (rm != 15 && rm != 13) { 1102 microOps[uopIdx++] = 1103 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); 1104 } else { 1105 microOps[uopIdx++] = 1106 new MicroAddiUop(machInst, rn, rn, storeSize); 1107 } 1108 } 1109 assert(uopIdx == numMicroops); 1110 1111 for (unsigned i = 0; i < numMicroops - 1; i++) { 1112 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 1113 assert(uopPtr); 1114 uopPtr->setDelayedCommit(); 1115 } 1116 microOps[0]->setFirstMicroop(); 1117 microOps[numMicroops - 1]->setLastMicroop(); 1118} 1119 1120VldMultOp64::VldMultOp64(const char *mnem, ExtMachInst machInst, 1121 OpClass __opClass, RegIndex rn, RegIndex vd, 1122 RegIndex rm, uint8_t eSize, uint8_t dataSize, 1123 uint8_t numStructElems, uint8_t numRegs, bool wb) : 1124 PredMacroOp(mnem, machInst, __opClass) 1125{ 1126 RegIndex vx = NumFloatV8ArchRegs / 4; 1127 RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn); 1128 bool baseIsSP = isSP((IntRegIndex) rnsp); 1129 1130 numMicroops = wb ? 1 : 0; 1131 1132 int totNumBytes = numRegs * dataSize / 8; 1133 assert(totNumBytes <= 64); 1134 1135 // The guiding principle here is that no more than 16 bytes can be 1136 // transferred at a time 1137 int numMemMicroops = totNumBytes / 16; 1138 int residuum = totNumBytes % 16; 1139 if (residuum) 1140 ++numMemMicroops; 1141 numMicroops += numMemMicroops; 1142 1143 int numMarshalMicroops = numRegs / 2 + (numRegs % 2 ? 1 : 0); 1144 numMicroops += numMarshalMicroops; 1145 1146 microOps = new StaticInstPtr[numMicroops]; 1147 unsigned uopIdx = 0; 1148 uint32_t memaccessFlags = TLB::MustBeOne | (TLB::ArmFlags) eSize | 1149 TLB::AllowUnaligned; 1150 1151 int i = 0;
|