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