| 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 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 if (!BuildDefs::dump()) | 453 if (!BuildDefs::dump()) |
| 454 return InstARM32::InstSize; | 454 return InstARM32::InstSize; |
| 455 Ostream &Str = Ctx->getStrEmit(); | 455 Ostream &Str = Ctx->getStrEmit(); |
| 456 IValueT Inst = Asm.load<IValueT>(position()); | 456 IValueT Inst = Asm.load<IValueT>(position()); |
| 457 Str << "\t" | 457 Str << "\t" |
| 458 << "bl\t" << symbol(Ctx) << "\t@ .word " | 458 << "bl\t" << symbol(Ctx) << "\t@ .word " |
| 459 << llvm::format_hex_no_prefix(Inst, 8) << "\n"; | 459 << llvm::format_hex_no_prefix(Inst, 8) << "\n"; |
| 460 return InstARM32::InstSize; | 460 return InstARM32::InstSize; |
| 461 } | 461 } |
| 462 | 462 |
| 463 void AssemblerARM32::padWithNop(intptr_t Padding) { |
| 464 constexpr intptr_t InstWidth = sizeof(IValueT); |
| 465 assert(Padding % InstWidth == 0 && |
| 466 "Padding not multiple of instruction size"); |
| 467 for (intptr_t i = 0; i < Padding; i += InstWidth) |
| 468 nop(); |
| 469 } |
| 470 |
| 463 BlRelocatableFixup * | 471 BlRelocatableFixup * |
| 464 AssemblerARM32::createBlFixup(const ConstantRelocatable *BlTarget) { | 472 AssemblerARM32::createBlFixup(const ConstantRelocatable *BlTarget) { |
| 465 BlRelocatableFixup *F = | 473 BlRelocatableFixup *F = |
| 466 new (allocate<BlRelocatableFixup>()) BlRelocatableFixup(); | 474 new (allocate<BlRelocatableFixup>()) BlRelocatableFixup(); |
| 467 F->set_kind(llvm::ELF::R_ARM_CALL); | 475 F->set_kind(llvm::ELF::R_ARM_CALL); |
| 468 F->set_value(BlTarget); | 476 F->set_value(BlTarget); |
| 469 Buffer.installFixup(F); | 477 Buffer.installFixup(F); |
| 470 return F; | 478 return F; |
| 471 } | 479 } |
| 472 | 480 |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 // TODO(kschimpf): Handle far jumps. | 652 // TODO(kschimpf): Handle far jumps. |
| 645 constexpr const char *BranchName = "b"; | 653 constexpr const char *BranchName = "b"; |
| 646 if (L->isBound()) { | 654 if (L->isBound()) { |
| 647 const int32_t Dest = L->getPosition() - Buffer.size(); | 655 const int32_t Dest = L->getPosition() - Buffer.size(); |
| 648 emitType05(Cond, Dest, Link, BranchName); | 656 emitType05(Cond, Dest, Link, BranchName); |
| 649 return; | 657 return; |
| 650 } | 658 } |
| 651 const IOffsetT Position = Buffer.size(); | 659 const IOffsetT Position = Buffer.size(); |
| 652 // Use the offset field of the branch instruction for linking the sites. | 660 // Use the offset field of the branch instruction for linking the sites. |
| 653 emitType05(Cond, L->getEncodedPosition(), Link, BranchName); | 661 emitType05(Cond, L->getEncodedPosition(), Link, BranchName); |
| 654 if (!needsTextFixup()) | 662 L->linkTo(*this, Position); |
| 655 L->linkTo(Position); | |
| 656 } | 663 } |
| 657 | 664 |
| 658 void AssemblerARM32::emitCompareOp(CondARM32::Cond Cond, IValueT Opcode, | 665 void AssemblerARM32::emitCompareOp(CondARM32::Cond Cond, IValueT Opcode, |
| 659 const Operand *OpRn, const Operand *OpSrc1, | 666 const Operand *OpRn, const Operand *OpSrc1, |
| 660 const char *InstName) { | 667 const char *InstName) { |
| 661 // XXX (register) | 668 // XXX (register) |
| 662 // XXX<c> <Rn>, <Rm>{, <shift>} | 669 // XXX<c> <Rn>, <Rm>{, <shift>} |
| 663 // | 670 // |
| 664 // ccccyyyxxxx1nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, iiiii | 671 // ccccyyyxxxx1nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, iiiii |
| 665 // defines shift constant, tt=ShiftKind, yyy=kInstTypeDataRegister, and | 672 // defines shift constant, tt=ShiftKind, yyy=kInstTypeDataRegister, and |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 710 | 717 |
| 711 // Check if conditions of rules violated. | 718 // Check if conditions of rules violated. |
| 712 verifyRegNotPc(Rn, "Rn", InstName); | 719 verifyRegNotPc(Rn, "Rn", InstName); |
| 713 verifyPOrNotW(Address, InstName); | 720 verifyPOrNotW(Address, InstName); |
| 714 if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) && | 721 if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) && |
| 715 isBitSet(U, Address) && !isBitSet(W, Address) && | 722 isBitSet(U, Address) && !isBitSet(W, Address) && |
| 716 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) | 723 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) |
| 717 llvm::report_fatal_error(std::string(InstName) + | 724 llvm::report_fatal_error(std::string(InstName) + |
| 718 ": Use push/pop instead"); | 725 ": Use push/pop instead"); |
| 719 | 726 |
| 720 return emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address, | 727 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address, |
| 721 InstName); | 728 InstName); |
| 729 return; |
| 722 } | 730 } |
| 723 case EncodedAsShiftRotateImm5: { | 731 case EncodedAsShiftRotateImm5: { |
| 724 // XXX{B} (register) | 732 // XXX{B} (register) |
| 725 // xxx{b}<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | 733 // xxx{b}<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
| 726 // xxx{b}<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} | 734 // xxx{b}<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} |
| 727 // | 735 // |
| 728 // cccc011pubwlnnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, | 736 // cccc011pubwlnnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, |
| 729 // b=IsByte, U=1 if +, pu0b is a BlockAddr, l=IsLoad, and | 737 // b=IsByte, U=1 if +, pu0b is a BlockAddr, l=IsLoad, and |
| 730 // pu0w0nnnn0000iiiiiss0mmmm=Address. | 738 // pu0w0nnnn0000iiiiiss0mmmm=Address. |
| 731 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); | 739 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); |
| 732 RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address); | 740 RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address); |
| 733 | 741 |
| 734 // Check if conditions of rules violated. | 742 // Check if conditions of rules violated. |
| 735 verifyPOrNotW(Address, InstName); | 743 verifyPOrNotW(Address, InstName); |
| 736 verifyRegNotPc(Rm, "Rm", InstName); | 744 verifyRegNotPc(Rm, "Rm", InstName); |
| 737 if (IsByte) | 745 if (IsByte) |
| 738 verifyRegNotPc(Rt, "Rt", InstName); | 746 verifyRegNotPc(Rt, "Rt", InstName); |
| 739 if (isBitSet(W, Address)) { | 747 if (isBitSet(W, Address)) { |
| 740 verifyRegNotPc(Rn, "Rn", InstName); | 748 verifyRegNotPc(Rn, "Rn", InstName); |
| 741 verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName); | 749 verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName); |
| 742 } | 750 } |
| 743 return emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address, | 751 emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address, |
| 744 InstName); | 752 InstName); |
| 753 return; |
| 745 } | 754 } |
| 746 } | 755 } |
| 747 } | 756 } |
| 748 | 757 |
| 749 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, | 758 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, |
| 750 IValueT Rt, const Operand *OpAddress, | 759 IValueT Rt, const Operand *OpAddress, |
| 751 const TargetInfo &TInfo, | 760 const TargetInfo &TInfo, |
| 752 const char *InstName) { | 761 const char *InstName) { |
| 753 IValueT Address; | 762 IValueT Address; |
| 754 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { | 763 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 766 // and pu0w0nnnn0000iiii0000jjjj=Address. | 775 // and pu0w0nnnn0000iiii0000jjjj=Address. |
| 767 verifyRegDefined(Rt, "Rt", InstName); | 776 verifyRegDefined(Rt, "Rt", InstName); |
| 768 verifyCondDefined(Cond, InstName); | 777 verifyCondDefined(Cond, InstName); |
| 769 verifyPOrNotW(Address, InstName); | 778 verifyPOrNotW(Address, InstName); |
| 770 verifyRegNotPc(Rt, "Rt", InstName); | 779 verifyRegNotPc(Rt, "Rt", InstName); |
| 771 if (isBitSet(W, Address)) | 780 if (isBitSet(W, Address)) |
| 772 verifyRegsNotEq(getGPRReg(kRnShift, Address), "Rn", Rt, "Rt", InstName); | 781 verifyRegsNotEq(getGPRReg(kRnShift, Address), "Rn", Rt, "Rt", InstName); |
| 773 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | | 782 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | |
| 774 Opcode | (Rt << kRdShift) | Address; | 783 Opcode | (Rt << kRdShift) | Address; |
| 775 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 784 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 776 return emitInst(Encoding); | 785 emitInst(Encoding); |
| 786 return; |
| 777 } | 787 } |
| 778 case EncodedAsShiftRotateImm5: { | 788 case EncodedAsShiftRotateImm5: { |
| 779 // XXXH (register) | 789 // XXXH (register) |
| 780 // xxxh<c> <Rt>, [<Rn>, +/-<Rm>]{!} | 790 // xxxh<c> <Rt>, [<Rn>, +/-<Rm>]{!} |
| 781 // xxxh<c> <Rt>, [<Rn>], +/-<Rm> | 791 // xxxh<c> <Rt>, [<Rn>], +/-<Rm> |
| 782 // | 792 // |
| 783 // cccc000pu0wxnnnntttt00001011mmmm where cccc=Cond, tttt=Rt, nnnn=Rn, | 793 // cccc000pu0wxnnnntttt00001011mmmm where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 784 // mmmm=Rm, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, and | 794 // mmmm=Rm, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, and |
| 785 // pu0w0nnnn000000000000mmmm=Address. | 795 // pu0w0nnnn000000000000mmmm=Address. |
| 786 verifyRegDefined(Rt, "Rt", InstName); | 796 verifyRegDefined(Rt, "Rt", InstName); |
| 787 verifyCondDefined(Cond, InstName); | 797 verifyCondDefined(Cond, InstName); |
| 788 verifyPOrNotW(Address, InstName); | 798 verifyPOrNotW(Address, InstName); |
| 789 verifyRegNotPc(Rt, "Rt", InstName); | 799 verifyRegNotPc(Rt, "Rt", InstName); |
| 790 verifyAddrRegNotPc(kRmShift, Address, "Rm", InstName); | 800 verifyAddrRegNotPc(kRmShift, Address, "Rm", InstName); |
| 791 const RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); | 801 const RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); |
| 792 if (isBitSet(W, Address)) { | 802 if (isBitSet(W, Address)) { |
| 793 verifyRegNotPc(Rn, "Rn", InstName); | 803 verifyRegNotPc(Rn, "Rn", InstName); |
| 794 verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName); | 804 verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName); |
| 795 } | 805 } |
| 796 if (mask(Address, kShiftImmShift, 5) != 0) | 806 if (mask(Address, kShiftImmShift, 5) != 0) |
| 797 // For encoding 3, no shift is allowed. | 807 // For encoding 3, no shift is allowed. |
| 798 llvm::report_fatal_error(std::string(InstName) + | 808 llvm::report_fatal_error(std::string(InstName) + |
| 799 ": Shift constant not allowed"); | 809 ": Shift constant not allowed"); |
| 800 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | | 810 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | |
| 801 Opcode | (Rt << kRdShift) | Address; | 811 Opcode | (Rt << kRdShift) | Address; |
| 802 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 812 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 803 return emitInst(Encoding); | 813 emitInst(Encoding); |
| 814 return; |
| 804 } | 815 } |
| 805 } | 816 } |
| 806 } | 817 } |
| 807 | 818 |
| 808 void AssemblerARM32::emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, | 819 void AssemblerARM32::emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, |
| 809 IValueT Rn, IValueT Rm, const char *InstName) { | 820 IValueT Rn, IValueT Rm, const char *InstName) { |
| 810 verifyRegDefined(Rd, "Rd", InstName); | 821 verifyRegDefined(Rd, "Rd", InstName); |
| 811 verifyRegDefined(Rn, "Rn", InstName); | 822 verifyRegDefined(Rn, "Rn", InstName); |
| 812 verifyRegDefined(Rm, "Rm", InstName); | 823 verifyRegDefined(Rm, "Rm", InstName); |
| 813 verifyCondDefined(Cond, InstName); | 824 verifyCondDefined(Cond, InstName); |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1123 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and | 1134 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and |
| 1124 // pu0w0nnnn0000iiiiiiiiiiii=Address. | 1135 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
| 1125 // | 1136 // |
| 1126 // LDRB (register) - ARM section A8.8.66, encoding A1: | 1137 // LDRB (register) - ARM section A8.8.66, encoding A1: |
| 1127 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | 1138 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
| 1128 // ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} | 1139 // ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} |
| 1129 // | 1140 // |
| 1130 // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b | 1141 // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b |
| 1131 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. | 1142 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. |
| 1132 constexpr bool IsByte = true; | 1143 constexpr bool IsByte = true; |
| 1133 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); | 1144 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); |
| 1145 return; |
| 1134 } | 1146 } |
| 1135 case 1: { | 1147 case 1: { |
| 1136 // Handles i16 loads. | 1148 // Handles i16 loads. |
| 1137 // | 1149 // |
| 1138 // LDRH (immediate) - ARM section A8.8.80, encoding A1: | 1150 // LDRH (immediate) - ARM section A8.8.80, encoding A1: |
| 1139 // ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] | 1151 // ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] |
| 1140 // ldrh<c> <Rt>, [<Rn>], #+/-<Imm8> | 1152 // ldrh<c> <Rt>, [<Rn>], #+/-<Imm8> |
| 1141 // ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | 1153 // ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
| 1142 // | 1154 // |
| 1143 // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1155 // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1144 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and | 1156 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and |
| 1145 // pu0w0nnnn0000iiiiiiiiiiii=Address. | 1157 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
| 1146 constexpr const char *Ldrh = "ldrh"; | 1158 constexpr const char *Ldrh = "ldrh"; |
| 1147 return emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo, Ldrh); | 1159 emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo, Ldrh); |
| 1160 return; |
| 1148 } | 1161 } |
| 1149 case 2: { | 1162 case 2: { |
| 1150 // Note: Handles i32 and float loads. Target lowering handles i64 and | 1163 // Note: Handles i32 and float loads. Target lowering handles i64 and |
| 1151 // double by using two (32 bit) load instructions. | 1164 // double by using two (32 bit) load instructions. |
| 1152 // | 1165 // |
| 1153 // LDR (immediate) - ARM section A8.8.63, encoding A1: | 1166 // LDR (immediate) - ARM section A8.8.63, encoding A1: |
| 1154 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1167 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 1155 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1168 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 1156 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1169 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 1157 // | 1170 // |
| 1158 // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1171 // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1159 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and | 1172 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and |
| 1160 // | 1173 // |
| 1161 // LDR (register) - ARM section A8.8.70, encoding A1: | 1174 // LDR (register) - ARM section A8.8.70, encoding A1: |
| 1162 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | 1175 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
| 1163 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>} | 1176 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>} |
| 1164 // | 1177 // |
| 1165 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b | 1178 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b |
| 1166 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. | 1179 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. |
| 1167 constexpr bool IsByte = false; | 1180 constexpr bool IsByte = false; |
| 1168 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); | 1181 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); |
| 1182 return; |
| 1169 } | 1183 } |
| 1170 } | 1184 } |
| 1171 } | 1185 } |
| 1172 | 1186 |
| 1173 void AssemblerARM32::emitShift(const CondARM32::Cond Cond, | 1187 void AssemblerARM32::emitShift(const CondARM32::Cond Cond, |
| 1174 const OperandARM32::ShiftKind Shift, | 1188 const OperandARM32::ShiftKind Shift, |
| 1175 const Operand *OpRd, const Operand *OpRm, | 1189 const Operand *OpRd, const Operand *OpRm, |
| 1176 const Operand *OpSrc1, const bool SetFlags, | 1190 const Operand *OpSrc1, const bool SetFlags, |
| 1177 const char *InstName) { | 1191 const char *InstName) { |
| 1178 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101 | 1192 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1320 // mmmm=Rm, iiii defines shift constant, and tt=ShiftKind. | 1334 // mmmm=Rm, iiii defines shift constant, and tt=ShiftKind. |
| 1321 constexpr const char *MvnName = "mvn"; | 1335 constexpr const char *MvnName = "mvn"; |
| 1322 IValueT Rd = encodeRegister(OpRd, "Rd", MvnName); | 1336 IValueT Rd = encodeRegister(OpRd, "Rd", MvnName); |
| 1323 constexpr IValueT MvnOpcode = B3 | B2 | B1 | B0; // i.e. 1111 | 1337 constexpr IValueT MvnOpcode = B3 | B2 | B1 | B0; // i.e. 1111 |
| 1324 constexpr IValueT Rn = 0; | 1338 constexpr IValueT Rn = 0; |
| 1325 constexpr bool SetFlags = false; | 1339 constexpr bool SetFlags = false; |
| 1326 emitType01(Cond, MvnOpcode, Rd, Rn, OpSrc, SetFlags, RdIsPcAndSetFlags, | 1340 emitType01(Cond, MvnOpcode, Rd, Rn, OpSrc, SetFlags, RdIsPcAndSetFlags, |
| 1327 MvnName); | 1341 MvnName); |
| 1328 } | 1342 } |
| 1329 | 1343 |
| 1344 void AssemblerARM32::nop() { |
| 1345 // NOP - Section A8.8.119, encoding A1: |
| 1346 // nop<c> |
| 1347 // |
| 1348 // cccc0011001000001111000000000000 where cccc=Cond. |
| 1349 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 1350 constexpr CondARM32::Cond Cond = CondARM32::AL; |
| 1351 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B25 | |
| 1352 B24 | B21 | B15 | B14 | B13 | B12; |
| 1353 emitInst(Encoding); |
| 1354 } |
| 1355 |
| 1330 void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn, | 1356 void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn, |
| 1331 const Operand *OpSrc1, bool SetFlags, | 1357 const Operand *OpSrc1, bool SetFlags, |
| 1332 CondARM32::Cond Cond) { | 1358 CondARM32::Cond Cond) { |
| 1333 // SBC (register) - ARM section 18.8.162, encoding A1: | 1359 // SBC (register) - ARM section 18.8.162, encoding A1: |
| 1334 // sbc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} | 1360 // sbc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} |
| 1335 // | 1361 // |
| 1336 // cccc0000110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 1362 // cccc0000110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 1337 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. | 1363 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. |
| 1338 // | 1364 // |
| 1339 // SBC (Immediate) - ARM section A8.8.161, encoding A1: | 1365 // SBC (Immediate) - ARM section A8.8.161, encoding A1: |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1384 // Handles i1 and i8 stores. | 1410 // Handles i1 and i8 stores. |
| 1385 // | 1411 // |
| 1386 // STRB (immediate) - ARM section A8.8.207, encoding A1: | 1412 // STRB (immediate) - ARM section A8.8.207, encoding A1: |
| 1387 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1413 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 1388 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1414 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 1389 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1415 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 1390 // | 1416 // |
| 1391 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1417 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1392 // iiiiiiiiiiii=imm12, u=1 if +. | 1418 // iiiiiiiiiiii=imm12, u=1 if +. |
| 1393 constexpr bool IsByte = true; | 1419 constexpr bool IsByte = true; |
| 1394 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); | 1420 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); |
| 1421 return; |
| 1395 } | 1422 } |
| 1396 case 1: { | 1423 case 1: { |
| 1397 // Handles i16 stores. | 1424 // Handles i16 stores. |
| 1398 // | 1425 // |
| 1399 // STRH (immediate) - ARM section A8.*.217, encoding A1: | 1426 // STRH (immediate) - ARM section A8.*.217, encoding A1: |
| 1400 // strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] | 1427 // strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] |
| 1401 // strh<c> <Rt>, [<Rn>], #+/-<Imm8> | 1428 // strh<c> <Rt>, [<Rn>], #+/-<Imm8> |
| 1402 // strh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | 1429 // strh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
| 1403 // | 1430 // |
| 1404 // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1431 // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1405 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and | 1432 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and |
| 1406 // pu0w0nnnn0000iiiiiiiiiiii=Address. | 1433 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
| 1407 constexpr const char *Strh = "strh"; | 1434 constexpr const char *Strh = "strh"; |
| 1408 return emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo, Strh); | 1435 emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo, Strh); |
| 1436 return; |
| 1409 } | 1437 } |
| 1410 case 2: { | 1438 case 2: { |
| 1411 // Note: Handles i32 and float stores. Target lowering handles i64 and | 1439 // Note: Handles i32 and float stores. Target lowering handles i64 and |
| 1412 // double by using two (32 bit) store instructions. | 1440 // double by using two (32 bit) store instructions. |
| 1413 // | 1441 // |
| 1414 // STR (immediate) - ARM section A8.8.207, encoding A1: | 1442 // STR (immediate) - ARM section A8.8.207, encoding A1: |
| 1415 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1443 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 1416 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1444 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 1417 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1445 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 1418 // | 1446 // |
| 1419 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1447 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1420 // iiiiiiiiiiii=imm12, u=1 if +. | 1448 // iiiiiiiiiiii=imm12, u=1 if +. |
| 1421 constexpr bool IsByte = false; | 1449 constexpr bool IsByte = false; |
| 1422 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); | 1450 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); |
| 1423 return setNeedsTextFixup(); | 1451 return; |
| 1424 } | 1452 } |
| 1425 } | 1453 } |
| 1426 } | 1454 } |
| 1427 | 1455 |
| 1428 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, | 1456 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, |
| 1429 const Operand *OpSrc1, bool SetFlags, | 1457 const Operand *OpSrc1, bool SetFlags, |
| 1430 CondARM32::Cond Cond) { | 1458 CondARM32::Cond Cond) { |
| 1431 // ORR (register) - ARM Section A8.8.123, encoding A1: | 1459 // ORR (register) - ARM Section A8.8.123, encoding A1: |
| 1432 // orr{s}<c> <Rd>, <Rn>, <Rm> | 1460 // orr{s}<c> <Rd>, <Rn>, <Rm> |
| 1433 // | 1461 // |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1658 | 1686 |
| 1659 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, | 1687 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, |
| 1660 CondARM32::Cond Cond) { | 1688 CondARM32::Cond Cond) { |
| 1661 constexpr const char *UxtName = "uxt"; | 1689 constexpr const char *UxtName = "uxt"; |
| 1662 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; | 1690 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; |
| 1663 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); | 1691 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); |
| 1664 } | 1692 } |
| 1665 | 1693 |
| 1666 } // end of namespace ARM32 | 1694 } // end of namespace ARM32 |
| 1667 } // end of namespace Ice | 1695 } // end of namespace Ice |
| OLD | NEW |