| 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 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 addSource(Src1); | 375 addSource(Src1); |
| 376 } | 376 } |
| 377 | 377 |
| 378 InstARM32Vcvt::InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, | 378 InstARM32Vcvt::InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, |
| 379 VcvtVariant Variant, CondARM32::Cond Predicate) | 379 VcvtVariant Variant, CondARM32::Cond Predicate) |
| 380 : InstARM32Pred(Func, InstARM32::Vcvt, 1, Dest, Predicate), | 380 : InstARM32Pred(Func, InstARM32::Vcvt, 1, Dest, Predicate), |
| 381 Variant(Variant) { | 381 Variant(Variant) { |
| 382 addSource(Src); | 382 addSource(Src); |
| 383 } | 383 } |
| 384 | 384 |
| 385 InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Variable *Src1, |
| 386 CondARM32::Cond Predicate) |
| 387 : InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) { |
| 388 addSource(Src0); |
| 389 addSource(Src1); |
| 390 } |
| 391 |
| 392 InstARM32Vmrs::InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate) |
| 393 : InstARM32Pred(Func, InstARM32::Vmrs, 0, nullptr, Predicate) {} |
| 394 |
| 385 // ======================== Dump routines ======================== // | 395 // ======================== Dump routines ======================== // |
| 386 | 396 |
| 387 // Two-addr ops | 397 // Two-addr ops |
| 388 template <> const char *InstARM32Movt::Opcode = "movt"; | 398 template <> const char *InstARM32Movt::Opcode = "movt"; |
| 389 // Unary ops | 399 // Unary ops |
| 390 template <> const char *InstARM32Movw::Opcode = "movw"; | 400 template <> const char *InstARM32Movw::Opcode = "movw"; |
| 391 template <> const char *InstARM32Clz::Opcode = "clz"; | 401 template <> const char *InstARM32Clz::Opcode = "clz"; |
| 392 template <> const char *InstARM32Mvn::Opcode = "mvn"; | 402 template <> const char *InstARM32Mvn::Opcode = "mvn"; |
| 393 template <> const char *InstARM32Rbit::Opcode = "rbit"; | 403 template <> const char *InstARM32Rbit::Opcode = "rbit"; |
| 394 template <> const char *InstARM32Rev::Opcode = "rev"; | 404 template <> const char *InstARM32Rev::Opcode = "rev"; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 return; | 510 return; |
| 501 Ostream &Str = Func->getContext()->getStrEmit(); | 511 Ostream &Str = Func->getContext()->getStrEmit(); |
| 502 Variable *Dest0 = getDest(); | 512 Variable *Dest0 = getDest(); |
| 503 Operand *Src0 = getSrc(0); | 513 Operand *Src0 = getSrc(0); |
| 504 | 514 |
| 505 assert(Dest0->hasReg()); | 515 assert(Dest0->hasReg()); |
| 506 assert(Dest1->hasReg()); | 516 assert(Dest1->hasReg()); |
| 507 assert(!llvm::isa<OperandARM32Mem>(Src0)); | 517 assert(!llvm::isa<OperandARM32Mem>(Src0)); |
| 508 | 518 |
| 509 Str << "\t" | 519 Str << "\t" |
| 510 << "vmov" | 520 << "vmov" << getPredicate() << "\t"; |
| 511 << "\t"; | |
| 512 Dest0->emit(Func); | 521 Dest0->emit(Func); |
| 513 Str << ", "; | 522 Str << ", "; |
| 514 Dest1->emit(Func); | 523 Dest1->emit(Func); |
| 515 Str << ", "; | 524 Str << ", "; |
| 516 Src0->emit(Func); | 525 Src0->emit(Func); |
| 517 } | 526 } |
| 518 | 527 |
| 519 void InstARM32Vmov::emitSingleDestMultiSource(const Cfg *Func) const { | 528 void InstARM32Vmov::emitSingleDestMultiSource(const Cfg *Func) const { |
| 520 if (!BuildDefs::dump()) | 529 if (!BuildDefs::dump()) |
| 521 return; | 530 return; |
| 522 Ostream &Str = Func->getContext()->getStrEmit(); | 531 Ostream &Str = Func->getContext()->getStrEmit(); |
| 523 Variable *Dest0 = getDest(); | 532 Variable *Dest0 = getDest(); |
| 524 Operand *Src0 = getSrc(0); | 533 Operand *Src0 = getSrc(0); |
| 525 Operand *Src1 = getSrc(1); | 534 Operand *Src1 = getSrc(1); |
| 526 | 535 |
| 527 assert(Dest0->hasReg()); | 536 assert(Dest0->hasReg()); |
| 528 assert(!llvm::isa<OperandARM32Mem>(Src0)); | 537 assert(!llvm::isa<OperandARM32Mem>(Src0)); |
| 529 assert(!llvm::isa<OperandARM32Mem>(Src1)); | 538 assert(!llvm::isa<OperandARM32Mem>(Src1)); |
| 530 | 539 |
| 531 Str << "\t" | 540 Str << "\t" |
| 532 << "vmov" | 541 << "vmov" << getPredicate() << "\t"; |
| 533 << "\t"; | |
| 534 Dest0->emit(Func); | 542 Dest0->emit(Func); |
| 535 Str << ", "; | 543 Str << ", "; |
| 536 Src0->emit(Func); | 544 Src0->emit(Func); |
| 537 Str << ", "; | 545 Str << ", "; |
| 538 Src1->emit(Func); | 546 Src1->emit(Func); |
| 539 } | 547 } |
| 540 | 548 |
| 541 namespace { | 549 namespace { |
| 542 bool isVariableWithoutRegister(const Operand *Op) { | 550 bool isVariableWithoutRegister(const Operand *Op) { |
| 543 if (const auto *OpV = llvm::dyn_cast<const Variable>(Op)) { | 551 if (const auto *OpV = llvm::dyn_cast<const Variable>(Op)) { |
| 544 return !OpV->hasReg(); | 552 return !OpV->hasReg(); |
| 545 } | 553 } |
| 546 return false; | 554 return false; |
| 547 } | 555 } |
| 548 | 556 |
| 549 bool isMemoryAccess(Operand *Op) { | 557 bool isMemoryAccess(Operand *Op) { |
| 550 return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op); | 558 return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op); |
| 551 } | 559 } |
| 560 |
| 561 bool isMoveBetweenCoreAndVFPRegisters(Variable *Dest, Operand *Src) { |
| 562 const Type DestTy = Dest->getType(); |
| 563 const Type SrcTy = Src->getType(); |
| 564 assert(!(isScalarIntegerType(DestTy) && isScalarIntegerType(SrcTy)) && |
| 565 "At most one of vmov's operands can be a core register."); |
| 566 return isScalarIntegerType(DestTy) || isScalarIntegerType(SrcTy); |
| 567 } |
| 552 } // end of anonymous namespace | 568 } // end of anonymous namespace |
| 553 | 569 |
| 554 void InstARM32Vmov::emitSingleDestSingleSource(const Cfg *Func) const { | 570 void InstARM32Vmov::emitSingleDestSingleSource(const Cfg *Func) const { |
| 555 if (!BuildDefs::dump()) | 571 if (!BuildDefs::dump()) |
| 556 return; | 572 return; |
| 557 Ostream &Str = Func->getContext()->getStrEmit(); | 573 Ostream &Str = Func->getContext()->getStrEmit(); |
| 558 Variable *Dest = getDest(); | 574 Variable *Dest = getDest(); |
| 559 if (Dest->hasReg()) { | 575 if (Dest->hasReg()) { |
| 560 Operand *Src0 = getSrc(0); | 576 Operand *Src0 = getSrc(0); |
| 561 const char *ActualOpcode = isMemoryAccess(Src0) ? "vldr" : "vmov"; | 577 const char *ActualOpcode = isMemoryAccess(Src0) ? "vldr" : "vmov"; |
| 562 Str << "\t" << ActualOpcode << "\t"; | 578 // when vmov{c}'ing, we need to emit a width string. Otherwise, the |
| 579 // assembler might be tempted to assume we want a vector vmov{c}, and that |
| 580 // is disallowed because ARM. |
| 581 const char *WidthString = |
| 582 (isMemoryAccess(Src0) || isMoveBetweenCoreAndVFPRegisters(Dest, Src0)) |
| 583 ? "" |
| 584 : getVecWidthString(Src0->getType()); |
| 585 Str << "\t" << ActualOpcode << getPredicate() << WidthString << "\t"; |
| 563 Dest->emit(Func); | 586 Dest->emit(Func); |
| 564 Str << ", "; | 587 Str << ", "; |
| 565 Src0->emit(Func); | 588 Src0->emit(Func); |
| 566 } else { | 589 } else { |
| 567 Variable *Src0 = llvm::cast<Variable>(getSrc(0)); | 590 Variable *Src0 = llvm::cast<Variable>(getSrc(0)); |
| 568 assert(Src0->hasReg()); | 591 assert(Src0->hasReg()); |
| 569 Str << "\t" | 592 Str << "\t" |
| 570 "vstr" | 593 "vstr" << getPredicate() << "\t"; |
| 571 "\t"; | |
| 572 Src0->emit(Func); | 594 Src0->emit(Func); |
| 573 Str << ", "; | 595 Str << ", "; |
| 574 Dest->emit(Func); | 596 Dest->emit(Func); |
| 575 } | 597 } |
| 576 } | 598 } |
| 577 | 599 |
| 578 void InstARM32Vmov::emit(const Cfg *Func) const { | 600 void InstARM32Vmov::emit(const Cfg *Func) const { |
| 579 if (!BuildDefs::dump()) | 601 if (!BuildDefs::dump()) |
| 580 return; | 602 return; |
| 581 assert(CondARM32::AL == getPredicate()); | |
| 582 assert(isMultiDest() + isMultiSource() <= 1 && "Invalid vmov type."); | 603 assert(isMultiDest() + isMultiSource() <= 1 && "Invalid vmov type."); |
| 583 if (isMultiDest()) { | 604 if (isMultiDest()) { |
| 584 emitMultiDestSingleSource(Func); | 605 emitMultiDestSingleSource(Func); |
| 585 return; | 606 return; |
| 586 } | 607 } |
| 587 | 608 |
| 588 if (isMultiSource()) { | 609 if (isMultiSource()) { |
| 589 emitSingleDestMultiSource(Func); | 610 emitSingleDestMultiSource(Func); |
| 590 return; | 611 return; |
| 591 } | 612 } |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1038 void InstARM32Vcvt::dump(const Cfg *Func) const { | 1059 void InstARM32Vcvt::dump(const Cfg *Func) const { |
| 1039 if (!BuildDefs::dump()) | 1060 if (!BuildDefs::dump()) |
| 1040 return; | 1061 return; |
| 1041 Ostream &Str = Func->getContext()->getStrDump(); | 1062 Ostream &Str = Func->getContext()->getStrDump(); |
| 1042 dumpDest(Func); | 1063 dumpDest(Func); |
| 1043 Str << " = " | 1064 Str << " = " |
| 1044 << "vcvt" << getPredicate() << vcvtVariantSuffix(Variant) << " "; | 1065 << "vcvt" << getPredicate() << vcvtVariantSuffix(Variant) << " "; |
| 1045 dumpSources(Func); | 1066 dumpSources(Func); |
| 1046 } | 1067 } |
| 1047 | 1068 |
| 1069 void InstARM32Vcmp::emit(const Cfg *Func) const { |
| 1070 if (!BuildDefs::dump()) |
| 1071 return; |
| 1072 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1073 assert(getSrcSize() == 2); |
| 1074 Str << "\t" |
| 1075 "vcmp" << getPredicate() << getVecWidthString(getSrc(0)->getType()) |
| 1076 << "\t"; |
| 1077 getSrc(0)->emit(Func); |
| 1078 Str << ", "; |
| 1079 getSrc(1)->emit(Func); |
| 1080 } |
| 1081 |
| 1082 void InstARM32Vcmp::emitIAS(const Cfg *Func) const { |
| 1083 assert(getSrcSize() == 2); |
| 1084 (void)Func; |
| 1085 llvm_unreachable("Not yet implemented"); |
| 1086 } |
| 1087 |
| 1088 void InstARM32Vcmp::dump(const Cfg *Func) const { |
| 1089 if (!BuildDefs::dump()) |
| 1090 return; |
| 1091 Ostream &Str = Func->getContext()->getStrDump(); |
| 1092 Str << "vcmp" << getPredicate() << getVecWidthString(getSrc(0)->getType()); |
| 1093 dumpSources(Func); |
| 1094 } |
| 1095 |
| 1096 void InstARM32Vmrs::emit(const Cfg *Func) const { |
| 1097 if (!BuildDefs::dump()) |
| 1098 return; |
| 1099 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1100 assert(getSrcSize() == 0); |
| 1101 Str << "\t" |
| 1102 "vmrs" << getPredicate() << "\t" |
| 1103 "APSR_nzcv" |
| 1104 ", " |
| 1105 "FPSCR"; |
| 1106 } |
| 1107 |
| 1108 void InstARM32Vmrs::emitIAS(const Cfg *Func) const { |
| 1109 assert(getSrcSize() == 0); |
| 1110 (void)Func; |
| 1111 llvm_unreachable("Not yet implemented"); |
| 1112 } |
| 1113 |
| 1114 void InstARM32Vmrs::dump(const Cfg *Func) const { |
| 1115 if (!BuildDefs::dump()) |
| 1116 return; |
| 1117 Ostream &Str = Func->getContext()->getStrDump(); |
| 1118 Str << "APSR{n,z,v,c} = vmrs" << getPredicate() << "\t" |
| 1119 "FPSCR{n,z,c,v}"; |
| 1120 } |
| 1121 |
| 1048 void OperandARM32Mem::emit(const Cfg *Func) const { | 1122 void OperandARM32Mem::emit(const Cfg *Func) const { |
| 1049 if (!BuildDefs::dump()) | 1123 if (!BuildDefs::dump()) |
| 1050 return; | 1124 return; |
| 1051 Ostream &Str = Func->getContext()->getStrEmit(); | 1125 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1052 Str << "["; | 1126 Str << "["; |
| 1053 getBase()->emit(Func); | 1127 getBase()->emit(Func); |
| 1054 switch (getAddrMode()) { | 1128 switch (getAddrMode()) { |
| 1055 case PostIndex: | 1129 case PostIndex: |
| 1056 case NegPostIndex: | 1130 case NegPostIndex: |
| 1057 Str << "], "; | 1131 Str << "], "; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1154 if (getShiftOp() != kNoShift) { | 1228 if (getShiftOp() != kNoShift) { |
| 1155 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; | 1229 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; |
| 1156 if (Func) | 1230 if (Func) |
| 1157 getShiftAmt()->dump(Func); | 1231 getShiftAmt()->dump(Func); |
| 1158 else | 1232 else |
| 1159 getShiftAmt()->dump(Str); | 1233 getShiftAmt()->dump(Str); |
| 1160 } | 1234 } |
| 1161 } | 1235 } |
| 1162 | 1236 |
| 1163 } // end of namespace Ice | 1237 } // end of namespace Ice |
| OLD | NEW |