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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 static constexpr uint32_t kRotateShift = 8; | 63 static constexpr uint32_t kRotateShift = 8; |
64 | 64 |
65 // Shift instruction register fields encodings. | 65 // Shift instruction register fields encodings. |
66 static constexpr uint32_t kShiftImmShift = 7; | 66 static constexpr uint32_t kShiftImmShift = 7; |
67 static constexpr uint32_t kShiftImmBits = 5; | 67 static constexpr uint32_t kShiftImmBits = 5; |
68 static constexpr uint32_t kShiftShift = 5; | 68 static constexpr uint32_t kShiftShift = 5; |
69 | 69 |
70 static constexpr uint32_t kImmed12Bits = 12; | 70 static constexpr uint32_t kImmed12Bits = 12; |
71 static constexpr uint32_t kImm12Shift = 0; | 71 static constexpr uint32_t kImm12Shift = 0; |
72 | 72 |
| 73 // Type of instruction encoding (bits 25-27). See ARM section A5.1 |
| 74 static constexpr uint32_t kInstTypeDataRegister = 0; // i.e. 000 |
| 75 static constexpr uint32_t kInstTypeDataImmediate = 1; // i.e. 001 |
| 76 static constexpr uint32_t kInstTypeMemImmediate = 2; // i.e. 010 |
| 77 |
73 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } | 78 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } |
74 | 79 |
75 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { | 80 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { |
76 return static_cast<uint32_t>(Rn); | 81 return static_cast<uint32_t>(Rn); |
77 } | 82 } |
78 | 83 |
79 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { | 84 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { |
80 return R != RegARM32::Encoded_Not_GPR; | 85 return R != RegARM32::Encoded_Not_GPR; |
81 } | 86 } |
82 | 87 |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 while (label->isLinked()) { | 229 while (label->isLinked()) { |
225 intptr_t position = label->getLinkPosition(); | 230 intptr_t position = label->getLinkPosition(); |
226 intptr_t next = Buffer.load<int32_t>(position); | 231 intptr_t next = Buffer.load<int32_t>(position); |
227 Buffer.store<int32_t>(position, bound - (position + 4)); | 232 Buffer.store<int32_t>(position, bound - (position + 4)); |
228 label->setPosition(next); | 233 label->setPosition(next); |
229 } | 234 } |
230 // TODO(kschimpf) Decide if we have near jumps. | 235 // TODO(kschimpf) Decide if we have near jumps. |
231 label->bindTo(bound); | 236 label->bindTo(bound); |
232 } | 237 } |
233 | 238 |
| 239 void ARM32::AssemblerARM32::emitTextInst(const std::string &Text) { |
| 240 static constexpr uint32_t Placeholder = 0; |
| 241 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 242 AssemblerFixup *F = createTextFixup(Text, sizeof(Placeholder)); |
| 243 emitFixup(F); |
| 244 emitInst(Placeholder); |
| 245 } |
| 246 |
234 void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, | 247 void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, |
235 uint32_t Opcode, bool SetCc, uint32_t Rn, | 248 uint32_t Opcode, bool SetCc, uint32_t Rn, |
236 uint32_t Rd, uint32_t Imm12) { | 249 uint32_t Rd, uint32_t Imm12) { |
237 assert(isGPRRegisterDefined(Rd)); | 250 assert(isGPRRegisterDefined(Rd)); |
238 // TODO(kschimpf): Remove void cast when MINIMAL build allows. | 251 // TODO(kschimpf): Remove void cast when MINIMAL build allows. |
239 (void)isGPRRegisterDefined(Rd); | 252 (void)isGPRRegisterDefined(Rd); |
240 assert(Cond != CondARM32::kNone); | 253 assert(Cond != CondARM32::kNone); |
241 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 254 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
242 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | | 255 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | |
243 (Type << kTypeShift) | (Opcode << kOpcodeShift) | | 256 (Type << kTypeShift) | (Opcode << kOpcodeShift) | |
(...skipping 10 matching lines...) Expand all Loading... |
254 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 267 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
255 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | | 268 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | |
256 (InstType << kTypeShift) | (IsLoad ? L : 0) | | 269 (InstType << kTypeShift) | (IsLoad ? L : 0) | |
257 (IsByte ? B : 0) | (Rt << kRdShift) | Address; | 270 (IsByte ? B : 0) | (Rt << kRdShift) | Address; |
258 emitInst(Encoding); | 271 emitInst(Encoding); |
259 } | 272 } |
260 | 273 |
261 void ARM32::AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn, | 274 void ARM32::AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn, |
262 const Operand *OpSrc1, bool SetFlags, | 275 const Operand *OpSrc1, bool SetFlags, |
263 CondARM32::Cond Cond) { | 276 CondARM32::Cond Cond) { |
264 // Note: Loop is used so that we can short circuit using break; | 277 uint32_t Rd; |
265 do { | 278 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
266 uint32_t Rd; | 279 return setNeedsTextFixup(); |
267 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 280 uint32_t Rn; |
268 break; | 281 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
269 uint32_t Rn; | 282 return setNeedsTextFixup(); |
270 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 283 constexpr uint32_t Add = B2; // 0100 |
271 break; | 284 uint32_t Src1Value; |
272 constexpr uint32_t Add = B2; // 0100 | 285 // TODO(kschimpf) Other possible decodings of add. |
273 uint32_t Src1Value; | 286 switch (decodeOperand(OpSrc1, Src1Value)) { |
274 // TODO(kschimpf) Other possible decodings of add. | 287 default: |
275 switch (decodeOperand(OpSrc1, Src1Value)) { | 288 return setNeedsTextFixup(); |
276 default: | 289 case DecodedAsRegister: { |
277 break; | 290 // ADD (register) - ARM section A8.8.7, encoding A1: |
278 case DecodedAsRegister: { | 291 // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} |
279 // ADD (register) - ARM section A8.8.7, encoding A1: | 292 // ADD (Sp plus register) - ARM section A8.8.11, encoding A1: |
280 // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} | 293 // add{s}<c> sp, <Rn>, <Rm>{, <shiff>} |
281 // ADD (Sp plus register) - ARM section A8.8.11, encoding A1: | 294 // |
282 // add{s}<c> sp, <Rn>, <Rm>{, <shiff>} | 295 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
283 // | 296 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags |
284 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 297 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); |
285 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags | 298 if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) |
286 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); | 299 // Conditions of rule violated. |
287 if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) | 300 return setNeedsTextFixup(); |
288 // Conditions of rule violated. | 301 emitType01(Cond, kInstTypeDataRegister, Add, SetFlags, Rn, Rd, Src1Value); |
289 break; | 302 return; |
290 constexpr uint32_t InstTypeRegister = 0; | 303 } |
291 emitType01(Cond, InstTypeRegister, Add, SetFlags, Rn, Rd, Src1Value); | 304 case DecodedAsRotatedImm8: { |
292 return; | 305 // ADD (Immediate) - ARM section A8.8.5, encoding A1: |
293 } | 306 // add{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
294 case DecodedAsRotatedImm8: { | 307 // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1. |
295 // ADD (Immediate) - ARM section A8.8.5, encoding A1: | 308 // add{s}<c> <Rd>, sp, #<RotatedImm8> |
296 // add{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 309 // |
297 // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1. | 310 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
298 // add{s}<c> <Rd>, sp, #<RotatedImm8> | 311 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8. |
299 // | 312 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
300 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 313 // Conditions of rule violated. |
301 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8. | 314 return setNeedsTextFixup(); |
302 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) | 315 emitType01(Cond, kInstTypeDataImmediate, Add, SetFlags, Rn, Rd, Src1Value); |
303 // Conditions of rule violated. | 316 return; |
304 break; | 317 } |
305 constexpr uint32_t InstTypeImmediate = 1; | 318 }; |
306 emitType01(Cond, InstTypeImmediate, Add, SetFlags, Rn, Rd, Src1Value); | |
307 return; | |
308 } | |
309 } | |
310 } while (0); | |
311 UnimplementedError(Ctx->getFlags()); | |
312 } | 319 } |
313 | 320 |
314 void ARM32::AssemblerARM32::bkpt(uint16_t Imm16) { | 321 void ARM32::AssemblerARM32::bkpt(uint16_t Imm16) { |
315 // BKPT - ARM section A*.8.24 - encoding A1: | 322 // BKPT - ARM section A*.8.24 - encoding A1: |
316 // bkpt #<Imm16> | 323 // bkpt #<Imm16> |
317 // | 324 // |
318 // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and iiiiiiiiiiiiiiii=Imm16 | 325 // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and iiiiiiiiiiiiiiii=Imm16 |
319 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 326 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
320 const uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | | 327 const uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | |
321 ((Imm16 >> 4) << 8) | B6 | B5 | B4 | (Imm16 & 0xf); | 328 ((Imm16 >> 4) << 8) | B6 | B5 | B4 | (Imm16 & 0xf); |
322 emitInst(Encoding); | 329 emitInst(Encoding); |
323 } | 330 } |
324 | 331 |
325 void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { | 332 void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { |
326 // BX - ARM section A8.8.27, encoding A1: | 333 // BX - ARM section A8.8.27, encoding A1: |
327 // bx<c> <Rm> | 334 // bx<c> <Rm> |
328 // | 335 // |
329 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. | 336 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. |
330 assert(isGPRRegisterDefined(Rm)); | 337 if (!(isGPRRegisterDefined(Rm) && isConditionDefined(Cond))) |
331 // TODO(kschimpf): Remove void cast when MINIMAL build allows. | 338 return setNeedsTextFixup(); |
332 (void)isGPRRegisterDefined(Rm); | |
333 assert(isConditionDefined(Cond)); | |
334 (void)isConditionDefined(Cond); | |
335 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 339 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
336 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | | 340 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | |
337 B21 | (0xfff << 8) | B4 | | 341 B21 | (0xfff << 8) | B4 | |
338 (encodeGPRRegister(Rm) << kRmShift); | 342 (encodeGPRRegister(Rm) << kRmShift); |
339 emitInst(Encoding); | 343 emitInst(Encoding); |
340 } | 344 } |
341 | 345 |
342 void ARM32::AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, | 346 void ARM32::AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, |
343 CondARM32::Cond Cond) { | 347 CondARM32::Cond Cond) { |
344 // Note: Loop is used so that we can short ciruit using break; | 348 uint32_t Rt; |
345 do { | 349 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
346 uint32_t Rt; | 350 return setNeedsTextFixup(); |
347 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 351 uint32_t Address; |
348 break; | 352 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |
349 uint32_t Address; | 353 return setNeedsTextFixup(); |
350 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) | 354 // LDR (immediate) - ARM section A8.8.63, encoding A1: |
351 break; | 355 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
352 // LDR (immediate) - ARM section A8.8.63, encoding A1: | 356 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
353 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 357 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
354 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 358 // LDRB (immediate) - ARM section A8.8.68, encoding A1: |
355 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 359 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
356 // LDRB (immediate) - ARM section A8.8.68, encoding A1: | 360 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
357 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 361 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
358 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 362 // |
359 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 363 // cccc010pubw1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
360 // | 364 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. |
361 // cccc010pubw1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 365 constexpr bool IsLoad = true; |
362 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. | 366 const Type Ty = OpRt->getType(); |
363 constexpr uint32_t InstType = B1; // 010 | 367 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |
364 constexpr bool IsLoad = true; | 368 return setNeedsTextFixup(); |
365 const Type Ty = OpRt->getType(); | 369 const bool IsByte = typeWidthInBytes(Ty) == 1; |
366 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | 370 // Check conditions of rules violated. |
367 break; | 371 if (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) |
368 const bool IsByte = typeWidthInBytes(Ty) == 1; | 372 return setNeedsTextFixup(); |
369 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || | 373 if (!isBitSet(P, Address) && isBitSet(W, Address)) |
370 (!isBitSet(P, Address) && isBitSet(W, Address)) || | 374 return setNeedsTextFixup(); |
371 (!IsByte && | 375 if (!IsByte && (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && |
372 (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | 376 !isBitSet(P, Address) && isBitSet(U, Address) & !isBitSet(W, Address) && |
373 !isBitSet(P, Address) && | 377 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) |
374 isBitSet(U, Address) & !isBitSet(W, Address) && | 378 return setNeedsTextFixup(); |
375 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) | 379 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); |
376 break; | |
377 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); | |
378 return; | |
379 } while (0); | |
380 UnimplementedError(Ctx->getFlags()); | |
381 } | 380 } |
382 | 381 |
383 void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, | 382 void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |
384 CondARM32::Cond Cond) { | 383 CondARM32::Cond Cond) { |
385 // Note: Loop is used so that we can short ciruit using break; | 384 uint32_t Rd; |
386 do { | 385 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
387 uint32_t Rd; | 386 return setNeedsTextFixup(); |
388 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 387 uint32_t Src; |
389 break; | 388 // TODO(kschimpf) Handle other forms of mov. |
390 uint32_t Src; | 389 if (decodeOperand(OpSrc, Src) != DecodedAsRotatedImm8) |
391 // TODO(kschimpf) Handle other forms of mov. | 390 return setNeedsTextFixup(); |
392 if (decodeOperand(OpSrc, Src) == DecodedAsRotatedImm8) { | 391 // MOV (immediate) - ARM section A8.8.102, encoding A1: |
393 // MOV (immediate) - ARM section A8.8.102, encoding A1: | 392 // mov{S}<c> <Rd>, #<RotatedImm8> |
394 // mov{S}<c> <Rd>, #<RotatedImm8> | 393 // |
395 // | 394 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, |
396 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, | 395 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this |
397 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this | 396 // assembler. |
398 // assembler. | 397 constexpr bool SetFlags = false; |
399 constexpr bool SetFlags = false; | 398 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
400 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) | 399 // Conditions of rule violated. |
401 // Conditions of rule violated. | 400 return setNeedsTextFixup(); |
402 break; | 401 constexpr uint32_t Rn = 0; |
403 constexpr uint32_t Rn = 0; | 402 constexpr uint32_t Mov = B3 | B2 | B0; // 1101. |
404 constexpr uint32_t Mov = B3 | B2 | B0; // 1101. | 403 emitType01(Cond, kInstTypeDataImmediate, Mov, SetFlags, Rn, Rd, Src); |
405 constexpr uint32_t InstType = 1; | |
406 emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src); | |
407 return; | |
408 } | |
409 } while (0); | |
410 UnimplementedError(Ctx->getFlags()); | |
411 } | 404 } |
412 | 405 |
413 void ARM32::AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, | 406 void ARM32::AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
414 CondARM32::Cond Cond) { | 407 CondARM32::Cond Cond) { |
415 // Note: Loop is used so that we can short ciruit using break; | 408 uint32_t Rt; |
416 do { | 409 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
417 uint32_t Rt; | 410 return setNeedsTextFixup(); |
418 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 411 uint32_t Address; |
419 break; | 412 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |
420 uint32_t Address; | 413 return setNeedsTextFixup(); |
421 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) | 414 // STR (immediate) - ARM section A8.8.204, encoding A1: |
422 break; | 415 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
423 // STR (immediate) - ARM section A8.8.204, encoding A1: | 416 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
424 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 417 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
425 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 418 // STRB (immediate) - ARM section A8.8.207, encoding A1: |
426 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 419 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
427 // STRB (immediate) - ARM section A8.8.207, encoding A1: | 420 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
428 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 421 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
429 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 422 // |
430 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 423 // cccc010pubw0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
431 // | 424 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. |
432 // cccc010pubw0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 425 constexpr bool IsLoad = false; |
433 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. | 426 const Type Ty = OpRt->getType(); |
434 constexpr uint32_t InstType = B1; // 010 | 427 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |
435 constexpr bool IsLoad = false; | 428 return setNeedsTextFixup(); |
436 const Type Ty = OpRt->getType(); | 429 const bool IsByte = typeWidthInBytes(Ty) == 1; |
437 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | 430 // Check for rule violations. |
438 break; | 431 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc)) |
439 const bool IsByte = typeWidthInBytes(Ty) == 1; | 432 return setNeedsTextFixup(); |
440 // Check for rule violations. | 433 if (!isBitSet(P, Address) && isBitSet(W, Address)) |
441 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || | 434 return setNeedsTextFixup(); |
442 (!isBitSet(P, Address) && isBitSet(W, Address)) || | 435 if (!IsByte && (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && |
443 (!IsByte && | 436 isBitSet(P, Address) && !isBitSet(U, Address) && isBitSet(W, Address) && |
444 (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | 437 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) |
445 isBitSet(P, Address) && !isBitSet(U, Address) && | 438 return setNeedsTextFixup(); |
446 isBitSet(W, Address) && | 439 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); |
447 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) | |
448 // Conditions of rule violated. | |
449 break; | |
450 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); | |
451 return; | |
452 } while (0); | |
453 UnimplementedError(Ctx->getFlags()); | |
454 } | 440 } |
455 | 441 |
456 void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, | 442 void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, |
457 const Operand *OpSrc1, bool SetFlags, | 443 const Operand *OpSrc1, bool SetFlags, |
458 CondARM32::Cond Cond) { | 444 CondARM32::Cond Cond) { |
459 // Note: Loop is used so that we can short circuit using break; | 445 uint32_t Rd; |
460 do { | 446 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
461 uint32_t Rd; | 447 return setNeedsTextFixup(); |
462 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 448 uint32_t Rn; |
463 break; | 449 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
464 uint32_t Rn; | 450 return setNeedsTextFixup(); |
465 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 451 constexpr uint32_t Sub = B1; // 0010 |
466 break; | 452 uint32_t Src1Value; |
467 constexpr uint32_t Sub = B1; // 0010 | 453 // TODO(kschimpf) Other possible decodings of sub. |
468 uint32_t Src1Value; | 454 switch (decodeOperand(OpSrc1, Src1Value)) { |
469 // TODO(kschimpf) Other possible decodings of sub. | 455 default: |
470 switch (decodeOperand(OpSrc1, Src1Value)) { | 456 return setNeedsTextFixup(); |
471 default: | 457 case DecodedAsRegister: { |
472 break; | 458 // SUB (register) - ARM section A8.8.223, encoding A1: |
473 case DecodedAsRegister: { | 459 // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} |
474 // SUB (register) - ARM section A8.8.223, encoding A1: | 460 // SUB (SP minus register): See ARM section 8.8.226, encoding A1: |
475 // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} | 461 // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>} |
476 // SUB (SP minus register): See ARM section 8.8.226, encoding A1: | 462 // |
477 // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>} | 463 // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
478 // | 464 // mmmm=Rm, iiiiii=shift, tt=ShiftKind, and s=SetFlags. |
479 // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 465 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); |
480 // mmmm=Rm, iiiiii=shift, tt=ShiftKind, and s=SetFlags. | 466 if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) |
481 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); | 467 // Conditions of rule violated. |
482 constexpr uint32_t InstType = 0; // i.e. register | 468 return setNeedsTextFixup(); |
483 if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) | 469 emitType01(Cond, kInstTypeDataRegister, Sub, SetFlags, Rn, Rd, Src1Value); |
484 // Conditions of rule violated. | 470 return; |
485 break; | 471 } |
486 emitType01(Cond, InstType, Sub, SetFlags, Rn, Rd, Src1Value); | 472 case DecodedAsRotatedImm8: { |
487 return; | 473 // Sub (Immediate) - ARM section A8.8.222, encoding A1: |
488 } | 474 // sub{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
489 case DecodedAsRotatedImm8: { | 475 // Sub (Sp minus immediate) - ARM section A8.*.225, encoding A1: |
490 // Sub (Immediate) - ARM section A8.8.222, encoding A1: | 476 // sub{s}<c> sp, <Rn>, #<RotatedImm8> |
491 // sub{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 477 // |
492 // Sub (Sp minus immediate) - ARM section A8.*.225, encoding A1: | 478 // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
493 // sub{s}<c> sp, <Rn>, #<RotatedImm8> | 479 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8 |
494 // | 480 if (Rd == RegARM32::Encoded_Reg_pc) |
495 // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 481 // Conditions of rule violated. |
496 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8 | 482 return setNeedsTextFixup(); |
497 if (Rd == RegARM32::Encoded_Reg_pc) | 483 emitType01(Cond, kInstTypeDataImmediate, Sub, SetFlags, Rn, Rd, Src1Value); |
498 // Conditions of rule violated. | 484 return; |
499 break; | 485 } |
500 constexpr uint32_t InstType = 1; | 486 } |
501 emitType01(Cond, InstType, Sub, SetFlags, Rn, Rd, Src1Value); | |
502 return; | |
503 } | |
504 } | |
505 } while (0); | |
506 UnimplementedError(Ctx->getFlags()); | |
507 } | 487 } |
508 | 488 |
509 } // end of namespace Ice | 489 } // end of namespace Ice |
OLD | NEW |