| OLD | NEW |
| 1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===// | 1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 if (!Reg->hasReg()) { | 698 if (!Reg->hasReg()) { |
| 699 llvm::report_fatal_error("Push/pop operand does not have a register " | 699 llvm::report_fatal_error("Push/pop operand does not have a register " |
| 700 "assigned to it."); | 700 "assigned to it."); |
| 701 } | 701 } |
| 702 | 702 |
| 703 PreviousTy = Reg->getType(); | 703 PreviousTy = Reg->getType(); |
| 704 } | 704 } |
| 705 } | 705 } |
| 706 } // end of anonymous namespace | 706 } // end of anonymous namespace |
| 707 | 707 |
| 708 void InstARM32RegisterStackOp::emit(const Cfg *Func) const { |
| 709 if (!BuildDefs::dump()) |
| 710 return; |
| 711 emitUsingForm(Func, Emit_Text); |
| 712 } |
| 713 |
| 714 void InstARM32RegisterStackOp::emitIAS(const Cfg *Func) const { |
| 715 emitUsingForm(Func, Emit_Binary); |
| 716 assert(!Func->getAssembler<ARM32::AssemblerARM32>()->needsTextFixup()); |
| 717 } |
| 718 |
| 719 void InstARM32RegisterStackOp::dump(const Cfg *Func) const { |
| 720 if (!BuildDefs::dump()) |
| 721 return; |
| 722 Ostream &Str = Func->getContext()->getStrDump(); |
| 723 Str << getDumpOpcode() << " "; |
| 724 SizeT NumRegs = getNumStackRegs(); |
| 725 for (SizeT I = 0; I < NumRegs; ++I) { |
| 726 if (I > 0) |
| 727 Str << ", "; |
| 728 getStackReg(I)->dump(Func); |
| 729 } |
| 730 } |
| 731 |
| 732 void InstARM32RegisterStackOp::emitGPRsAsText(const Cfg *Func) const { |
| 733 if (!BuildDefs::dump()) |
| 734 return; |
| 735 Ostream &Str = Func->getContext()->getStrEmit(); |
| 736 Str << "\t" << getGPROpcode() << "\t{"; |
| 737 getStackReg(0)->emit(Func); |
| 738 const SizeT NumRegs = getNumStackRegs(); |
| 739 for (SizeT i = 1; i < NumRegs; ++i) { |
| 740 Str << ", "; |
| 741 getStackReg(i)->emit(Func); |
| 742 } |
| 743 Str << "}"; |
| 744 } |
| 745 |
| 746 void InstARM32RegisterStackOp::emitSRegsAsText(const Cfg *Func, |
| 747 const Variable *BaseReg, |
| 748 SizeT RegCount) const { |
| 749 if (!BuildDefs::dump()) |
| 750 return; |
| 751 Ostream &Str = Func->getContext()->getStrEmit(); |
| 752 Str << "\t" << getSRegOpcode() << "\t{"; |
| 753 bool IsFirst = true; |
| 754 int32_t Base = BaseReg->getRegNum(); |
| 755 for (SizeT i = 0; i < RegCount; ++i) { |
| 756 if (IsFirst) |
| 757 IsFirst = false; |
| 758 else |
| 759 Str << ", "; |
| 760 Str << RegARM32::getSRegName(Base + i); |
| 761 } |
| 762 Str << "}"; |
| 763 } |
| 764 |
| 765 namespace { |
| 766 |
| 767 bool isAssignedConsecutiveRegisters(const Variable *Before, |
| 768 const Variable *After) { |
| 769 assert(Before->hasReg()); |
| 770 assert(After->hasReg()); |
| 771 return Before->getRegNum() + 1 == After->getRegNum(); |
| 772 } |
| 773 |
| 774 } // end of anonymous namespace |
| 775 |
| 776 void InstARM32RegisterStackOp::emitUsingForm(const Cfg *Func, |
| 777 const EmitForm Form) const { |
| 778 SizeT NumRegs = getNumStackRegs(); |
| 779 assert(NumRegs); |
| 780 |
| 781 const auto *Reg = llvm::cast<Variable>(getStackReg(0)); |
| 782 if (isScalarIntegerType(Reg->getType())) { |
| 783 // Pop GPR registers. |
| 784 SizeT IntegerCount = 0; |
| 785 ARM32::IValueT GPRegisters = 0; |
| 786 const Variable *LastDest = nullptr; |
| 787 for (SizeT i = 0; i < NumRegs; ++i) { |
| 788 const Variable *Var = getStackReg(i); |
| 789 assert(Var->hasReg() && "stack op only applies to registers"); |
| 790 int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum()); |
| 791 LastDest = Var; |
| 792 GPRegisters |= (1 << Reg); |
| 793 ++IntegerCount; |
| 794 } |
| 795 if (IntegerCount == 1) { |
| 796 emitSingleGPR(Func, Form, LastDest); |
| 797 } else { |
| 798 emitMultipleGPRs(Func, Form, GPRegisters); |
| 799 } |
| 800 } else { |
| 801 // Pop vector/floating point registers. |
| 802 const Variable *BaseReg = nullptr; |
| 803 SizeT RegCount = 0; |
| 804 for (SizeT i = 0; i < NumRegs; ++i) { |
| 805 const Variable *NextReg = getStackReg(i); |
| 806 if (BaseReg == nullptr) { |
| 807 BaseReg = NextReg; |
| 808 RegCount = 1; |
| 809 } else if (RegCount < VpushVpopMaxConsecRegs && |
| 810 isAssignedConsecutiveRegisters(Reg, NextReg)) { |
| 811 ++RegCount; |
| 812 } else { |
| 813 emitSRegs(Func, Form, BaseReg, RegCount); |
| 814 if (Form == Emit_Text && BuildDefs::dump()) { |
| 815 startNextInst(Func); |
| 816 Func->getContext()->getStrEmit() << "\n"; |
| 817 } |
| 818 BaseReg = NextReg; |
| 819 RegCount = 1; |
| 820 } |
| 821 Reg = NextReg; |
| 822 } |
| 823 if (RegCount) { |
| 824 emitSRegs(Func, Form, BaseReg, RegCount); |
| 825 } |
| 826 } |
| 827 } |
| 828 |
| 708 InstARM32Pop::InstARM32Pop(Cfg *Func, const VarList &Dests) | 829 InstARM32Pop::InstARM32Pop(Cfg *Func, const VarList &Dests) |
| 709 : InstARM32(Func, InstARM32::Pop, 0, nullptr), Dests(Dests) { | 830 : InstARM32RegisterStackOp(Func, InstARM32::Pop, 0, nullptr), Dests(Dests) { |
| 710 // Track modifications to Dests separately via FakeDefs. Also, a pop | 831 // Track modifications to Dests separately via FakeDefs. Also, a pop |
| 711 // instruction affects the stack pointer and so it should not be allowed to | 832 // instruction affects the stack pointer and so it should not be allowed to |
| 712 // be automatically dead-code eliminated. This is automatic since we leave | 833 // be automatically dead-code eliminated. This is automatic since we leave |
| 713 // the Dest as nullptr. | 834 // the Dest as nullptr. |
| 714 validatePushOrPopRegisterListOrDie(Dests); | 835 validatePushOrPopRegisterListOrDie(Dests); |
| 715 } | 836 } |
| 716 | 837 |
| 717 InstARM32Push::InstARM32Push(Cfg *Func, const VarList &Srcs) | 838 InstARM32Push::InstARM32Push(Cfg *Func, const VarList &Srcs) |
| 718 : InstARM32(Func, InstARM32::Push, Srcs.size(), nullptr) { | 839 : InstARM32RegisterStackOp(Func, InstARM32::Push, Srcs.size(), nullptr) { |
| 719 validatePushOrPopRegisterListOrDie(Srcs); | 840 validatePushOrPopRegisterListOrDie(Srcs); |
| 720 for (Variable *Source : Srcs) { | 841 for (Variable *Source : Srcs) { |
| 721 addSource(Source); | 842 addSource(Source); |
| 722 } | 843 } |
| 723 } | 844 } |
| 724 | 845 |
| 725 InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source) | 846 InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source) |
| 726 : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) { | 847 : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) { |
| 727 addSource(LR); | 848 addSource(LR); |
| 728 if (Source) | 849 if (Source) |
| (...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1383 } | 1504 } |
| 1384 | 1505 |
| 1385 template <> void InstARM32Uxt::emitIAS(const Cfg *Func) const { | 1506 template <> void InstARM32Uxt::emitIAS(const Cfg *Func) const { |
| 1386 assert(getSrcSize() == 1); | 1507 assert(getSrcSize() == 1); |
| 1387 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 1508 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 1388 Asm->uxt(getDest(), getSrc(0), getPredicate()); | 1509 Asm->uxt(getDest(), getSrc(0), getPredicate()); |
| 1389 if (Asm->needsTextFixup()) | 1510 if (Asm->needsTextFixup()) |
| 1390 emitUsingTextFixup(Func); | 1511 emitUsingTextFixup(Func); |
| 1391 } | 1512 } |
| 1392 | 1513 |
| 1393 namespace { | 1514 const char *InstARM32Pop::getGPROpcode() const { return "pop"; } |
| 1394 | 1515 |
| 1395 bool isAssignedConsecutiveRegisters(const Variable *Before, | 1516 const char *InstARM32Pop::getSRegOpcode() const { return "vpop"; } |
| 1396 const Variable *After) { | |
| 1397 assert(Before->hasReg()); | |
| 1398 assert(After->hasReg()); | |
| 1399 return Before->getRegNum() + 1 == After->getRegNum(); | |
| 1400 } | |
| 1401 | 1517 |
| 1402 } // end of anonymous namespace | 1518 Variable *InstARM32Pop::getStackReg(SizeT Index) const { return Dests[Index]; } |
| 1403 | 1519 |
| 1404 void InstARM32Pop::emit(const Cfg *Func) const { | 1520 SizeT InstARM32Pop::getNumStackRegs() const { return Dests.size(); } |
| 1405 if (!BuildDefs::dump()) | 1521 |
| 1522 void InstARM32Pop::emitSingleGPR(const Cfg *Func, const EmitForm Form, |
| 1523 const Variable *Reg) const { |
| 1524 switch (Form) { |
| 1525 case Emit_Text: |
| 1526 emitGPRsAsText(Func); |
| 1406 return; | 1527 return; |
| 1407 | 1528 case Emit_Binary: |
| 1408 const SizeT DestSize = Dests.size(); | 1529 Func->getAssembler<ARM32::AssemblerARM32>()->pop(Reg, CondARM32::AL); |
| 1409 if (DestSize == 0) { | |
| 1410 assert(false && "Empty pop list"); | |
| 1411 return; | 1530 return; |
| 1412 } | 1531 } |
| 1413 | |
| 1414 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1415 | |
| 1416 Variable *Reg = Dests[0]; | |
| 1417 if (isScalarIntegerType(Reg->getType())) { | |
| 1418 // GPR push. | |
| 1419 Str << "\t" | |
| 1420 "pop" | |
| 1421 "\t{"; | |
| 1422 Reg->emit(Func); | |
| 1423 for (SizeT i = 1; i < DestSize; ++i) { | |
| 1424 Str << ", "; | |
| 1425 Reg = Dests[i]; | |
| 1426 Reg->emit(Func); | |
| 1427 } | |
| 1428 Str << "}"; | |
| 1429 return; | |
| 1430 } | |
| 1431 | |
| 1432 // VFP "s" reg push. | |
| 1433 SizeT End = DestSize - 1; | |
| 1434 SizeT Start = DestSize - 1; | |
| 1435 Reg = Dests[DestSize - 1]; | |
| 1436 Str << "\t" | |
| 1437 "vpop" | |
| 1438 "\t{"; | |
| 1439 for (SizeT i = 2; i <= DestSize; ++i) { | |
| 1440 Variable *PreviousReg = Dests[DestSize - i]; | |
| 1441 if (!isAssignedConsecutiveRegisters(PreviousReg, Reg)) { | |
| 1442 Dests[Start]->emit(Func); | |
| 1443 for (SizeT j = Start + 1; j <= End; ++j) { | |
| 1444 Str << ", "; | |
| 1445 Dests[j]->emit(Func); | |
| 1446 } | |
| 1447 startNextInst(Func); | |
| 1448 Str << "}\n\t" | |
| 1449 "vpop" | |
| 1450 "\t{"; | |
| 1451 End = DestSize - i; | |
| 1452 } | |
| 1453 Reg = PreviousReg; | |
| 1454 Start = DestSize - i; | |
| 1455 } | |
| 1456 Dests[Start]->emit(Func); | |
| 1457 for (SizeT j = Start + 1; j <= End; ++j) { | |
| 1458 Str << ", "; | |
| 1459 Dests[j]->emit(Func); | |
| 1460 } | |
| 1461 Str << "}"; | |
| 1462 } | |
| 1463 | |
| 1464 void InstARM32Pop::emitIAS(const Cfg *Func) const { | |
| 1465 // Pop can't be emitted if there are no registers to load. This should never | |
| 1466 // happen, but if it does, we don't need to bring Subzero down -- we just skip | |
| 1467 // emitting the pop instruction (and maybe emit a nop?) The assert() is here | |
| 1468 // so that we can detect this error during development. | |
| 1469 const SizeT DestSize = Dests.size(); | |
| 1470 if (DestSize == 0) { | |
| 1471 assert(false && "Empty pop list"); | |
| 1472 return; | |
| 1473 } | |
| 1474 | |
| 1475 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 1476 const auto *Reg = llvm::cast<Variable>(Dests[0]); | |
| 1477 if (isScalarIntegerType(Reg->getType())) { | |
| 1478 // Pop GPR registers. | |
| 1479 SizeT IntegerCount = 0; | |
| 1480 ARM32::IValueT GPRegisters = 0; | |
| 1481 const Variable *LastDest = nullptr; | |
| 1482 for (const Variable *Var : Dests) { | |
| 1483 assert(Var->hasReg() && "pop only applies to registers"); | |
| 1484 int32_t Reg = RegARM32::getEncodedGPReg(Var->getRegNum()); | |
| 1485 LastDest = Var; | |
| 1486 GPRegisters |= (1 << Reg); | |
| 1487 ++IntegerCount; | |
| 1488 } | |
| 1489 switch (IntegerCount) { | |
| 1490 case 0: | |
| 1491 return; | |
| 1492 case 1: | |
| 1493 // Note: Can only apply pop register if single register is not sp. | |
| 1494 assert((RegARM32::Encoded_Reg_sp != LastDest->getRegNum()) && | |
| 1495 "Effects of pop register SP is undefined!"); | |
| 1496 Asm->pop(LastDest, CondARM32::AL); | |
| 1497 break; | |
| 1498 default: | |
| 1499 Asm->popList(GPRegisters, CondARM32::AL); | |
| 1500 break; | |
| 1501 } | |
| 1502 } else { | |
| 1503 // Pop vector/floating point registers. | |
| 1504 const Variable *BaseReg = nullptr; | |
| 1505 SizeT RegCount = 0; | |
| 1506 for (const Variable *NextReg : Dests) { | |
| 1507 if (BaseReg == nullptr) { | |
| 1508 BaseReg = NextReg; | |
| 1509 RegCount = 1; | |
| 1510 } else if (RegCount < VpushVpopMaxConsecRegs && | |
| 1511 isAssignedConsecutiveRegisters(Reg, NextReg)) { | |
| 1512 ++RegCount; | |
| 1513 } else { | |
| 1514 Asm->vpop(BaseReg, RegCount, CondARM32::AL); | |
| 1515 BaseReg = NextReg; | |
| 1516 RegCount = 1; | |
| 1517 } | |
| 1518 Reg = NextReg; | |
| 1519 } | |
| 1520 if (RegCount) | |
| 1521 Asm->vpop(BaseReg, RegCount, CondARM32::AL); | |
| 1522 } | |
| 1523 if (Asm->needsTextFixup()) | |
| 1524 emitUsingTextFixup(Func); | |
| 1525 } | |
| 1526 | |
| 1527 void InstARM32Pop::dump(const Cfg *Func) const { | |
| 1528 if (!BuildDefs::dump()) | |
| 1529 return; | |
| 1530 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1531 Str << "pop" | |
| 1532 << " "; | |
| 1533 for (SizeT I = 0; I < Dests.size(); ++I) { | |
| 1534 if (I > 0) | |
| 1535 Str << ", "; | |
| 1536 Dests[I]->dump(Func); | |
| 1537 } | |
| 1538 } | 1532 } |
| 1539 | 1533 |
| 1540 void InstARM32Push::emit(const Cfg *Func) const { | 1534 void InstARM32Pop::emitMultipleGPRs(const Cfg *Func, const EmitForm Form, |
| 1541 if (!BuildDefs::dump()) | 1535 IValueT Registers) const { |
| 1536 switch (Form) { |
| 1537 case Emit_Text: |
| 1538 emitGPRsAsText(Func); |
| 1542 return; | 1539 return; |
| 1543 | 1540 case Emit_Binary: |
| 1544 // Push can't be emitted if there are no registers to save. This should never | 1541 Func->getAssembler<ARM32::AssemblerARM32>()->popList(Registers, |
| 1545 // happen, but if it does, we don't need to bring Subzero down -- we just skip | 1542 CondARM32::AL); |
| 1546 // emitting the push instruction (and maybe emit a nop?) The assert() is here | |
| 1547 // so that we can detect this error during development. | |
| 1548 const SizeT SrcSize = getSrcSize(); | |
| 1549 if (SrcSize == 0) { | |
| 1550 assert(false && "Empty push list"); | |
| 1551 return; | 1543 return; |
| 1552 } | 1544 } |
| 1545 } |
| 1553 | 1546 |
| 1554 Ostream &Str = Func->getContext()->getStrEmit(); | 1547 void InstARM32Pop::emitSRegs(const Cfg *Func, const EmitForm Form, |
| 1555 | 1548 const Variable *BaseReg, SizeT RegCount) const { |
| 1556 const auto *Reg = llvm::cast<Variable>(getSrc(0)); | 1549 switch (Form) { |
| 1557 if (isScalarIntegerType(Reg->getType())) { | 1550 case Emit_Text: |
| 1558 // GPR push. | 1551 emitSRegsAsText(Func, BaseReg, RegCount); |
| 1559 Str << "\t" | 1552 return; |
| 1560 "push" | 1553 case Emit_Binary: |
| 1561 "\t{"; | 1554 Func->getAssembler<ARM32::AssemblerARM32>()->vpop(BaseReg, RegCount, |
| 1562 Reg->emit(Func); | 1555 CondARM32::AL); |
| 1563 for (SizeT i = 1; i < SrcSize; ++i) { | |
| 1564 Str << ", "; | |
| 1565 getSrc(i)->emit(Func); | |
| 1566 } | |
| 1567 Str << "}"; | |
| 1568 return; | 1556 return; |
| 1569 } | 1557 } |
| 1570 | |
| 1571 // VFP "s" reg push. | |
| 1572 Str << "\t" | |
| 1573 "vpush" | |
| 1574 "\t{"; | |
| 1575 Reg->emit(Func); | |
| 1576 SizeT RegCount = 1; | |
| 1577 for (SizeT i = 1; i < SrcSize; ++i) { | |
| 1578 const auto *NextReg = llvm::cast<Variable>(getSrc(i)); | |
| 1579 if (RegCount < VpushVpopMaxConsecRegs && | |
| 1580 isAssignedConsecutiveRegisters(Reg, NextReg)) { | |
| 1581 ++RegCount; | |
| 1582 Str << ", "; | |
| 1583 } else { | |
| 1584 startNextInst(Func); | |
| 1585 RegCount = 1; | |
| 1586 Str << "}\n\t" | |
| 1587 "vpush" | |
| 1588 "\t{"; | |
| 1589 } | |
| 1590 Reg = NextReg; | |
| 1591 Reg->emit(Func); | |
| 1592 } | |
| 1593 Str << "}"; | |
| 1594 } | 1558 } |
| 1595 | 1559 |
| 1596 void InstARM32Push::emitIAS(const Cfg *Func) const { | 1560 const char *InstARM32Push::getGPROpcode() const { return "push"; } |
| 1597 // Push can't be emitted if there are no registers to save. This should never | 1561 |
| 1598 // happen, but if it does, we don't need to bring Subzero down -- we just skip | 1562 const char *InstARM32Push::getSRegOpcode() const { return "vpush"; } |
| 1599 // emitting the push instruction (and maybe emit a nop?) The assert() is here | 1563 |
| 1600 // so that we can detect this error during development. | 1564 Variable *InstARM32Push::getStackReg(SizeT Index) const { |
| 1601 const SizeT SrcSize = getSrcSize(); | 1565 return llvm::cast<Variable>(getSrc(Index)); |
| 1602 if (SrcSize == 0) { | 1566 } |
| 1603 assert(false && "Empty push list"); | 1567 |
| 1568 SizeT InstARM32Push::getNumStackRegs() const { return getSrcSize(); } |
| 1569 |
| 1570 void InstARM32Push::emitSingleGPR(const Cfg *Func, const EmitForm Form, |
| 1571 const Variable *Reg) const { |
| 1572 switch (Form) { |
| 1573 case Emit_Text: |
| 1574 emitGPRsAsText(Func); |
| 1575 return; |
| 1576 case Emit_Binary: |
| 1577 Func->getAssembler<ARM32::AssemblerARM32>()->push(Reg, CondARM32::AL); |
| 1604 return; | 1578 return; |
| 1605 } | 1579 } |
| 1606 | |
| 1607 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 1608 const auto *Reg = llvm::cast<Variable>(getSrc(0)); | |
| 1609 if (isScalarIntegerType(Reg->getType())) { | |
| 1610 // Push GPR registers. | |
| 1611 SizeT IntegerCount = 0; | |
| 1612 ARM32::IValueT GPRegisters = 0; | |
| 1613 const Variable *LastSrc = nullptr; | |
| 1614 for (SizeT Index = 0; Index < getSrcSize(); ++Index) { | |
| 1615 const auto *Var = llvm::cast<Variable>(getSrc(Index)); | |
| 1616 int32_t Reg = RegARM32::getEncodedGPReg(Var->getRegNum()); | |
| 1617 assert(Reg != RegARM32::Encoded_Not_GPR); | |
| 1618 LastSrc = Var; | |
| 1619 GPRegisters |= (1 << Reg); | |
| 1620 ++IntegerCount; | |
| 1621 } | |
| 1622 switch (IntegerCount) { | |
| 1623 case 0: | |
| 1624 return; | |
| 1625 case 1: { | |
| 1626 // Note: Can only apply push register if single register is not sp. | |
| 1627 assert((RegARM32::Encoded_Reg_sp != LastSrc->getRegNum()) && | |
| 1628 "Effects of push register SP is undefined!"); | |
| 1629 Asm->push(LastSrc, CondARM32::AL); | |
| 1630 break; | |
| 1631 } | |
| 1632 default: | |
| 1633 Asm->pushList(GPRegisters, CondARM32::AL); | |
| 1634 break; | |
| 1635 } | |
| 1636 } else { | |
| 1637 // Push vector/Floating point registers. | |
| 1638 const Variable *BaseReg = Reg; | |
| 1639 SizeT RegCount = 1; | |
| 1640 for (SizeT i = 1; i < SrcSize; ++i) { | |
| 1641 const auto *NextReg = llvm::cast<Variable>(getSrc(i)); | |
| 1642 if (RegCount < VpushVpopMaxConsecRegs && | |
| 1643 isAssignedConsecutiveRegisters(Reg, NextReg)) { | |
| 1644 ++RegCount; | |
| 1645 } else { | |
| 1646 Asm->vpush(BaseReg, RegCount, CondARM32::AL); | |
| 1647 BaseReg = NextReg; | |
| 1648 RegCount = 1; | |
| 1649 } | |
| 1650 Reg = NextReg; | |
| 1651 } | |
| 1652 Asm->vpush(BaseReg, RegCount, CondARM32::AL); | |
| 1653 } | |
| 1654 if (Asm->needsTextFixup()) | |
| 1655 emitUsingTextFixup(Func); | |
| 1656 } | 1580 } |
| 1657 | 1581 |
| 1658 void InstARM32Push::dump(const Cfg *Func) const { | 1582 void InstARM32Push::emitMultipleGPRs(const Cfg *Func, const EmitForm Form, |
| 1659 if (!BuildDefs::dump()) | 1583 IValueT Registers) const { |
| 1584 switch (Form) { |
| 1585 case Emit_Text: |
| 1586 emitGPRsAsText(Func); |
| 1660 return; | 1587 return; |
| 1661 Ostream &Str = Func->getContext()->getStrDump(); | 1588 case Emit_Binary: |
| 1662 Str << "push" | 1589 Func->getAssembler<ARM32::AssemblerARM32>()->pushList(Registers, |
| 1663 << " "; | 1590 CondARM32::AL); |
| 1664 dumpSources(Func); | 1591 return; |
| 1592 } |
| 1593 } |
| 1594 |
| 1595 void InstARM32Push::emitSRegs(const Cfg *Func, const EmitForm Form, |
| 1596 const Variable *BaseReg, SizeT RegCount) const { |
| 1597 switch (Form) { |
| 1598 case Emit_Text: |
| 1599 emitSRegsAsText(Func, BaseReg, RegCount); |
| 1600 return; |
| 1601 case Emit_Binary: |
| 1602 Func->getAssembler<ARM32::AssemblerARM32>()->vpush(BaseReg, RegCount, |
| 1603 CondARM32::AL); |
| 1604 return; |
| 1605 } |
| 1665 } | 1606 } |
| 1666 | 1607 |
| 1667 void InstARM32Ret::emit(const Cfg *Func) const { | 1608 void InstARM32Ret::emit(const Cfg *Func) const { |
| 1668 if (!BuildDefs::dump()) | 1609 if (!BuildDefs::dump()) |
| 1669 return; | 1610 return; |
| 1670 assert(getSrcSize() > 0); | 1611 assert(getSrcSize() > 0); |
| 1671 auto *LR = llvm::cast<Variable>(getSrc(0)); | 1612 auto *LR = llvm::cast<Variable>(getSrc(0)); |
| 1672 assert(LR->hasReg()); | 1613 assert(LR->hasReg()); |
| 1673 assert(LR->getRegNum() == RegARM32::Reg_lr); | 1614 assert(LR->getRegNum() == RegARM32::Reg_lr); |
| 1674 Ostream &Str = Func->getContext()->getStrEmit(); | 1615 Ostream &Str = Func->getContext()->getStrEmit(); |
| (...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2242 | 2183 |
| 2243 template class InstARM32FourAddrGPR<InstARM32::Mla>; | 2184 template class InstARM32FourAddrGPR<InstARM32::Mla>; |
| 2244 template class InstARM32FourAddrGPR<InstARM32::Mls>; | 2185 template class InstARM32FourAddrGPR<InstARM32::Mls>; |
| 2245 | 2186 |
| 2246 template class InstARM32CmpLike<InstARM32::Cmn>; | 2187 template class InstARM32CmpLike<InstARM32::Cmn>; |
| 2247 template class InstARM32CmpLike<InstARM32::Cmp>; | 2188 template class InstARM32CmpLike<InstARM32::Cmp>; |
| 2248 template class InstARM32CmpLike<InstARM32::Tst>; | 2189 template class InstARM32CmpLike<InstARM32::Tst>; |
| 2249 | 2190 |
| 2250 } // end of namespace ARM32 | 2191 } // end of namespace ARM32 |
| 2251 } // end of namespace Ice | 2192 } // end of namespace Ice |
| OLD | NEW |