Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(913)

Side by Side Diff: src/IceInstARM32.cpp

Issue 1535233002: Refactor PUSH/POP in ARM assemblers. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix remaining issues. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceInstARM32.h ('k') | src/IceRegistersARM32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/IceInstARM32.h ('k') | src/IceRegistersARM32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698