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

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: Refactor and fix trivial bug (insertion of newline for vpush). 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
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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 81
82 void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode, 82 void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode,
83 Type Ty) const { 83 Type Ty) const {
84 Str << Opcode << getPredicate() << "." << Ty; 84 Str << Opcode << getPredicate() << "." << Ty;
85 } 85 }
86 86
87 CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) { 87 CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) {
88 return InstARM32CondAttributes[Cond].Opposite; 88 return InstARM32CondAttributes[Cond].Opposite;
89 } 89 }
90 90
91 template <>
92 void InstARM32::startNextAsmInst<InstARM32::TextualOutput>(
93 const Cfg *Func) const {
94 startNextInst(Func);
95 Func->getContext()->getStrEmit() << "\n";
96 }
97
98 template <>
99 void InstARM32::startNextAsmInst<InstARM32::BinaryOutput>(
John 2016/01/06 16:10:21 The fact that this does nothing tells me this meth
Karl 2016/01/06 23:21:58 Removed.
100 const Cfg *Func) const {
101 (void)Func;
102 }
103
91 void InstARM32::startNextInst(const Cfg *Func) const { 104 void InstARM32::startNextInst(const Cfg *Func) const {
92 if (auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>()) 105 if (auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>())
93 Asm->incEmitTextSize(InstSize); 106 Asm->incEmitTextSize(InstSize);
94 } 107 }
95 108
96 void InstARM32::emitUsingTextFixup(const Cfg *Func) const { 109 void InstARM32::emitUsingTextFixup(const Cfg *Func) const {
97 if (!BuildDefs::dump()) 110 if (!BuildDefs::dump())
98 return; 111 return;
99 GlobalContext *Ctx = Func->getContext(); 112 GlobalContext *Ctx = Func->getContext();
100 if (Ctx->getFlags().getDisableHybridAssembly()) { 113 if (Ctx->getFlags().getDisableHybridAssembly()) {
(...skipping 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after
1317 1330
1318 bool isAssignedConsecutiveRegisters(const Variable *Before, 1331 bool isAssignedConsecutiveRegisters(const Variable *Before,
1319 const Variable *After) { 1332 const Variable *After) {
1320 assert(Before->hasReg()); 1333 assert(Before->hasReg());
1321 assert(After->hasReg()); 1334 assert(After->hasReg());
1322 return Before->getRegNum() + 1 == After->getRegNum(); 1335 return Before->getRegNum() + 1 == After->getRegNum();
1323 } 1336 }
1324 1337
1325 } // end of anonymous namespace 1338 } // end of anonymous namespace
1326 1339
1327 void InstARM32Pop::emit(const Cfg *Func) const { 1340 void InstARM32Pop::emitPop(const Cfg *Func) const {
1328 if (!BuildDefs::dump()) 1341 if (!BuildDefs::dump())
1329 return; 1342 return;
1330 1343 Ostream &Str = Func->getContext()->getStrEmit();
1344 Str << "\t"
1345 << "pop"
1346 << "\t{";
1347 Dests[0]->emit(Func);
1331 const SizeT DestSize = Dests.size(); 1348 const SizeT DestSize = Dests.size();
1332 if (DestSize == 0) { 1349 for (SizeT i = 1; i < DestSize; ++i) {
1333 assert(false && "Empty pop list");
1334 return;
1335 }
1336
1337 Ostream &Str = Func->getContext()->getStrEmit();
1338
1339 Variable *Reg = Dests[0];
1340 if (isScalarIntegerType(Reg->getType())) {
1341 // GPR push.
1342 Str << "\t"
1343 "pop"
1344 "\t{";
1345 Reg->emit(Func);
1346 for (SizeT i = 1; i < DestSize; ++i) {
1347 Str << ", ";
1348 Reg = Dests[i];
1349 Reg->emit(Func);
1350 }
1351 Str << "}";
1352 return;
1353 }
1354
1355 // VFP "s" reg push.
1356 SizeT End = DestSize - 1;
1357 SizeT Start = DestSize - 1;
1358 Reg = Dests[DestSize - 1];
1359 Str << "\t"
1360 "vpop"
1361 "\t{";
1362 for (SizeT i = 2; i <= DestSize; ++i) {
1363 Variable *PreviousReg = Dests[DestSize - i];
1364 if (!isAssignedConsecutiveRegisters(PreviousReg, Reg)) {
1365 Dests[Start]->emit(Func);
1366 for (SizeT j = Start + 1; j <= End; ++j) {
1367 Str << ", ";
1368 Dests[j]->emit(Func);
1369 }
1370 startNextInst(Func);
1371 Str << "}\n\t"
1372 "vpop"
1373 "\t{";
1374 End = DestSize - i;
1375 }
1376 Reg = PreviousReg;
1377 Start = DestSize - i;
1378 }
1379 Dests[Start]->emit(Func);
1380 for (SizeT j = Start + 1; j <= End; ++j) {
1381 Str << ", "; 1350 Str << ", ";
1382 Dests[j]->emit(Func); 1351 Dests[i]->emit(Func);
1383 } 1352 }
1384 Str << "}"; 1353 Str << "}";
1385 } 1354 }
1386 1355
1387 void InstARM32Pop::emitIAS(const Cfg *Func) const { 1356 template <>
1357 void InstARM32Pop::emitPop<InstARM32::TextualOutput>(
1358 const Cfg *Func, const Variable *Reg) const {
1359 (void)Reg;
1360 this->emitPop(Func);
1361 }
1362
1363 template <>
1364 void InstARM32Pop::emitPop<InstARM32::BinaryOutput>(const Cfg *Func,
1365 const Variable *Reg) const {
1366 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1367 Asm->pop(Reg, CondARM32::AL);
1368 }
1369
1370 template <>
1371 void InstARM32Pop::emitPopList<InstARM32::TextualOutput>(
1372 const Cfg *Func, ARM32::IValueT Registers) const {
1373 (void)Registers;
1374 emitPop(Func);
1375 }
1376
1377 template <>
1378 void InstARM32Pop::emitPopList<InstARM32::BinaryOutput>(
1379 const Cfg *Func, ARM32::IValueT Registers) const {
1380 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1381 Asm->popList(Registers, CondARM32::AL);
1382 }
1383
1384 template <>
1385 void InstARM32Pop::emitVpop<InstARM32::TextualOutput>(const Cfg *Func,
1386 const Variable *BaseReg,
1387 SizeT RegCount) const {
1388 if (!BuildDefs::dump())
1389 return;
1390 Ostream &Str = Func->getContext()->getStrEmit();
1391 Str << "\t"
1392 << "vpop"
1393 << "\t{";
1394 bool IsFirst = true;
1395 IValueT Base = AssemblerARM32::getEncodedSRegNum(BaseReg);
John 2016/01/06 16:10:21 Why using this method? RegARM32::getEncodedSReg()
Karl 2016/01/06 23:21:58 Fixed.
1396 for (SizeT i = 0; i < RegCount; ++i) {
1397 if (IsFirst)
1398 IsFirst = false;
1399 else
1400 Str << ", ";
1401 Str << RegARM32::getSRegName(Base + i);
1402 }
1403 Str << "}";
1404 }
1405
1406 template <>
1407 void InstARM32Pop::emitVpop<InstARM32::BinaryOutput>(const Cfg *Func,
1408 const Variable *BaseReg,
1409 SizeT RegCount) const {
1410 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1411 Asm->vpop(BaseReg, RegCount, CondARM32::AL);
1412 }
1413
1414 template <InstARM32::OutputForm Form>
1415 void InstARM32Pop::assemble(const Cfg *Func) const {
1416 if (!BuildDefs::dump() && Form == TextualOutput)
1417 return;
1388 // Pop can't be emitted if there are no registers to load. This should never 1418 // Pop can't be emitted if there are no registers to load. This should never
1389 // happen, but if it does, we don't need to bring Subzero down -- we just skip 1419 // happen, but if it does, we don't need to bring Subzero down -- we just skip
1390 // emitting the pop instruction (and maybe emit a nop?) The assert() is here 1420 // emitting the pop instruction (and maybe emit a nop?) The assert() is here
1391 // so that we can detect this error during development. 1421 // so that we can detect this error during development.
1392 const SizeT DestSize = Dests.size(); 1422 const SizeT DestSize = Dests.size();
1393 if (DestSize == 0) { 1423 if (DestSize == 0) {
1394 assert(false && "Empty pop list"); 1424 assert(false && "Empty pop list");
1395 return; 1425 return;
1396 } 1426 }
1397 1427
1398 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1399 const auto *Reg = llvm::cast<Variable>(Dests[0]); 1428 const auto *Reg = llvm::cast<Variable>(Dests[0]);
1400 if (isScalarIntegerType(Reg->getType())) { 1429 if (isScalarIntegerType(Reg->getType())) {
1401 // Pop GPR registers. 1430 // Pop GPR registers.
1402 SizeT IntegerCount = 0; 1431 SizeT IntegerCount = 0;
1403 ARM32::IValueT GPRegisters = 0; 1432 ARM32::IValueT GPRegisters = 0;
1404 const Variable *LastDest = nullptr; 1433 const Variable *LastDest = nullptr;
1405 for (const Variable *Var : Dests) { 1434 for (const Variable *Var : Dests) {
1406 assert(Var->hasReg() && "pop only applies to registers"); 1435 assert(Var->hasReg() && "pop only applies to registers");
1407 int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum()); 1436 int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum());
1408 LastDest = Var; 1437 LastDest = Var;
1409 GPRegisters |= (1 << Reg); 1438 GPRegisters |= (1 << Reg);
1410 ++IntegerCount; 1439 ++IntegerCount;
1411 } 1440 }
1412 switch (IntegerCount) { 1441 switch (IntegerCount) {
1413 case 0: 1442 case 0:
1414 return; 1443 return;
1415 case 1: 1444 case 1:
1416 // Note: Can only apply pop register if single register is not sp. 1445 // Note: Can only apply pop register if single register is not sp.
1417 assert((RegARM32::Encoded_Reg_sp != LastDest->getRegNum()) && 1446 assert((RegARM32::Encoded_Reg_sp != LastDest->getRegNum()) &&
1418 "Effects of pop register SP is undefined!"); 1447 "Effects of pop register SP is undefined!");
1419 Asm->pop(LastDest, CondARM32::AL); 1448 emitPop<Form>(Func, LastDest);
1420 break; 1449 break;
1421 default: 1450 default:
1422 Asm->popList(GPRegisters, CondARM32::AL); 1451 emitPopList<Form>(Func, GPRegisters);
1423 break; 1452 break;
1424 } 1453 }
1425 } else { 1454 } else {
1426 // Pop vector/floating point registers. 1455 // Pop vector/floating point registers.
1427 const Variable *BaseReg = nullptr; 1456 const Variable *BaseReg = nullptr;
1428 SizeT RegCount = 0; 1457 SizeT RegCount = 0;
1429 for (const Variable *NextReg : Dests) { 1458 for (const Variable *NextReg : Dests) {
1430 if (BaseReg == nullptr) { 1459 if (BaseReg == nullptr) {
1431 BaseReg = NextReg; 1460 BaseReg = NextReg;
1432 RegCount = 1; 1461 RegCount = 1;
1433 } else if (RegCount < VpushVpopMaxConsecRegs && 1462 } else if (RegCount < VpushVpopMaxConsecRegs &&
1434 isAssignedConsecutiveRegisters(Reg, NextReg)) { 1463 isAssignedConsecutiveRegisters(Reg, NextReg)) {
1435 ++RegCount; 1464 ++RegCount;
1436 } else { 1465 } else {
1437 Asm->vpop(BaseReg, RegCount, CondARM32::AL); 1466 emitVpop<Form>(Func, BaseReg, RegCount);
1467 this->startNextAsmInst<Form>(Func);
1438 BaseReg = NextReg; 1468 BaseReg = NextReg;
1439 RegCount = 1; 1469 RegCount = 1;
1440 } 1470 }
1441 Reg = NextReg; 1471 Reg = NextReg;
1442 } 1472 }
1443 if (RegCount) 1473 if (RegCount) {
1444 Asm->vpop(BaseReg, RegCount, CondARM32::AL); 1474 emitVpop<Form>(Func, BaseReg, RegCount);
1475 }
1445 } 1476 }
1446 if (Asm->needsTextFixup()) 1477 assert(!Func->getAssembler<ARM32::AssemblerARM32>()->needsTextFixup());
1447 emitUsingTextFixup(Func);
1448 } 1478 }
1449 1479
1450 void InstARM32Pop::dump(const Cfg *Func) const { 1480 void InstARM32Pop::dump(const Cfg *Func) const {
1451 if (!BuildDefs::dump()) 1481 if (!BuildDefs::dump())
1452 return; 1482 return;
1453 Ostream &Str = Func->getContext()->getStrDump(); 1483 Ostream &Str = Func->getContext()->getStrDump();
1454 Str << "pop" 1484 Str << "pop"
1455 << " "; 1485 << " ";
1456 for (SizeT I = 0; I < Dests.size(); ++I) { 1486 for (SizeT I = 0; I < Dests.size(); ++I) {
1457 if (I > 0) 1487 if (I > 0)
1458 Str << ", "; 1488 Str << ", ";
1459 Dests[I]->dump(Func); 1489 Dests[I]->dump(Func);
1460 } 1490 }
1461 } 1491 }
1462 1492
1463 void InstARM32Push::emit(const Cfg *Func) const { 1493 void InstARM32Pop::emit(const Cfg *Func) const {
1494 assemble<TextualOutput>(Func);
John 2016/01/06 16:10:21 I would rather have the if (!BuildDefs::dump()) {
Karl 2016/01/06 23:21:58 Done.
1495 }
1496
1497 void InstARM32Pop::emitIAS(const Cfg *Func) const {
1498 assemble<BinaryOutput>(Func);
1499 }
1500
1501 void InstARM32Push::emitPush(const Cfg *Func) const {
1464 if (!BuildDefs::dump()) 1502 if (!BuildDefs::dump())
1465 return; 1503 return;
1466 1504 Ostream &Str = Func->getContext()->getStrEmit();
1467 // Push can't be emitted if there are no registers to save. This should never 1505 Str << "\t"
1468 // happen, but if it does, we don't need to bring Subzero down -- we just skip 1506 << "push"
1469 // emitting the push instruction (and maybe emit a nop?) The assert() is here 1507 << "\t{";
1470 // so that we can detect this error during development. 1508 getSrc(0)->emit(Func);
1471 const SizeT SrcSize = getSrcSize(); 1509 const SizeT SrcSize = getSrcSize();
1472 if (SrcSize == 0) {
1473 assert(false && "Empty push list");
1474 return;
1475 }
1476
1477 Ostream &Str = Func->getContext()->getStrEmit();
1478
1479 const auto *Reg = llvm::cast<Variable>(getSrc(0));
1480 if (isScalarIntegerType(Reg->getType())) {
1481 // GPR push.
1482 Str << "\t"
1483 "push"
1484 "\t{";
1485 Reg->emit(Func);
1486 for (SizeT i = 1; i < SrcSize; ++i) {
1487 Str << ", ";
1488 getSrc(i)->emit(Func);
1489 }
1490 Str << "}";
1491 return;
1492 }
1493
1494 // VFP "s" reg push.
1495 Str << "\t"
1496 "vpush"
1497 "\t{";
1498 Reg->emit(Func);
1499 SizeT RegCount = 1;
1500 for (SizeT i = 1; i < SrcSize; ++i) { 1510 for (SizeT i = 1; i < SrcSize; ++i) {
1501 const auto *NextReg = llvm::cast<Variable>(getSrc(i)); 1511 Str << ", ";
1502 if (RegCount < VpushVpopMaxConsecRegs && 1512 getSrc(i)->emit(Func);
1503 isAssignedConsecutiveRegisters(Reg, NextReg)) {
1504 ++RegCount;
1505 Str << ", ";
1506 } else {
1507 startNextInst(Func);
1508 RegCount = 1;
1509 Str << "}\n\t"
1510 "vpush"
1511 "\t{";
1512 }
1513 Reg = NextReg;
1514 Reg->emit(Func);
1515 } 1513 }
1516 Str << "}"; 1514 Str << "}";
1517 } 1515 }
1518 1516
1519 void InstARM32Push::emitIAS(const Cfg *Func) const { 1517 template <>
1518 void InstARM32Push::emitPush<InstARM32::TextualOutput>(
1519 const Cfg *Func, const Variable *Reg) const {
1520 (void)Reg;
1521 this->emitPush(Func);
John 2016/01/06 16:10:21 do you need the this-> ?
Karl 2016/01/06 23:21:58 Removed.
1522 }
1523
1524 template <>
1525 void InstARM32Push::emitPush<InstARM32::BinaryOutput>(
1526 const Cfg *Func, const Variable *Reg) const {
1527 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1528 Asm->push(Reg, CondARM32::AL);
1529 }
1530
1531 template <>
1532 void InstARM32Push::emitPushList<InstARM32::TextualOutput>(
1533 const Cfg *Func, ARM32::IValueT Registers) const {
1534 (void)Registers;
1535 emitPush(Func);
1536 }
1537
1538 template <>
1539 void InstARM32Push::emitPushList<InstARM32::BinaryOutput>(
1540 const Cfg *Func, ARM32::IValueT Registers) const {
1541 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1542 Asm->pushList(Registers, CondARM32::AL);
1543 }
1544
1545 template <>
1546 void InstARM32Push::emitVPush<InstARM32::TextualOutput>(const Cfg *Func,
1547 const Variable *BaseReg,
1548 SizeT RegCount) const {
1549 if (!BuildDefs::dump())
1550 return;
1551 Ostream &Str = Func->getContext()->getStrEmit();
1552 Str << "\t"
1553 << "vpush"
1554 << "\t{";
1555 bool IsFirst = true;
1556 IValueT Base = AssemblerARM32::getEncodedSRegNum(BaseReg);
John 2016/01/06 16:10:21 ditto.
Karl 2016/01/06 23:21:58 Done.
1557 for (SizeT i = 0; i < RegCount; ++i) {
1558 if (IsFirst)
1559 IsFirst = false;
1560 else
1561 Str << ", ";
1562 Str << RegARM32::getSRegName(Base + i);
1563 }
1564 Str << "}";
1565 }
1566
1567 template <>
1568 void InstARM32Push::emitVPush<InstARM32::BinaryOutput>(const Cfg *Func,
1569 const Variable *BaseReg,
1570 SizeT RegCount) const {
1571 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1572 Asm->vpush(BaseReg, RegCount, CondARM32::AL);
1573 }
1574
1575 template <InstARM32::OutputForm Form>
1576 void InstARM32Push::assemble(const Cfg *Func) const {
John 2016/01/06 16:10:21 assemble is not really meaningful for textual outp
Karl 2016/01/06 23:21:58 renamed to emitUsingForm().
1577 if (!BuildDefs::dump() && Form == TextualOutput)
1578 return;
1520 // Push can't be emitted if there are no registers to save. This should never 1579 // Push can't be emitted if there are no registers to save. This should never
1521 // happen, but if it does, we don't need to bring Subzero down -- we just skip 1580 // happen, but if it does, we don't need to bring Subzero down -- we just skip
1522 // emitting the push instruction (and maybe emit a nop?) The assert() is here 1581 // emitting the push instruction (and maybe emit a nop?) The assert() is here
1523 // so that we can detect this error during development. 1582 // so that we can detect this error during development.
1524 const SizeT SrcSize = getSrcSize(); 1583 const SizeT SrcSize = getSrcSize();
1525 if (SrcSize == 0) { 1584 if (SrcSize == 0) {
1526 assert(false && "Empty push list"); 1585 assert(false && "Empty push list");
1527 return; 1586 return;
1528 } 1587 }
1529 1588
1530 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1531 const auto *Reg = llvm::cast<Variable>(getSrc(0)); 1589 const auto *Reg = llvm::cast<Variable>(getSrc(0));
1532 if (isScalarIntegerType(Reg->getType())) { 1590 if (isScalarIntegerType(Reg->getType())) {
1533 // Push GPR registers. 1591 // Push GPR registers.
1534 SizeT IntegerCount = 0; 1592 SizeT IntegerCount = 0;
1535 ARM32::IValueT GPRegisters = 0; 1593 ARM32::IValueT GPRegisters = 0;
1536 const Variable *LastSrc = nullptr; 1594 const Variable *LastSrc = nullptr;
1537 for (SizeT Index = 0; Index < getSrcSize(); ++Index) { 1595 for (SizeT Index = 0; Index < getSrcSize(); ++Index) {
1538 const auto *Var = llvm::cast<Variable>(getSrc(Index)); 1596 const auto *Var = llvm::cast<Variable>(getSrc(Index));
1539 int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum()); 1597 int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum());
1540 assert(Reg != RegARM32::Encoded_Not_GPR); 1598 assert(Reg != RegARM32::Encoded_Not_GPR);
1541 LastSrc = Var; 1599 LastSrc = Var;
1542 GPRegisters |= (1 << Reg); 1600 GPRegisters |= (1 << Reg);
1543 ++IntegerCount; 1601 ++IntegerCount;
1544 } 1602 }
1545 switch (IntegerCount) { 1603 switch (IntegerCount) {
1546 case 0: 1604 case 0:
1547 return; 1605 return;
John 2016/01/06 16:10:21 You should llvm::report_fatal_error() here. It is
Karl 2016/01/06 23:21:58 Actually, this case can't happen due to the test "
1548 case 1: { 1606 case 1: {
1549 // Note: Can only apply push register if single register is not sp. 1607 // Note: Can only apply push register if single register is not sp.
1550 assert((RegARM32::Encoded_Reg_sp != LastSrc->getRegNum()) && 1608 assert((RegARM32::Encoded_Reg_sp != LastSrc->getRegNum()) &&
1551 "Effects of push register SP is undefined!"); 1609 "Effects of push register SP is undefined!");
1552 Asm->push(LastSrc, CondARM32::AL); 1610 emitPush<Form>(Func, LastSrc);
1553 break; 1611 break;
1554 } 1612 }
1555 default: 1613 default:
1556 Asm->pushList(GPRegisters, CondARM32::AL); 1614 emitPushList<Form>(Func, GPRegisters);
1557 break; 1615 break;
1558 } 1616 }
1559 } else { 1617 } else {
1560 // Push vector/Floating point registers. 1618 // Push vector/Floating point registers.
1561 const Variable *BaseReg = Reg; 1619 const Variable *BaseReg = Reg;
1562 SizeT RegCount = 1; 1620 SizeT RegCount = 1;
1563 for (SizeT i = 1; i < SrcSize; ++i) { 1621 for (SizeT i = 1; i < SrcSize; ++i) {
1564 const auto *NextReg = llvm::cast<Variable>(getSrc(i)); 1622 const auto *NextReg = llvm::cast<Variable>(getSrc(i));
1565 if (RegCount < VpushVpopMaxConsecRegs && 1623 if (RegCount < VpushVpopMaxConsecRegs &&
1566 isAssignedConsecutiveRegisters(Reg, NextReg)) { 1624 isAssignedConsecutiveRegisters(Reg, NextReg)) {
1567 ++RegCount; 1625 ++RegCount;
1568 } else { 1626 } else {
1569 Asm->vpush(BaseReg, RegCount, CondARM32::AL); 1627 emitVPush<Form>(Func, BaseReg, RegCount);
1628 this->startNextAsmInst<Form>(Func);
1570 BaseReg = NextReg; 1629 BaseReg = NextReg;
1571 RegCount = 1; 1630 RegCount = 1;
1572 } 1631 }
1573 Reg = NextReg; 1632 Reg = NextReg;
1574 } 1633 }
1575 Asm->vpush(BaseReg, RegCount, CondARM32::AL); 1634 emitVPush<Form>(Func, BaseReg, RegCount);
1576 } 1635 }
1577 if (Asm->needsTextFixup()) 1636 assert(!Func->getAssembler<ARM32::AssemblerARM32>()->needsTextFixup());
1578 emitUsingTextFixup(Func); 1637 }
1638
1639 void InstARM32Push::emit(const Cfg *Func) const {
1640 assemble<TextualOutput>(Func);
1641 }
1642
1643 void InstARM32Push::emitIAS(const Cfg *Func) const {
1644 assemble<BinaryOutput>(Func);
1579 } 1645 }
1580 1646
1581 void InstARM32Push::dump(const Cfg *Func) const { 1647 void InstARM32Push::dump(const Cfg *Func) const {
1582 if (!BuildDefs::dump()) 1648 if (!BuildDefs::dump())
1583 return; 1649 return;
1584 Ostream &Str = Func->getContext()->getStrDump(); 1650 Ostream &Str = Func->getContext()->getStrDump();
1585 Str << "push" 1651 Str << "push"
1586 << " "; 1652 << " ";
1587 dumpSources(Func); 1653 dumpSources(Func);
1588 } 1654 }
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after
2147 2213
2148 template class InstARM32FourAddrGPR<InstARM32::Mla>; 2214 template class InstARM32FourAddrGPR<InstARM32::Mla>;
2149 template class InstARM32FourAddrGPR<InstARM32::Mls>; 2215 template class InstARM32FourAddrGPR<InstARM32::Mls>;
2150 2216
2151 template class InstARM32CmpLike<InstARM32::Cmn>; 2217 template class InstARM32CmpLike<InstARM32::Cmn>;
2152 template class InstARM32CmpLike<InstARM32::Cmp>; 2218 template class InstARM32CmpLike<InstARM32::Cmp>;
2153 template class InstARM32CmpLike<InstARM32::Tst>; 2219 template class InstARM32CmpLike<InstARM32::Tst>;
2154 2220
2155 } // end of namespace ARM32 2221 } // end of namespace ARM32
2156 } // end of namespace Ice 2222 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698