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 |