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 << "\t"; | |
| 235 if (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC) | |
|
Jim Stichnoth
2015/10/28 22:28:55
What do you think of a long statement like
Str <
Karl
2015/10/29 16:57:53
Done.
| |
| 236 Str << "movw"; | |
| 237 else | |
| 238 Str << "movt"; | |
| 239 Str << "\t" << RegARM32::RegNames[(Inst >> kRdShift) & 0xF] << ", #:"; | |
| 240 if (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC) | |
| 241 Str << "lower"; | |
| 242 else | |
| 243 Str << "upper"; | |
| 244 Str << "16:" << symbol(Ctx) << "\t@ .word "; | |
| 245 IValueT HexMask = 0xF; | |
| 246 for (int HexDigit = 2 * FixupSize; HexDigit > 0; --HexDigit) { | |
|
Jim Stichnoth
2015/10/28 22:28:55
Can you use llvm::format_hex_no_prefix() ? This i
Karl
2015/10/29 16:57:53
Done.
| |
| 247 Str.write_hex((Inst >> 4 * (HexDigit - 1)) & HexMask); | |
| 248 } | |
| 249 Str << "\n"; | |
| 250 return FixupSize; | |
| 251 } | |
| 252 | |
| 253 MoveRelocatableFixup *AssemblerARM32::createMoveFixup(bool IsMovW, | |
| 254 const Constant *Value) { | |
| 255 MoveRelocatableFixup *F = | |
| 256 new (allocate<MoveRelocatableFixup>()) MoveRelocatableFixup(); | |
| 257 F->set_kind(IsMovW ? llvm::ELF::R_ARM_MOVW_ABS_NC | |
| 258 : llvm::ELF::R_ARM_MOVT_ABS); | |
| 259 F->set_value(Value); | |
| 260 Buffer.installFixup(F); | |
| 261 return F; | |
| 262 } | |
| 263 | |
| 225 void AssemblerARM32::bindCfgNodeLabel(const CfgNode *Node) { | 264 void AssemblerARM32::bindCfgNodeLabel(const CfgNode *Node) { |
| 226 if (BuildDefs::dump() && !Ctx->getFlags().getDisableHybridAssembly()) { | 265 if (BuildDefs::dump() && !Ctx->getFlags().getDisableHybridAssembly()) { |
| 227 // Generate label name so that branches can find it. | 266 // Generate label name so that branches can find it. |
| 228 constexpr SizeT InstSize = 0; | 267 constexpr SizeT InstSize = 0; |
| 229 emitTextInst(Node->getAsmName() + ":", InstSize); | 268 emitTextInst(Node->getAsmName() + ":", InstSize); |
| 230 } | 269 } |
| 231 SizeT NodeNumber = Node->getIndex(); | 270 SizeT NodeNumber = Node->getIndex(); |
| 232 assert(!getPreliminary()); | 271 assert(!getPreliminary()); |
| 233 Label *L = getOrCreateCfgNodeLabel(NodeNumber); | 272 Label *L = getOrCreateCfgNodeLabel(NodeNumber); |
| 234 this->bind(L); | 273 this->bind(L); |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 521 // assembler. | 560 // assembler. |
| 522 constexpr bool SetFlags = false; | 561 constexpr bool SetFlags = false; |
| 523 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) | 562 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
| 524 // Conditions of rule violated. | 563 // Conditions of rule violated. |
| 525 return setNeedsTextFixup(); | 564 return setNeedsTextFixup(); |
| 526 constexpr IValueT Rn = 0; | 565 constexpr IValueT Rn = 0; |
| 527 constexpr IValueT Mov = B3 | B2 | B0; // 1101. | 566 constexpr IValueT Mov = B3 | B2 | B0; // 1101. |
| 528 emitType01(Cond, kInstTypeDataImmediate, Mov, SetFlags, Rn, Rd, Src); | 567 emitType01(Cond, kInstTypeDataImmediate, Mov, SetFlags, Rn, Rd, Src); |
| 529 } | 568 } |
| 530 | 569 |
| 570 void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc, | |
| 571 CondARM32::Cond Cond) { | |
| 572 (void)Cond; | |
|
Jim Stichnoth
2015/10/28 22:28:55
Remove this?
Karl
2015/10/29 16:57:53
Done.
| |
| 573 IValueT Rd; | |
| 574 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | |
| 575 return setNeedsTextFixup(); | |
| 576 if (auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc)) { | |
| 577 // MOV (immediate) - ARM section A8.8.102, encoding A2: | |
| 578 // movw<c> <Rd>, #<imm16> | |
| 579 // | |
| 580 // cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, | |
| 581 // and iiiiiiiiiiiiiiii=imm16. | |
| 582 if (!isConditionDefined(Cond)) | |
| 583 // Conditions of rule violated. | |
| 584 return setNeedsTextFixup(); | |
| 585 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | |
| 586 // Use 0 for the lower 16 bits of the relocatable, and add a | |
|
Jim Stichnoth
2015/10/28 22:28:55
reflow comment to 80-col
Karl
2015/10/29 16:57:53
Done.
| |
| 587 // fixup to install the correct bits. | |
| 588 constexpr bool IsMovW = true; | |
| 589 emitFixup(createMoveFixup(IsMovW, Src)); | |
| 590 constexpr IValueT Imm16 = 0; | |
| 591 const IValueT Encoding = encodeCondition(Cond) << kConditionShift | B25 | | |
| 592 B24 | ((Imm16 >> 12) << 16) | Rd << kRdShift | | |
| 593 (Imm16 & 0xfff); | |
| 594 emitInst(Encoding); | |
| 595 } | |
| 596 setNeedsTextFixup(); | |
|
Jim Stichnoth
2015/10/28 22:28:55
This call is a little puzzling because I think it
Karl
2015/10/29 16:57:53
Hmm, this is a mistake. It shouldn't even be there
| |
| 597 } | |
| 598 | |
| 599 void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc, | |
| 600 CondARM32::Cond Cond) { | |
| 601 (void)Cond; | |
|
Jim Stichnoth
2015/10/28 22:28:55
remove?
Karl
2015/10/29 16:57:53
Done.
| |
| 602 IValueT Rd; | |
| 603 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | |
| 604 return setNeedsTextFixup(); | |
| 605 if (auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc)) { | |
| 606 // MOVT - ARM section A8.8.102, encoding A2: | |
| 607 // movt<c> <Rd>, #<imm16> | |
| 608 // | |
| 609 // cccc00110100iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, | |
| 610 // and iiiiiiiiiiiiiiii=imm16. | |
| 611 if (!isConditionDefined(Cond)) | |
| 612 // Conditions of rule violated. | |
| 613 return setNeedsTextFixup(); | |
| 614 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | |
| 615 // Use 0 for the lower 16 bits of the relocatable, and add a | |
| 616 // fixup to install the correct bits. | |
| 617 constexpr bool IsMovW = false; | |
| 618 emitFixup(createMoveFixup(IsMovW, Src)); | |
| 619 constexpr IValueT Imm16 = 0; | |
| 620 const IValueT Encoding = encodeCondition(Cond) << kConditionShift | B25 | | |
| 621 B24 | B22 | ((Imm16 >> 12) << 16) | | |
| 622 Rd << kRdShift | (Imm16 & 0xfff); | |
| 623 emitInst(Encoding); | |
| 624 } | |
| 625 setNeedsTextFixup(); | |
|
Karl
2015/10/29 16:57:53
Removed this also.
| |
| 626 } | |
| 627 | |
| 531 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, | 628 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
| 532 CondARM32::Cond Cond) { | 629 CondARM32::Cond Cond) { |
| 533 IValueT Rt; | 630 IValueT Rt; |
| 534 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 631 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
| 535 return setNeedsTextFixup(); | 632 return setNeedsTextFixup(); |
| 536 IValueT Address; | 633 IValueT Address; |
| 537 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) | 634 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |
| 538 return setNeedsTextFixup(); | 635 return setNeedsTextFixup(); |
| 539 // STR (immediate) - ARM section A8.8.204, encoding A1: | 636 // STR (immediate) - ARM section A8.8.204, encoding A1: |
| 540 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 637 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 606 // Conditions of rule violated. | 703 // Conditions of rule violated. |
| 607 return setNeedsTextFixup(); | 704 return setNeedsTextFixup(); |
| 608 emitType01(Cond, kInstTypeDataImmediate, Sub, SetFlags, Rn, Rd, Src1Value); | 705 emitType01(Cond, kInstTypeDataImmediate, Sub, SetFlags, Rn, Rd, Src1Value); |
| 609 return; | 706 return; |
| 610 } | 707 } |
| 611 } | 708 } |
| 612 } | 709 } |
| 613 | 710 |
| 614 } // end of namespace ARM32 | 711 } // end of namespace ARM32 |
| 615 } // end of namespace Ice | 712 } // end of namespace Ice |
| OLD | NEW |