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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
55 static constexpr uint32_t kRnShift = 16; | 55 static constexpr uint32_t kRnShift = 16; |
56 static constexpr uint32_t kSShift = 20; | 56 static constexpr uint32_t kSShift = 20; |
57 static constexpr uint32_t kTypeShift = 25; | 57 static constexpr uint32_t kTypeShift = 25; |
58 | 58 |
59 // Immediate instruction fields encoding. | 59 // Immediate instruction fields encoding. |
60 static constexpr uint32_t kImmed8Bits = 8; | 60 static constexpr uint32_t kImmed8Bits = 8; |
61 static constexpr uint32_t kImmed8Shift = 0; | 61 static constexpr uint32_t kImmed8Shift = 0; |
62 static constexpr uint32_t kRotateBits = 4; | 62 static constexpr uint32_t kRotateBits = 4; |
63 static constexpr uint32_t kRotateShift = 8; | 63 static constexpr uint32_t kRotateShift = 8; |
64 | 64 |
65 // Shift instruction register fields encodings. | |
66 static constexpr uint32_t kShiftImmShift = 7; | |
67 static constexpr uint32_t kShiftImmBits = 5; | |
68 static constexpr uint32_t kShiftShift = 5; | |
69 | |
65 static constexpr uint32_t kImmed12Bits = 12; | 70 static constexpr uint32_t kImmed12Bits = 12; |
66 static constexpr uint32_t kImm12Shift = 0; | 71 static constexpr uint32_t kImm12Shift = 0; |
67 | 72 |
68 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } | 73 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } |
69 | 74 |
70 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { | 75 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { |
71 return static_cast<uint32_t>(Rn); | 76 return static_cast<uint32_t>(Rn); |
72 } | 77 } |
73 | 78 |
74 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { | 79 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { |
75 return R != RegARM32::Encoded_Not_GPR; | 80 return R != RegARM32::Encoded_Not_GPR; |
76 } | 81 } |
77 | 82 |
78 inline bool isGPRRegisterDefined(uint32_t R) { | 83 inline bool isGPRRegisterDefined(uint32_t R) { |
79 return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR); | 84 return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR); |
80 } | 85 } |
81 | 86 |
82 inline bool isConditionDefined(CondARM32::Cond Cond) { | 87 inline bool isConditionDefined(CondARM32::Cond Cond) { |
83 return Cond != CondARM32::kNone; | 88 return Cond != CondARM32::kNone; |
84 } | 89 } |
85 | 90 |
86 inline uint32_t encodeCondition(CondARM32::Cond Cond) { | 91 inline uint32_t encodeCondition(CondARM32::Cond Cond) { |
87 return static_cast<uint32_t>(Cond); | 92 return static_cast<uint32_t>(Cond); |
88 } | 93 } |
89 | 94 |
95 uint32_t encodeShift(OperandARM32::ShiftKind Shift) { | |
96 // Follows encoding in ARM section A8.4.1 "Constant shifts". | |
97 switch (Shift) { | |
98 case OperandARM32::kNoShift: | |
99 case OperandARM32::LSL: | |
100 return 0; // 0b00 | |
101 case OperandARM32::LSR: | |
102 return 1; // 0b01 | |
103 case OperandARM32::ASR: | |
104 return 2; // 0b10 | |
105 case OperandARM32::ROR: | |
106 case OperandARM32::RRX: | |
107 return 3; // 0b11 | |
108 } | |
109 } | |
110 | |
90 // Returns the bits in the corresponding masked value. | 111 // Returns the bits in the corresponding masked value. |
91 inline uint32_t mask(uint32_t Value, uint32_t Shift, uint32_t Bits) { | 112 inline uint32_t mask(uint32_t Value, uint32_t Shift, uint32_t Bits) { |
92 return (Value >> Shift) & ((1 << Bits) - 1); | 113 return (Value >> Shift) & ((1 << Bits) - 1); |
93 } | 114 } |
94 | 115 |
95 // Extract out a Bit in Value. | 116 // Extract out a Bit in Value. |
96 inline bool isBitSet(uint32_t Bit, uint32_t Value) { | 117 inline bool isBitSet(uint32_t Bit, uint32_t Value) { |
97 return (Value & Bit) == Bit; | 118 return (Value & Bit) == Bit; |
98 } | 119 } |
99 | 120 |
(...skipping 11 matching lines...) Expand all Loading... | |
111 DecodedAsRegister, | 132 DecodedAsRegister, |
112 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 | 133 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 |
113 // value. | 134 // value. |
114 DecodedAsRotatedImm8, | 135 DecodedAsRotatedImm8, |
115 // i.e. 0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, | 136 // i.e. 0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, |
116 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to | 137 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to |
117 // Rn should be used, and iiiiiiiiiiii is the offset. | 138 // Rn should be used, and iiiiiiiiiiii is the offset. |
118 DecodedAsImmRegOffset | 139 DecodedAsImmRegOffset |
119 }; | 140 }; |
120 | 141 |
142 // Encodes iiiiitt0mmmm for data-processing (2nd) operands where iiiii=Imm5, | |
143 // tt=Shift, and mmmm=Rm. | |
144 uint32_t encodeShiftRotateImm5(uint32_t Rm, OperandARM32::ShiftKind Shift, | |
145 uint32_t imm5) { | |
146 assert(imm5 < (1 << kShiftImmBits)); | |
147 return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm; | |
148 } | |
149 | |
121 DecodedResult decodeOperand(const Operand *Opnd, uint32_t &Value) { | 150 DecodedResult decodeOperand(const Operand *Opnd, uint32_t &Value) { |
122 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 151 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
123 if (Var->hasReg()) { | 152 if (Var->hasReg()) { |
124 Value = Var->getRegNum(); | 153 Value = Var->getRegNum(); |
125 return DecodedAsRegister; | 154 return DecodedAsRegister; |
126 } | 155 } |
127 } else if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { | 156 } else if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { |
128 const uint32_t Immed8 = FlexImm->getImm(); | 157 const uint32_t Immed8 = FlexImm->getImm(); |
129 const uint32_t Rotate = FlexImm->getRotateAmt(); | 158 const uint32_t Rotate = FlexImm->getRotateAmt(); |
130 assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))); | 159 assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
227 const Operand *OpSrc1, bool SetFlags, | 256 const Operand *OpSrc1, bool SetFlags, |
228 CondARM32::Cond Cond) { | 257 CondARM32::Cond Cond) { |
229 // Note: Loop is used so that we can short circuit using break; | 258 // Note: Loop is used so that we can short circuit using break; |
230 do { | 259 do { |
231 uint32_t Rd; | 260 uint32_t Rd; |
232 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 261 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
233 break; | 262 break; |
234 uint32_t Rn; | 263 uint32_t Rn; |
235 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 264 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
236 break; | 265 break; |
266 constexpr uint32_t Add = B2; // 0100 | |
237 uint32_t Src1Value; | 267 uint32_t Src1Value; |
238 // TODO(kschimpf) Other possible decodings of add. | 268 // TODO(kschimpf) Other possible decodings of add. |
239 if (decodeOperand(OpSrc1, Src1Value) == DecodedAsRotatedImm8) { | 269 switch (decodeOperand(OpSrc1, Src1Value)) { |
240 // ADD (Immediate): See ARM section A8.8.5, rule A1. | 270 default: |
241 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 271 break; |
242 // s=SetFlags and iiiiiiiiiiii=Src1Value | 272 case DecodedAsRegister: { |
243 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags) || | 273 // ADD (register) - ARM section A8.8.7, encoding A1: |
244 (Rn == RegARM32::Reg_lr) || (Rn == RegARM32::Reg_pc && SetFlags)) | 274 // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} |
275 // ADD (Sp plus register) - ARM section A8.8.11, encoding A1: | |
276 // add{s}<c> sp, <Rn>, <Rm>{, <shiff>} | |
277 // | |
278 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | |
279 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags | |
280 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); | |
281 if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) | |
245 // Conditions of rule violated. | 282 // Conditions of rule violated. |
246 break; | 283 break; |
247 constexpr uint32_t Add = B2; // 0100 | 284 constexpr uint32_t InstType = 0; // i.e. register |
Jim Stichnoth
2015/10/16 21:30:09
Might be clearer to name this InstTypeReg.
(and In
Karl
2015/10/17 20:00:41
Done.
| |
248 constexpr uint32_t InstType = 1; | |
249 emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value); | 285 emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value); |
250 return; | 286 return; |
251 } | 287 } |
288 case DecodedAsRotatedImm8: { | |
289 // ADD (Immediate) - ARM section A8.8.5, encoding A1: | |
290 // add{s}<c> <Rd>, <Rn>, #<RotatedImm8> | |
291 // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1. | |
292 // add{s}<c> <Rd>, sp, #<RotatedImm8> | |
293 // | |
294 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | |
295 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8. | |
296 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) | |
297 // Conditions of rule violated. | |
298 break; | |
299 constexpr uint32_t InstType = 1; // i.e. immediate. | |
300 emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value); | |
301 return; | |
302 } | |
303 } | |
252 } while (0); | 304 } while (0); |
253 UnimplementedError(Ctx->getFlags()); | 305 UnimplementedError(Ctx->getFlags()); |
254 } | 306 } |
255 | 307 |
256 void ARM32::AssemblerARM32::bkpt(uint16_t imm16) { | 308 void ARM32::AssemblerARM32::bkpt(uint16_t Imm16) { |
309 // BKPT - ARM section A*.8.24 - encoding A1: | |
310 // bkpt #<Imm16> | |
311 // | |
312 // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and iiiiiiiiiiiiiiii=Imm16 | |
257 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 313 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
258 const uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | | 314 const uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | |
259 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf); | 315 ((Imm16 >> 4) << 8) | B6 | B5 | B4 | (Imm16 & 0xf); |
260 emitInst(Encoding); | 316 emitInst(Encoding); |
261 } | 317 } |
262 | 318 |
263 void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { | 319 void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { |
320 // BX - ARM section A8.8.27, encoding A1: | |
321 // bx<c> <Rm> | |
322 // | |
264 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. | 323 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. |
265 // (ARM section A8.8.27, encoding A1). | |
266 assert(isGPRRegisterDefined(Rm)); | 324 assert(isGPRRegisterDefined(Rm)); |
267 assert(isConditionDefined(Cond)); | 325 assert(isConditionDefined(Cond)); |
268 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 326 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
269 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | | 327 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | |
270 B21 | (0xfff << 8) | B4 | | 328 B21 | (0xfff << 8) | B4 | |
271 (encodeGPRRegister(Rm) << kRmShift); | 329 (encodeGPRRegister(Rm) << kRmShift); |
272 emitInst(Encoding); | 330 emitInst(Encoding); |
273 } | 331 } |
274 | 332 |
275 void ARM32::AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, | 333 void ARM32::AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, |
276 CondARM32::Cond Cond) { | 334 CondARM32::Cond Cond) { |
277 // Note: Loop is used so that we can short ciruit using break; | 335 // Note: Loop is used so that we can short ciruit using break; |
278 do { | 336 do { |
279 uint32_t Rt; | 337 uint32_t Rt; |
280 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 338 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
281 break; | 339 break; |
282 uint32_t Address; | 340 uint32_t Address; |
283 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) | 341 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |
284 break; | 342 break; |
285 // cccc010pu0w1nnnnttttiiiiiiiiiiii (ARM section A8.8.63, encoding A1; and | 343 // LDR (immediate) - ARM section A8.8.63, encoding A1: |
286 // section A8.6.68, encoding A1). | 344 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
345 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | |
346 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | |
347 // LDRB (immediate) - ARM section A8.8.68, encoding A1: | |
348 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | |
349 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | |
350 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | |
351 // | |
352 // cccc010pubw1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | |
353 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. | |
287 constexpr uint32_t InstType = B1; // 010 | 354 constexpr uint32_t InstType = B1; // 010 |
288 constexpr bool IsLoad = true; | 355 constexpr bool IsLoad = true; |
289 const Type Ty = OpRt->getType(); | 356 const Type Ty = OpRt->getType(); |
290 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | 357 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |
291 break; | 358 break; |
292 const bool IsByte = typeWidthInBytes(Ty) == 1; | 359 const bool IsByte = typeWidthInBytes(Ty) == 1; |
293 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || | 360 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || |
294 (!IsByte && !isBitSet(P, Address) && isBitSet(W, Address)) || | 361 (!isBitSet(P, Address) && isBitSet(W, Address)) || |
295 ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | 362 (!IsByte && |
363 (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | |
296 !isBitSet(P, Address) && | 364 !isBitSet(P, Address) && |
297 isBitSet(U, Address) & !isBitSet(W, Address) && | 365 isBitSet(U, Address) & !isBitSet(W, Address) && |
298 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) | 366 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) |
299 break; | 367 break; |
300 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); | 368 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); |
301 return; | 369 return; |
302 } while (0); | 370 } while (0); |
303 UnimplementedError(Ctx->getFlags()); | 371 UnimplementedError(Ctx->getFlags()); |
304 } | 372 } |
305 | 373 |
306 void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, | 374 void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |
307 CondARM32::Cond Cond) { | 375 CondARM32::Cond Cond) { |
308 // Note: Loop is used so that we can short ciruit using break; | 376 // Note: Loop is used so that we can short ciruit using break; |
309 do { | 377 do { |
310 uint32_t Rd; | 378 uint32_t Rd; |
311 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 379 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
312 break; | 380 break; |
313 uint32_t Src; | 381 uint32_t Src; |
314 // TODO(kschimpf) Handle other forms of mov. | 382 // TODO(kschimpf) Handle other forms of mov. |
315 if (decodeOperand(OpSrc, Src) == DecodedAsRotatedImm8) { | 383 if (decodeOperand(OpSrc, Src) == DecodedAsRotatedImm8) { |
316 // cccc0011101s0000ddddiiiiiiiiiiii (ARM section A8.8.102, encoding A1) | 384 // MOV (immediate) - ARM section A8.8.102, encoding A1: |
317 // Note: We don't use movs in this assembler. | 385 // mov{S}<c> <Rd>, #<RotatedImm8> |
386 // | |
387 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, | |
388 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this | |
389 // assembler. | |
318 constexpr bool SetFlags = false; | 390 constexpr bool SetFlags = false; |
319 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags)) | 391 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
320 // Conditions of rule violated. | 392 // Conditions of rule violated. |
321 break; | 393 break; |
322 constexpr uint32_t Rn = 0; | 394 constexpr uint32_t Rn = 0; |
323 constexpr uint32_t Mov = B3 | B2 | B0; // 1101. | 395 constexpr uint32_t Mov = B3 | B2 | B0; // 1101. |
324 constexpr uint32_t InstType = 1; | 396 constexpr uint32_t InstType = 1; |
325 emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src); | 397 emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src); |
326 return; | 398 return; |
327 } | 399 } |
328 } while (0); | 400 } while (0); |
329 UnimplementedError(Ctx->getFlags()); | 401 UnimplementedError(Ctx->getFlags()); |
330 } | 402 } |
331 | 403 |
332 void ARM32::AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, | 404 void ARM32::AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
333 CondARM32::Cond Cond) { | 405 CondARM32::Cond Cond) { |
334 // Note: Loop is used so that we can short ciruit using break; | 406 // Note: Loop is used so that we can short ciruit using break; |
335 do { | 407 do { |
336 uint32_t Rt; | 408 uint32_t Rt; |
337 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 409 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
338 break; | 410 break; |
339 uint32_t Address; | 411 uint32_t Address; |
340 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) | 412 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |
341 break; | 413 break; |
342 // cccc010pub0nnnnttttiiiiiiiiiiii (ARM section A8.8.204, encoding A1; and | 414 // STR (immediate) - ARM section A8.8.204, encoding A1: |
343 // section 18.8.207, encoding A1). | 415 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
416 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | |
417 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | |
418 // STRB (immediate) - ARM section A8.8.207, encoding A1: | |
419 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | |
420 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | |
421 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | |
422 // | |
423 // cccc010pubw0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | |
424 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. | |
344 constexpr uint32_t InstType = B1; // 010 | 425 constexpr uint32_t InstType = B1; // 010 |
345 constexpr bool IsLoad = false; | 426 constexpr bool IsLoad = false; |
346 const Type Ty = OpRt->getType(); | 427 const Type Ty = OpRt->getType(); |
347 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | 428 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |
348 break; | 429 break; |
349 const bool IsByte = typeWidthInBytes(Ty) == 1; | 430 const bool IsByte = typeWidthInBytes(Ty) == 1; |
350 // Check for rule violations. | 431 // Check for rule violations. |
351 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || | 432 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || |
352 (!isBitSet(P, Address) && isBitSet(W, Address)) || | 433 (!isBitSet(P, Address) && isBitSet(W, Address)) || |
353 (!IsByte && | 434 (!IsByte && |
354 (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | 435 (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && |
355 isBitSet(P, Address) && !isBitSet(U, Address) && | 436 isBitSet(P, Address) && !isBitSet(U, Address) && |
356 isBitSet(W, Address) && | 437 isBitSet(W, Address) && |
357 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) | 438 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) |
439 // Conditions of rule violated. | |
358 break; | 440 break; |
359 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); | 441 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); |
360 return; | 442 return; |
361 } while (0); | 443 } while (0); |
362 UnimplementedError(Ctx->getFlags()); | 444 UnimplementedError(Ctx->getFlags()); |
363 } | 445 } |
364 | 446 |
365 void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, | 447 void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, |
366 const Operand *OpSrc1, bool SetFlags, | 448 const Operand *OpSrc1, bool SetFlags, |
367 CondARM32::Cond Cond) { | 449 CondARM32::Cond Cond) { |
368 // Note: Loop is used so that we can short circuit using break; | 450 // Note: Loop is used so that we can short circuit using break; |
369 do { | 451 do { |
370 uint32_t Rd; | 452 uint32_t Rd; |
371 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 453 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
372 break; | 454 break; |
373 uint32_t Rn; | 455 uint32_t Rn; |
374 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 456 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
375 break; | 457 break; |
458 constexpr uint32_t Sub = B1; // 0010 | |
376 uint32_t Src1Value; | 459 uint32_t Src1Value; |
377 // TODO(kschimpf) Other possible decodings of add. | 460 // TODO(kschimpf) Other possible decodings of sub. |
378 if (decodeOperand(OpSrc1, Src1Value) == DecodedAsRotatedImm8) { | 461 switch (decodeOperand(OpSrc1, Src1Value)) { |
379 // Sub (Immediate): See ARM section A8.8.222, rule A1. | 462 default: |
380 // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 463 break; |
381 // s=SetFlags and iiiiiiiiiiii=Src1Value | 464 case DecodedAsRegister: { |
382 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags) || | 465 // SUB (register) - ARM section A8.8.223, encoding A1: |
383 (Rn == RegARM32::Reg_lr) || (Rn == RegARM32::Reg_pc && SetFlags)) | 466 // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} |
467 // SUB (SP minus register): See ARM section 8.8.226, encoding A1: | |
468 // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>} | |
469 // | |
470 // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | |
471 // mmmm=Rm, iiiiii=shift, tt=ShiftKind, and s=SetFlags. | |
472 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); | |
473 constexpr uint32_t InstType = 0; // i.e. register | |
474 if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) | |
384 // Conditions of rule violated. | 475 // Conditions of rule violated. |
385 break; | 476 break; |
386 constexpr uint32_t Add = B1; // 0010 | 477 emitType01(Cond, InstType, Sub, SetFlags, Rn, Rd, Src1Value); |
478 return; | |
479 } | |
480 case DecodedAsRotatedImm8: { | |
481 // Sub (Immediate) - ARM section A8.8.222, encoding A1: | |
482 // sub{s}<c> <Rd>, <Rn>, #<RotatedImm8> | |
483 // Sub (Sp minus immediate) - ARM section A8.*.225, encoding A1: | |
484 // sub{s}<c> sp, <Rn>, #<RotatedImm8> | |
485 // | |
486 // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | |
487 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8 | |
488 if (Rd == RegARM32::Encoded_Reg_pc) | |
489 // Conditions of rule violated. | |
490 break; | |
387 constexpr uint32_t InstType = 1; | 491 constexpr uint32_t InstType = 1; |
388 emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value); | 492 emitType01(Cond, InstType, Sub, SetFlags, Rn, Rd, Src1Value); |
389 return; | 493 return; |
390 } | 494 } |
495 } | |
391 } while (0); | 496 } while (0); |
392 UnimplementedError(Ctx->getFlags()); | 497 UnimplementedError(Ctx->getFlags()); |
393 } | 498 } |
394 | 499 |
395 } // end of namespace Ice | 500 } // end of namespace Ice |
OLD | NEW |