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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 // Shift instruction register fields encodings. | 93 // Shift instruction register fields encodings. |
94 static constexpr IValueT kShiftImmShift = 7; | 94 static constexpr IValueT kShiftImmShift = 7; |
95 static constexpr IValueT kShiftImmBits = 5; | 95 static constexpr IValueT kShiftImmBits = 5; |
96 static constexpr IValueT kShiftShift = 5; | 96 static constexpr IValueT kShiftShift = 5; |
97 static constexpr IValueT kImmed12Bits = 12; | 97 static constexpr IValueT kImmed12Bits = 12; |
98 static constexpr IValueT kImm12Shift = 0; | 98 static constexpr IValueT kImm12Shift = 0; |
99 | 99 |
100 // Rotation instructions (uxtb etc.). | 100 // Rotation instructions (uxtb etc.). |
101 static constexpr IValueT kRotationShift = 10; | 101 static constexpr IValueT kRotationShift = 10; |
102 | 102 |
| 103 // MemEx instructions. |
| 104 static constexpr IValueT kMemExOpcodeShift = 20; |
| 105 |
103 // Div instruction register field encodings. | 106 // Div instruction register field encodings. |
104 static constexpr IValueT kDivRdShift = 16; | 107 static constexpr IValueT kDivRdShift = 16; |
105 static constexpr IValueT kDivRmShift = 8; | 108 static constexpr IValueT kDivRmShift = 8; |
106 static constexpr IValueT kDivRnShift = 0; | 109 static constexpr IValueT kDivRnShift = 0; |
107 | 110 |
108 // Type of instruction encoding (bits 25-27). See ARM section A5.1 | 111 // Type of instruction encoding (bits 25-27). See ARM section A5.1 |
109 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000 | 112 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000 |
110 static constexpr IValueT kInstTypeDataRegShift = 0; // i.e. 000 | 113 static constexpr IValueT kInstTypeDataRegShift = 0; // i.e. 000 |
111 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001 | 114 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001 |
112 static constexpr IValueT kInstTypeMemImmediate = 2; // i.e. 010 | 115 static constexpr IValueT kInstTypeMemImmediate = 2; // i.e. 010 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 } | 173 } |
171 | 174 |
172 // Extract out a Bit in Value. | 175 // Extract out a Bit in Value. |
173 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; } | 176 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; } |
174 | 177 |
175 // Returns the GPR register at given Shift in Value. | 178 // Returns the GPR register at given Shift in Value. |
176 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { | 179 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { |
177 return decodeGPRRegister((Value >> Shift) & 0xF); | 180 return decodeGPRRegister((Value >> Shift) & 0xF); |
178 } | 181 } |
179 | 182 |
| 183 // Defines alternate layouts of instruction operands, should the (common) |
| 184 // default pattern not be used. |
| 185 enum OpEncoding { |
| 186 // No alternate layout specified. |
| 187 DefaultOpEncoding, |
| 188 // Alternate encoding 3 for memory operands (like in strb, strh, ldrb, and |
| 189 // ldrh. |
| 190 OpEncoding3, |
| 191 // Alternate encoding for memory operands for ldrex and strex, which only |
| 192 // actually expect a register. |
| 193 OpEncodingMemEx |
| 194 }; |
| 195 |
| 196 IValueT getEncodedGPRegNum(const Variable *Var) { |
| 197 int32_t Reg = Var->getRegNum(); |
| 198 return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg) |
| 199 : RegARM32::getEncodedGPR(Reg); |
| 200 } |
| 201 |
180 // The way an operand is encoded into a sequence of bits in functions | 202 // The way an operand is encoded into a sequence of bits in functions |
181 // encodeOperand and encodeAddress below. | 203 // encodeOperand and encodeAddress below. |
182 enum EncodedOperand { | 204 enum EncodedOperand { |
183 // Unable to encode, value left undefined. | 205 // Unable to encode, value left undefined. |
184 CantEncode = 0, | 206 CantEncode = 0, |
185 // Value is register found. | 207 // Value is register found. |
186 EncodedAsRegister, | 208 EncodedAsRegister, |
187 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 | 209 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 |
188 // value. | 210 // value. |
189 EncodedAsRotatedImm8, | 211 EncodedAsRotatedImm8, |
| 212 // EncodedAsImmRegOffset is a memory operand that can take three forms, based |
| 213 // on OpEncoding: |
| 214 // |
| 215 // ***** DefaultOpEncoding ***** |
| 216 // |
190 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, | 217 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, |
191 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to | 218 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to |
192 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. | 219 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. |
193 EncodedAsImmRegOffset, | 220 // |
| 221 // ***** OpEncoding3 ***** |
| 222 // |
194 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 | 223 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 |
195 // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to | 224 // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to |
196 // Rn. | 225 // Rn. |
197 EncodedAsImmRegOffsetEnc3, | 226 // |
| 227 // ***** OpEncodingMemEx ***** |
| 228 // |
| 229 // Value=000000000000nnnn0000000000000000 where nnnn=Rn. |
| 230 EncodedAsImmRegOffset, |
198 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, | 231 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, |
199 // mmmm is the index register Rm, iiiii is the shift amount, ss is the shift | 232 // mmmm is the index register Rm, iiiii is the shift amount, ss is the shift |
200 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if | 233 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if |
201 // writeback to Rn. | 234 // writeback to Rn. |
202 EncodedAsShiftRotateImm5, | 235 EncodedAsShiftRotateImm5, |
203 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value | 236 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value |
204 // to shift. | 237 // to shift. |
205 EncodedAsShiftImm5, | 238 EncodedAsShiftImm5, |
206 // Value=iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift | 239 // Value=iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift |
207 // kind, and iiiii is the shift amount. | 240 // kind, and iiiii is the shift amount. |
(...skipping 25 matching lines...) Expand all Loading... |
233 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, | 266 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, |
234 IValueT Rs) { | 267 IValueT Rs) { |
235 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | | 268 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | |
236 (Rm << kRmShift); | 269 (Rm << kRmShift); |
237 } | 270 } |
238 | 271 |
239 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value) { | 272 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value) { |
240 Value = 0; // Make sure initialized. | 273 Value = 0; // Make sure initialized. |
241 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 274 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
242 if (Var->hasReg()) { | 275 if (Var->hasReg()) { |
243 Value = Var->getRegNum(); | 276 Value = getEncodedGPRegNum(Var); |
244 return EncodedAsRegister; | 277 return EncodedAsRegister; |
245 } | 278 } |
246 return CantEncode; | 279 return CantEncode; |
247 } | 280 } |
248 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { | 281 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { |
249 const IValueT Immed8 = FlexImm->getImm(); | 282 const IValueT Immed8 = FlexImm->getImm(); |
250 const IValueT Rotate = FlexImm->getRotateAmt(); | 283 const IValueT Rotate = FlexImm->getRotateAmt(); |
251 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) | 284 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) |
252 return CantEncode; | 285 return CantEncode; |
253 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); | 286 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 IValueT Value = Mode | (Rn << kRnShift); | 342 IValueT Value = Mode | (Rn << kRnShift); |
310 if (Imm8 < 0) { | 343 if (Imm8 < 0) { |
311 Imm8 = -Imm8; | 344 Imm8 = -Imm8; |
312 Value = (Value ^ U); | 345 Value = (Value ^ U); |
313 } | 346 } |
314 assert(Imm8 < (1 << 8)); | 347 assert(Imm8 < (1 << 8)); |
315 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); | 348 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); |
316 return Value; | 349 return Value; |
317 } | 350 } |
318 | 351 |
319 // Defines alternate layouts of instruction operands, should the (common) | 352 IValueT encodeImmRegOffset(OpEncoding AddressEncoding, IValueT Reg, |
320 // default pattern not be used. | 353 IOffsetT Offset, OperandARM32Mem::AddrMode Mode) { |
321 enum OpEncoding { | 354 switch (AddressEncoding) { |
322 // No alternate layout specified. | 355 case DefaultOpEncoding: |
323 DefaultOpEncoding, | 356 return encodeImmRegOffset(Reg, Offset, Mode); |
324 // Alternate encoding 3. | 357 case OpEncoding3: |
325 OpEncoding3 | 358 return encodeImmRegOffsetEnc3(Reg, Offset, Mode); |
326 }; | 359 case OpEncodingMemEx: |
| 360 assert(Offset == 0); |
| 361 assert(Mode == OperandARM32Mem::Offset); |
| 362 return Reg << kRnShift; |
| 363 } |
| 364 } |
327 | 365 |
328 // Encodes memory address Opnd, and encodes that information into Value, based | 366 // Encodes memory address Opnd, and encodes that information into Value, based |
329 // on how ARM represents the address. Returns how the value was encoded. | 367 // on how ARM represents the address. Returns how the value was encoded. |
330 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, | 368 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, |
331 const AssemblerARM32::TargetInfo &TInfo, | 369 const AssemblerARM32::TargetInfo &TInfo, |
332 OpEncoding AddressEncoding = DefaultOpEncoding) { | 370 OpEncoding AddressEncoding = DefaultOpEncoding) { |
333 Value = 0; // Make sure initialized. | 371 Value = 0; // Make sure initialized. |
334 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 372 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
335 // Should be a stack variable, with an offset. | 373 // Should be a stack variable, with an offset. |
336 if (Var->hasReg()) | 374 if (Var->hasReg()) |
337 return CantEncode; | 375 return CantEncode; |
338 IOffsetT Offset = Var->getStackOffset(); | 376 IOffsetT Offset = Var->getStackOffset(); |
339 if (!Utils::IsAbsoluteUint(12, Offset)) | 377 if (!Utils::IsAbsoluteUint(12, Offset)) |
340 return CantEncode; | 378 return CantEncode; |
341 int32_t BaseRegNum = Var->getBaseRegNum(); | 379 int32_t BaseRegNum = Var->getBaseRegNum(); |
342 if (BaseRegNum == Variable::NoRegister) | 380 if (BaseRegNum == Variable::NoRegister) |
343 BaseRegNum = TInfo.FrameOrStackReg; | 381 BaseRegNum = TInfo.FrameOrStackReg; |
344 Value = encodeImmRegOffset(BaseRegNum, Offset, OperandARM32Mem::Offset); | 382 Value = encodeImmRegOffset(AddressEncoding, BaseRegNum, Offset, |
| 383 OperandARM32Mem::Offset); |
345 return EncodedAsImmRegOffset; | 384 return EncodedAsImmRegOffset; |
346 } | 385 } |
347 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { | 386 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { |
348 Variable *Var = Mem->getBase(); | 387 Variable *Var = Mem->getBase(); |
349 if (!Var->hasReg()) | 388 if (!Var->hasReg()) |
350 return CantEncode; | 389 return CantEncode; |
351 IValueT Rn = Var->getRegNum(); | 390 IValueT Rn = getEncodedGPRegNum(Var); |
352 if (Mem->isRegReg()) { | 391 if (Mem->isRegReg()) { |
353 const Variable *Index = Mem->getIndex(); | 392 const Variable *Index = Mem->getIndex(); |
354 if (Var == nullptr) | 393 if (Var == nullptr) |
355 return CantEncode; | 394 return CantEncode; |
356 Value = (Rn << kRnShift) | Mem->getAddrMode() | | 395 Value = (Rn << kRnShift) | Mem->getAddrMode() | |
357 encodeShiftRotateImm5(Index->getRegNum(), Mem->getShiftOp(), | 396 encodeShiftRotateImm5(getEncodedGPRegNum(Index), |
358 Mem->getShiftAmt()); | 397 Mem->getShiftOp(), Mem->getShiftAmt()); |
359 return EncodedAsShiftRotateImm5; | 398 return EncodedAsShiftRotateImm5; |
360 } | 399 } |
361 // Encoded as immediate register offset. | 400 // Encoded as immediate register offset. |
362 ConstantInteger32 *Offset = Mem->getOffset(); | 401 ConstantInteger32 *Offset = Mem->getOffset(); |
363 switch (AddressEncoding) { | 402 Value = encodeImmRegOffset(AddressEncoding, Rn, Offset->getValue(), |
364 case DefaultOpEncoding: | 403 Mem->getAddrMode()); |
365 Value = encodeImmRegOffset(Rn, Offset->getValue(), Mem->getAddrMode()); | 404 return EncodedAsImmRegOffset; |
366 return EncodedAsImmRegOffset; | |
367 case OpEncoding3: | |
368 Value = | |
369 encodeImmRegOffsetEnc3(Rn, Offset->getValue(), Mem->getAddrMode()); | |
370 return EncodedAsImmRegOffsetEnc3; | |
371 } | |
372 } | 405 } |
373 return CantEncode; | 406 return CantEncode; |
374 } | 407 } |
375 | 408 |
376 // Checks that Offset can fit in imm24 constant of branch (b) instruction. | 409 // Checks that Offset can fit in imm24 constant of branch (b) instruction. |
377 bool canEncodeBranchOffset(IOffsetT Offset) { | 410 bool canEncodeBranchOffset(IOffsetT Offset) { |
378 return Utils::IsAligned(Offset, 4) && | 411 return Utils::IsAligned(Offset, 4) && |
379 Utils::IsInt(kBranchOffsetBits, Offset >> 2); | 412 Utils::IsInt(kBranchOffsetBits, Offset >> 2); |
380 } | 413 } |
381 | 414 |
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 | 825 |
793 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, | 826 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, |
794 IValueT Rt, const Operand *OpAddress, | 827 IValueT Rt, const Operand *OpAddress, |
795 const TargetInfo &TInfo, | 828 const TargetInfo &TInfo, |
796 const char *InstName) { | 829 const char *InstName) { |
797 IValueT Address; | 830 IValueT Address; |
798 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { | 831 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { |
799 default: | 832 default: |
800 llvm::report_fatal_error(std::string(InstName) + | 833 llvm::report_fatal_error(std::string(InstName) + |
801 ": Memory address not understood"); | 834 ": Memory address not understood"); |
802 case EncodedAsImmRegOffsetEnc3: { | 835 case EncodedAsImmRegOffset: { |
803 // XXXH (immediate) | 836 // XXXH (immediate) |
804 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] | 837 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] |
805 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] | 838 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] |
806 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | 839 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
807 // | 840 // |
808 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, | 841 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, |
809 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, | 842 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, |
810 // and pu0w0nnnn0000iiii0000jjjj=Address. | 843 // and pu0w0nnnn0000iiii0000jjjj=Address. |
811 verifyRegDefined(Rt, "Rt", InstName); | 844 verifyRegDefined(Rt, "Rt", InstName); |
812 verifyCondDefined(Cond, InstName); | 845 verifyCondDefined(Cond, InstName); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
899 } | 932 } |
900 | 933 |
901 void AssemblerARM32::emitSignExtend(CondARM32::Cond Cond, IValueT Opcode, | 934 void AssemblerARM32::emitSignExtend(CondARM32::Cond Cond, IValueT Opcode, |
902 const Operand *OpRd, const Operand *OpSrc0, | 935 const Operand *OpRd, const Operand *OpSrc0, |
903 const char *InstName) { | 936 const char *InstName) { |
904 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); | 937 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); |
905 IValueT Rm = encodeRegister(OpSrc0, "Rm", InstName); | 938 IValueT Rm = encodeRegister(OpSrc0, "Rm", InstName); |
906 // Note: For the moment, we assume no rotation is specified. | 939 // Note: For the moment, we assume no rotation is specified. |
907 RotationValue Rotation = kRotateNone; | 940 RotationValue Rotation = kRotateNone; |
908 constexpr IValueT Rn = RegARM32::Encoded_Reg_pc; | 941 constexpr IValueT Rn = RegARM32::Encoded_Reg_pc; |
909 switch (typeWidthInBytes(OpSrc0->getType())) { | 942 const Type Ty = OpSrc0->getType(); |
| 943 switch (Ty) { |
910 default: | 944 default: |
911 llvm::report_fatal_error(std::string(InstName) + | 945 llvm::report_fatal_error(std::string(InstName) + ": Type " + |
912 ": Type of Rm not understood"); | 946 typeString(Ty) + " not allowed"); |
913 break; | 947 break; |
914 case 1: { | 948 case IceType_i1: |
| 949 case IceType_i8: { |
915 // SXTB/UXTB - Arm sections A8.8.233 and A8.8.274, encoding A1: | 950 // SXTB/UXTB - Arm sections A8.8.233 and A8.8.274, encoding A1: |
916 // sxtb<c> <Rd>, <Rm>{, <rotate>} | 951 // sxtb<c> <Rd>, <Rm>{, <rotate>} |
917 // uxtb<c> <Rd>, <Rm>{, <rotate>} | 952 // uxtb<c> <Rd>, <Rm>{, <rotate>} |
918 // | 953 // |
919 // ccccxxxxxxxx1111ddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode, | 954 // ccccxxxxxxxx1111ddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode, |
920 // dddd=Rd, mmmm=Rm, and rr defined (RotationValue) rotate. | 955 // dddd=Rd, mmmm=Rm, and rr defined (RotationValue) rotate. |
921 break; | 956 break; |
922 } | 957 } |
923 case 2: { | 958 case IceType_i16: { |
924 // SXTH/UXTH - ARM sections A8.8.235 and A8.8.276, encoding A1: | 959 // SXTH/UXTH - ARM sections A8.8.235 and A8.8.276, encoding A1: |
925 // uxth<c> <Rd>< <Rm>{, <rotate>} | 960 // uxth<c> <Rd>< <Rm>{, <rotate>} |
926 // | 961 // |
927 // cccc01101111nnnnddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and | 962 // cccc01101111nnnnddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and |
928 // rr defined (RotationValue) rotate. | 963 // rr defined (RotationValue) rotate. |
929 Opcode |= B20; | 964 Opcode |= B20; |
930 break; | 965 break; |
931 } | 966 } |
932 } | 967 } |
933 | 968 |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1156 emitType01(Cond, EorOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, | 1191 emitType01(Cond, EorOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, |
1157 EorName); | 1192 EorName); |
1158 } | 1193 } |
1159 | 1194 |
1160 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, | 1195 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, |
1161 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 1196 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
1162 constexpr const char *LdrName = "ldr"; | 1197 constexpr const char *LdrName = "ldr"; |
1163 constexpr bool IsLoad = true; | 1198 constexpr bool IsLoad = true; |
1164 IValueT Rt = encodeRegister(OpRt, "Rt", LdrName); | 1199 IValueT Rt = encodeRegister(OpRt, "Rt", LdrName); |
1165 const Type Ty = OpRt->getType(); | 1200 const Type Ty = OpRt->getType(); |
1166 switch (typeWidthInBytesLog2(Ty)) { | 1201 switch (Ty) { |
1167 case 3: | 1202 case IceType_i64: |
1168 // LDRD is not implemented because target lowering handles i64 and double by | 1203 // LDRD is not implemented because target lowering handles i64 and double by |
1169 // using two (32-bit) load instructions. Note: Intenionally drop to default | 1204 // using two (32-bit) load instructions. Note: Intentionally drop to default |
1170 // case. | 1205 // case. |
| 1206 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) + |
| 1207 " not implemented"); |
1171 default: | 1208 default: |
1172 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) + | 1209 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) + |
1173 " not implementable\n"); | 1210 " not allowed"); |
1174 case 0: { | 1211 case IceType_i1: |
1175 // Handles i1 and i8 loads. | 1212 case IceType_i8: { |
1176 // | |
1177 // LDRB (immediate) - ARM section A8.8.68, encoding A1: | 1213 // LDRB (immediate) - ARM section A8.8.68, encoding A1: |
1178 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1214 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
1179 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1215 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
1180 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1216 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
1181 // | 1217 // |
1182 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1218 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
1183 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and | 1219 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and |
1184 // pu0w0nnnn0000iiiiiiiiiiii=Address. | 1220 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
1185 // | 1221 // |
1186 // LDRB (register) - ARM section A8.8.66, encoding A1: | 1222 // LDRB (register) - ARM section A8.8.66, encoding A1: |
1187 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | 1223 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
1188 // ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} | 1224 // ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} |
1189 // | 1225 // |
1190 // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b | 1226 // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b |
1191 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. | 1227 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. |
1192 constexpr bool IsByte = true; | 1228 constexpr bool IsByte = true; |
1193 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); | 1229 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); |
1194 return; | 1230 return; |
1195 } | 1231 } |
1196 case 1: { | 1232 case IceType_i16: { |
1197 // Handles i16 loads. | |
1198 // | |
1199 // LDRH (immediate) - ARM section A8.8.80, encoding A1: | 1233 // LDRH (immediate) - ARM section A8.8.80, encoding A1: |
1200 // ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] | 1234 // ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] |
1201 // ldrh<c> <Rt>, [<Rn>], #+/-<Imm8> | 1235 // ldrh<c> <Rt>, [<Rn>], #+/-<Imm8> |
1202 // ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | 1236 // ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
1203 // | 1237 // |
1204 // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1238 // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
1205 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and | 1239 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and |
1206 // pu0w0nnnn0000iiiiiiiiiiii=Address. | 1240 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
1207 constexpr const char *Ldrh = "ldrh"; | 1241 constexpr const char *Ldrh = "ldrh"; |
1208 emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo, Ldrh); | 1242 emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo, Ldrh); |
1209 return; | 1243 return; |
1210 } | 1244 } |
1211 case 2: { | 1245 case IceType_i32: { |
1212 // Note: Handles i32 and float loads. Target lowering handles i64 and | |
1213 // double by using two (32 bit) load instructions. | |
1214 // | |
1215 // LDR (immediate) - ARM section A8.8.63, encoding A1: | 1246 // LDR (immediate) - ARM section A8.8.63, encoding A1: |
1216 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1247 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
1217 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1248 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
1218 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1249 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
1219 // | 1250 // |
1220 // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1251 // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
1221 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and | 1252 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and |
1222 // | 1253 // |
1223 // LDR (register) - ARM section A8.8.70, encoding A1: | 1254 // LDR (register) - ARM section A8.8.70, encoding A1: |
1224 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | 1255 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
1225 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>} | 1256 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>} |
1226 // | 1257 // |
1227 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b | 1258 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b |
1228 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. | 1259 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. |
1229 constexpr bool IsByte = false; | 1260 constexpr bool IsByte = false; |
1230 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); | 1261 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); |
1231 return; | 1262 return; |
1232 } | 1263 } |
1233 } | 1264 } |
1234 } | 1265 } |
1235 | 1266 |
| 1267 void AssemblerARM32::emitMemExOp(CondARM32::Cond Cond, Type Ty, bool IsLoad, |
| 1268 const Operand *OpRd, IValueT Rt, |
| 1269 const Operand *OpAddress, |
| 1270 const TargetInfo &TInfo, |
| 1271 const char *InstName) { |
| 1272 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); |
| 1273 IValueT MemExOpcode = IsLoad ? B0 : 0; |
| 1274 switch (Ty) { |
| 1275 default: |
| 1276 llvm::report_fatal_error(std::string(InstName) + ": Type " + |
| 1277 typeString(Ty) + " not allowed"); |
| 1278 case IceType_i1: |
| 1279 case IceType_i8: |
| 1280 MemExOpcode |= B2; |
| 1281 break; |
| 1282 case IceType_i16: |
| 1283 MemExOpcode |= B2 | B1; |
| 1284 break; |
| 1285 case IceType_i32: |
| 1286 break; |
| 1287 case IceType_i64: |
| 1288 MemExOpcode |= B1; |
| 1289 } |
| 1290 IValueT AddressRn; |
| 1291 if (encodeAddress(OpAddress, AddressRn, TInfo, OpEncodingMemEx) != |
| 1292 EncodedAsImmRegOffset) |
| 1293 llvm::report_fatal_error(std::string(InstName) + |
| 1294 ": Can't extract Rn from address"); |
| 1295 assert(Utils::IsAbsoluteUint(3, MemExOpcode)); |
| 1296 verifyRegDefined(Rd, "Rd", InstName); |
| 1297 verifyRegDefined(Rt, "Rt", InstName); |
| 1298 verifyCondDefined(Cond, InstName); |
| 1299 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 1300 IValueT Encoding = (Cond << kConditionShift) | B24 | B23 | B11 | B10 | B9 | |
| 1301 B8 | B7 | B4 | (MemExOpcode << kMemExOpcodeShift) | |
| 1302 AddressRn | (Rd << kRdShift) | (Rt << kRmShift); |
| 1303 emitInst(Encoding); |
| 1304 return; |
| 1305 } |
| 1306 |
| 1307 void AssemblerARM32::ldrex(const Operand *OpRt, const Operand *OpAddress, |
| 1308 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
| 1309 // LDREXB - ARM section A8.8.76, encoding A1: |
| 1310 // ldrexb<c> <Rt>, [<Rn>] |
| 1311 // |
| 1312 // cccc00011101nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. |
| 1313 // |
| 1314 // LDREXH - ARM section A8.8.78, encoding A1: |
| 1315 // ldrexh<c> <Rt>, [<Rn>] |
| 1316 // |
| 1317 // cccc00011111nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. |
| 1318 // |
| 1319 // LDREX - ARM section A8.8.75, encoding A1: |
| 1320 // ldrex<c> <Rt>, [<Rn>] |
| 1321 // |
| 1322 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. |
| 1323 // |
| 1324 // LDREXD - ARM section A8. |
| 1325 // ldrexd<c> <Rt>, [<Rn>] |
| 1326 // |
| 1327 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. |
| 1328 constexpr const char *LdrexName = "ldrex"; |
| 1329 const Type Ty = OpRt->getType(); |
| 1330 constexpr bool IsLoad = true; |
| 1331 constexpr IValueT Rm = RegARM32::Encoded_Reg_pc; |
| 1332 emitMemExOp(Cond, Ty, IsLoad, OpRt, Rm, OpAddress, TInfo, LdrexName); |
| 1333 } |
| 1334 |
1236 void AssemblerARM32::emitShift(const CondARM32::Cond Cond, | 1335 void AssemblerARM32::emitShift(const CondARM32::Cond Cond, |
1237 const OperandARM32::ShiftKind Shift, | 1336 const OperandARM32::ShiftKind Shift, |
1238 const Operand *OpRd, const Operand *OpRm, | 1337 const Operand *OpRd, const Operand *OpRm, |
1239 const Operand *OpSrc1, const bool SetFlags, | 1338 const Operand *OpSrc1, const bool SetFlags, |
1240 const char *InstName) { | 1339 const char *InstName) { |
1241 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101 | 1340 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101 |
1242 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); | 1341 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); |
1243 IValueT Rm = encodeRegister(OpRm, "Rm", InstName); | 1342 IValueT Rm = encodeRegister(OpRm, "Rm", InstName); |
1244 IValueT Value; | 1343 IValueT Value; |
1245 switch (encodeOperand(OpSrc1, Value)) { | 1344 switch (encodeOperand(OpSrc1, Value)) { |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1440 constexpr IValueT SdivOpcode = 0; | 1539 constexpr IValueT SdivOpcode = 0; |
1441 emitDivOp(Cond, SdivOpcode, Rd, Rn, Rm, SdivName); | 1540 emitDivOp(Cond, SdivOpcode, Rd, Rn, Rm, SdivName); |
1442 } | 1541 } |
1443 | 1542 |
1444 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, | 1543 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
1445 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 1544 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
1446 constexpr const char *StrName = "str"; | 1545 constexpr const char *StrName = "str"; |
1447 constexpr bool IsLoad = false; | 1546 constexpr bool IsLoad = false; |
1448 IValueT Rt = encodeRegister(OpRt, "Rt", StrName); | 1547 IValueT Rt = encodeRegister(OpRt, "Rt", StrName); |
1449 const Type Ty = OpRt->getType(); | 1548 const Type Ty = OpRt->getType(); |
1450 switch (typeWidthInBytesLog2(Ty)) { | 1549 switch (Ty) { |
1451 case 3: | 1550 case IceType_i64: |
1452 // STRD is not implemented because target lowering handles i64 and double by | 1551 // STRD is not implemented because target lowering handles i64 and double by |
1453 // using two (32-bit) store instructions. Note: Intenionally drop to | 1552 // using two (32-bit) store instructions. Note: Intentionally drop to |
1454 // default case. | 1553 // default case. |
| 1554 llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) + |
| 1555 " not implemented"); |
1455 default: | 1556 default: |
1456 llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) + | 1557 llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) + |
1457 " not implemented"); | 1558 " not allowed"); |
1458 case 0: { | 1559 case IceType_i1: |
1459 // Handles i1 and i8 stores. | 1560 case IceType_i8: { |
1460 // | |
1461 // STRB (immediate) - ARM section A8.8.207, encoding A1: | 1561 // STRB (immediate) - ARM section A8.8.207, encoding A1: |
1462 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1562 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
1463 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1563 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
1464 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1564 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
1465 // | 1565 // |
1466 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1566 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
1467 // iiiiiiiiiiii=imm12, u=1 if +. | 1567 // iiiiiiiiiiii=imm12, u=1 if +. |
1468 constexpr bool IsByte = true; | 1568 constexpr bool IsByte = true; |
1469 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); | 1569 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); |
1470 return; | 1570 return; |
1471 } | 1571 } |
1472 case 1: { | 1572 case IceType_i16: { |
1473 // Handles i16 stores. | |
1474 // | |
1475 // STRH (immediate) - ARM section A8.*.217, encoding A1: | 1573 // STRH (immediate) - ARM section A8.*.217, encoding A1: |
1476 // strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] | 1574 // strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] |
1477 // strh<c> <Rt>, [<Rn>], #+/-<Imm8> | 1575 // strh<c> <Rt>, [<Rn>], #+/-<Imm8> |
1478 // strh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | 1576 // strh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
1479 // | 1577 // |
1480 // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1578 // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
1481 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and | 1579 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and |
1482 // pu0w0nnnn0000iiiiiiiiiiii=Address. | 1580 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
1483 constexpr const char *Strh = "strh"; | 1581 constexpr const char *Strh = "strh"; |
1484 emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo, Strh); | 1582 emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo, Strh); |
1485 return; | 1583 return; |
1486 } | 1584 } |
1487 case 2: { | 1585 case IceType_i32: { |
1488 // Note: Handles i32 and float stores. Target lowering handles i64 and | 1586 // Note: Handles i32 and float stores. Target lowering handles i64 and |
1489 // double by using two (32 bit) store instructions. | 1587 // double by using two (32 bit) store instructions. |
1490 // | 1588 // |
1491 // STR (immediate) - ARM section A8.8.207, encoding A1: | 1589 // STR (immediate) - ARM section A8.8.207, encoding A1: |
1492 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1590 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
1493 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1591 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
1494 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1592 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
1495 // | 1593 // |
1496 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1594 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
1497 // iiiiiiiiiiii=imm12, u=1 if +. | 1595 // iiiiiiiiiiii=imm12, u=1 if +. |
1498 constexpr bool IsByte = false; | 1596 constexpr bool IsByte = false; |
1499 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); | 1597 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); |
1500 return; | 1598 return; |
1501 } | 1599 } |
1502 } | 1600 } |
1503 } | 1601 } |
1504 | 1602 |
| 1603 void AssemblerARM32::strex(const Operand *OpRd, const Operand *OpRt, |
| 1604 const Operand *OpAddress, CondARM32::Cond Cond, |
| 1605 const TargetInfo &TInfo) { |
| 1606 // STREXB - ARM section A8.8.213, encoding A1: |
| 1607 // strexb<c> <Rd>, <Rt>, [<Rn>] |
| 1608 // |
| 1609 // cccc00011100nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and |
| 1610 // nnnn=Rn. |
| 1611 // |
| 1612 // STREXH - ARM section A8.8.215, encoding A1: |
| 1613 // strexh<c> <Rd>, <Rt>, [<Rn>] |
| 1614 // |
| 1615 // cccc00011110nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and |
| 1616 // nnnn=Rn. |
| 1617 // |
| 1618 // STREX - ARM section A8.8.212, encoding A1: |
| 1619 // strex<c> <Rd>, <Rt>, [<Rn>] |
| 1620 // |
| 1621 // cccc00011000nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and |
| 1622 // nnnn=Rn. |
| 1623 // |
| 1624 // STREXD - ARM section A8.8.214, encoding A1: |
| 1625 // strexd<c> <Rd>, <Rt>, [<Rn>] |
| 1626 // |
| 1627 // cccc00011010nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and |
| 1628 // nnnn=Rn. |
| 1629 constexpr const char *StrexName = "strex"; |
| 1630 // Note: Rt uses Rm shift in encoding. |
| 1631 IValueT Rt = encodeRegister(OpRt, "Rt", StrexName); |
| 1632 const Type Ty = OpRt->getType(); |
| 1633 constexpr bool IsLoad = true; |
| 1634 emitMemExOp(Cond, Ty, !IsLoad, OpRd, Rt, OpAddress, TInfo, StrexName); |
| 1635 } |
| 1636 |
1505 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, | 1637 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, |
1506 const Operand *OpSrc1, bool SetFlags, | 1638 const Operand *OpSrc1, bool SetFlags, |
1507 CondARM32::Cond Cond) { | 1639 CondARM32::Cond Cond) { |
1508 // ORR (register) - ARM Section A8.8.123, encoding A1: | 1640 // ORR (register) - ARM Section A8.8.123, encoding A1: |
1509 // orr{s}<c> <Rd>, <Rn>, <Rm> | 1641 // orr{s}<c> <Rd>, <Rn>, <Rm> |
1510 // | 1642 // |
1511 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 1643 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
1512 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. | 1644 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. |
1513 // | 1645 // |
1514 // ORR (register) - ARM Section A8.8.123, encoding A1: | 1646 // ORR (register) - ARM Section A8.8.123, encoding A1: |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1778 | 1910 |
1779 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, | 1911 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, |
1780 CondARM32::Cond Cond) { | 1912 CondARM32::Cond Cond) { |
1781 constexpr const char *UxtName = "uxt"; | 1913 constexpr const char *UxtName = "uxt"; |
1782 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; | 1914 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; |
1783 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); | 1915 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); |
1784 } | 1916 } |
1785 | 1917 |
1786 } // end of namespace ARM32 | 1918 } // end of namespace ARM32 |
1787 } // end of namespace Ice | 1919 } // end of namespace Ice |
OLD | NEW |