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...) 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...) 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 (void)kShiftImmBits; |
| 147 assert(imm5 < (1 << kShiftImmBits)); |
| 148 return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm; |
| 149 } |
| 150 |
121 DecodedResult decodeOperand(const Operand *Opnd, uint32_t &Value) { | 151 DecodedResult decodeOperand(const Operand *Opnd, uint32_t &Value) { |
122 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 152 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
123 if (Var->hasReg()) { | 153 if (Var->hasReg()) { |
124 Value = Var->getRegNum(); | 154 Value = Var->getRegNum(); |
125 return DecodedAsRegister; | 155 return DecodedAsRegister; |
126 } | 156 } |
127 } else if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { | 157 } else if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { |
128 const uint32_t Immed8 = FlexImm->getImm(); | 158 const uint32_t Immed8 = FlexImm->getImm(); |
129 const uint32_t Rotate = FlexImm->getRotateAmt(); | 159 const uint32_t Rotate = FlexImm->getRotateAmt(); |
130 assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))); | 160 assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))); |
131 // TODO(kschimpf): Remove void casts when MINIMAL build allows. | 161 // TODO(kschimpf): Remove void casts when MINIMAL build allows. |
132 (void) kRotateBits; | 162 (void)kRotateBits; |
133 (void) kImmed8Bits; | 163 (void)kImmed8Bits; |
134 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); | 164 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); |
135 return DecodedAsRotatedImm8; | 165 return DecodedAsRotatedImm8; |
136 } | 166 } |
137 return CantDecode; | 167 return CantDecode; |
138 } | 168 } |
139 | 169 |
140 uint32_t decodeImmRegOffset(RegARM32::GPRRegister Reg, int32_t Offset, | 170 uint32_t decodeImmRegOffset(RegARM32::GPRRegister Reg, int32_t Offset, |
141 OperandARM32Mem::AddrMode Mode) { | 171 OperandARM32Mem::AddrMode Mode) { |
142 uint32_t Value = Mode | (encodeGPRRegister(Reg) << kRnShift); | 172 uint32_t Value = Mode | (encodeGPRRegister(Reg) << kRnShift); |
143 if (Offset < 0) { | 173 if (Offset < 0) { |
(...skipping 55 matching lines...) Loading... |
199 } | 229 } |
200 // TODO(kschimpf) Decide if we have near jumps. | 230 // TODO(kschimpf) Decide if we have near jumps. |
201 label->bindTo(bound); | 231 label->bindTo(bound); |
202 } | 232 } |
203 | 233 |
204 void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, | 234 void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, |
205 uint32_t Opcode, bool SetCc, uint32_t Rn, | 235 uint32_t Opcode, bool SetCc, uint32_t Rn, |
206 uint32_t Rd, uint32_t Imm12) { | 236 uint32_t Rd, uint32_t Imm12) { |
207 assert(isGPRRegisterDefined(Rd)); | 237 assert(isGPRRegisterDefined(Rd)); |
208 // TODO(kschimpf): Remove void cast when MINIMAL build allows. | 238 // TODO(kschimpf): Remove void cast when MINIMAL build allows. |
209 (void) isGPRRegisterDefined(Rd); | 239 (void)isGPRRegisterDefined(Rd); |
210 assert(Cond != CondARM32::kNone); | 240 assert(Cond != CondARM32::kNone); |
211 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 241 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
212 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | | 242 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | |
213 (Type << kTypeShift) | (Opcode << kOpcodeShift) | | 243 (Type << kTypeShift) | (Opcode << kOpcodeShift) | |
214 (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) | | 244 (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) | |
215 (Rd << kRdShift) | Imm12; | 245 (Rd << kRdShift) | Imm12; |
216 emitInst(Encoding); | 246 emitInst(Encoding); |
217 } | 247 } |
218 | 248 |
219 void ARM32::AssemblerARM32::emitMemOp(CondARM32::Cond Cond, uint32_t InstType, | 249 void ARM32::AssemblerARM32::emitMemOp(CondARM32::Cond Cond, uint32_t InstType, |
(...skipping 12 matching lines...) Loading... |
232 const Operand *OpSrc1, bool SetFlags, | 262 const Operand *OpSrc1, bool SetFlags, |
233 CondARM32::Cond Cond) { | 263 CondARM32::Cond Cond) { |
234 // Note: Loop is used so that we can short circuit using break; | 264 // Note: Loop is used so that we can short circuit using break; |
235 do { | 265 do { |
236 uint32_t Rd; | 266 uint32_t Rd; |
237 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 267 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
238 break; | 268 break; |
239 uint32_t Rn; | 269 uint32_t Rn; |
240 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 270 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
241 break; | 271 break; |
| 272 constexpr uint32_t Add = B2; // 0100 |
242 uint32_t Src1Value; | 273 uint32_t Src1Value; |
243 // TODO(kschimpf) Other possible decodings of add. | 274 // TODO(kschimpf) Other possible decodings of add. |
244 if (decodeOperand(OpSrc1, Src1Value) == DecodedAsRotatedImm8) { | 275 switch (decodeOperand(OpSrc1, Src1Value)) { |
245 // ADD (Immediate): See ARM section A8.8.5, rule A1. | 276 default: |
246 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 277 break; |
247 // s=SetFlags and iiiiiiiiiiii=Src1Value | 278 case DecodedAsRegister: { |
248 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags) || | 279 // ADD (register) - ARM section A8.8.7, encoding A1: |
249 (Rn == RegARM32::Reg_lr) || (Rn == RegARM32::Reg_pc && SetFlags)) | 280 // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} |
| 281 // ADD (Sp plus register) - ARM section A8.8.11, encoding A1: |
| 282 // add{s}<c> sp, <Rn>, <Rm>{, <shiff>} |
| 283 // |
| 284 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 285 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags |
| 286 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); |
| 287 if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) |
250 // Conditions of rule violated. | 288 // Conditions of rule violated. |
251 break; | 289 break; |
252 constexpr uint32_t Add = B2; // 0100 | 290 constexpr uint32_t InstTypeRegister = 0; |
253 constexpr uint32_t InstType = 1; | 291 emitType01(Cond, InstTypeRegister, Add, SetFlags, Rn, Rd, Src1Value); |
254 emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value); | |
255 return; | 292 return; |
256 } | 293 } |
| 294 case DecodedAsRotatedImm8: { |
| 295 // ADD (Immediate) - ARM section A8.8.5, encoding A1: |
| 296 // add{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 297 // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1. |
| 298 // add{s}<c> <Rd>, sp, #<RotatedImm8> |
| 299 // |
| 300 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 301 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8. |
| 302 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
| 303 // Conditions of rule violated. |
| 304 break; |
| 305 constexpr uint32_t InstTypeImmediate = 1; |
| 306 emitType01(Cond, InstTypeImmediate, Add, SetFlags, Rn, Rd, Src1Value); |
| 307 return; |
| 308 } |
| 309 } |
257 } while (0); | 310 } while (0); |
258 UnimplementedError(Ctx->getFlags()); | 311 UnimplementedError(Ctx->getFlags()); |
259 } | 312 } |
260 | 313 |
261 void ARM32::AssemblerARM32::bkpt(uint16_t imm16) { | 314 void ARM32::AssemblerARM32::bkpt(uint16_t Imm16) { |
| 315 // BKPT - ARM section A*.8.24 - encoding A1: |
| 316 // bkpt #<Imm16> |
| 317 // |
| 318 // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and iiiiiiiiiiiiiiii=Imm16 |
262 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 319 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
263 const uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | | 320 const uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | |
264 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf); | 321 ((Imm16 >> 4) << 8) | B6 | B5 | B4 | (Imm16 & 0xf); |
265 emitInst(Encoding); | 322 emitInst(Encoding); |
266 } | 323 } |
267 | 324 |
268 void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { | 325 void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { |
| 326 // BX - ARM section A8.8.27, encoding A1: |
| 327 // bx<c> <Rm> |
| 328 // |
269 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. | 329 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. |
270 // (ARM section A8.8.27, encoding A1). | |
271 assert(isGPRRegisterDefined(Rm)); | 330 assert(isGPRRegisterDefined(Rm)); |
272 // TODO(kschimpf): Remove void cast when MINIMAL build allows. | 331 // TODO(kschimpf): Remove void cast when MINIMAL build allows. |
273 (void) isGPRRegisterDefined(Rm); | 332 (void)isGPRRegisterDefined(Rm); |
274 assert(isConditionDefined(Cond)); | 333 assert(isConditionDefined(Cond)); |
| 334 (void)isConditionDefined(Cond); |
275 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 335 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
276 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | | 336 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | |
277 B21 | (0xfff << 8) | B4 | | 337 B21 | (0xfff << 8) | B4 | |
278 (encodeGPRRegister(Rm) << kRmShift); | 338 (encodeGPRRegister(Rm) << kRmShift); |
279 emitInst(Encoding); | 339 emitInst(Encoding); |
280 } | 340 } |
281 | 341 |
282 void ARM32::AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, | 342 void ARM32::AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, |
283 CondARM32::Cond Cond) { | 343 CondARM32::Cond Cond) { |
284 // Note: Loop is used so that we can short ciruit using break; | 344 // Note: Loop is used so that we can short ciruit using break; |
285 do { | 345 do { |
286 uint32_t Rt; | 346 uint32_t Rt; |
287 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 347 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
288 break; | 348 break; |
289 uint32_t Address; | 349 uint32_t Address; |
290 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) | 350 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |
291 break; | 351 break; |
292 // cccc010pu0w1nnnnttttiiiiiiiiiiii (ARM section A8.8.63, encoding A1; and | 352 // LDR (immediate) - ARM section A8.8.63, encoding A1: |
293 // section A8.6.68, encoding A1). | 353 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 354 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 355 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 356 // LDRB (immediate) - ARM section A8.8.68, encoding A1: |
| 357 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 358 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 359 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 360 // |
| 361 // cccc010pubw1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 362 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. |
294 constexpr uint32_t InstType = B1; // 010 | 363 constexpr uint32_t InstType = B1; // 010 |
295 constexpr bool IsLoad = true; | 364 constexpr bool IsLoad = true; |
296 const Type Ty = OpRt->getType(); | 365 const Type Ty = OpRt->getType(); |
297 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | 366 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |
298 break; | 367 break; |
299 const bool IsByte = typeWidthInBytes(Ty) == 1; | 368 const bool IsByte = typeWidthInBytes(Ty) == 1; |
300 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || | 369 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || |
301 (!IsByte && !isBitSet(P, Address) && isBitSet(W, Address)) || | 370 (!isBitSet(P, Address) && isBitSet(W, Address)) || |
302 ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | 371 (!IsByte && |
| 372 (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && |
303 !isBitSet(P, Address) && | 373 !isBitSet(P, Address) && |
304 isBitSet(U, Address) & !isBitSet(W, Address) && | 374 isBitSet(U, Address) & !isBitSet(W, Address) && |
305 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) | 375 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) |
306 break; | 376 break; |
307 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); | 377 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); |
308 return; | 378 return; |
309 } while (0); | 379 } while (0); |
310 UnimplementedError(Ctx->getFlags()); | 380 UnimplementedError(Ctx->getFlags()); |
311 } | 381 } |
312 | 382 |
313 void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, | 383 void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |
314 CondARM32::Cond Cond) { | 384 CondARM32::Cond Cond) { |
315 // Note: Loop is used so that we can short ciruit using break; | 385 // Note: Loop is used so that we can short ciruit using break; |
316 do { | 386 do { |
317 uint32_t Rd; | 387 uint32_t Rd; |
318 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 388 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
319 break; | 389 break; |
320 uint32_t Src; | 390 uint32_t Src; |
321 // TODO(kschimpf) Handle other forms of mov. | 391 // TODO(kschimpf) Handle other forms of mov. |
322 if (decodeOperand(OpSrc, Src) == DecodedAsRotatedImm8) { | 392 if (decodeOperand(OpSrc, Src) == DecodedAsRotatedImm8) { |
323 // cccc0011101s0000ddddiiiiiiiiiiii (ARM section A8.8.102, encoding A1) | 393 // MOV (immediate) - ARM section A8.8.102, encoding A1: |
324 // Note: We don't use movs in this assembler. | 394 // mov{S}<c> <Rd>, #<RotatedImm8> |
| 395 // |
| 396 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, |
| 397 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this |
| 398 // assembler. |
325 constexpr bool SetFlags = false; | 399 constexpr bool SetFlags = false; |
326 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags)) | 400 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
327 // Conditions of rule violated. | 401 // Conditions of rule violated. |
328 break; | 402 break; |
329 constexpr uint32_t Rn = 0; | 403 constexpr uint32_t Rn = 0; |
330 constexpr uint32_t Mov = B3 | B2 | B0; // 1101. | 404 constexpr uint32_t Mov = B3 | B2 | B0; // 1101. |
331 constexpr uint32_t InstType = 1; | 405 constexpr uint32_t InstType = 1; |
332 emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src); | 406 emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src); |
333 return; | 407 return; |
334 } | 408 } |
335 } while (0); | 409 } while (0); |
336 UnimplementedError(Ctx->getFlags()); | 410 UnimplementedError(Ctx->getFlags()); |
337 } | 411 } |
338 | 412 |
339 void ARM32::AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, | 413 void ARM32::AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
340 CondARM32::Cond Cond) { | 414 CondARM32::Cond Cond) { |
341 // Note: Loop is used so that we can short ciruit using break; | 415 // Note: Loop is used so that we can short ciruit using break; |
342 do { | 416 do { |
343 uint32_t Rt; | 417 uint32_t Rt; |
344 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 418 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
345 break; | 419 break; |
346 uint32_t Address; | 420 uint32_t Address; |
347 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) | 421 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |
348 break; | 422 break; |
349 // cccc010pub0nnnnttttiiiiiiiiiiii (ARM section A8.8.204, encoding A1; and | 423 // STR (immediate) - ARM section A8.8.204, encoding A1: |
350 // section 18.8.207, encoding A1). | 424 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 425 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 426 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 427 // STRB (immediate) - ARM section A8.8.207, encoding A1: |
| 428 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 429 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 430 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 431 // |
| 432 // cccc010pubw0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 433 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. |
351 constexpr uint32_t InstType = B1; // 010 | 434 constexpr uint32_t InstType = B1; // 010 |
352 constexpr bool IsLoad = false; | 435 constexpr bool IsLoad = false; |
353 const Type Ty = OpRt->getType(); | 436 const Type Ty = OpRt->getType(); |
354 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | 437 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |
355 break; | 438 break; |
356 const bool IsByte = typeWidthInBytes(Ty) == 1; | 439 const bool IsByte = typeWidthInBytes(Ty) == 1; |
357 // Check for rule violations. | 440 // Check for rule violations. |
358 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || | 441 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || |
359 (!isBitSet(P, Address) && isBitSet(W, Address)) || | 442 (!isBitSet(P, Address) && isBitSet(W, Address)) || |
360 (!IsByte && | 443 (!IsByte && |
361 (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | 444 (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && |
362 isBitSet(P, Address) && !isBitSet(U, Address) && | 445 isBitSet(P, Address) && !isBitSet(U, Address) && |
363 isBitSet(W, Address) && | 446 isBitSet(W, Address) && |
364 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) | 447 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) |
| 448 // Conditions of rule violated. |
365 break; | 449 break; |
366 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); | 450 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); |
367 return; | 451 return; |
368 } while (0); | 452 } while (0); |
369 UnimplementedError(Ctx->getFlags()); | 453 UnimplementedError(Ctx->getFlags()); |
370 } | 454 } |
371 | 455 |
372 void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, | 456 void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, |
373 const Operand *OpSrc1, bool SetFlags, | 457 const Operand *OpSrc1, bool SetFlags, |
374 CondARM32::Cond Cond) { | 458 CondARM32::Cond Cond) { |
375 // Note: Loop is used so that we can short circuit using break; | 459 // Note: Loop is used so that we can short circuit using break; |
376 do { | 460 do { |
377 uint32_t Rd; | 461 uint32_t Rd; |
378 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 462 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
379 break; | 463 break; |
380 uint32_t Rn; | 464 uint32_t Rn; |
381 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 465 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
382 break; | 466 break; |
| 467 constexpr uint32_t Sub = B1; // 0010 |
383 uint32_t Src1Value; | 468 uint32_t Src1Value; |
384 // TODO(kschimpf) Other possible decodings of add. | 469 // TODO(kschimpf) Other possible decodings of sub. |
385 if (decodeOperand(OpSrc1, Src1Value) == DecodedAsRotatedImm8) { | 470 switch (decodeOperand(OpSrc1, Src1Value)) { |
386 // Sub (Immediate): See ARM section A8.8.222, rule A1. | 471 default: |
387 // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 472 break; |
388 // s=SetFlags and iiiiiiiiiiii=Src1Value | 473 case DecodedAsRegister: { |
389 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags) || | 474 // SUB (register) - ARM section A8.8.223, encoding A1: |
390 (Rn == RegARM32::Reg_lr) || (Rn == RegARM32::Reg_pc && SetFlags)) | 475 // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} |
| 476 // SUB (SP minus register): See ARM section 8.8.226, encoding A1: |
| 477 // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>} |
| 478 // |
| 479 // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 480 // mmmm=Rm, iiiiii=shift, tt=ShiftKind, and s=SetFlags. |
| 481 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); |
| 482 constexpr uint32_t InstType = 0; // i.e. register |
| 483 if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) |
391 // Conditions of rule violated. | 484 // Conditions of rule violated. |
392 break; | 485 break; |
393 constexpr uint32_t Add = B1; // 0010 | 486 emitType01(Cond, InstType, Sub, SetFlags, Rn, Rd, Src1Value); |
| 487 return; |
| 488 } |
| 489 case DecodedAsRotatedImm8: { |
| 490 // Sub (Immediate) - ARM section A8.8.222, encoding A1: |
| 491 // sub{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 492 // Sub (Sp minus immediate) - ARM section A8.*.225, encoding A1: |
| 493 // sub{s}<c> sp, <Rn>, #<RotatedImm8> |
| 494 // |
| 495 // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 496 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8 |
| 497 if (Rd == RegARM32::Encoded_Reg_pc) |
| 498 // Conditions of rule violated. |
| 499 break; |
394 constexpr uint32_t InstType = 1; | 500 constexpr uint32_t InstType = 1; |
395 emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value); | 501 emitType01(Cond, InstType, Sub, SetFlags, Rn, Rd, Src1Value); |
396 return; | 502 return; |
397 } | 503 } |
| 504 } |
398 } while (0); | 505 } while (0); |
399 UnimplementedError(Ctx->getFlags()); | 506 UnimplementedError(Ctx->getFlags()); |
400 } | 507 } |
401 | 508 |
402 } // end of namespace Ice | 509 } // end of namespace Ice |
OLD | NEW |