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 20 matching lines...) Expand all Loading... | |
31 | 31 |
32 // The following define individual bits. | 32 // The following define individual bits. |
33 static constexpr IValueT B0 = 1; | 33 static constexpr IValueT B0 = 1; |
34 static constexpr IValueT B1 = 1 << 1; | 34 static constexpr IValueT B1 = 1 << 1; |
35 static constexpr IValueT B2 = 1 << 2; | 35 static constexpr IValueT B2 = 1 << 2; |
36 static constexpr IValueT B3 = 1 << 3; | 36 static constexpr IValueT B3 = 1 << 3; |
37 static constexpr IValueT B4 = 1 << 4; | 37 static constexpr IValueT B4 = 1 << 4; |
38 static constexpr IValueT B5 = 1 << 5; | 38 static constexpr IValueT B5 = 1 << 5; |
39 static constexpr IValueT B6 = 1 << 6; | 39 static constexpr IValueT B6 = 1 << 6; |
40 static constexpr IValueT B21 = 1 << 21; | 40 static constexpr IValueT B21 = 1 << 21; |
41 static constexpr IValueT B22 = 1 << 22; | |
41 static constexpr IValueT B24 = 1 << 24; | 42 static constexpr IValueT B24 = 1 << 24; |
43 static constexpr IValueT B25 = 1 << 25; | |
42 | 44 |
43 // Constants used for the decoding or encoding of the individual fields of | 45 // Constants used for the decoding or encoding of the individual fields of |
44 // instructions. Based on ARM section A5.1. | 46 // instructions. Based on ARM section A5.1. |
45 static constexpr IValueT L = 1 << 20; // load (or store) | 47 static constexpr IValueT L = 1 << 20; // load (or store) |
46 static constexpr IValueT W = 1 << 21; // writeback base register | 48 static constexpr IValueT W = 1 << 21; // writeback base register |
47 // (or leave unchanged) | 49 // (or leave unchanged) |
48 static constexpr IValueT B = 1 << 22; // unsigned byte (or word) | 50 static constexpr IValueT B = 1 << 22; // unsigned byte (or word) |
49 static constexpr IValueT U = 1 << 23; // positive (or negative) | 51 static constexpr IValueT U = 1 << 23; // positive (or negative) |
50 // offset/index | 52 // offset/index |
51 static constexpr IValueT P = 1 << 24; // offset/pre-indexed | 53 static constexpr IValueT P = 1 << 24; // offset/pre-indexed |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
215 bool canEncodeBranchOffset(IOffsetT Offset) { | 217 bool canEncodeBranchOffset(IOffsetT Offset) { |
216 return Utils::IsAligned(Offset, 4) && | 218 return Utils::IsAligned(Offset, 4) && |
217 Utils::IsInt(kBranchOffsetBits, Offset >> 2); | 219 Utils::IsInt(kBranchOffsetBits, Offset >> 2); |
218 } | 220 } |
219 | 221 |
220 } // end of anonymous namespace | 222 } // end of anonymous namespace |
221 | 223 |
222 namespace Ice { | 224 namespace Ice { |
223 namespace ARM32 { | 225 namespace ARM32 { |
224 | 226 |
227 size_t MoveRelocatableFixup::emit(GlobalContext *Ctx, | |
228 const Assembler &Asm) const { | |
229 static constexpr const size_t FixupSize = sizeof(IValueT); | |
230 if (!BuildDefs::dump()) | |
231 return FixupSize; | |
232 Ostream &Str = Ctx->getStrEmit(); | |
233 IValueT Inst = Asm.load<IValueT>(position()); | |
234 Str << "\tmov" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "w" : "t") << "\t" | |
235 << RegARM32::RegNames[(Inst >> kRdShift) & 0xF] | |
236 << ", #:" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "lower" : "upper") | |
237 << "16:" << symbol(Ctx) << "\t@ .word " | |
238 << llvm::format_hex_no_prefix(Inst, 8) << "\n"; | |
239 return FixupSize; | |
240 } | |
241 | |
242 MoveRelocatableFixup *AssemblerARM32::createMoveFixup(bool IsMovW, | |
243 const Constant *Value) { | |
244 MoveRelocatableFixup *F = | |
245 new (allocate<MoveRelocatableFixup>()) MoveRelocatableFixup(); | |
246 F->set_kind(IsMovW ? llvm::ELF::R_ARM_MOVW_ABS_NC | |
247 : llvm::ELF::R_ARM_MOVT_ABS); | |
248 F->set_value(Value); | |
249 Buffer.installFixup(F); | |
250 return F; | |
251 } | |
252 | |
225 void AssemblerARM32::bindCfgNodeLabel(const CfgNode *Node) { | 253 void AssemblerARM32::bindCfgNodeLabel(const CfgNode *Node) { |
226 GlobalContext *Ctx = Node->getCfg()->getContext(); | 254 GlobalContext *Ctx = Node->getCfg()->getContext(); |
227 if (BuildDefs::dump() && !Ctx->getFlags().getDisableHybridAssembly()) { | 255 if (BuildDefs::dump() && !Ctx->getFlags().getDisableHybridAssembly()) { |
228 // Generate label name so that branches can find it. | 256 // Generate label name so that branches can find it. |
229 constexpr SizeT InstSize = 0; | 257 constexpr SizeT InstSize = 0; |
230 emitTextInst(Node->getAsmName() + ":", InstSize); | 258 emitTextInst(Node->getAsmName() + ":", InstSize); |
231 } | 259 } |
232 SizeT NodeNumber = Node->getIndex(); | 260 SizeT NodeNumber = Node->getIndex(); |
233 assert(!getPreliminary()); | 261 assert(!getPreliminary()); |
234 Label *L = getOrCreateCfgNodeLabel(NodeNumber); | 262 Label *L = getOrCreateCfgNodeLabel(NodeNumber); |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
510 IValueT Rd; | 538 IValueT Rd; |
511 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 539 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
512 return setNeedsTextFixup(); | 540 return setNeedsTextFixup(); |
513 IValueT Src; | 541 IValueT Src; |
514 // TODO(kschimpf) Handle other forms of mov. | 542 // TODO(kschimpf) Handle other forms of mov. |
515 if (decodeOperand(OpSrc, Src) != DecodedAsRotatedImm8) | 543 if (decodeOperand(OpSrc, Src) != DecodedAsRotatedImm8) |
516 return setNeedsTextFixup(); | 544 return setNeedsTextFixup(); |
517 // MOV (immediate) - ARM section A8.8.102, encoding A1: | 545 // MOV (immediate) - ARM section A8.8.102, encoding A1: |
518 // mov{S}<c> <Rd>, #<RotatedImm8> | 546 // mov{S}<c> <Rd>, #<RotatedImm8> |
519 // | 547 // |
520 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, | 548 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, and |
521 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this | 549 // iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this assembler. |
522 // assembler. | |
523 constexpr bool SetFlags = false; | 550 constexpr bool SetFlags = false; |
524 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) | 551 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
525 // Conditions of rule violated. | 552 // Conditions of rule violated. |
526 return setNeedsTextFixup(); | 553 return setNeedsTextFixup(); |
527 constexpr IValueT Rn = 0; | 554 constexpr IValueT Rn = 0; |
528 constexpr IValueT Mov = B3 | B2 | B0; // 1101. | 555 constexpr IValueT Mov = B3 | B2 | B0; // 1101. |
529 emitType01(Cond, kInstTypeDataImmediate, Mov, SetFlags, Rn, Rd, Src); | 556 emitType01(Cond, kInstTypeDataImmediate, Mov, SetFlags, Rn, Rd, Src); |
530 } | 557 } |
531 | 558 |
559 void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc, | |
560 CondARM32::Cond Cond) { | |
561 IValueT Rd; | |
562 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | |
563 return setNeedsTextFixup(); | |
564 auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc); | |
565 if (Src == nullptr) | |
Karl
2015/10/29 18:35:06
Added fallback if not relocatable constant.
| |
566 return setNeedsTextFixup(); | |
567 // MOV (immediate) - ARM section A8.8.102, encoding A2: | |
568 // movw<c> <Rd>, #<imm16> | |
569 // | |
570 // cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and | |
571 // iiiiiiiiiiiiiiii=imm16. | |
572 if (!isConditionDefined(Cond)) | |
573 // Conditions of rule violated. | |
574 return setNeedsTextFixup(); | |
575 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | |
576 // Use 0 for the lower 16 bits of the relocatable, and add a fixup to | |
577 // install the correct bits. | |
578 constexpr bool IsMovW = true; | |
579 emitFixup(createMoveFixup(IsMovW, Src)); | |
580 constexpr IValueT Imm16 = 0; | |
581 const IValueT Encoding = encodeCondition(Cond) << kConditionShift | B25 | | |
582 B24 | ((Imm16 >> 12) << 16) | Rd << kRdShift | | |
583 (Imm16 & 0xfff); | |
584 emitInst(Encoding); | |
585 } | |
586 | |
587 void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc, | |
588 CondARM32::Cond Cond) { | |
589 IValueT Rd; | |
590 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | |
591 return setNeedsTextFixup(); | |
592 auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc); | |
593 if (Src == nullptr) | |
Karl
2015/10/29 18:35:06
Added fallback if not relocatable constant.
| |
594 return setNeedsTextFixup(); | |
595 // MOVT - ARM section A8.8.102, encoding A2: | |
596 // movt<c> <Rd>, #<imm16> | |
597 // | |
598 // cccc00110100iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and | |
599 // iiiiiiiiiiiiiiii=imm16. | |
600 if (!isConditionDefined(Cond)) | |
601 // Conditions of rule violated. | |
602 return setNeedsTextFixup(); | |
603 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | |
604 // Use 0 for the lower 16 bits of the relocatable, and add a fixup to | |
605 // install the correct bits. | |
606 constexpr bool IsMovW = false; | |
607 emitFixup(createMoveFixup(IsMovW, Src)); | |
608 constexpr IValueT Imm16 = 0; | |
609 const IValueT Encoding = encodeCondition(Cond) << kConditionShift | B25 | | |
610 B24 | B22 | ((Imm16 >> 12) << 16) | Rd << kRdShift | | |
611 (Imm16 & 0xfff); | |
612 emitInst(Encoding); | |
613 } | |
614 | |
532 void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn, | 615 void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn, |
533 const Operand *OpSrc1, bool SetFlags, | 616 const Operand *OpSrc1, bool SetFlags, |
534 CondARM32::Cond Cond) { | 617 CondARM32::Cond Cond) { |
535 IValueT Rd; | 618 IValueT Rd; |
536 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 619 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
537 return setNeedsTextFixup(); | 620 return setNeedsTextFixup(); |
538 IValueT Rn; | 621 IValueT Rn; |
539 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 622 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
540 return setNeedsTextFixup(); | 623 return setNeedsTextFixup(); |
541 constexpr IValueT Sbc = B2 | B1; // 0110 | 624 constexpr IValueT Sbc = B2 | B1; // 0110 |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
651 // Conditions of rule violated. | 734 // Conditions of rule violated. |
652 return setNeedsTextFixup(); | 735 return setNeedsTextFixup(); |
653 emitType01(Cond, kInstTypeDataImmediate, Sub, SetFlags, Rn, Rd, Src1Value); | 736 emitType01(Cond, kInstTypeDataImmediate, Sub, SetFlags, Rn, Rd, Src1Value); |
654 return; | 737 return; |
655 } | 738 } |
656 } | 739 } |
657 } | 740 } |
658 | 741 |
659 } // end of namespace ARM32 | 742 } // end of namespace ARM32 |
660 } // end of namespace Ice | 743 } // end of namespace Ice |
OLD | NEW |