Chromium Code Reviews| 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); | |
|
Jim Stichnoth
2016/02/03 23:18:27
Maybe just:
assert(canEncodeBranchOffset(Offset)
John
2016/02/04 18:28:50
Done.
| |
| 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 } | |
| 624 | |
| 598 MoveRelocatableFixup *AssemblerARM32::createMoveFixup(bool IsMovW, | 625 MoveRelocatableFixup *AssemblerARM32::createMoveFixup(bool IsMovW, |
| 599 const Constant *Value) { | 626 const Constant *Value) { |
| 600 MoveRelocatableFixup *F = | 627 MoveRelocatableFixup *F = |
| 601 new (allocate<MoveRelocatableFixup>()) MoveRelocatableFixup(); | 628 new (allocate<MoveRelocatableFixup>()) MoveRelocatableFixup(); |
| 602 F->set_kind(IsMovW ? llvm::ELF::R_ARM_MOVW_ABS_NC | 629 F->set_kind(IsMovW ? llvm::ELF::R_ARM_MOVW_ABS_NC |
| 603 : llvm::ELF::R_ARM_MOVT_ABS); | 630 : llvm::ELF::R_ARM_MOVT_ABS); |
| 604 F->set_value(Value); | 631 F->set_value(Value); |
| 605 Buffer.installFixup(F); | 632 Buffer.installFixup(F); |
| 606 return F; | 633 return F; |
| 607 } | 634 } |
| 608 | 635 |
| 609 size_t BlRelocatableFixup::emit(GlobalContext *Ctx, | 636 size_t BlRelocatableFixup::emit(GlobalContext *Ctx, |
| 610 const Assembler &Asm) const { | 637 const Assembler &Asm) const { |
| 611 if (!BuildDefs::dump()) | 638 if (!BuildDefs::dump()) |
| 612 return InstARM32::InstSize; | 639 return InstARM32::InstSize; |
| 613 Ostream &Str = Ctx->getStrEmit(); | 640 Ostream &Str = Ctx->getStrEmit(); |
| 614 IValueT Inst = Asm.load<IValueT>(position()); | 641 IValueT Inst = Asm.load<IValueT>(position()); |
| 615 Str << "\t" | 642 Str << "\t" |
| 616 "bl\t" << symbol(Ctx, &Asm) << "\t@ .word " | 643 "bl\t" << symbol(Ctx, &Asm) << "\t@ .word " |
| 617 << llvm::format_hex_no_prefix(Inst, 8) << "\n"; | 644 << llvm::format_hex_no_prefix(Inst, 8) << "\n"; |
| 618 return InstARM32::InstSize; | 645 return InstARM32::InstSize; |
| 619 } | 646 } |
| 620 | 647 |
| 648 void BlRelocatableFixup::emitOffset(Assembler *Asm) const { | |
| 649 // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and | |
| 650 // iiiiiiiiiiiiiiiiiiiiiiii= | |
| 651 // EncodedBranchOffset(cccc101l000000000000000000000000, Offset); | |
| 652 const IValueT Inst = Asm->load<IValueT>(position()); | |
| 653 constexpr IValueT OffsetMask = 0x00FFFFFF; | |
| 654 Asm->store(position(), encodeBranchOffset(offset(), Inst & ~OffsetMask)); | |
| 655 } | |
| 656 | |
| 621 void AssemblerARM32::padWithNop(intptr_t Padding) { | 657 void AssemblerARM32::padWithNop(intptr_t Padding) { |
| 622 constexpr intptr_t InstWidth = sizeof(IValueT); | 658 constexpr intptr_t InstWidth = sizeof(IValueT); |
| 623 assert(Padding % InstWidth == 0 && | 659 assert(Padding % InstWidth == 0 && |
| 624 "Padding not multiple of instruction size"); | 660 "Padding not multiple of instruction size"); |
| 625 for (intptr_t i = 0; i < Padding; i += InstWidth) | 661 for (intptr_t i = 0; i < Padding; i += InstWidth) |
| 626 nop(); | 662 nop(); |
| 627 } | 663 } |
| 628 | 664 |
| 629 BlRelocatableFixup * | 665 BlRelocatableFixup * |
| 630 AssemblerARM32::createBlFixup(const ConstantRelocatable *BlTarget) { | 666 AssemblerARM32::createBlFixup(const ConstantRelocatable *BlTarget) { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 660 Labels.resize(Number + 1); | 696 Labels.resize(Number + 1); |
| 661 } | 697 } |
| 662 L = Labels[Number]; | 698 L = Labels[Number]; |
| 663 if (!L) { | 699 if (!L) { |
| 664 L = new (this->allocate<Label>()) Label(); | 700 L = new (this->allocate<Label>()) Label(); |
| 665 Labels[Number] = L; | 701 Labels[Number] = L; |
| 666 } | 702 } |
| 667 return L; | 703 return L; |
| 668 } | 704 } |
| 669 | 705 |
| 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. | 706 // Pull out offset from branch Inst. |
| 685 IOffsetT AssemblerARM32::decodeBranchOffset(IValueT Inst) { | 707 IOffsetT AssemblerARM32::decodeBranchOffset(IValueT Inst) { |
| 686 // Sign-extend, left-shift by 2, and adjust to the way ARM CPUs read PC. | 708 // Sign-extend, left-shift by 2, and adjust to the way ARM CPUs read PC. |
| 687 IOffsetT Offset = static_cast<IOffsetT>((Inst & kBranchOffsetMask) << 8); | 709 IOffsetT Offset = static_cast<IOffsetT>((Inst & kBranchOffsetMask) << 8); |
| 688 return (Offset >> 6) + kPCReadOffset; | 710 return (Offset >> 6) + kPCReadOffset; |
| 689 } | 711 } |
| 690 | 712 |
| 691 void AssemblerARM32::bind(Label *L) { | 713 void AssemblerARM32::bind(Label *L) { |
| 692 IOffsetT BoundPc = Buffer.size(); | 714 IOffsetT BoundPc = Buffer.size(); |
| 693 assert(!L->isBound()); // Labels can only be bound once. | 715 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"; | 2943 constexpr const char *Vsqrts = "vsqrts"; |
| 2922 IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts); | 2944 IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts); |
| 2923 IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts); | 2945 IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts); |
| 2924 constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6; | 2946 constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6; |
| 2925 constexpr IValueT S0 = 0; | 2947 constexpr IValueT S0 = 0; |
| 2926 emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm); | 2948 emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm); |
| 2927 } | 2949 } |
| 2928 | 2950 |
| 2929 } // end of namespace ARM32 | 2951 } // end of namespace ARM32 |
| 2930 } // end of namespace Ice | 2952 } // end of namespace Ice |
| OLD | NEW |