| 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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 | 95 |
| 96 // Div instruction register field encodings. | 96 // Div instruction register field encodings. |
| 97 static constexpr IValueT kDivRdShift = 16; | 97 static constexpr IValueT kDivRdShift = 16; |
| 98 static constexpr IValueT kDivRmShift = 8; | 98 static constexpr IValueT kDivRmShift = 8; |
| 99 static constexpr IValueT kDivRnShift = 0; | 99 static constexpr IValueT kDivRnShift = 0; |
| 100 | 100 |
| 101 // Type of instruction encoding (bits 25-27). See ARM section A5.1 | 101 // Type of instruction encoding (bits 25-27). See ARM section A5.1 |
| 102 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000 | 102 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000 |
| 103 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001 | 103 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001 |
| 104 static constexpr IValueT kInstTypeMemImmediate = 2; // i.e. 010 | 104 static constexpr IValueT kInstTypeMemImmediate = 2; // i.e. 010 |
| 105 static constexpr IValueT kInstTypeRegisterShift = 3; // i.e. 011 |
| 105 | 106 |
| 106 // Offset modifier to current PC for next instruction. The offset is off by 8 | 107 // Offset modifier to current PC for next instruction. The offset is off by 8 |
| 107 // due to the way the ARM CPUs read PC. | 108 // due to the way the ARM CPUs read PC. |
| 108 static constexpr IOffsetT kPCReadOffset = 8; | 109 static constexpr IOffsetT kPCReadOffset = 8; |
| 109 | 110 |
| 110 // Mask to pull out PC offset from branch (b) instruction. | 111 // Mask to pull out PC offset from branch (b) instruction. |
| 111 static constexpr int kBranchOffsetBits = 24; | 112 static constexpr int kBranchOffsetBits = 24; |
| 112 static constexpr IOffsetT kBranchOffsetMask = 0x00ffffff; | 113 static constexpr IOffsetT kBranchOffsetMask = 0x00ffffff; |
| 113 | 114 |
| 114 inline IValueT encodeBool(bool B) { return B ? 1 : 0; } | 115 inline IValueT encodeBool(bool B) { return B ? 1 : 0; } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 enum DecodedResult { | 181 enum DecodedResult { |
| 181 // Unable to decode, value left undefined. | 182 // Unable to decode, value left undefined. |
| 182 CantDecode = 0, | 183 CantDecode = 0, |
| 183 // Value is register found. | 184 // Value is register found. |
| 184 DecodedAsRegister, | 185 DecodedAsRegister, |
| 185 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 | 186 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 |
| 186 // value. | 187 // value. |
| 187 DecodedAsRotatedImm8, | 188 DecodedAsRotatedImm8, |
| 188 // i.e. 0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, | 189 // i.e. 0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, |
| 189 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to | 190 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to |
| 190 // Rn should be used, and iiiiiiiiiiii is the offset. | 191 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. |
| 191 DecodedAsImmRegOffset, | 192 DecodedAsImmRegOffset, |
| 193 // i.e. 0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, |
| 194 // mmmm is the index register Rm, iiiii is the shift amount, ss is the shift |
| 195 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if |
| 196 // writeback to Rn. |
| 197 DecodedAsShiftRotateImm5, |
| 192 // Value is 32bit integer constant. | 198 // Value is 32bit integer constant. |
| 193 DecodedAsConstI32 | 199 DecodedAsConstI32 |
| 194 }; | 200 }; |
| 195 | 201 |
| 196 // Sets Encoding to a rotated Imm8 encoding of Value, if possible. | 202 // Sets Encoding to a rotated Imm8 encoding of Value, if possible. |
| 197 inline IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) { | 203 inline IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) { |
| 198 assert(RotateAmt < (1 << kRotateBits)); | 204 assert(RotateAmt < (1 << kRotateBits)); |
| 199 assert(Immed8 < (1 << kImmed8Bits)); | 205 assert(Immed8 < (1 << kImmed8Bits)); |
| 200 return (RotateAmt << kRotateShift) | (Immed8 << kImmed8Shift); | 206 return (RotateAmt << kRotateShift) | (Immed8 << kImmed8Shift); |
| 201 } | 207 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 if (BaseRegNum == Variable::NoRegister) { | 262 if (BaseRegNum == Variable::NoRegister) { |
| 257 BaseRegNum = TInfo.FrameOrStackReg; | 263 BaseRegNum = TInfo.FrameOrStackReg; |
| 258 if (!TInfo.HasFramePointer) | 264 if (!TInfo.HasFramePointer) |
| 259 Offset += TInfo.StackAdjustment; | 265 Offset += TInfo.StackAdjustment; |
| 260 } | 266 } |
| 261 Value = decodeImmRegOffset(decodeGPRRegister(BaseRegNum), Offset, | 267 Value = decodeImmRegOffset(decodeGPRRegister(BaseRegNum), Offset, |
| 262 OperandARM32Mem::Offset); | 268 OperandARM32Mem::Offset); |
| 263 return DecodedAsImmRegOffset; | 269 return DecodedAsImmRegOffset; |
| 264 } | 270 } |
| 265 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { | 271 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { |
| 266 if (Mem->isRegReg()) | |
| 267 // TODO(kschimpf) Add this case. | |
| 268 return CantDecode; | |
| 269 Variable *Var = Mem->getBase(); | 272 Variable *Var = Mem->getBase(); |
| 270 if (!Var->hasReg()) | 273 if (!Var->hasReg()) |
| 271 return CantDecode; | 274 return CantDecode; |
| 275 IValueT Rn = Var->getRegNum(); |
| 276 if (Mem->isRegReg()) { |
| 277 const Variable *Index = Mem->getIndex(); |
| 278 if (Var == nullptr) |
| 279 return CantDecode; |
| 280 Value = (Rn << kRnShift) | Mem->getAddrMode() | |
| 281 encodeShiftRotateImm5(Index->getRegNum(), Mem->getShiftOp(), |
| 282 Mem->getShiftAmt()); |
| 283 return DecodedAsShiftRotateImm5; |
| 284 } |
| 285 // Decoded as immediate register offset. |
| 272 ConstantInteger32 *Offset = Mem->getOffset(); | 286 ConstantInteger32 *Offset = Mem->getOffset(); |
| 273 Value = decodeImmRegOffset(decodeGPRRegister(Var->getRegNum()), | 287 Value = decodeImmRegOffset(decodeGPRRegister(Rn), Offset->getValue(), |
| 274 Offset->getValue(), Mem->getAddrMode()); | 288 Mem->getAddrMode()); |
| 275 return DecodedAsImmRegOffset; | 289 return DecodedAsImmRegOffset; |
| 276 } | 290 } |
| 277 return CantDecode; | 291 return CantDecode; |
| 278 } | 292 } |
| 279 | 293 |
| 280 // Checks that Offset can fit in imm24 constant of branch (b) instruction. | 294 // Checks that Offset can fit in imm24 constant of branch (b) instruction. |
| 281 bool canEncodeBranchOffset(IOffsetT Offset) { | 295 bool canEncodeBranchOffset(IOffsetT Offset) { |
| 282 return Utils::IsAligned(Offset, 4) && | 296 return Utils::IsAligned(Offset, 4) && |
| 283 Utils::IsInt(kBranchOffsetBits, Offset >> 2); | 297 Utils::IsInt(kBranchOffsetBits, Offset >> 2); |
| 284 } | 298 } |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 // eor{s}<c> <Rd>, <Rn>, #RotatedImm8 | 730 // eor{s}<c> <Rd>, <Rn>, #RotatedImm8 |
| 717 // | 731 // |
| 718 // cccc0010001snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 732 // cccc0010001snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 719 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 733 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
| 720 constexpr IValueT Eor = B0; // 0001 | 734 constexpr IValueT Eor = B0; // 0001 |
| 721 emitType01(Eor, OpRd, OpRn, OpSrc1, SetFlags, Cond); | 735 emitType01(Eor, OpRd, OpRn, OpSrc1, SetFlags, Cond); |
| 722 } | 736 } |
| 723 | 737 |
| 724 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, | 738 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, |
| 725 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 739 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
| 740 constexpr bool IsLoad = true; |
| 726 IValueT Rt; | 741 IValueT Rt; |
| 727 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 742 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
| 728 return setNeedsTextFixup(); | 743 return setNeedsTextFixup(); |
| 729 IValueT Address; | |
| 730 if (decodeAddress(OpAddress, Address, TInfo) != DecodedAsImmRegOffset) | |
| 731 return setNeedsTextFixup(); | |
| 732 // LDR (immediate) - ARM section A8.8.63, encoding A1: | |
| 733 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | |
| 734 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | |
| 735 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | |
| 736 // | |
| 737 // LDRB (immediate) - ARM section A8.8.68, encoding A1: | |
| 738 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | |
| 739 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | |
| 740 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | |
| 741 // | |
| 742 // cccc010pubw1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | |
| 743 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. | |
| 744 constexpr bool IsLoad = true; | |
| 745 const Type Ty = OpRt->getType(); | 744 const Type Ty = OpRt->getType(); |
| 746 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | 745 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |
| 747 return setNeedsTextFixup(); | 746 return setNeedsTextFixup(); |
| 748 const bool IsByte = isByteSizedType(Ty); | 747 const bool IsByte = isByteSizedType(Ty); |
| 749 // Check conditions of rules violated. | 748 IValueT Address; |
| 750 if (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) | 749 switch (decodeAddress(OpAddress, Address, TInfo)) { |
| 750 default: |
| 751 return setNeedsTextFixup(); | 751 return setNeedsTextFixup(); |
| 752 if (!isBitSet(P, Address) && isBitSet(W, Address)) | 752 case DecodedAsImmRegOffset: { |
| 753 return setNeedsTextFixup(); | 753 // LDR (immediate) - ARM section A8.8.63, encoding A1: |
| 754 if (!IsByte && (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | 754 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 755 !isBitSet(P, Address) && isBitSet(U, Address) & !isBitSet(W, Address) && | 755 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 756 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) | 756 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 757 return setNeedsTextFixup(); | 757 // |
| 758 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); | 758 // LDRB (immediate) - ARM section A8.8.68, encoding A1: |
| 759 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 760 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 761 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 762 // |
| 763 // cccc010pubw1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 764 // iiiiiiiiiiii=imm12, b=1 if LDRB, u=1 if +, pu0w is a BlockAddr, and |
| 765 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
| 766 |
| 767 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); |
| 768 |
| 769 // Check if conditions of rules violated. |
| 770 if (Rn == RegARM32::Encoded_Reg_pc) |
| 771 return setNeedsTextFixup(); |
| 772 if (!isBitSet(P, Address) && isBitSet(W, Address)) |
| 773 return setNeedsTextFixup(); |
| 774 if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) && |
| 775 isBitSet(U, Address) & !isBitSet(W, Address) && |
| 776 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) |
| 777 return setNeedsTextFixup(); |
| 778 |
| 779 return emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); |
| 780 } |
| 781 case DecodedAsShiftRotateImm5: { |
| 782 // LDR (register) - ARM section A8.8.66, encoding A1: |
| 783 // ldr<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
| 784 // ldr<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} |
| 785 // |
| 786 // LDRB (register) - ARM section A8.8.70, encoding A1: |
| 787 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
| 788 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>} |
| 789 // |
| 790 // cccc011pubw1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, |
| 791 // b=1 if LDRB, U=1 if +, pu0b is a BlockAddr, and |
| 792 // pu0w0nnnn0000iiiiiss0mmmm=Address. |
| 793 |
| 794 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); |
| 795 RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address); |
| 796 |
| 797 // Check if conditions of rules violated. |
| 798 if (isBitSet(P, Address) && isBitSet(W, Address)) |
| 799 // Instruction LDRBT! |
| 800 return setNeedsTextFixup(); |
| 801 if (IsByte && |
| 802 ((Rt == RegARM32::Encoded_Reg_pc) || (Rm == RegARM32::Encoded_Reg_pc))) |
| 803 // Unpredictable. |
| 804 return setNeedsTextFixup(); |
| 805 if (!IsByte && Rm == RegARM32::Encoded_Reg_pc) |
| 806 // Unpredictable. |
| 807 return setNeedsTextFixup(); |
| 808 if (isBitSet(W, Address) && |
| 809 ((Rn == RegARM32::Encoded_Reg_pc) || encodeGPRRegister(Rn) == Rt)) |
| 810 // Unpredictable |
| 811 return setNeedsTextFixup(); |
| 812 |
| 813 return emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address); |
| 814 } |
| 815 } |
| 759 } | 816 } |
| 760 | 817 |
| 761 void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, | 818 void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |
| 762 CondARM32::Cond Cond) { | 819 CondARM32::Cond Cond) { |
| 763 // MOV (register) - ARM section A8.8.104, encoding A1: | 820 // MOV (register) - ARM section A8.8.104, encoding A1: |
| 764 // mov{S}<c> <Rd>, <Rn> | 821 // mov{S}<c> <Rd>, <Rn> |
| 765 // | 822 // |
| 766 // cccc0001101s0000dddd00000000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, | 823 // cccc0001101s0000dddd00000000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, |
| 767 // and nnnn=Rn. | 824 // and nnnn=Rn. |
| 768 // | 825 // |
| (...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1185 // rr defined (RotationValue) rotate. | 1242 // rr defined (RotationValue) rotate. |
| 1186 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21 | B20; | 1243 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21 | B20; |
| 1187 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); | 1244 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); |
| 1188 return; | 1245 return; |
| 1189 } | 1246 } |
| 1190 } | 1247 } |
| 1191 } | 1248 } |
| 1192 | 1249 |
| 1193 } // end of namespace ARM32 | 1250 } // end of namespace ARM32 |
| 1194 } // end of namespace Ice | 1251 } // end of namespace Ice |
| OLD | NEW |