OLD | NEW |
---|---|
1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// | 1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// |
2 // | 2 // |
3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
4 // for details. All rights reserved. Use of this source code is governed by a | 4 // for details. All rights reserved. Use of this source code is governed by a |
5 // BSD-style license that can be found in the LICENSE file. | 5 // BSD-style license that can be found in the LICENSE file. |
6 // | 6 // |
7 // Modified by the Subzero authors. | 7 // Modified by the Subzero authors. |
8 // | 8 // |
9 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// |
10 // | 10 // |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
499 } | 499 } |
500 return CantEncode; | 500 return CantEncode; |
501 } | 501 } |
502 | 502 |
503 // Checks that Offset can fit in imm24 constant of branch (b) instruction. | 503 // Checks that Offset can fit in imm24 constant of branch (b) instruction. |
504 bool canEncodeBranchOffset(IOffsetT Offset) { | 504 bool canEncodeBranchOffset(IOffsetT Offset) { |
505 return Utils::IsAligned(Offset, 4) && | 505 return Utils::IsAligned(Offset, 4) && |
506 Utils::IsInt(kBranchOffsetBits, Offset >> 2); | 506 Utils::IsInt(kBranchOffsetBits, Offset >> 2); |
507 } | 507 } |
508 | 508 |
509 IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) { | |
510 // Adjust offset to the way ARM CPUs read PC. | |
511 Offset -= kPCReadOffset; | |
512 | |
513 bool IsGoodOffset = canEncodeBranchOffset(Offset); | |
514 assert(IsGoodOffset); | |
515 (void)IsGoodOffset; | |
516 | |
517 // Properly preserve only the bits supported in the instruction. | |
518 Offset >>= 2; | |
519 Offset &= kBranchOffsetMask; | |
520 return (Inst & ~kBranchOffsetMask) | Offset; | |
521 } | |
522 | |
509 IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet, | 523 IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet, |
510 const char *RegName, const char *InstName) { | 524 const char *RegName, const char *InstName) { |
511 IValueT Reg = 0; | 525 IValueT Reg = 0; |
512 if (encodeOperand(OpReg, Reg, WantedRegSet) != EncodedAsRegister) | 526 if (encodeOperand(OpReg, Reg, WantedRegSet) != EncodedAsRegister) |
513 llvm::report_fatal_error(std::string(InstName) + ": Can't find register " + | 527 llvm::report_fatal_error(std::string(InstName) + ": Can't find register " + |
514 RegName); | 528 RegName); |
515 return Reg; | 529 return Reg; |
516 } | 530 } |
517 | 531 |
518 IValueT encodeGPRegister(const Operand *OpReg, const char *RegName, | 532 IValueT encodeGPRegister(const Operand *OpReg, const char *RegName, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
588 IValueT Inst = Asm.load<IValueT>(position()); | 602 IValueT Inst = Asm.load<IValueT>(position()); |
589 Str << "\t" | 603 Str << "\t" |
590 "mov" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "w" : "t") << "\t" | 604 "mov" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "w" : "t") << "\t" |
591 << RegARM32::getRegName((Inst >> kRdShift) & 0xF) | 605 << RegARM32::getRegName((Inst >> kRdShift) & 0xF) |
592 << ", #:" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "lower" : "upper") | 606 << ", #:" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "lower" : "upper") |
593 << "16:" << symbol(Ctx, &Asm) << "\t@ .word " | 607 << "16:" << symbol(Ctx, &Asm) << "\t@ .word " |
594 << llvm::format_hex_no_prefix(Inst, 8) << "\n"; | 608 << llvm::format_hex_no_prefix(Inst, 8) << "\n"; |
595 return InstARM32::InstSize; | 609 return InstARM32::InstSize; |
596 } | 610 } |
597 | 611 |
612 // This fixup points to an ARM32 instruction with the following format: | |
613 void MoveRelocatableFixup::emitOffset(Assembler *Asm) const { | |
614 // cccc00110T00iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, | |
615 // iiiiiiiiiiiiiiii = Imm16, and T=1 for movt. | |
616 | |
617 const IValueT Inst = Asm->load<IValueT>(position()); | |
618 constexpr IValueT Imm16Mask = 0x000F0FFF; | |
619 const IValueT Imm16 = | |
620 offset() >> (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? 0 : 16) & 0xffff; | |
621 Asm->store(position(), | |
622 (Inst & ~Imm16Mask) | ((Imm16 >> 12) << 16) | (Imm16 & 0xfff)); | |
623 } | |
Karl
2016/02/03 21:03:05
Add blank line?
John
2016/02/03 21:25:20
Done.
| |
598 MoveRelocatableFixup *AssemblerARM32::createMoveFixup(bool IsMovW, | 624 MoveRelocatableFixup *AssemblerARM32::createMoveFixup(bool IsMovW, |
599 const Constant *Value) { | 625 const Constant *Value) { |
600 MoveRelocatableFixup *F = | 626 MoveRelocatableFixup *F = |
601 new (allocate<MoveRelocatableFixup>()) MoveRelocatableFixup(); | 627 new (allocate<MoveRelocatableFixup>()) MoveRelocatableFixup(); |
602 F->set_kind(IsMovW ? llvm::ELF::R_ARM_MOVW_ABS_NC | 628 F->set_kind(IsMovW ? llvm::ELF::R_ARM_MOVW_ABS_NC |
603 : llvm::ELF::R_ARM_MOVT_ABS); | 629 : llvm::ELF::R_ARM_MOVT_ABS); |
604 F->set_value(Value); | 630 F->set_value(Value); |
605 Buffer.installFixup(F); | 631 Buffer.installFixup(F); |
606 return F; | 632 return F; |
607 } | 633 } |
608 | 634 |
609 size_t BlRelocatableFixup::emit(GlobalContext *Ctx, | 635 size_t BlRelocatableFixup::emit(GlobalContext *Ctx, |
610 const Assembler &Asm) const { | 636 const Assembler &Asm) const { |
611 if (!BuildDefs::dump()) | 637 if (!BuildDefs::dump()) |
612 return InstARM32::InstSize; | 638 return InstARM32::InstSize; |
613 Ostream &Str = Ctx->getStrEmit(); | 639 Ostream &Str = Ctx->getStrEmit(); |
614 IValueT Inst = Asm.load<IValueT>(position()); | 640 IValueT Inst = Asm.load<IValueT>(position()); |
615 Str << "\t" | 641 Str << "\t" |
616 "bl\t" << symbol(Ctx, &Asm) << "\t@ .word " | 642 "bl\t" << symbol(Ctx, &Asm) << "\t@ .word " |
617 << llvm::format_hex_no_prefix(Inst, 8) << "\n"; | 643 << llvm::format_hex_no_prefix(Inst, 8) << "\n"; |
618 return InstARM32::InstSize; | 644 return InstARM32::InstSize; |
619 } | 645 } |
620 | 646 |
647 void BlRelocatableFixup::emitOffset(Assembler *Asm) const { | |
648 // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and | |
649 // iiiiiiiiiiiiiiiiiiiiiiii= | |
650 // EncodedBranchOffset(cccc101l000000000000000000000000, Offset); | |
651 const IValueT Inst = Asm->load<IValueT>(position()); | |
652 constexpr IValueT OffsetMask = 0x00FFFFFF; | |
653 Asm->store(position(), encodeBranchOffset(offset(), Inst & ~OffsetMask)); | |
654 } | |
655 | |
621 void AssemblerARM32::padWithNop(intptr_t Padding) { | 656 void AssemblerARM32::padWithNop(intptr_t Padding) { |
622 constexpr intptr_t InstWidth = sizeof(IValueT); | 657 constexpr intptr_t InstWidth = sizeof(IValueT); |
623 assert(Padding % InstWidth == 0 && | 658 assert(Padding % InstWidth == 0 && |
624 "Padding not multiple of instruction size"); | 659 "Padding not multiple of instruction size"); |
625 for (intptr_t i = 0; i < Padding; i += InstWidth) | 660 for (intptr_t i = 0; i < Padding; i += InstWidth) |
626 nop(); | 661 nop(); |
627 } | 662 } |
628 | 663 |
629 BlRelocatableFixup * | 664 BlRelocatableFixup * |
630 AssemblerARM32::createBlFixup(const ConstantRelocatable *BlTarget) { | 665 AssemblerARM32::createBlFixup(const ConstantRelocatable *BlTarget) { |
(...skipping 29 matching lines...) Expand all Loading... | |
660 Labels.resize(Number + 1); | 695 Labels.resize(Number + 1); |
661 } | 696 } |
662 L = Labels[Number]; | 697 L = Labels[Number]; |
663 if (!L) { | 698 if (!L) { |
664 L = new (this->allocate<Label>()) Label(); | 699 L = new (this->allocate<Label>()) Label(); |
665 Labels[Number] = L; | 700 Labels[Number] = L; |
666 } | 701 } |
667 return L; | 702 return L; |
668 } | 703 } |
669 | 704 |
670 IValueT AssemblerARM32::encodeBranchOffset(IOffsetT Offset, IValueT Inst) { | |
671 // Adjust offset to the way ARM CPUs read PC. | |
672 Offset -= kPCReadOffset; | |
673 | |
674 bool IsGoodOffset = canEncodeBranchOffset(Offset); | |
675 assert(IsGoodOffset); | |
676 (void)IsGoodOffset; | |
677 | |
678 // Properly preserve only the bits supported in the instruction. | |
679 Offset >>= 2; | |
680 Offset &= kBranchOffsetMask; | |
681 return (Inst & ~kBranchOffsetMask) | Offset; | |
682 } | |
683 | |
684 // Pull out offset from branch Inst. | 705 // Pull out offset from branch Inst. |
685 IOffsetT AssemblerARM32::decodeBranchOffset(IValueT Inst) { | 706 IOffsetT AssemblerARM32::decodeBranchOffset(IValueT Inst) { |
686 // Sign-extend, left-shift by 2, and adjust to the way ARM CPUs read PC. | 707 // Sign-extend, left-shift by 2, and adjust to the way ARM CPUs read PC. |
687 IOffsetT Offset = static_cast<IOffsetT>((Inst & kBranchOffsetMask) << 8); | 708 IOffsetT Offset = static_cast<IOffsetT>((Inst & kBranchOffsetMask) << 8); |
688 return (Offset >> 6) + kPCReadOffset; | 709 return (Offset >> 6) + kPCReadOffset; |
689 } | 710 } |
690 | 711 |
691 void AssemblerARM32::bind(Label *L) { | 712 void AssemblerARM32::bind(Label *L) { |
692 IOffsetT BoundPc = Buffer.size(); | 713 IOffsetT BoundPc = Buffer.size(); |
693 assert(!L->isBound()); // Labels can only be bound once. | 714 assert(!L->isBound()); // Labels can only be bound once. |
(...skipping 2227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2921 constexpr const char *Vsqrts = "vsqrts"; | 2942 constexpr const char *Vsqrts = "vsqrts"; |
2922 IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts); | 2943 IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts); |
2923 IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts); | 2944 IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts); |
2924 constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6; | 2945 constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6; |
2925 constexpr IValueT S0 = 0; | 2946 constexpr IValueT S0 = 0; |
2926 emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm); | 2947 emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm); |
2927 } | 2948 } |
2928 | 2949 |
2929 } // end of namespace ARM32 | 2950 } // end of namespace ARM32 |
2930 } // end of namespace Ice | 2951 } // end of namespace Ice |
OLD | NEW |