Chromium Code Reviews| 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 |