| 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 15 matching lines...) Expand all Loading... |
| 26 namespace Ice { | 26 namespace Ice { |
| 27 | 27 |
| 28 namespace { | 28 namespace { |
| 29 | 29 |
| 30 const struct TypeARM32Attributes_ { | 30 const struct TypeARM32Attributes_ { |
| 31 const char *WidthString; // b, h, <blank>, or d | 31 const char *WidthString; // b, h, <blank>, or d |
| 32 const char *VecWidthString; // i8, i16, i32, f32, f64 | 32 const char *VecWidthString; // i8, i16, i32, f32, f64 |
| 33 int8_t SExtAddrOffsetBits; | 33 int8_t SExtAddrOffsetBits; |
| 34 int8_t ZExtAddrOffsetBits; | 34 int8_t ZExtAddrOffsetBits; |
| 35 } TypeARM32Attributes[] = { | 35 } TypeARM32Attributes[] = { |
| 36 #define X(tag, elementty, int_width, vec_width, sbits, ubits) \ | 36 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr) \ |
| 37 { int_width, vec_width, sbits, ubits } \ | 37 { int_width, vec_width, sbits, ubits } \ |
| 38 , | 38 , |
| 39 ICETYPEARM32_TABLE | 39 ICETYPEARM32_TABLE |
| 40 #undef X | 40 #undef X |
| 41 }; | 41 }; |
| 42 | 42 |
| 43 const struct InstARM32ShiftAttributes_ { | 43 const struct InstARM32ShiftAttributes_ { |
| 44 const char *EmitString; | 44 const char *EmitString; |
| 45 } InstARM32ShiftAttributes[] = { | 45 } InstARM32ShiftAttributes[] = { |
| 46 #define X(tag, emit) \ | 46 #define X(tag, emit) \ |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 Vars[1] = Index; | 204 Vars[1] = Index; |
| 205 } | 205 } |
| 206 | 206 |
| 207 bool OperandARM32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) { | 207 bool OperandARM32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) { |
| 208 int32_t Bits = SignExt ? TypeARM32Attributes[Ty].SExtAddrOffsetBits | 208 int32_t Bits = SignExt ? TypeARM32Attributes[Ty].SExtAddrOffsetBits |
| 209 : TypeARM32Attributes[Ty].ZExtAddrOffsetBits; | 209 : TypeARM32Attributes[Ty].ZExtAddrOffsetBits; |
| 210 if (Bits == 0) | 210 if (Bits == 0) |
| 211 return Offset == 0; | 211 return Offset == 0; |
| 212 // Note that encodings for offsets are sign-magnitude for ARM, so we check | 212 // Note that encodings for offsets are sign-magnitude for ARM, so we check |
| 213 // with IsAbsoluteUint(). | 213 // with IsAbsoluteUint(). |
| 214 if (isScalarFloatingType(Ty)) | |
| 215 return Utils::IsAligned(Offset, 4) && Utils::IsAbsoluteUint(Bits, Offset); | |
| 216 return Utils::IsAbsoluteUint(Bits, Offset); | 214 return Utils::IsAbsoluteUint(Bits, Offset); |
| 217 } | 215 } |
| 218 | 216 |
| 219 OperandARM32FlexImm::OperandARM32FlexImm(Cfg * /* Func */, Type Ty, | 217 OperandARM32FlexImm::OperandARM32FlexImm(Cfg * /* Func */, Type Ty, |
| 220 uint32_t Imm, uint32_t RotateAmt) | 218 uint32_t Imm, uint32_t RotateAmt) |
| 221 : OperandARM32Flex(kFlexImm, Ty), Imm(Imm), RotateAmt(RotateAmt) { | 219 : OperandARM32Flex(kFlexImm, Ty), Imm(Imm), RotateAmt(RotateAmt) { |
| 222 NumVars = 0; | 220 NumVars = 0; |
| 223 Vars = nullptr; | 221 Vars = nullptr; |
| 224 } | 222 } |
| 225 | 223 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Variable *Src1, | 383 InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Variable *Src1, |
| 386 CondARM32::Cond Predicate) | 384 CondARM32::Cond Predicate) |
| 387 : InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) { | 385 : InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) { |
| 388 addSource(Src0); | 386 addSource(Src0); |
| 389 addSource(Src1); | 387 addSource(Src1); |
| 390 } | 388 } |
| 391 | 389 |
| 392 InstARM32Vmrs::InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate) | 390 InstARM32Vmrs::InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate) |
| 393 : InstARM32Pred(Func, InstARM32::Vmrs, 0, nullptr, Predicate) {} | 391 : InstARM32Pred(Func, InstARM32::Vmrs, 0, nullptr, Predicate) {} |
| 394 | 392 |
| 393 InstARM32Vabs::InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src, |
| 394 CondARM32::Cond Predicate) |
| 395 : InstARM32Pred(Func, InstARM32::Vabs, 1, Dest, Predicate) { |
| 396 addSource(Src); |
| 397 } |
| 395 // ======================== Dump routines ======================== // | 398 // ======================== Dump routines ======================== // |
| 396 | 399 |
| 397 // Two-addr ops | 400 // Two-addr ops |
| 398 template <> const char *InstARM32Movt::Opcode = "movt"; | 401 template <> const char *InstARM32Movt::Opcode = "movt"; |
| 399 // Unary ops | 402 // Unary ops |
| 400 template <> const char *InstARM32Movw::Opcode = "movw"; | 403 template <> const char *InstARM32Movw::Opcode = "movw"; |
| 401 template <> const char *InstARM32Clz::Opcode = "clz"; | 404 template <> const char *InstARM32Clz::Opcode = "clz"; |
| 402 template <> const char *InstARM32Mvn::Opcode = "mvn"; | 405 template <> const char *InstARM32Mvn::Opcode = "mvn"; |
| 403 template <> const char *InstARM32Rbit::Opcode = "rbit"; | 406 template <> const char *InstARM32Rbit::Opcode = "rbit"; |
| 404 template <> const char *InstARM32Rev::Opcode = "rev"; | 407 template <> const char *InstARM32Rev::Opcode = "rev"; |
| 405 template <> const char *InstARM32Sxt::Opcode = "sxt"; // still requires b/h | 408 template <> const char *InstARM32Sxt::Opcode = "sxt"; // still requires b/h |
| 406 template <> const char *InstARM32Uxt::Opcode = "uxt"; // still requires b/h | 409 template <> const char *InstARM32Uxt::Opcode = "uxt"; // still requires b/h |
| 407 // FP | 410 // FP |
| 408 template <> const char *InstARM32Vsqrt::Opcode = "vsqrt"; | 411 template <> const char *InstARM32Vsqrt::Opcode = "vsqrt"; |
| 409 // Mov-like ops | 412 // Mov-like ops |
| 410 template <> const char *InstARM32Ldr::Opcode = "ldr"; | 413 template <> const char *InstARM32Ldr::Opcode = "ldr"; |
| 411 template <> const char *InstARM32Mov::Opcode = "mov"; | |
| 412 // FP | |
| 413 template <> const char *InstARM32Vldr::Opcode = "vldr"; | |
| 414 // Three-addr ops | 414 // Three-addr ops |
| 415 template <> const char *InstARM32Adc::Opcode = "adc"; | 415 template <> const char *InstARM32Adc::Opcode = "adc"; |
| 416 template <> const char *InstARM32Add::Opcode = "add"; | 416 template <> const char *InstARM32Add::Opcode = "add"; |
| 417 template <> const char *InstARM32And::Opcode = "and"; | 417 template <> const char *InstARM32And::Opcode = "and"; |
| 418 template <> const char *InstARM32Asr::Opcode = "asr"; | 418 template <> const char *InstARM32Asr::Opcode = "asr"; |
| 419 template <> const char *InstARM32Bic::Opcode = "bic"; | 419 template <> const char *InstARM32Bic::Opcode = "bic"; |
| 420 template <> const char *InstARM32Eor::Opcode = "eor"; | 420 template <> const char *InstARM32Eor::Opcode = "eor"; |
| 421 template <> const char *InstARM32Lsl::Opcode = "lsl"; | 421 template <> const char *InstARM32Lsl::Opcode = "lsl"; |
| 422 template <> const char *InstARM32Lsr::Opcode = "lsr"; | 422 template <> const char *InstARM32Lsr::Opcode = "lsr"; |
| 423 template <> const char *InstARM32Mul::Opcode = "mul"; | 423 template <> const char *InstARM32Mul::Opcode = "mul"; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 440 template <> const char *InstARM32Tst::Opcode = "tst"; | 440 template <> const char *InstARM32Tst::Opcode = "tst"; |
| 441 | 441 |
| 442 void InstARM32::dump(const Cfg *Func) const { | 442 void InstARM32::dump(const Cfg *Func) const { |
| 443 if (!BuildDefs::dump()) | 443 if (!BuildDefs::dump()) |
| 444 return; | 444 return; |
| 445 Ostream &Str = Func->getContext()->getStrDump(); | 445 Ostream &Str = Func->getContext()->getStrDump(); |
| 446 Str << "[ARM32] "; | 446 Str << "[ARM32] "; |
| 447 Inst::dump(Func); | 447 Inst::dump(Func); |
| 448 } | 448 } |
| 449 | 449 |
| 450 template <> void InstARM32Mov::emit(const Cfg *Func) const { | 450 void InstARM32Mov::emitMultiDestSingleSource(const Cfg *Func) const { |
| 451 if (!BuildDefs::dump()) | 451 if (!BuildDefs::dump()) |
| 452 return; | 452 return; |
| 453 Ostream &Str = Func->getContext()->getStrEmit(); | 453 Ostream &Str = Func->getContext()->getStrEmit(); |
| 454 assert(getSrcSize() == 1); | 454 auto *Dest = llvm::cast<Variable64On32>(getDest()); |
| 455 Variable *Dest = getDest(); | 455 Operand *Src = getSrc(0); |
| 456 if (Dest->hasReg()) { | 456 |
| 457 IceString ActualOpcode = Opcode; | 457 assert(Dest->getType() == IceType_i64); |
| 458 Operand *Src0 = getSrc(0); | 458 assert(Dest->getHi()->hasReg()); |
| 459 if (const auto *Src0V = llvm::dyn_cast<Variable>(Src0)) { | 459 assert(Dest->getLo()->hasReg()); |
| 460 if (!Src0V->hasReg()) { | 460 assert(!llvm::isa<OperandARM32Mem>(Src)); |
| 461 // Always use the whole stack slot. A 32-bit load has a larger range of | 461 |
| 462 // offsets than 16-bit, etc. | 462 Str << "\t" |
| 463 ActualOpcode = IceString("ldr"); | 463 << "vmov" << getPredicate() << "\t"; |
| 464 } | 464 Dest->getLo()->emit(Func); |
| 465 } else { | 465 Str << ", "; |
| 466 if (llvm::isa<OperandARM32Mem>(Src0)) | 466 Dest->getHi()->emit(Func); |
| 467 ActualOpcode = IceString("ldr") + getWidthString(Dest->getType()); | 467 Str << ", "; |
| 468 } | 468 Src->emit(Func); |
| 469 Str << "\t" << ActualOpcode << getPredicate() << "\t"; | |
| 470 getDest()->emit(Func); | |
| 471 Str << ", "; | |
| 472 getSrc(0)->emit(Func); | |
| 473 } else { | |
| 474 Variable *Src0 = llvm::cast<Variable>(getSrc(0)); | |
| 475 assert(Src0->hasReg()); | |
| 476 Str << "\t" | |
| 477 << "str" << getPredicate() << "\t"; | |
| 478 Src0->emit(Func); | |
| 479 Str << ", "; | |
| 480 Dest->emit(Func); | |
| 481 } | |
| 482 } | 469 } |
| 483 | 470 |
| 484 template <> void InstARM32Mov::emitIAS(const Cfg *Func) const { | 471 void InstARM32Mov::emitSingleDestMultiSource(const Cfg *Func) const { |
| 485 assert(getSrcSize() == 1); | |
| 486 (void)Func; | |
| 487 llvm_unreachable("Not yet implemented"); | |
| 488 } | |
| 489 | |
| 490 template <> void InstARM32Vldr::emit(const Cfg *Func) const { | |
| 491 if (!BuildDefs::dump()) | 472 if (!BuildDefs::dump()) |
| 492 return; | 473 return; |
| 493 Ostream &Str = Func->getContext()->getStrEmit(); | 474 Ostream &Str = Func->getContext()->getStrEmit(); |
| 494 assert(getSrcSize() == 1); | 475 Variable *Dest = getDest(); |
| 495 assert(getDest()->hasReg()); | 476 auto *Src = llvm::cast<Variable64On32>(getSrc(0)); |
| 496 Str << "\t" << Opcode << getPredicate() << "\t"; | |
| 497 getDest()->emit(Func); | |
| 498 Str << ", "; | |
| 499 getSrc(0)->emit(Func); | |
| 500 } | |
| 501 | 477 |
| 502 template <> void InstARM32Vldr::emitIAS(const Cfg *Func) const { | 478 assert(Src->getType() == IceType_i64); |
| 503 assert(getSrcSize() == 1); | 479 assert(Src->getHi()->hasReg()); |
| 504 (void)Func; | 480 assert(Src->getLo()->hasReg()); |
| 505 llvm_unreachable("Not yet implemented"); | 481 assert(Dest->hasReg()); |
| 506 } | |
| 507 | |
| 508 void InstARM32Vmov::emitMultiDestSingleSource(const Cfg *Func) const { | |
| 509 if (!BuildDefs::dump()) | |
| 510 return; | |
| 511 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 512 Variable *Dest0 = getDest(); | |
| 513 Operand *Src0 = getSrc(0); | |
| 514 | |
| 515 assert(Dest0->hasReg()); | |
| 516 assert(Dest1->hasReg()); | |
| 517 assert(!llvm::isa<OperandARM32Mem>(Src0)); | |
| 518 | 482 |
| 519 Str << "\t" | 483 Str << "\t" |
| 520 << "vmov" << getPredicate() << "\t"; | 484 << "vmov" << getPredicate() << "\t"; |
| 521 Dest0->emit(Func); | 485 Dest->emit(Func); |
| 522 Str << ", "; | 486 Str << ", "; |
| 523 Dest1->emit(Func); | 487 Src->getLo()->emit(Func); |
| 524 Str << ", "; | 488 Str << ", "; |
| 525 Src0->emit(Func); | 489 Src->getHi()->emit(Func); |
| 526 } | |
| 527 | |
| 528 void InstARM32Vmov::emitSingleDestMultiSource(const Cfg *Func) const { | |
| 529 if (!BuildDefs::dump()) | |
| 530 return; | |
| 531 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 532 Variable *Dest0 = getDest(); | |
| 533 Operand *Src0 = getSrc(0); | |
| 534 Operand *Src1 = getSrc(1); | |
| 535 | |
| 536 assert(Dest0->hasReg()); | |
| 537 assert(!llvm::isa<OperandARM32Mem>(Src0)); | |
| 538 assert(!llvm::isa<OperandARM32Mem>(Src1)); | |
| 539 | |
| 540 Str << "\t" | |
| 541 << "vmov" << getPredicate() << "\t"; | |
| 542 Dest0->emit(Func); | |
| 543 Str << ", "; | |
| 544 Src0->emit(Func); | |
| 545 Str << ", "; | |
| 546 Src1->emit(Func); | |
| 547 } | 490 } |
| 548 | 491 |
| 549 namespace { | 492 namespace { |
| 493 |
| 550 bool isVariableWithoutRegister(const Operand *Op) { | 494 bool isVariableWithoutRegister(const Operand *Op) { |
| 551 if (const auto *OpV = llvm::dyn_cast<const Variable>(Op)) { | 495 if (const auto *OpV = llvm::dyn_cast<const Variable>(Op)) { |
| 552 return !OpV->hasReg(); | 496 return !OpV->hasReg(); |
| 553 } | 497 } |
| 554 return false; | 498 return false; |
| 555 } | 499 } |
| 556 | |
| 557 bool isMemoryAccess(Operand *Op) { | 500 bool isMemoryAccess(Operand *Op) { |
| 558 return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op); | 501 return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op); |
| 559 } | 502 } |
| 560 | 503 |
| 561 bool isMoveBetweenCoreAndVFPRegisters(Variable *Dest, Operand *Src) { | 504 bool isMoveBetweenCoreAndVFPRegisters(Variable *Dest, Operand *Src) { |
| 562 const Type DestTy = Dest->getType(); | 505 const Type DestTy = Dest->getType(); |
| 563 const Type SrcTy = Src->getType(); | 506 const Type SrcTy = Src->getType(); |
| 564 assert(!(isScalarIntegerType(DestTy) && isScalarIntegerType(SrcTy)) && | 507 return !isVectorType(DestTy) && !isVectorType(SrcTy) && |
| 565 "At most one of vmov's operands can be a core register."); | 508 (isScalarIntegerType(DestTy) == isScalarFloatingType(SrcTy)); |
| 566 return isScalarIntegerType(DestTy) || isScalarIntegerType(SrcTy); | |
| 567 } | 509 } |
| 510 |
| 568 } // end of anonymous namespace | 511 } // end of anonymous namespace |
| 569 | 512 |
| 570 void InstARM32Vmov::emitSingleDestSingleSource(const Cfg *Func) const { | 513 void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const { |
| 571 if (!BuildDefs::dump()) | 514 if (!BuildDefs::dump()) |
| 572 return; | 515 return; |
| 573 Ostream &Str = Func->getContext()->getStrEmit(); | 516 Ostream &Str = Func->getContext()->getStrEmit(); |
| 574 Variable *Dest = getDest(); | 517 Variable *Dest = getDest(); |
| 518 |
| 575 if (Dest->hasReg()) { | 519 if (Dest->hasReg()) { |
| 520 Type DestTy = Dest->getType(); |
| 576 Operand *Src0 = getSrc(0); | 521 Operand *Src0 = getSrc(0); |
| 577 const char *ActualOpcode = isMemoryAccess(Src0) ? "vldr" : "vmov"; | 522 const bool DestIsVector = isVectorType(DestTy); |
| 523 const bool DestIsScalarFP = isScalarFloatingType(Dest->getType()); |
| 524 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0); |
| 525 const char *LoadOpcode = |
| 526 DestIsVector ? "vld1" : (DestIsScalarFP ? "vldr" : "ldr"); |
| 527 const char *RegMovOpcode = |
| 528 (DestIsVector || DestIsScalarFP || CoreVFPMove) ? "vmov" : "mov"; |
| 529 const char *ActualOpcode = isMemoryAccess(Src0) ? LoadOpcode : RegMovOpcode; |
| 578 // when vmov{c}'ing, we need to emit a width string. Otherwise, the | 530 // 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 | 531 // assembler might be tempted to assume we want a vector vmov{c}, and that |
| 580 // is disallowed because ARM. | 532 // is disallowed because ARM. |
| 533 const char *NoWidthString = ""; |
| 581 const char *WidthString = | 534 const char *WidthString = |
| 582 (isMemoryAccess(Src0) || isMoveBetweenCoreAndVFPRegisters(Dest, Src0)) | 535 isMemoryAccess(Src0) |
| 583 ? "" | 536 ? (DestIsVector ? ".64" : NoWidthString) |
| 584 : getVecWidthString(Src0->getType()); | 537 : (!CoreVFPMove ? getVecWidthString(DestTy) : NoWidthString); |
| 538 |
| 585 Str << "\t" << ActualOpcode << getPredicate() << WidthString << "\t"; | 539 Str << "\t" << ActualOpcode << getPredicate() << WidthString << "\t"; |
| 586 Dest->emit(Func); | 540 Dest->emit(Func); |
| 587 Str << ", "; | 541 Str << ", "; |
| 588 Src0->emit(Func); | 542 Src0->emit(Func); |
| 589 } else { | 543 } else { |
| 590 Variable *Src0 = llvm::cast<Variable>(getSrc(0)); | 544 Variable *Src0 = llvm::cast<Variable>(getSrc(0)); |
| 591 assert(Src0->hasReg()); | 545 assert(Src0->hasReg()); |
| 592 Str << "\t" | 546 const char *ActualOpcode = |
| 593 "vstr" << getPredicate() << "\t"; | 547 isVectorType(Src0->getType()) |
| 548 ? "vst1" |
| 549 : (isScalarFloatingType(Src0->getType()) ? "vstr" : "str"); |
| 550 const char *NoWidthString = ""; |
| 551 const char *WidthString = |
| 552 isVectorType(Src0->getType()) ? ".64" : NoWidthString; |
| 553 Str << "\t" << ActualOpcode << getPredicate() << WidthString << "\t"; |
| 594 Src0->emit(Func); | 554 Src0->emit(Func); |
| 595 Str << ", "; | 555 Str << ", "; |
| 596 Dest->emit(Func); | 556 Dest->emit(Func); |
| 597 } | 557 } |
| 598 } | 558 } |
| 599 | 559 |
| 600 void InstARM32Vmov::emit(const Cfg *Func) const { | 560 void InstARM32Mov::emit(const Cfg *Func) const { |
| 601 if (!BuildDefs::dump()) | 561 if (!BuildDefs::dump()) |
| 602 return; | 562 return; |
| 603 assert(isMultiDest() + isMultiSource() <= 1 && "Invalid vmov type."); | 563 assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); |
| 604 if (isMultiDest()) { | 564 if (isMultiDest()) { |
| 605 emitMultiDestSingleSource(Func); | 565 emitMultiDestSingleSource(Func); |
| 606 return; | 566 return; |
| 607 } | 567 } |
| 608 | 568 |
| 609 if (isMultiSource()) { | 569 if (isMultiSource()) { |
| 610 emitSingleDestMultiSource(Func); | 570 emitSingleDestMultiSource(Func); |
| 611 return; | 571 return; |
| 612 } | 572 } |
| 613 | 573 |
| 614 emitSingleDestSingleSource(Func); | 574 emitSingleDestSingleSource(Func); |
| 615 } | 575 } |
| 616 | 576 |
| 617 void InstARM32Vmov::emitIAS(const Cfg *Func) const { | 577 void InstARM32Mov::emitIAS(const Cfg *Func) const { |
| 618 assert(getSrcSize() == 1); | 578 assert(getSrcSize() == 1); |
| 619 (void)Func; | 579 (void)Func; |
| 620 llvm_unreachable("Not yet implemented"); | 580 llvm_unreachable("Not yet implemented"); |
| 621 } | 581 } |
| 622 | 582 |
| 623 void InstARM32Vmov::dump(const Cfg *Func) const { | 583 void InstARM32Mov::dump(const Cfg *Func) const { |
| 624 if (!BuildDefs::dump()) | 584 if (!BuildDefs::dump()) |
| 625 return; | 585 return; |
| 586 assert(getSrcSize() == 1); |
| 626 Ostream &Str = Func->getContext()->getStrDump(); | 587 Ostream &Str = Func->getContext()->getStrDump(); |
| 627 dumpOpcodePred(Str, "vmov", getDest()->getType()); | 588 Variable *Dest = getDest(); |
| 589 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) { |
| 590 Dest64->getLo()->dump(Func); |
| 591 Str << ", "; |
| 592 Dest64->getHi()->dump(Func); |
| 593 } else { |
| 594 Dest->dump(Func); |
| 595 } |
| 596 |
| 597 dumpOpcodePred(Str, " = mov", getDest()->getType()); |
| 628 Str << " "; | 598 Str << " "; |
| 629 dumpDest(Func); | 599 |
| 630 Str << ", "; | 600 Operand *Src = getSrc(0); |
| 631 dumpSources(Func); | 601 if (auto *Src64 = llvm::dyn_cast<Variable64On32>(Src)) { |
| 602 Src64->getLo()->dump(Func); |
| 603 Str << ", "; |
| 604 Src64->getHi()->dump(Func); |
| 605 } else { |
| 606 Src->dump(Func); |
| 607 } |
| 632 } | 608 } |
| 633 | 609 |
| 634 void InstARM32Br::emit(const Cfg *Func) const { | 610 void InstARM32Br::emit(const Cfg *Func) const { |
| 635 if (!BuildDefs::dump()) | 611 if (!BuildDefs::dump()) |
| 636 return; | 612 return; |
| 637 Ostream &Str = Func->getContext()->getStrEmit(); | 613 Ostream &Str = Func->getContext()->getStrEmit(); |
| 638 Str << "\t" | 614 Str << "\t" |
| 639 << "b" << getPredicate() << "\t"; | 615 << "b" << getPredicate() << "\t"; |
| 640 if (Label) { | 616 if (Label) { |
| 641 Str << Label->getName(Func); | 617 Str << Label->getName(Func); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 Ostream &Str = Func->getContext()->getStrDump(); | 717 Ostream &Str = Func->getContext()->getStrDump(); |
| 742 Str << getName(Func) << ":"; | 718 Str << getName(Func) << ":"; |
| 743 } | 719 } |
| 744 | 720 |
| 745 template <> void InstARM32Ldr::emit(const Cfg *Func) const { | 721 template <> void InstARM32Ldr::emit(const Cfg *Func) const { |
| 746 if (!BuildDefs::dump()) | 722 if (!BuildDefs::dump()) |
| 747 return; | 723 return; |
| 748 Ostream &Str = Func->getContext()->getStrEmit(); | 724 Ostream &Str = Func->getContext()->getStrEmit(); |
| 749 assert(getSrcSize() == 1); | 725 assert(getSrcSize() == 1); |
| 750 assert(getDest()->hasReg()); | 726 assert(getDest()->hasReg()); |
| 751 Type Ty = getSrc(0)->getType(); | 727 Variable *Dest = getDest(); |
| 752 Str << "\t" << Opcode << getWidthString(Ty) << getPredicate() << "\t"; | 728 Type DestTy = Dest->getType(); |
| 729 const bool DestIsVector = isVectorType(DestTy); |
| 730 const bool DestIsScalarFloat = isScalarFloatingType(DestTy); |
| 731 const char *ActualOpcode = |
| 732 DestIsVector ? "vld1" : (DestIsScalarFloat ? "vldr" : "ldr"); |
| 733 const char *VectorMarker = DestIsVector ? ".64" : ""; |
| 734 const char *WidthString = DestIsVector ? "" : getWidthString(DestTy); |
| 735 Str << "\t" << ActualOpcode << WidthString << getPredicate() << VectorMarker |
| 736 << "\t"; |
| 753 getDest()->emit(Func); | 737 getDest()->emit(Func); |
| 754 Str << ", "; | 738 Str << ", "; |
| 755 getSrc(0)->emit(Func); | 739 getSrc(0)->emit(Func); |
| 756 } | 740 } |
| 757 | 741 |
| 758 template <> void InstARM32Ldr::emitIAS(const Cfg *Func) const { | 742 template <> void InstARM32Ldr::emitIAS(const Cfg *Func) const { |
| 759 assert(getSrcSize() == 1); | 743 assert(getSrcSize() == 1); |
| 760 (void)Func; | 744 (void)Func; |
| 761 llvm_unreachable("Not yet implemented"); | 745 llvm_unreachable("Not yet implemented"); |
| 762 } | 746 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 792 Str << "#:upper16:"; | 776 Str << "#:upper16:"; |
| 793 CR->emitWithoutPrefix(Func->getTarget()); | 777 CR->emitWithoutPrefix(Func->getTarget()); |
| 794 } else { | 778 } else { |
| 795 Src1->emit(Func); | 779 Src1->emit(Func); |
| 796 } | 780 } |
| 797 } | 781 } |
| 798 | 782 |
| 799 void InstARM32Pop::emit(const Cfg *Func) const { | 783 void InstARM32Pop::emit(const Cfg *Func) const { |
| 800 if (!BuildDefs::dump()) | 784 if (!BuildDefs::dump()) |
| 801 return; | 785 return; |
| 802 assert(Dests.size() > 0); | 786 SizeT IntegerCount = 0; |
| 787 for (const Operand *Op : Dests) { |
| 788 if (isScalarIntegerType(Op->getType())) { |
| 789 ++IntegerCount; |
| 790 } |
| 791 } |
| 803 Ostream &Str = Func->getContext()->getStrEmit(); | 792 Ostream &Str = Func->getContext()->getStrEmit(); |
| 793 if (IntegerCount == 0) { |
| 794 Str << "\t@ empty pop"; |
| 795 return; |
| 796 } |
| 804 Str << "\t" | 797 Str << "\t" |
| 805 << "pop" | 798 << "pop" |
| 806 << "\t{"; | 799 << "\t{"; |
| 807 for (SizeT I = 0; I < Dests.size(); ++I) { | 800 bool PrintComma = false; |
| 808 if (I > 0) | 801 for (const Operand *Op : Dests) { |
| 809 Str << ", "; | 802 if (isScalarIntegerType(Op->getType())) { |
| 810 Dests[I]->emit(Func); | 803 if (PrintComma) |
| 804 Str << ", "; |
| 805 Op->emit(Func); |
| 806 PrintComma = true; |
| 807 } |
| 811 } | 808 } |
| 812 Str << "}"; | 809 Str << "}"; |
| 813 } | 810 } |
| 814 | 811 |
| 815 void InstARM32Pop::emitIAS(const Cfg *Func) const { | 812 void InstARM32Pop::emitIAS(const Cfg *Func) const { |
| 816 (void)Func; | 813 (void)Func; |
| 817 llvm_unreachable("Not yet implemented"); | 814 llvm_unreachable("Not yet implemented"); |
| 818 } | 815 } |
| 819 | 816 |
| 820 void InstARM32Pop::dump(const Cfg *Func) const { | 817 void InstARM32Pop::dump(const Cfg *Func) const { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 getDest()->dump(Func); | 856 getDest()->dump(Func); |
| 860 Str << " = sub.i32 "; | 857 Str << " = sub.i32 "; |
| 861 getSrc(0)->dump(Func); | 858 getSrc(0)->dump(Func); |
| 862 Str << ", " << Amount << " ; "; | 859 Str << ", " << Amount << " ; "; |
| 863 getSrc(1)->dump(Func); | 860 getSrc(1)->dump(Func); |
| 864 } | 861 } |
| 865 | 862 |
| 866 void InstARM32Push::emit(const Cfg *Func) const { | 863 void InstARM32Push::emit(const Cfg *Func) const { |
| 867 if (!BuildDefs::dump()) | 864 if (!BuildDefs::dump()) |
| 868 return; | 865 return; |
| 869 assert(getSrcSize() > 0); | 866 SizeT IntegerCount = 0; |
| 867 for (SizeT i = 0; i < getSrcSize(); ++i) { |
| 868 if (isScalarIntegerType(getSrc(i)->getType())) { |
| 869 ++IntegerCount; |
| 870 } |
| 871 } |
| 870 Ostream &Str = Func->getContext()->getStrEmit(); | 872 Ostream &Str = Func->getContext()->getStrEmit(); |
| 873 if (IntegerCount == 0) { |
| 874 Str << "\t" |
| 875 << "@empty push"; |
| 876 return; |
| 877 } |
| 871 Str << "\t" | 878 Str << "\t" |
| 872 << "push" | 879 << "push" |
| 873 << "\t{"; | 880 << "\t{"; |
| 874 emitSources(Func); | 881 bool PrintComma = false; |
| 882 for (SizeT i = 0; i < getSrcSize(); ++i) { |
| 883 Operand *Op = getSrc(i); |
| 884 if (isScalarIntegerType(Op->getType())) { |
| 885 if (PrintComma) |
| 886 Str << ", "; |
| 887 Op->emit(Func); |
| 888 PrintComma = true; |
| 889 } |
| 890 } |
| 875 Str << "}"; | 891 Str << "}"; |
| 876 } | 892 } |
| 877 | 893 |
| 878 void InstARM32Push::emitIAS(const Cfg *Func) const { | 894 void InstARM32Push::emitIAS(const Cfg *Func) const { |
| 879 (void)Func; | 895 (void)Func; |
| 880 llvm_unreachable("Not yet implemented"); | 896 llvm_unreachable("Not yet implemented"); |
| 881 } | 897 } |
| 882 | 898 |
| 883 void InstARM32Push::dump(const Cfg *Func) const { | 899 void InstARM32Push::dump(const Cfg *Func) const { |
| 884 if (!BuildDefs::dump()) | 900 if (!BuildDefs::dump()) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 Str << "ret." << Ty << " "; | 932 Str << "ret." << Ty << " "; |
| 917 dumpSources(Func); | 933 dumpSources(Func); |
| 918 } | 934 } |
| 919 | 935 |
| 920 void InstARM32Str::emit(const Cfg *Func) const { | 936 void InstARM32Str::emit(const Cfg *Func) const { |
| 921 if (!BuildDefs::dump()) | 937 if (!BuildDefs::dump()) |
| 922 return; | 938 return; |
| 923 Ostream &Str = Func->getContext()->getStrEmit(); | 939 Ostream &Str = Func->getContext()->getStrEmit(); |
| 924 assert(getSrcSize() == 2); | 940 assert(getSrcSize() == 2); |
| 925 Type Ty = getSrc(0)->getType(); | 941 Type Ty = getSrc(0)->getType(); |
| 926 const char *Opcode = isScalarFloatingType(Ty) ? "vstr" : "str"; | 942 const bool IsVectorStore = isVectorType(Ty); |
| 927 Str << "\t" << Opcode << getWidthString(Ty) << getPredicate() << "\t"; | 943 const char *Opcode = |
| 944 IsVectorStore ? "vst1" : (isScalarFloatingType(Ty) ? "vstr" : "str"); |
| 945 const char *VecEltWidthString = IsVectorStore ? ".64" : ""; |
| 946 Str << "\t" << Opcode << getWidthString(Ty) << getPredicate() |
| 947 << VecEltWidthString << "\t"; |
| 928 getSrc(0)->emit(Func); | 948 getSrc(0)->emit(Func); |
| 929 Str << ", "; | 949 Str << ", "; |
| 930 getSrc(1)->emit(Func); | 950 getSrc(1)->emit(Func); |
| 931 } | 951 } |
| 932 | 952 |
| 933 void InstARM32Str::emitIAS(const Cfg *Func) const { | 953 void InstARM32Str::emitIAS(const Cfg *Func) const { |
| 934 assert(getSrcSize() == 2); | 954 assert(getSrcSize() == 2); |
| 935 (void)Func; | 955 (void)Func; |
| 936 llvm_unreachable("Not yet implemented"); | 956 llvm_unreachable("Not yet implemented"); |
| 937 } | 957 } |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 } | 1132 } |
| 1113 | 1133 |
| 1114 void InstARM32Vmrs::dump(const Cfg *Func) const { | 1134 void InstARM32Vmrs::dump(const Cfg *Func) const { |
| 1115 if (!BuildDefs::dump()) | 1135 if (!BuildDefs::dump()) |
| 1116 return; | 1136 return; |
| 1117 Ostream &Str = Func->getContext()->getStrDump(); | 1137 Ostream &Str = Func->getContext()->getStrDump(); |
| 1118 Str << "APSR{n,z,v,c} = vmrs" << getPredicate() << "\t" | 1138 Str << "APSR{n,z,v,c} = vmrs" << getPredicate() << "\t" |
| 1119 "FPSCR{n,z,c,v}"; | 1139 "FPSCR{n,z,c,v}"; |
| 1120 } | 1140 } |
| 1121 | 1141 |
| 1142 void InstARM32Vabs::emit(const Cfg *Func) const { |
| 1143 if (!BuildDefs::dump()) |
| 1144 return; |
| 1145 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1146 assert(getSrcSize() == 1); |
| 1147 Str << "\t" |
| 1148 "vabs" << getPredicate() << getVecWidthString(getSrc(0)->getType()) |
| 1149 << "\t"; |
| 1150 getDest()->emit(Func); |
| 1151 Str << ", "; |
| 1152 getSrc(0)->emit(Func); |
| 1153 } |
| 1154 |
| 1155 void InstARM32Vabs::emitIAS(const Cfg *Func) const { |
| 1156 assert(getSrcSize() == 1); |
| 1157 (void)Func; |
| 1158 llvm_unreachable("Not yet implemented"); |
| 1159 } |
| 1160 |
| 1161 void InstARM32Vabs::dump(const Cfg *Func) const { |
| 1162 if (!BuildDefs::dump()) |
| 1163 return; |
| 1164 Ostream &Str = Func->getContext()->getStrDump(); |
| 1165 dumpDest(Func); |
| 1166 Str << " = vabs" << getPredicate() << getVecWidthString(getSrc(0)->getType()); |
| 1167 } |
| 1168 |
| 1122 void OperandARM32Mem::emit(const Cfg *Func) const { | 1169 void OperandARM32Mem::emit(const Cfg *Func) const { |
| 1123 if (!BuildDefs::dump()) | 1170 if (!BuildDefs::dump()) |
| 1124 return; | 1171 return; |
| 1125 Ostream &Str = Func->getContext()->getStrEmit(); | 1172 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1126 Str << "["; | 1173 Str << "["; |
| 1127 getBase()->emit(Func); | 1174 getBase()->emit(Func); |
| 1128 switch (getAddrMode()) { | 1175 switch (getAddrMode()) { |
| 1129 case PostIndex: | 1176 case PostIndex: |
| 1130 case NegPostIndex: | 1177 case NegPostIndex: |
| 1131 Str << "], "; | 1178 Str << "]"; |
| 1132 break; | 1179 break; |
| 1133 default: | 1180 default: |
| 1134 Str << ", "; | |
| 1135 break; | 1181 break; |
| 1136 } | 1182 } |
| 1137 if (isRegReg()) { | 1183 if (isRegReg()) { |
| 1184 Str << ", "; |
| 1138 if (isNegAddrMode()) { | 1185 if (isNegAddrMode()) { |
| 1139 Str << "-"; | 1186 Str << "-"; |
| 1140 } | 1187 } |
| 1141 getIndex()->emit(Func); | 1188 getIndex()->emit(Func); |
| 1142 if (getShiftOp() != kNoShift) { | 1189 if (getShiftOp() != kNoShift) { |
| 1143 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #" | 1190 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #" |
| 1144 << getShiftAmt(); | 1191 << getShiftAmt(); |
| 1145 } | 1192 } |
| 1146 } else { | 1193 } else { |
| 1147 getOffset()->emit(Func); | 1194 ConstantInteger32 *Offset = getOffset(); |
| 1195 if (Offset && Offset->getValue() != 0) { |
| 1196 Str << ", "; |
| 1197 Offset->emit(Func); |
| 1198 } |
| 1148 } | 1199 } |
| 1149 switch (getAddrMode()) { | 1200 switch (getAddrMode()) { |
| 1150 case Offset: | 1201 case Offset: |
| 1151 case NegOffset: | 1202 case NegOffset: |
| 1152 Str << "]"; | 1203 Str << "]"; |
| 1153 break; | 1204 break; |
| 1154 case PreIndex: | 1205 case PreIndex: |
| 1155 case NegPreIndex: | 1206 case NegPreIndex: |
| 1156 Str << "]!"; | 1207 Str << "]!"; |
| 1157 break; | 1208 break; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1228 if (getShiftOp() != kNoShift) { | 1279 if (getShiftOp() != kNoShift) { |
| 1229 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; | 1280 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; |
| 1230 if (Func) | 1281 if (Func) |
| 1231 getShiftAmt()->dump(Func); | 1282 getShiftAmt()->dump(Func); |
| 1232 else | 1283 else |
| 1233 getShiftAmt()->dump(Str); | 1284 getShiftAmt()->dump(Str); |
| 1234 } | 1285 } |
| 1235 } | 1286 } |
| 1236 | 1287 |
| 1237 } // end of namespace Ice | 1288 } // end of namespace Ice |
| OLD | NEW |