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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 // Immediate instruction fields encoding. | 79 // Immediate instruction fields encoding. |
| 80 static constexpr IValueT kImmed8Bits = 8; | 80 static constexpr IValueT kImmed8Bits = 8; |
| 81 static constexpr IValueT kImmed8Shift = 0; | 81 static constexpr IValueT kImmed8Shift = 0; |
| 82 static constexpr IValueT kRotateBits = 4; | 82 static constexpr IValueT kRotateBits = 4; |
| 83 static constexpr IValueT kRotateShift = 8; | 83 static constexpr IValueT kRotateShift = 8; |
| 84 | 84 |
| 85 // Shift instruction register fields encodings. | 85 // Shift instruction register fields encodings. |
| 86 static constexpr IValueT kShiftImmShift = 7; | 86 static constexpr IValueT kShiftImmShift = 7; |
| 87 static constexpr IValueT kShiftImmBits = 5; | 87 static constexpr IValueT kShiftImmBits = 5; |
| 88 static constexpr IValueT kShiftShift = 5; | 88 static constexpr IValueT kShiftShift = 5; |
| 89 | |
| 90 static constexpr IValueT kImmed12Bits = 12; | 89 static constexpr IValueT kImmed12Bits = 12; |
| 91 static constexpr IValueT kImm12Shift = 0; | 90 static constexpr IValueT kImm12Shift = 0; |
| 92 | 91 |
| 93 // Rotation instructions (uxtb etc.). | 92 // Rotation instructions (uxtb etc.). |
| 94 static constexpr IValueT kRotationShift = 10; | 93 static constexpr IValueT kRotationShift = 10; |
| 95 | 94 |
| 96 // Div instruction register field encodings. | 95 // Div instruction register field encodings. |
| 97 static constexpr IValueT kDivRdShift = 16; | 96 static constexpr IValueT kDivRdShift = 16; |
| 98 static constexpr IValueT kDivRmShift = 8; | 97 static constexpr IValueT kDivRmShift = 8; |
| 99 static constexpr IValueT kDivRnShift = 0; | 98 static constexpr IValueT kDivRnShift = 0; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 120 } | 119 } |
| 121 | 120 |
| 122 inline IValueT encodeGPRRegister(RegARM32::GPRRegister Rn) { | 121 inline IValueT encodeGPRRegister(RegARM32::GPRRegister Rn) { |
| 123 return static_cast<IValueT>(Rn); | 122 return static_cast<IValueT>(Rn); |
| 124 } | 123 } |
| 125 | 124 |
| 126 inline RegARM32::GPRRegister decodeGPRRegister(IValueT R) { | 125 inline RegARM32::GPRRegister decodeGPRRegister(IValueT R) { |
| 127 return static_cast<RegARM32::GPRRegister>(R); | 126 return static_cast<RegARM32::GPRRegister>(R); |
| 128 } | 127 } |
| 129 | 128 |
| 130 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { | |
| 131 return R != RegARM32::Encoded_Not_GPR; | |
| 132 } | |
| 133 | |
| 134 inline bool isGPRRegisterDefined(IValueT R) { | 129 inline bool isGPRRegisterDefined(IValueT R) { |
| 135 return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR); | 130 return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR); |
| 136 } | 131 } |
| 137 | 132 |
| 138 inline bool isConditionDefined(CondARM32::Cond Cond) { | 133 inline bool isConditionDefined(CondARM32::Cond Cond) { |
| 139 return Cond != CondARM32::kNone; | 134 return Cond != CondARM32::kNone; |
| 140 } | 135 } |
| 141 | 136 |
| 142 inline IValueT encodeCondition(CondARM32::Cond Cond) { | 137 inline IValueT encodeCondition(CondARM32::Cond Cond) { |
| 143 return static_cast<IValueT>(Cond); | 138 return static_cast<IValueT>(Cond); |
| 144 } | 139 } |
| 145 | 140 |
| 146 IValueT encodeShift(OperandARM32::ShiftKind Shift) { | 141 IValueT encodeShift(OperandARM32::ShiftKind Shift) { |
| 147 // Follows encoding in ARM section A8.4.1 "Constant shifts". | 142 // Follows encoding in ARM section A8.4.1 "Constant shifts". |
| 148 switch (Shift) { | 143 switch (Shift) { |
| 149 case OperandARM32::kNoShift: | 144 case OperandARM32::kNoShift: |
| 150 case OperandARM32::LSL: | 145 case OperandARM32::LSL: |
| 151 return 0; // 0b00 | 146 return 0; // 0b00 |
| 152 case OperandARM32::LSR: | 147 case OperandARM32::LSR: |
| 153 return 1; // 0b01 | 148 return 1; // 0b01 |
| 154 case OperandARM32::ASR: | 149 case OperandARM32::ASR: |
| 155 return 2; // 0b10 | 150 return 2; // 0b10 |
| 156 case OperandARM32::ROR: | 151 case OperandARM32::ROR: |
| 157 case OperandARM32::RRX: | 152 case OperandARM32::RRX: |
| 158 return 3; // 0b11 | 153 return 3; // 0b11 |
| 159 } | 154 } |
| 160 | |
| 161 llvm::report_fatal_error("Unknown Shift value"); | 155 llvm::report_fatal_error("Unknown Shift value"); |
| 162 return 0; | 156 return 0; |
| 163 } | 157 } |
| 164 | 158 |
| 165 // Returns the bits in the corresponding masked value. | 159 // Returns the bits in the corresponding masked value. |
| 166 inline IValueT mask(IValueT Value, IValueT Shift, IValueT Bits) { | 160 inline IValueT mask(IValueT Value, IValueT Shift, IValueT Bits) { |
| 167 return (Value >> Shift) & ((1 << Bits) - 1); | 161 return (Value >> Shift) & ((1 << Bits) - 1); |
| 168 } | 162 } |
| 169 | 163 |
| 170 // Extract out a Bit in Value. | 164 // Extract out a Bit in Value. |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 356 } | 350 } |
| 357 return CantEncode; | 351 return CantEncode; |
| 358 } | 352 } |
| 359 | 353 |
| 360 // Checks that Offset can fit in imm24 constant of branch (b) instruction. | 354 // Checks that Offset can fit in imm24 constant of branch (b) instruction. |
| 361 bool canEncodeBranchOffset(IOffsetT Offset) { | 355 bool canEncodeBranchOffset(IOffsetT Offset) { |
| 362 return Utils::IsAligned(Offset, 4) && | 356 return Utils::IsAligned(Offset, 4) && |
| 363 Utils::IsInt(kBranchOffsetBits, Offset >> 2); | 357 Utils::IsInt(kBranchOffsetBits, Offset >> 2); |
| 364 } | 358 } |
| 365 | 359 |
| 360 inline IValueT encodeRegister(const Operand *OpReg, const char *RegName, | |
|
Jim Stichnoth
2015/12/03 21:19:49
I don't think all the "inline" specifications are
Karl
2015/12/03 23:52:59
Removed inlines.
| |
| 361 const char *InstName) { | |
| 362 IValueT Reg = 0; | |
| 363 if (encodeOperand(OpReg, Reg) != EncodedAsRegister) | |
| 364 llvm::report_fatal_error(std::string(InstName) + ": Can't find register " + | |
| 365 RegName); | |
| 366 return Reg; | |
| 367 } | |
| 368 | |
| 369 inline void verifyRegDefined(IValueT Reg, const char *RegName, | |
| 370 const char *InstName) { | |
| 371 if (!isGPRRegisterDefined(Reg)) | |
|
Jim Stichnoth
2015/12/03 21:19:49
What do you think about using BuildDefs to disable
Karl
2015/12/03 23:52:59
I guess it is ok. Changing.
| |
| 372 llvm::report_fatal_error(std::string(InstName) + ": Can't find " + RegName); | |
| 373 } | |
| 374 | |
| 375 inline void verifyCondDefined(CondARM32::Cond Cond, const char *InstName) { | |
| 376 if (!isConditionDefined(Cond)) | |
| 377 llvm::report_fatal_error(std::string(InstName) + ": Condition not defined"); | |
| 378 } | |
| 379 | |
| 380 inline void verifyNot_NotPAndW(IValueT Address, const char *InstName) { | |
|
Jim Stichnoth
2015/12/03 21:19:49
The "Not_Not" substring, including the use of unde
Karl
2015/12/03 23:52:59
Renamed to verifyPOrNotW().
| |
| 381 if (!isBitSet(P, Address) && isBitSet(W, Address)) | |
| 382 llvm::report_fatal_error(std::string(InstName) + | |
| 383 ": P=0 when W=1 not allowed"); | |
| 384 } | |
| 385 | |
| 386 inline void verifyRegsNotEq(IValueT Reg1, const char *Reg1Name, IValueT Reg2, | |
| 387 const char *Reg2Name, const char *InstName) { | |
| 388 if (Reg1 == Reg2) | |
| 389 llvm::report_fatal_error(std::string(InstName) + ": " + Reg1Name + "=" + | |
| 390 Reg2Name + " not allowed"); | |
| 391 } | |
| 392 | |
| 393 inline void verifyRegNotPc(IValueT Reg, const char *RegName, | |
| 394 const char *InstName) { | |
| 395 verifyRegsNotEq(Reg, RegName, RegARM32::Encoded_Reg_pc, "pc", InstName); | |
| 396 } | |
| 397 | |
| 398 inline void verifyAddrRegNotPc(IValueT RegShift, IValueT Address, | |
| 399 const char *RegName, const char *InstName) { | |
| 400 if (getGPRReg(RegShift, Address) == RegARM32::Encoded_Reg_pc) | |
| 401 llvm::report_fatal_error(std::string(InstName) + ": " + RegName + | |
| 402 "=pc not allowed"); | |
| 403 } | |
| 404 | |
| 405 inline void verifyRegNotPcWhenSetFlags(IValueT Reg, bool SetFlags, | |
| 406 const char *InstName) { | |
| 407 if (SetFlags && (Reg == RegARM32::Encoded_Reg_pc)) | |
| 408 llvm::report_fatal_error(std::string(InstName) + ": " + | |
| 409 RegARM32::RegNames[Reg] + | |
| 410 "=pc not allowed when CC=1"); | |
| 411 } | |
| 412 | |
| 366 } // end of anonymous namespace | 413 } // end of anonymous namespace |
| 367 | 414 |
| 368 namespace Ice { | 415 namespace Ice { |
| 369 namespace ARM32 { | 416 namespace ARM32 { |
| 370 | 417 |
| 371 size_t MoveRelocatableFixup::emit(GlobalContext *Ctx, | 418 size_t MoveRelocatableFixup::emit(GlobalContext *Ctx, |
| 372 const Assembler &Asm) const { | 419 const Assembler &Asm) const { |
| 373 if (!BuildDefs::dump()) | 420 if (!BuildDefs::dump()) |
| 374 return InstARM32::InstSize; | 421 return InstARM32::InstSize; |
| 375 Ostream &Str = Ctx->getStrEmit(); | 422 Ostream &Str = Ctx->getStrEmit(); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 483 | 530 |
| 484 void AssemblerARM32::emitTextInst(const std::string &Text, SizeT InstSize) { | 531 void AssemblerARM32::emitTextInst(const std::string &Text, SizeT InstSize) { |
| 485 AssemblerFixup *F = createTextFixup(Text, InstSize); | 532 AssemblerFixup *F = createTextFixup(Text, InstSize); |
| 486 emitFixup(F); | 533 emitFixup(F); |
| 487 for (SizeT I = 0; I < InstSize; ++I) { | 534 for (SizeT I = 0; I < InstSize; ++I) { |
| 488 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 535 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 489 Buffer.emit<char>(0); | 536 Buffer.emit<char>(0); |
| 490 } | 537 } |
| 491 } | 538 } |
| 492 | 539 |
| 493 void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Type, | 540 void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT InstType, |
| 494 IValueT Opcode, bool SetFlags, IValueT Rn, | 541 IValueT Opcode, bool SetFlags, IValueT Rn, |
| 495 IValueT Rd, IValueT Imm12, | 542 IValueT Rd, IValueT Imm12, |
| 496 EmitChecks RuleChecks) { | 543 EmitChecks RuleChecks, const char *InstName) { |
| 497 switch (RuleChecks) { | 544 switch (RuleChecks) { |
| 498 case NoChecks: | 545 case NoChecks: |
| 499 break; | 546 break; |
| 500 case RdIsPcAndSetFlags: | 547 case RdIsPcAndSetFlags: |
| 501 if ((Rd == RegARM32::Encoded_Reg_pc) && SetFlags) | 548 verifyRegNotPcWhenSetFlags(Rd, SetFlags, InstName); |
| 502 // Conditions of rule violated. | |
| 503 return setNeedsTextFixup(); | |
| 504 break; | 549 break; |
| 505 } | 550 } |
| 506 | 551 verifyRegDefined(Rd, "Rd", InstName); |
| 507 if (!isGPRRegisterDefined(Rd) || !isConditionDefined(Cond)) | 552 verifyCondDefined(Cond, InstName); |
| 508 return setNeedsTextFixup(); | |
| 509 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 553 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 510 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | | 554 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | |
| 511 (Type << kTypeShift) | (Opcode << kOpcodeShift) | | 555 (InstType << kTypeShift) | (Opcode << kOpcodeShift) | |
| 512 (encodeBool(SetFlags) << kSShift) | | 556 (encodeBool(SetFlags) << kSShift) | |
| 513 (Rn << kRnShift) | (Rd << kRdShift) | Imm12; | 557 (Rn << kRnShift) | (Rd << kRdShift) | Imm12; |
| 514 emitInst(Encoding); | 558 emitInst(Encoding); |
| 515 } | 559 } |
| 516 | 560 |
| 517 void AssemblerARM32::emitType01(IValueT Opcode, const Operand *OpRd, | 561 void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Opcode, |
| 518 const Operand *OpRn, const Operand *OpSrc1, | 562 const Operand *OpRd, const Operand *OpRn, |
| 519 bool SetFlags, CondARM32::Cond Cond, | 563 const Operand *OpSrc1, bool SetFlags, |
| 520 EmitChecks RuleChecks) { | 564 EmitChecks RuleChecks, const char *InstName) { |
| 521 IValueT Rd; | 565 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); |
| 522 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) | 566 IValueT Rn = encodeRegister(OpRn, "Rn", InstName); |
| 523 return setNeedsTextFixup(); | 567 emitType01(Cond, Opcode, Rd, Rn, OpSrc1, SetFlags, RuleChecks, InstName); |
| 524 IValueT Rn; | |
| 525 if (encodeOperand(OpRn, Rn) != EncodedAsRegister) | |
| 526 return setNeedsTextFixup(); | |
| 527 emitType01(Opcode, Rd, Rn, OpSrc1, SetFlags, Cond, RuleChecks); | |
| 528 } | 568 } |
| 529 | 569 |
| 530 void AssemblerARM32::emitType01(IValueT Opcode, IValueT Rd, IValueT Rn, | 570 void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Opcode, |
| 531 const Operand *OpSrc1, bool SetFlags, | 571 IValueT Rd, IValueT Rn, const Operand *OpSrc1, |
| 532 CondARM32::Cond Cond, EmitChecks RuleChecks) { | 572 bool SetFlags, EmitChecks RuleChecks, |
| 573 const char *InstName) { | |
| 533 | 574 |
| 534 IValueT Src1Value; | 575 IValueT Src1Value; |
| 535 // TODO(kschimpf) Other possible decodings of data operations. | 576 // TODO(kschimpf) Other possible decodings of data operations. |
| 536 switch (encodeOperand(OpSrc1, Src1Value)) { | 577 switch (encodeOperand(OpSrc1, Src1Value)) { |
| 537 default: | 578 default: |
| 579 // TODO(kschimpf): Figure out what additional cases need to be handled. | |
| 538 return setNeedsTextFixup(); | 580 return setNeedsTextFixup(); |
| 539 case EncodedAsRegister: { | 581 case EncodedAsRegister: { |
| 540 // XXX (register) | 582 // XXX (register) |
| 541 // xxx{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} | 583 // xxx{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} |
| 542 // | 584 // |
| 543 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 585 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 544 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. | 586 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. |
| 545 constexpr IValueT Imm5 = 0; | 587 constexpr IValueT Imm5 = 0; |
| 546 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Imm5); | 588 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Imm5); |
| 547 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, | 589 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, |
| 548 RuleChecks); | 590 RuleChecks, InstName); |
| 549 return; | 591 return; |
| 550 } | 592 } |
| 551 case EncodedAsShiftedRegister: { | 593 case EncodedAsShiftedRegister: { |
| 552 // Form is defined in case EncodedAsRegister. (i.e. XXX (register)). | 594 // Form is defined in case EncodedAsRegister. (i.e. XXX (register)). |
| 553 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, | 595 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, |
| 554 RuleChecks); | 596 RuleChecks, InstName); |
| 555 return; | 597 return; |
| 556 } | 598 } |
| 557 case EncodedAsConstI32: { | 599 case EncodedAsConstI32: { |
| 558 // See if we can convert this to an XXX (immediate). | 600 // See if we can convert this to an XXX (immediate). |
| 559 IValueT RotateAmt; | 601 IValueT RotateAmt; |
| 560 IValueT Imm8; | 602 IValueT Imm8; |
| 561 if (!OperandARM32FlexImm::canHoldImm(Src1Value, &RotateAmt, &Imm8)) | 603 if (!OperandARM32FlexImm::canHoldImm(Src1Value, &RotateAmt, &Imm8)) |
| 562 return setNeedsTextFixup(); | 604 llvm::report_fatal_error(std::string(InstName) + |
| 605 ": Immediate rotated constant not valid"); | |
| 563 Src1Value = encodeRotatedImm8(RotateAmt, Imm8); | 606 Src1Value = encodeRotatedImm8(RotateAmt, Imm8); |
| 564 // Intentionally fall to next case! | 607 // Intentionally fall to next case! |
| 565 } | 608 } |
| 566 case EncodedAsRotatedImm8: { | 609 case EncodedAsRotatedImm8: { |
| 567 // XXX (Immediate) | 610 // XXX (Immediate) |
| 568 // xxx{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 611 // xxx{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 569 // | 612 // |
| 570 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 613 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 571 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 614 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
| 572 emitType01(Cond, kInstTypeDataImmediate, Opcode, SetFlags, Rn, Rd, | 615 emitType01(Cond, kInstTypeDataImmediate, Opcode, SetFlags, Rn, Rd, |
| 573 Src1Value, RuleChecks); | 616 Src1Value, RuleChecks, InstName); |
| 574 return; | 617 return; |
| 575 } | 618 } |
| 576 } | 619 } |
| 577 } | 620 } |
| 578 | 621 |
| 579 void AssemblerARM32::emitType05(CondARM32::Cond Cond, IOffsetT Offset, | 622 void AssemblerARM32::emitType05(CondARM32::Cond Cond, IOffsetT Offset, |
| 580 bool Link) { | 623 bool Link, const char *InstName) { |
| 581 // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and | 624 // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and |
| 582 // iiiiiiiiiiiiiiiiiiiiiiii= | 625 // iiiiiiiiiiiiiiiiiiiiiiii= |
| 583 // EncodedBranchOffset(cccc101l000000000000000000000000, Offset); | 626 // EncodedBranchOffset(cccc101l000000000000000000000000, Offset); |
| 584 if (!isConditionDefined(Cond)) | 627 verifyCondDefined(Cond, InstName); |
| 585 return setNeedsTextFixup(); | |
| 586 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 628 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 587 IValueT Encoding = static_cast<int32_t>(Cond) << kConditionShift | | 629 IValueT Encoding = static_cast<int32_t>(Cond) << kConditionShift | |
| 588 5 << kTypeShift | (Link ? 1 : 0) << kLinkShift; | 630 5 << kTypeShift | (Link ? 1 : 0) << kLinkShift; |
| 589 Encoding = encodeBranchOffset(Offset, Encoding); | 631 Encoding = encodeBranchOffset(Offset, Encoding); |
| 590 emitInst(Encoding); | 632 emitInst(Encoding); |
| 591 } | 633 } |
| 592 | 634 |
| 593 void AssemblerARM32::emitBranch(Label *L, CondARM32::Cond Cond, bool Link) { | 635 void AssemblerARM32::emitBranch(Label *L, CondARM32::Cond Cond, bool Link) { |
| 594 // TODO(kschimpf): Handle far jumps. | 636 // TODO(kschimpf): Handle far jumps. |
| 637 constexpr const char *BranchName = "b"; | |
| 595 if (L->isBound()) { | 638 if (L->isBound()) { |
| 596 const int32_t Dest = L->getPosition() - Buffer.size(); | 639 const int32_t Dest = L->getPosition() - Buffer.size(); |
| 597 emitType05(Cond, Dest, Link); | 640 emitType05(Cond, Dest, Link, BranchName); |
| 598 return; | 641 return; |
| 599 } | 642 } |
| 600 const IOffsetT Position = Buffer.size(); | 643 const IOffsetT Position = Buffer.size(); |
| 601 // Use the offset field of the branch instruction for linking the sites. | 644 // Use the offset field of the branch instruction for linking the sites. |
| 602 emitType05(Cond, L->getEncodedPosition(), Link); | 645 emitType05(Cond, L->getEncodedPosition(), Link, BranchName); |
| 603 if (!needsTextFixup()) | 646 if (!needsTextFixup()) |
| 604 L->linkTo(Position); | 647 L->linkTo(Position); |
| 605 } | 648 } |
| 606 | 649 |
| 607 void AssemblerARM32::emitCompareOp(IValueT Opcode, const Operand *OpRn, | 650 void AssemblerARM32::emitCompareOp(CondARM32::Cond Cond, IValueT Opcode, |
| 608 const Operand *OpSrc1, | 651 const Operand *OpRn, const Operand *OpSrc1, |
| 609 CondARM32::Cond Cond) { | 652 const char *InstName) { |
| 610 // XXX (register) | 653 // XXX (register) |
| 611 // XXX<c> <Rn>, <Rm>{, <shift>} | 654 // XXX<c> <Rn>, <Rm>{, <shift>} |
| 612 // | 655 // |
| 613 // ccccyyyxxxx1nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, iiiii | 656 // ccccyyyxxxx1nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, iiiii |
| 614 // defines shift constant, tt=ShiftKind, yyy=kInstTypeDataRegister, and | 657 // defines shift constant, tt=ShiftKind, yyy=kInstTypeDataRegister, and |
| 615 // xxxx=Opcode. | 658 // xxxx=Opcode. |
| 616 // | 659 // |
| 617 // XXX (immediate) | 660 // XXX (immediate) |
| 618 // XXX<c> <Rn>, #<RotatedImm8> | 661 // XXX<c> <Rn>, #<RotatedImm8> |
| 619 // | 662 // |
| 620 // ccccyyyxxxx1nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 663 // ccccyyyxxxx1nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 621 // yyy=kInstTypeDataImmdiate, xxxx=Opcode, and iiiiiiiiiiii=Src1Value | 664 // yyy=kInstTypeDataImmdiate, xxxx=Opcode, and iiiiiiiiiiii=Src1Value |
| 622 // defining RotatedImm8. | 665 // defining RotatedImm8. |
| 623 constexpr bool SetFlags = true; | 666 constexpr bool SetFlags = true; |
| 624 constexpr IValueT Rd = RegARM32::Encoded_Reg_r0; | 667 constexpr IValueT Rd = RegARM32::Encoded_Reg_r0; |
| 625 IValueT Rn; | 668 IValueT Rn = encodeRegister(OpRn, "Rn", InstName); |
| 626 if (encodeOperand(OpRn, Rn) != EncodedAsRegister) | 669 emitType01(Cond, Opcode, Rd, Rn, OpSrc1, SetFlags, NoChecks, InstName); |
| 627 return setNeedsTextFixup(); | |
| 628 emitType01(Opcode, Rd, Rn, OpSrc1, SetFlags, Cond, NoChecks); | |
| 629 } | 670 } |
| 630 | 671 |
| 631 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType, | 672 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType, |
| 632 bool IsLoad, bool IsByte, IValueT Rt, | 673 bool IsLoad, bool IsByte, IValueT Rt, |
| 633 IValueT Address) { | 674 IValueT Address, const char *InstName) { |
| 634 if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond)) | 675 verifyRegDefined(Rt, "Rt", InstName); |
| 635 return setNeedsTextFixup(); | 676 verifyCondDefined(Cond, InstName); |
| 636 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 677 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 637 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | | 678 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | |
| 638 (InstType << kTypeShift) | (IsLoad ? L : 0) | | 679 (InstType << kTypeShift) | (IsLoad ? L : 0) | |
| 639 (IsByte ? B : 0) | (Rt << kRdShift) | Address; | 680 (IsByte ? B : 0) | (Rt << kRdShift) | Address; |
| 640 emitInst(Encoding); | 681 emitInst(Encoding); |
| 641 } | 682 } |
| 642 | 683 |
| 643 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, | 684 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, |
| 644 IValueT Rt, const Operand *OpAddress, | 685 IValueT Rt, const Operand *OpAddress, |
| 645 const TargetInfo &TInfo) { | 686 const TargetInfo &TInfo, const char *InstName) { |
| 646 IValueT Address; | 687 IValueT Address; |
| 647 switch (encodeAddress(OpAddress, Address, TInfo)) { | 688 switch (encodeAddress(OpAddress, Address, TInfo)) { |
| 648 default: | 689 default: |
| 649 return setNeedsTextFixup(); | 690 llvm::report_fatal_error(std::string(InstName) + |
| 691 ": Memory address not understood"); | |
| 650 case EncodedAsImmRegOffset: { | 692 case EncodedAsImmRegOffset: { |
| 651 // XXX{B} (immediate): | 693 // XXX{B} (immediate): |
| 652 // xxx{b}<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 694 // xxx{b}<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 653 // xxx{b}<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 695 // xxx{b}<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 654 // xxx{b}<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 696 // xxx{b}<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 655 // | 697 // |
| 656 // cccc010pubwlnnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 698 // cccc010pubwlnnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 657 // iiiiiiiiiiii=imm12, b=IsByte, pu0w<<21 is a BlockAddr, l=IsLoad, and | 699 // iiiiiiiiiiii=imm12, b=IsByte, pu0w<<21 is a BlockAddr, l=IsLoad, and |
| 658 // pu0w0nnnn0000iiiiiiiiiiii=Address. | 700 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
| 659 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); | 701 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); |
| 660 | 702 |
| 661 // Check if conditions of rules violated. | 703 // Check if conditions of rules violated. |
| 662 if (Rn == RegARM32::Encoded_Reg_pc) | 704 verifyRegNotPc(Rn, "Rn", InstName); |
| 663 return setNeedsTextFixup(); | 705 verifyNot_NotPAndW(Address, InstName); |
| 664 if (!isBitSet(P, Address) && isBitSet(W, Address)) | |
| 665 return setNeedsTextFixup(); | |
| 666 if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) && | 706 if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) && |
| 667 isBitSet(U, Address) & !isBitSet(W, Address) && | 707 isBitSet(U, Address) && !isBitSet(W, Address) && |
| 668 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) | 708 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) |
| 669 return setNeedsTextFixup(); | 709 llvm::report_fatal_error(std::string(InstName) + |
| 710 ": Use push/pop instead"); | |
| 670 | 711 |
| 671 return emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); | 712 return emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address, |
| 713 InstName); | |
| 672 } | 714 } |
| 673 case EncodedAsShiftRotateImm5: { | 715 case EncodedAsShiftRotateImm5: { |
| 674 // XXX{B} (register) | 716 // XXX{B} (register) |
| 675 // xxx{b}<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | 717 // xxx{b}<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
| 676 // xxx{b}<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} | 718 // xxx{b}<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} |
| 677 // | 719 // |
| 678 // cccc011pubwlnnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, | 720 // cccc011pubwlnnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, |
| 679 // b=IsByte, U=1 if +, pu0b is a BlockAddr, l=IsLoad, and | 721 // b=IsByte, U=1 if +, pu0b is a BlockAddr, l=IsLoad, and |
| 680 // pu0w0nnnn0000iiiiiss0mmmm=Address. | 722 // pu0w0nnnn0000iiiiiss0mmmm=Address. |
| 681 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); | 723 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); |
| 682 RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address); | 724 RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address); |
| 683 | 725 |
| 684 // Check if conditions of rules violated. | 726 // Check if conditions of rules violated. |
| 685 if (isBitSet(P, Address) && isBitSet(W, Address)) | 727 verifyNot_NotPAndW(Address, InstName); |
| 686 // Instruction XXXBT! | 728 verifyRegNotPc(Rm, "Rm", InstName); |
| 687 return setNeedsTextFixup(); | 729 if (IsByte) |
| 688 if (IsByte && | 730 verifyRegNotPc(Rt, "Rt", InstName); |
| 689 ((Rt == RegARM32::Encoded_Reg_pc) || (Rm == RegARM32::Encoded_Reg_pc))) | 731 if (isBitSet(W, Address)) { |
| 690 // Unpredictable. | 732 verifyRegNotPc(Rn, "Rn", InstName); |
| 691 return setNeedsTextFixup(); | 733 verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName); |
| 692 if (!IsByte && Rm == RegARM32::Encoded_Reg_pc) | 734 } |
| 693 // Unpredictable. | 735 return emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address, |
| 694 return setNeedsTextFixup(); | 736 InstName); |
| 695 if (isBitSet(W, Address) && | |
| 696 ((Rn == RegARM32::Encoded_Reg_pc) || encodeGPRRegister(Rn) == Rt)) | |
| 697 // Unpredictable | |
| 698 return setNeedsTextFixup(); | |
| 699 | |
| 700 return emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address); | |
| 701 } | 737 } |
| 702 } | 738 } |
| 703 } | 739 } |
| 704 | 740 |
| 705 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, | 741 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, |
| 706 IValueT Rt, const Operand *OpAddress, | 742 IValueT Rt, const Operand *OpAddress, |
| 707 const TargetInfo &TInfo) { | 743 const TargetInfo &TInfo, |
| 744 const char *InstName) { | |
| 708 IValueT Address; | 745 IValueT Address; |
| 709 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { | 746 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { |
| 710 default: | 747 default: |
| 711 return setNeedsTextFixup(); | 748 llvm::report_fatal_error(std::string(InstName) + |
| 749 ": Memory address not understood"); | |
| 712 case EncodedAsImmRegOffsetEnc3: { | 750 case EncodedAsImmRegOffsetEnc3: { |
| 713 // XXXH (immediate) | 751 // XXXH (immediate) |
| 714 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] | 752 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] |
| 715 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] | 753 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] |
| 716 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | 754 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
| 717 // | 755 // |
| 718 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, | 756 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, |
| 719 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, | 757 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, |
| 720 // and pu0w0nnnn0000iiii0000jjjj=Address. | 758 // and pu0w0nnnn0000iiii0000jjjj=Address. |
| 721 if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond)) | 759 verifyRegDefined(Rt, "Rt", InstName); |
| 722 return setNeedsTextFixup(); | 760 verifyCondDefined(Cond, InstName); |
| 723 if (!isBitSet(P, Address) && isBitSet(W, Address)) | 761 verifyNot_NotPAndW(Address, InstName); |
| 724 return setNeedsTextFixup(); | 762 verifyRegNotPc(Rt, "Rt", InstName); |
| 725 if ((Rt == RegARM32::Encoded_Reg_pc) || | 763 if (isBitSet(W, Address)) |
| 726 (isBitSet(W, Address) && | 764 verifyRegsNotEq(getGPRReg(kRnShift, Address), "Rn", Rt, "Rt", InstName); |
| 727 (getGPRReg(kRnShift, Address) == decodeGPRRegister(Rt)))) | |
| 728 return setNeedsTextFixup(); | |
| 729 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | | 765 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | |
| 730 Opcode | (Rt << kRdShift) | Address; | 766 Opcode | (Rt << kRdShift) | Address; |
| 731 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 767 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 732 return emitInst(Encoding); | 768 return emitInst(Encoding); |
| 733 } | 769 } |
| 734 case EncodedAsShiftRotateImm5: { | 770 case EncodedAsShiftRotateImm5: { |
| 735 // XXXH (register) | 771 // XXXH (register) |
| 736 // xxxh<c> <Rt>, [<Rn>, +/-<Rm>]{!} | 772 // xxxh<c> <Rt>, [<Rn>, +/-<Rm>]{!} |
| 737 // xxxh<c> <Rt>, [<Rn>], +/-<Rm> | 773 // xxxh<c> <Rt>, [<Rn>], +/-<Rm> |
| 738 // | 774 // |
| 739 // cccc000pu0wxnnnntttt00001011mmmm where cccc=Cond, tttt=Rt, nnnn=Rn, | 775 // cccc000pu0wxnnnntttt00001011mmmm where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 740 // mmmm=Rm, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, and | 776 // mmmm=Rm, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, and |
| 741 // pu0w0nnnn000000000000mmmm=Address. | 777 // pu0w0nnnn000000000000mmmm=Address. |
| 742 if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond)) | 778 verifyRegDefined(Rt, "Rt", InstName); |
| 743 return setNeedsTextFixup(); | 779 verifyCondDefined(Cond, InstName); |
| 744 if (!isBitSet(P, Address) && isBitSet(W, Address)) | 780 verifyNot_NotPAndW(Address, InstName); |
| 745 return setNeedsTextFixup(); | 781 verifyRegNotPc(Rt, "Rt", InstName); |
| 746 if (Rt == RegARM32::Encoded_Reg_pc) | 782 verifyAddrRegNotPc(kRmShift, Address, "Rm", InstName); |
| 747 return setNeedsTextFixup(); | |
| 748 if (getGPRReg(kRmShift, Address) == RegARM32::Encoded_Reg_pc) | |
| 749 return setNeedsTextFixup(); | |
| 750 const RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); | 783 const RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); |
| 751 if (isBitSet(W, Address) && | 784 if (isBitSet(W, Address)) { |
| 752 ((Rn == RegARM32::Encoded_Reg_pc) || (encodeGPRRegister(Rn) == Rt))) | 785 verifyRegNotPc(Rn, "Rn", InstName); |
| 753 return setNeedsTextFixup(); | 786 verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName); |
| 787 } | |
| 754 if (mask(Address, kShiftImmShift, 5) != 0) | 788 if (mask(Address, kShiftImmShift, 5) != 0) |
| 755 // For encoding 3, no shift is allowed. | 789 // For encoding 3, no shift is allowed. |
| 756 return setNeedsTextFixup(); | 790 llvm::report_fatal_error(std::string(InstName) + |
| 791 ": Shift constant not allowed"); | |
| 757 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | | 792 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | |
| 758 Opcode | (Rt << kRdShift) | Address; | 793 Opcode | (Rt << kRdShift) | Address; |
| 759 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 794 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 760 return emitInst(Encoding); | 795 return emitInst(Encoding); |
| 761 } | 796 } |
| 762 } | 797 } |
| 763 } | 798 } |
| 764 | 799 |
| 765 void AssemblerARM32::emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, | 800 void AssemblerARM32::emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, |
| 766 IValueT Rn, IValueT Rm) { | 801 IValueT Rn, IValueT Rm, const char *InstName) { |
| 767 if (!isGPRRegisterDefined(Rd) || !isGPRRegisterDefined(Rn) || | 802 verifyRegDefined(Rd, "Rd", InstName); |
| 768 !isGPRRegisterDefined(Rm) || !isConditionDefined(Cond)) | 803 verifyRegDefined(Rn, "Rn", InstName); |
| 769 return setNeedsTextFixup(); | 804 verifyRegDefined(Rm, "Rm", InstName); |
| 805 verifyCondDefined(Cond, InstName); | |
| 770 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 806 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 771 const IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | | 807 const IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | |
| 772 (Rn << kDivRnShift) | (Rd << kDivRdShift) | B26 | | 808 (Rn << kDivRnShift) | (Rd << kDivRdShift) | B26 | |
| 773 B25 | B24 | B20 | B15 | B14 | B13 | B12 | B4 | | 809 B25 | B24 | B20 | B15 | B14 | B13 | B12 | B4 | |
| 774 (Rm << kDivRmShift); | 810 (Rm << kDivRmShift); |
| 775 emitInst(Encoding); | 811 emitInst(Encoding); |
| 776 } | 812 } |
| 777 | 813 |
| 778 void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, | 814 void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, |
| 779 IValueT Rn, IValueT Rm, IValueT Rs, | 815 IValueT Rn, IValueT Rm, IValueT Rs, |
| 780 bool SetFlags) { | 816 bool SetFlags, const char *InstName) { |
| 781 if (!isGPRRegisterDefined(Rd) || !isGPRRegisterDefined(Rn) || | 817 verifyRegDefined(Rd, "Rd", InstName); |
| 782 !isGPRRegisterDefined(Rm) || !isGPRRegisterDefined(Rs) || | 818 verifyRegDefined(Rn, "Rn", InstName); |
| 783 !isConditionDefined(Cond)) | 819 verifyRegDefined(Rm, "Rm", InstName); |
| 784 return setNeedsTextFixup(); | 820 verifyRegDefined(Rs, "Rs", InstName); |
| 821 verifyCondDefined(Cond, InstName); | |
| 785 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 822 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 786 IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | | 823 IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | |
| 787 (encodeBool(SetFlags) << kSShift) | (Rn << kRnShift) | | 824 (encodeBool(SetFlags) << kSShift) | (Rn << kRnShift) | |
| 788 (Rd << kRdShift) | (Rs << kRsShift) | B7 | B4 | | 825 (Rd << kRdShift) | (Rs << kRsShift) | B7 | B4 | |
| 789 (Rm << kRmShift); | 826 (Rm << kRmShift); |
| 790 emitInst(Encoding); | 827 emitInst(Encoding); |
| 791 } | 828 } |
| 792 | 829 |
| 793 void AssemblerARM32::emitUxt(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, | 830 void AssemblerARM32::emitUxt(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, |
| 794 IValueT Rn, IValueT Rm, RotationValue Rotation) { | 831 IValueT Rn, IValueT Rm, RotationValue Rotation, |
| 832 const char *InstName) { | |
| 833 verifyCondDefined(Cond, InstName); | |
| 795 IValueT Rot = encodeRotation(Rotation); | 834 IValueT Rot = encodeRotation(Rotation); |
| 796 if (!isConditionDefined(Cond) || !Utils::IsUint(2, Rot)) | 835 if (!Utils::IsUint(2, Rot)) |
| 797 return setNeedsTextFixup(); | 836 llvm::report_fatal_error(std::string(InstName) + |
| 837 ": Illegal rotation value"); | |
| 798 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 838 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 799 IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | Opcode | | 839 IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | Opcode | |
| 800 (Rn << kRnShift) | (Rd << kRdShift) | | 840 (Rn << kRnShift) | (Rd << kRdShift) | |
| 801 (Rot << kRotationShift) | B6 | B5 | B4 | (Rm << kRmShift); | 841 (Rot << kRotationShift) | B6 | B5 | B4 | (Rm << kRmShift); |
| 802 emitInst(Encoding); | 842 emitInst(Encoding); |
| 803 } | 843 } |
| 804 | 844 |
| 805 void AssemblerARM32::emitMultiMemOp(CondARM32::Cond Cond, | 845 void AssemblerARM32::emitMultiMemOp(CondARM32::Cond Cond, |
| 806 BlockAddressMode AddressMode, bool IsLoad, | 846 BlockAddressMode AddressMode, bool IsLoad, |
| 807 IValueT BaseReg, IValueT Registers) { | 847 IValueT BaseReg, IValueT Registers, |
| 848 const char *InstName) { | |
| 808 constexpr IValueT NumGPRegisters = 16; | 849 constexpr IValueT NumGPRegisters = 16; |
| 809 if (!isConditionDefined(Cond) || !isGPRRegisterDefined(BaseReg) || | 850 verifyCondDefined(Cond, InstName); |
| 810 Registers >= (1 << NumGPRegisters)) | 851 verifyRegDefined(BaseReg, "base", InstName); |
| 811 return setNeedsTextFixup(); | 852 if (Registers >= (1 << NumGPRegisters)) |
| 853 llvm::report_fatal_error(std::string(InstName) + | |
| 854 ": Register set too large"); | |
| 812 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 855 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 813 IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 | | 856 IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 | |
| 814 AddressMode | (IsLoad ? L : 0) | (BaseReg << kRnShift) | | 857 AddressMode | (IsLoad ? L : 0) | (BaseReg << kRnShift) | |
| 815 Registers; | 858 Registers; |
| 816 emitInst(Encoding); | 859 emitInst(Encoding); |
| 817 } | 860 } |
| 818 | 861 |
| 819 void AssemblerARM32::adc(const Operand *OpRd, const Operand *OpRn, | 862 void AssemblerARM32::adc(const Operand *OpRd, const Operand *OpRn, |
| 820 const Operand *OpSrc1, bool SetFlags, | 863 const Operand *OpSrc1, bool SetFlags, |
| 821 CondARM32::Cond Cond) { | 864 CondARM32::Cond Cond) { |
| 822 // ADC (register) - ARM section 18.8.2, encoding A1: | 865 // ADC (register) - ARM section 18.8.2, encoding A1: |
| 823 // adc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} | 866 // adc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} |
| 824 // | 867 // |
| 825 // cccc0000101snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 868 // cccc0000101snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 826 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. | 869 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. |
| 827 // | 870 // |
| 828 // ADC (Immediate) - ARM section A8.8.1, encoding A1: | 871 // ADC (Immediate) - ARM section A8.8.1, encoding A1: |
| 829 // adc{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 872 // adc{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 830 // | 873 // |
| 831 // cccc0010101snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 874 // cccc0010101snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 832 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 875 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
| 833 constexpr IValueT Adc = B2 | B0; // 0101 | 876 constexpr const char *AdcName = "adc"; |
|
Jim Stichnoth
2015/12/03 21:19:50
Too bad you can't easily reuse e.g. InstARM32Adc::
Karl
2015/12/03 23:52:58
Acknowledged.
| |
| 834 emitType01(Adc, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); | 877 constexpr IValueT AdcOpcode = B2 | B0; // 0101 |
| 878 emitType01(Cond, AdcOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, | |
| 879 AdcName); | |
| 835 } | 880 } |
| 836 | 881 |
| 837 void AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn, | 882 void AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn, |
| 838 const Operand *OpSrc1, bool SetFlags, | 883 const Operand *OpSrc1, bool SetFlags, |
| 839 CondARM32::Cond Cond) { | 884 CondARM32::Cond Cond) { |
| 840 // ADD (register) - ARM section A8.8.7, encoding A1: | 885 // ADD (register) - ARM section A8.8.7, encoding A1: |
| 841 // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} | 886 // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} |
| 842 // ADD (Sp plus register) - ARM section A8.8.11, encoding A1: | 887 // ADD (Sp plus register) - ARM section A8.8.11, encoding A1: |
| 843 // add{s}<c> sp, <Rn>, <Rm>{, <shiff>} | 888 // add{s}<c> sp, <Rn>, <Rm>{, <shiff>} |
| 844 // | 889 // |
| 845 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 890 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 846 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. | 891 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. |
| 847 // | 892 // |
| 848 // ADD (Immediate) - ARM section A8.8.5, encoding A1: | 893 // ADD (Immediate) - ARM section A8.8.5, encoding A1: |
| 849 // add{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 894 // add{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 850 // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1. | 895 // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1. |
| 851 // add{s}<c> <Rd>, sp, #<RotatedImm8> | 896 // add{s}<c> <Rd>, sp, #<RotatedImm8> |
| 852 // | 897 // |
| 853 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 898 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 854 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 899 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
| 900 constexpr const char *AddName = "add"; | |
| 855 constexpr IValueT Add = B2; // 0100 | 901 constexpr IValueT Add = B2; // 0100 |
| 856 emitType01(Add, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); | 902 emitType01(Cond, Add, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, |
| 903 AddName); | |
| 857 } | 904 } |
| 858 | 905 |
| 859 void AssemblerARM32::and_(const Operand *OpRd, const Operand *OpRn, | 906 void AssemblerARM32::and_(const Operand *OpRd, const Operand *OpRn, |
| 860 const Operand *OpSrc1, bool SetFlags, | 907 const Operand *OpSrc1, bool SetFlags, |
| 861 CondARM32::Cond Cond) { | 908 CondARM32::Cond Cond) { |
| 862 // AND (register) - ARM section A8.8.14, encoding A1: | 909 // AND (register) - ARM section A8.8.14, encoding A1: |
| 863 // and{s}<c> <Rd>, <Rn>{, <shift>} | 910 // and{s}<c> <Rd>, <Rn>{, <shift>} |
| 864 // | 911 // |
| 865 // cccc0000000snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 912 // cccc0000000snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 866 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. | 913 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. |
| 867 // | 914 // |
| 868 // AND (Immediate) - ARM section A8.8.13, encoding A1: | 915 // AND (Immediate) - ARM section A8.8.13, encoding A1: |
| 869 // and{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 916 // and{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 870 // | 917 // |
| 871 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 918 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 872 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 919 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
| 920 constexpr const char *AndName = "and"; | |
| 873 constexpr IValueT And = 0; // 0000 | 921 constexpr IValueT And = 0; // 0000 |
| 874 emitType01(And, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); | 922 emitType01(Cond, And, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, |
| 923 AndName); | |
| 875 } | 924 } |
| 876 | 925 |
| 877 void AssemblerARM32::b(Label *L, CondARM32::Cond Cond) { | 926 void AssemblerARM32::b(Label *L, CondARM32::Cond Cond) { |
| 878 emitBranch(L, Cond, false); | 927 emitBranch(L, Cond, false); |
| 879 } | 928 } |
| 880 | 929 |
| 881 void AssemblerARM32::bkpt(uint16_t Imm16) { | 930 void AssemblerARM32::bkpt(uint16_t Imm16) { |
| 882 // BKPT - ARM section A*.8.24 - encoding A1: | 931 // BKPT - ARM section A*.8.24 - encoding A1: |
| 883 // bkpt #<Imm16> | 932 // bkpt #<Imm16> |
| 884 // | 933 // |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 896 // bic{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} | 945 // bic{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} |
| 897 // | 946 // |
| 898 // cccc0001110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 947 // cccc0001110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 899 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. | 948 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. |
| 900 // | 949 // |
| 901 // BIC (immediate) - ARM section A8.8.21, encoding A1: | 950 // BIC (immediate) - ARM section A8.8.21, encoding A1: |
| 902 // bic{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 951 // bic{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 903 // | 952 // |
| 904 // cccc0011110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rn, nnnn=Rn, | 953 // cccc0011110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rn, nnnn=Rn, |
| 905 // s=SetFlags, and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 954 // s=SetFlags, and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
| 906 IValueT Opcode = B3 | B2 | B1; // i.e. 1110 | 955 constexpr const char *BicName = "bic"; |
| 907 emitType01(Opcode, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); | 956 constexpr IValueT BicOpcode = B3 | B2 | B1; // i.e. 1110 |
| 957 emitType01(Cond, BicOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, | |
| 958 BicName); | |
| 908 } | 959 } |
| 909 | 960 |
| 910 void AssemblerARM32::bl(const ConstantRelocatable *Target) { | 961 void AssemblerARM32::bl(const ConstantRelocatable *Target) { |
| 911 // BL (immediate) - ARM section A8.8.25, encoding A1: | 962 // BL (immediate) - ARM section A8.8.25, encoding A1: |
| 912 // bl<c> <label> | 963 // bl<c> <label> |
| 913 // | 964 // |
| 914 // cccc1011iiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond (not currently allowed) | 965 // cccc1011iiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond (not currently allowed) |
| 915 // and iiiiiiiiiiiiiiiiiiiiiiii is the (encoded) Target to branch to. | 966 // and iiiiiiiiiiiiiiiiiiiiiiii is the (encoded) Target to branch to. |
| 916 emitFixup(createBlFixup(Target)); | 967 emitFixup(createBlFixup(Target)); |
| 968 constexpr const char *BlName = "bl"; | |
| 917 constexpr CondARM32::Cond Cond = CondARM32::AL; | 969 constexpr CondARM32::Cond Cond = CondARM32::AL; |
| 918 constexpr IValueT Immed = 0; | 970 constexpr IValueT Immed = 0; |
| 919 constexpr bool Link = true; | 971 constexpr bool Link = true; |
| 920 emitType05(Cond, Immed, Link); | 972 emitType05(Cond, Immed, Link, BlName); |
| 921 } | 973 } |
| 922 | 974 |
| 923 void AssemblerARM32::blx(const Operand *Target) { | 975 void AssemblerARM32::blx(const Operand *Target) { |
| 924 IValueT Rm; | |
| 925 if (encodeOperand(Target, Rm) != EncodedAsRegister) | |
| 926 return setNeedsTextFixup(); | |
| 927 // BLX (register) - ARM section A8.8.26, encoding A1: | 976 // BLX (register) - ARM section A8.8.26, encoding A1: |
| 928 // blx<c> <Rm> | 977 // blx<c> <Rm> |
| 929 // | 978 // |
| 930 // cccc000100101111111111110011mmmm where cccc=Cond (not currently allowed) | 979 // cccc000100101111111111110011mmmm where cccc=Cond (not currently allowed) |
| 931 // and mmmm=Rm. | 980 // and mmmm=Rm. |
| 932 if (Rm == RegARM32::Encoded_Reg_pc) | 981 constexpr const char *BlxName = "Blx"; |
| 933 // Unpredictable. | 982 IValueT Rm = encodeRegister(Target, "Rm", BlxName); |
| 934 return setNeedsTextFixup(); | 983 verifyRegNotPc(Rm, "Rm", BlxName); |
| 935 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 984 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 936 constexpr CondARM32::Cond Cond = CondARM32::AL; | 985 constexpr CondARM32::Cond Cond = CondARM32::AL; |
| 937 int32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | B21 | | 986 int32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | B21 | |
| 938 (0xfff << 8) | B5 | B4 | (Rm << kRmShift); | 987 (0xfff << 8) | B5 | B4 | (Rm << kRmShift); |
| 939 emitInst(Encoding); | 988 emitInst(Encoding); |
| 940 } | 989 } |
| 941 | 990 |
| 942 void AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { | 991 void AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { |
| 943 // BX - ARM section A8.8.27, encoding A1: | 992 // BX - ARM section A8.8.27, encoding A1: |
| 944 // bx<c> <Rm> | 993 // bx<c> <Rm> |
| 945 // | 994 // |
| 946 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. | 995 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. |
| 947 if (!(isGPRRegisterDefined(Rm) && isConditionDefined(Cond))) | 996 constexpr const char *BxName = "bx"; |
| 948 return setNeedsTextFixup(); | 997 verifyCondDefined(Cond, BxName); |
| 998 verifyRegDefined(Rm, "Rm", BxName); | |
| 949 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 999 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 950 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | | 1000 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | |
| 951 B21 | (0xfff << 8) | B4 | | 1001 B21 | (0xfff << 8) | B4 | |
| 952 (encodeGPRRegister(Rm) << kRmShift); | 1002 (encodeGPRRegister(Rm) << kRmShift); |
| 953 emitInst(Encoding); | 1003 emitInst(Encoding); |
| 954 } | 1004 } |
| 955 | 1005 |
| 956 void AssemblerARM32::cmp(const Operand *OpRn, const Operand *OpSrc1, | 1006 void AssemblerARM32::cmp(const Operand *OpRn, const Operand *OpSrc1, |
| 957 CondARM32::Cond Cond) { | 1007 CondARM32::Cond Cond) { |
| 958 // CMP (register) - ARM section A8.8.38, encoding A1: | 1008 // CMP (register) - ARM section A8.8.38, encoding A1: |
| 959 // cmp<c> <Rn>, <Rm>{, <shift>} | 1009 // cmp<c> <Rn>, <Rm>{, <shift>} |
| 960 // | 1010 // |
| 961 // cccc00010101nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, | 1011 // cccc00010101nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, |
| 962 // iiiii=Shift, and tt=ShiftKind. | 1012 // iiiii=Shift, and tt=ShiftKind. |
| 963 // | 1013 // |
| 964 // CMP (immediate) - ARM section A8.8.37 | 1014 // CMP (immediate) - ARM section A8.8.37 |
| 965 // cmp<c: <Rn>, #<RotatedImm8> | 1015 // cmp<c: <Rn>, #<RotatedImm8> |
| 966 // | 1016 // |
| 967 // cccc00110101nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 1017 // cccc00110101nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 968 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 1018 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
| 969 constexpr IValueT Opcode = B3 | B1; // ie. 1010 | 1019 constexpr const char *CmpName = "cmp"; |
| 970 emitCompareOp(Opcode, OpRn, OpSrc1, Cond); | 1020 constexpr IValueT CmpOpcode = B3 | B1; // ie. 1010 |
| 1021 emitCompareOp(Cond, CmpOpcode, OpRn, OpSrc1, CmpName); | |
| 971 } | 1022 } |
| 972 | 1023 |
| 973 void AssemblerARM32::eor(const Operand *OpRd, const Operand *OpRn, | 1024 void AssemblerARM32::eor(const Operand *OpRd, const Operand *OpRn, |
| 974 const Operand *OpSrc1, bool SetFlags, | 1025 const Operand *OpSrc1, bool SetFlags, |
| 975 CondARM32::Cond Cond) { | 1026 CondARM32::Cond Cond) { |
| 976 // EOR (register) - ARM section A*.8.47, encoding A1: | 1027 // EOR (register) - ARM section A*.8.47, encoding A1: |
| 977 // eor{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} | 1028 // eor{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} |
| 978 // | 1029 // |
| 979 // cccc0000001snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 1030 // cccc0000001snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 980 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. | 1031 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. |
| 981 // | 1032 // |
| 982 // EOR (Immediate) - ARM section A8.*.46, encoding A1: | 1033 // EOR (Immediate) - ARM section A8.*.46, encoding A1: |
| 983 // eor{s}<c> <Rd>, <Rn>, #RotatedImm8 | 1034 // eor{s}<c> <Rd>, <Rn>, #RotatedImm8 |
| 984 // | 1035 // |
| 985 // cccc0010001snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 1036 // cccc0010001snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 986 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 1037 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
| 987 constexpr IValueT Eor = B0; // 0001 | 1038 constexpr const char *EorName = "eor"; |
| 988 emitType01(Eor, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); | 1039 constexpr IValueT EorOpcode = B0; // 0001 |
| 1040 emitType01(Cond, EorOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, | |
| 1041 EorName); | |
| 989 } | 1042 } |
| 990 | 1043 |
| 991 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, | 1044 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, |
| 992 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 1045 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
| 1046 constexpr const char *LdrName = "ldr"; | |
| 993 constexpr bool IsLoad = true; | 1047 constexpr bool IsLoad = true; |
| 994 IValueT Rt; | 1048 IValueT Rt = encodeRegister(OpRt, "Rt", LdrName); |
| 995 if (encodeOperand(OpRt, Rt) != EncodedAsRegister) | |
| 996 return setNeedsTextFixup(); | |
| 997 const Type Ty = OpRt->getType(); | 1049 const Type Ty = OpRt->getType(); |
| 998 switch (typeWidthInBytesLog2(Ty)) { | 1050 switch (typeWidthInBytesLog2(Ty)) { |
| 999 case 3: | 1051 case 3: |
| 1000 // LDRD is not implemented because target lowering handles i64 and double by | 1052 // LDRD is not implemented because target lowering handles i64 and double by |
| 1001 // using two (32-bit) load instructions. Note: Intenionally drop to default | 1053 // using two (32-bit) load instructions. Note: Intenionally drop to default |
| 1002 // case. | 1054 // case. |
| 1003 default: | 1055 default: |
| 1004 llvm::report_fatal_error(std::string("Type ") + typeString(Ty) + | 1056 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) + |
| 1005 " not implementable using ldr\n"); | 1057 " not implementable\n"); |
| 1006 case 0: { | 1058 case 0: { |
| 1007 // Handles i1 and i8 loads. | 1059 // Handles i1 and i8 loads. |
| 1008 // | 1060 // |
| 1009 // LDRB (immediate) - ARM section A8.8.68, encoding A1: | 1061 // LDRB (immediate) - ARM section A8.8.68, encoding A1: |
| 1010 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1062 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 1011 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1063 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 1012 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1064 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 1013 // | 1065 // |
| 1014 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1066 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1015 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and | 1067 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and |
| 1016 // pu0w0nnnn0000iiiiiiiiiiii=Address. | 1068 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
| 1017 // | 1069 // |
| 1018 // LDRB (register) - ARM section A8.8.66, encoding A1: | 1070 // LDRB (register) - ARM section A8.8.66, encoding A1: |
| 1019 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | 1071 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
| 1020 // ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} | 1072 // ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} |
| 1021 // | 1073 // |
| 1022 // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b | 1074 // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b |
| 1023 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. | 1075 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. |
| 1024 constexpr bool IsByte = true; | 1076 constexpr bool IsByte = true; |
| 1025 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo); | 1077 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); |
| 1026 } | 1078 } |
| 1027 case 1: { | 1079 case 1: { |
| 1028 // Handles i16 loads. | 1080 // Handles i16 loads. |
| 1029 // | 1081 // |
| 1030 // LDRH (immediate) - ARM section A8.8.80, encoding A1: | 1082 // LDRH (immediate) - ARM section A8.8.80, encoding A1: |
| 1031 // ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] | 1083 // ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] |
| 1032 // ldrh<c> <Rt>, [<Rn>], #+/-<Imm8> | 1084 // ldrh<c> <Rt>, [<Rn>], #+/-<Imm8> |
| 1033 // ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | 1085 // ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
| 1034 // | 1086 // |
| 1035 // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1087 // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1036 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and | 1088 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and |
| 1037 // pu0w0nnnn0000iiiiiiiiiiii=Address. | 1089 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
| 1038 return emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo); | 1090 constexpr const char *Ldrh = "ldrh"; |
| 1091 return emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo, Ldrh); | |
| 1039 } | 1092 } |
| 1040 case 2: { | 1093 case 2: { |
| 1041 // Note: Handles i32 and float loads. Target lowering handles i64 and | 1094 // Note: Handles i32 and float loads. Target lowering handles i64 and |
| 1042 // double by using two (32 bit) load instructions. | 1095 // double by using two (32 bit) load instructions. |
| 1043 // | 1096 // |
| 1044 // LDR (immediate) - ARM section A8.8.63, encoding A1: | 1097 // LDR (immediate) - ARM section A8.8.63, encoding A1: |
| 1045 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1098 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 1046 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1099 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 1047 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1100 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 1048 // | 1101 // |
| 1049 // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1102 // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1050 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and | 1103 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and |
| 1051 // | 1104 // |
| 1052 // LDR (register) - ARM section A8.8.70, encoding A1: | 1105 // LDR (register) - ARM section A8.8.70, encoding A1: |
| 1053 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | 1106 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
| 1054 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>} | 1107 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>} |
| 1055 // | 1108 // |
| 1056 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b | 1109 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b |
| 1057 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. | 1110 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. |
| 1058 constexpr bool IsByte = false; | 1111 constexpr bool IsByte = false; |
| 1059 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo); | 1112 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); |
| 1060 } | 1113 } |
| 1061 } | 1114 } |
| 1062 } | 1115 } |
| 1063 | 1116 |
| 1064 void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm, | 1117 void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm, |
| 1065 const Operand *OpSrc1, bool SetFlags, | 1118 const Operand *OpSrc1, bool SetFlags, |
| 1066 CondARM32::Cond Cond) { | 1119 CondARM32::Cond Cond) { |
| 1067 constexpr IValueT Lsl = B3 | B2 | B0; // 1101 | 1120 constexpr const char *LslName = "lsl"; |
| 1068 constexpr IValueT Rn = 0; // Rn field is not used. | 1121 IValueT Rd = encodeRegister(OpRd, "Rd", LslName); |
| 1069 IValueT Rd; | 1122 IValueT Rm = encodeRegister(OpRm, "Rm", LslName); |
| 1070 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) | |
| 1071 return setNeedsTextFixup(); | |
| 1072 IValueT Rm; | |
| 1073 if (encodeOperand(OpRm, Rm) != EncodedAsRegister) | |
| 1074 return setNeedsTextFixup(); | |
| 1075 IValueT Value; | 1123 IValueT Value; |
| 1076 switch (encodeOperand(OpSrc1, Value)) { | 1124 switch (encodeOperand(OpSrc1, Value)) { |
| 1077 default: | 1125 default: |
| 1078 return setNeedsTextFixup(); | 1126 llvm::report_fatal_error(std::string(LslName) + |
| 1127 ": Last operand not understood"); | |
| 1079 case EncodedAsShiftImm5: { | 1128 case EncodedAsShiftImm5: { |
| 1080 // LSL (immediate) - ARM section A8.8.94, encoding A1: | 1129 // LSL (immediate) - ARM section A8.8.94, encoding A1: |
| 1081 // lsl{s}<c> <Rd>, <Rm>, #imm5 | 1130 // lsl{s}<c> <Rd>, <Rm>, #imm5 |
| 1082 // | 1131 // |
| 1083 // cccc0001101s0000ddddiiiii000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, | 1132 // cccc0001101s0000ddddiiiii000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, |
| 1084 // iiiii=imm5, and mmmm=Rm. | 1133 // iiiii=imm5, and mmmm=Rm. |
| 1134 constexpr IValueT LslOpcode = B3 | B2 | B0; // 1101 | |
| 1135 constexpr IValueT Rn = 0; // Rn field is not used. | |
| 1085 Value = Value | (Rm << kRmShift); | 1136 Value = Value | (Rm << kRmShift); |
| 1086 emitType01(Cond, kInstTypeDataRegShift, Lsl, SetFlags, Rn, Rd, Value, | 1137 emitType01(Cond, kInstTypeDataRegShift, LslOpcode, SetFlags, Rn, Rd, Value, |
| 1087 RdIsPcAndSetFlags); | 1138 RdIsPcAndSetFlags, LslName); |
| 1088 return; | 1139 return; |
| 1089 } | 1140 } |
| 1090 case EncodedAsRegister: { | 1141 case EncodedAsRegister: { |
| 1091 // LSL (register) - ARM section A8.8.95, encoding A1: | 1142 // LSL (register) - ARM section A8.8.95, encoding A1: |
| 1092 // lsl{S}<c> <Rd>, <Rm>, <Rs> | 1143 // lsl{S}<c> <Rd>, <Rm>, <Rs> |
| 1093 // | 1144 // |
| 1094 // cccc0001101s0000ddddssss0001mmmm where cccc=Cond, s=SetFlags, dddd=Rd, | 1145 // cccc0001101s0000ddddssss0001mmmm where cccc=Cond, s=SetFlags, dddd=Rd, |
| 1095 // mmmm=Rm, and ssss=Rs. | 1146 // mmmm=Rm, and ssss=Rs. |
| 1096 IValueT Rs; | 1147 constexpr IValueT LslOpcode = B3 | B2 | B0; // 1101 |
| 1097 if (encodeOperand(OpSrc1, Rs) != EncodedAsRegister) | 1148 constexpr IValueT Rn = 0; // Rn field is not used. |
| 1098 return setNeedsTextFixup(); | 1149 IValueT Rs = encodeRegister(OpSrc1, "Rs", LslName); |
| 1099 if ((Rd == RegARM32::Encoded_Reg_pc) || (Rm == RegARM32::Encoded_Reg_pc) || | 1150 verifyRegNotPc(Rd, "Rd", LslName); |
| 1100 (Rs == RegARM32::Encoded_Reg_pc)) | 1151 verifyRegNotPc(Rm, "Rm", LslName); |
| 1101 setNeedsTextFixup(); | 1152 verifyRegNotPc(Rs, "Rs", LslName); |
| 1102 emitType01(Cond, kInstTypeDataRegShift, Lsl, SetFlags, Rn, Rd, | 1153 emitType01(Cond, kInstTypeDataRegShift, LslOpcode, SetFlags, Rn, Rd, |
| 1103 encodeShiftRotateReg(Rm, OperandARM32::kNoShift, Rs), NoChecks); | 1154 encodeShiftRotateReg(Rm, OperandARM32::kNoShift, Rs), NoChecks, |
| 1155 LslName); | |
| 1104 return; | 1156 return; |
| 1105 } | 1157 } |
| 1106 } | 1158 } |
| 1107 } | 1159 } |
| 1108 | 1160 |
| 1109 void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, | 1161 void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |
| 1110 CondARM32::Cond Cond) { | 1162 CondARM32::Cond Cond) { |
| 1111 // MOV (register) - ARM section A8.8.104, encoding A1: | 1163 // MOV (register) - ARM section A8.8.104, encoding A1: |
| 1112 // mov{S}<c> <Rd>, <Rn> | 1164 // mov{S}<c> <Rd>, <Rn> |
| 1113 // | 1165 // |
| 1114 // cccc0001101s0000dddd00000000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, | 1166 // cccc0001101s0000dddd00000000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, |
| 1115 // and nnnn=Rn. | 1167 // and nnnn=Rn. |
| 1116 // | 1168 // |
| 1117 // MOV (immediate) - ARM section A8.8.102, encoding A1: | 1169 // MOV (immediate) - ARM section A8.8.102, encoding A1: |
| 1118 // mov{S}<c> <Rd>, #<RotatedImm8> | 1170 // mov{S}<c> <Rd>, #<RotatedImm8> |
| 1119 // | 1171 // |
| 1120 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, | 1172 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, |
| 1121 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this | 1173 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this |
| 1122 // assembler. | 1174 // assembler. |
| 1123 IValueT Rd; | 1175 constexpr const char *MovName = "mov"; |
| 1124 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) | 1176 IValueT Rd = encodeRegister(OpRd, "Rd", MovName); |
| 1125 return setNeedsTextFixup(); | |
| 1126 constexpr bool SetFlags = false; | 1177 constexpr bool SetFlags = false; |
| 1127 constexpr IValueT Rn = 0; | 1178 constexpr IValueT Rn = 0; |
| 1128 constexpr IValueT Mov = B3 | B2 | B0; // 1101. | 1179 constexpr IValueT MovOpcode = B3 | B2 | B0; // 1101. |
| 1129 emitType01(Mov, Rd, Rn, OpSrc, SetFlags, Cond, RdIsPcAndSetFlags); | 1180 emitType01(Cond, MovOpcode, Rd, Rn, OpSrc, SetFlags, RdIsPcAndSetFlags, |
| 1181 MovName); | |
| 1130 } | 1182 } |
| 1131 | 1183 |
| 1132 void AssemblerARM32::emitMovw(IValueT Opcode, IValueT Rd, IValueT Imm16, | 1184 void AssemblerARM32::emitMovw(IValueT Opcode, IValueT Rd, IValueT Imm16, |
| 1133 bool SetFlags, CondARM32::Cond Cond) { | 1185 bool SetFlags, CondARM32::Cond Cond) { |
| 1134 if (!isConditionDefined(Cond) || !Utils::IsAbsoluteUint(16, Imm16)) | 1186 constexpr const char *MovwName = "movw"; |
| 1135 return setNeedsTextFixup(); | 1187 verifyCondDefined(Cond, MovwName); |
| 1188 if (!Utils::IsAbsoluteUint(16, Imm16)) | |
| 1189 llvm::report_fatal_error(std::string(MovwName) + ": Not I16 constant"); | |
| 1136 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1190 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 1137 const IValueT Encoding = encodeCondition(Cond) << kConditionShift | Opcode | | 1191 const IValueT Encoding = encodeCondition(Cond) << kConditionShift | Opcode | |
| 1138 (encodeBool(SetFlags) << kSShift) | | 1192 (encodeBool(SetFlags) << kSShift) | |
| 1139 ((Imm16 >> 12) << 16) | Rd << kRdShift | | 1193 ((Imm16 >> 12) << 16) | Rd << kRdShift | |
| 1140 (Imm16 & 0xfff); | 1194 (Imm16 & 0xfff); |
| 1141 emitInst(Encoding); | 1195 emitInst(Encoding); |
| 1142 } | 1196 } |
| 1143 | 1197 |
| 1144 void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc, | 1198 void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc, |
| 1145 CondARM32::Cond Cond) { | 1199 CondARM32::Cond Cond) { |
| 1146 IValueT Rd; | 1200 constexpr const char *MovwName = "movw"; |
| 1147 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) | 1201 IValueT Rd = encodeRegister(OpRd, "Rd", MovwName); |
| 1148 return setNeedsTextFixup(); | |
| 1149 if (const auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc)) { | 1202 if (const auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc)) { |
| 1150 // MOVW (immediate) - ARM section A8.8.102, encoding A2: | 1203 // MOVW (immediate) - ARM section A8.8.102, encoding A2: |
| 1151 // movw<c> <Rd>, #<imm16> | 1204 // movw<c> <Rd>, #<imm16> |
| 1152 // | 1205 // |
| 1153 // cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and | 1206 // cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and |
| 1154 // iiiiiiiiiiiiiiii=imm16. | 1207 // iiiiiiiiiiiiiiii=imm16. |
| 1155 if (!isConditionDefined(Cond)) | 1208 verifyCondDefined(Cond, MovwName); |
| 1156 // Conditions of rule violated. | |
| 1157 return setNeedsTextFixup(); | |
| 1158 // Use 0 for the lower 16 bits of the relocatable, and add a fixup to | 1209 // Use 0 for the lower 16 bits of the relocatable, and add a fixup to |
| 1159 // install the correct bits. | 1210 // install the correct bits. |
| 1160 constexpr bool IsMovW = true; | 1211 constexpr bool IsMovW = true; |
| 1161 emitFixup(createMoveFixup(IsMovW, Src)); | 1212 emitFixup(createMoveFixup(IsMovW, Src)); |
| 1162 constexpr IValueT Imm16 = 0; | 1213 constexpr IValueT Imm16 = 0; |
| 1163 constexpr bool SetFlags = false; | 1214 constexpr bool SetFlags = false; |
| 1164 emitMovw(B25 | B24, Rd, Imm16, SetFlags, Cond); | 1215 emitMovw(B25 | B24, Rd, Imm16, SetFlags, Cond); |
| 1165 return; | 1216 return; |
| 1166 } | 1217 } |
| 1167 IValueT ConstVal; | 1218 IValueT ConstVal; |
| 1168 if (encodeOperand(OpSrc, ConstVal) != EncodedAsConstI32) | 1219 if (encodeOperand(OpSrc, ConstVal) != EncodedAsConstI32) |
| 1169 return setNeedsTextFixup(); | 1220 llvm::report_fatal_error(std::string(MovwName) + ": Constant not i32"); |
| 1221 | |
| 1170 // TODO(kschimpf): Determine if we want to handle rotated immediate 8 values | 1222 // TODO(kschimpf): Determine if we want to handle rotated immediate 8 values |
| 1171 // to handle cases where the constant is greater than 16 bits (encoding A1 | 1223 // to handle cases where the constant is greater than 16 bits (encoding A1 |
| 1172 // below). For now, handle using encoding A2. | 1224 // below). For now, handle using encoding A2. |
| 1173 constexpr bool SetFlags = 0; | 1225 constexpr bool SetFlags = 0; |
| 1174 emitMovw(B25 | B24, Rd, ConstVal, SetFlags, Cond); | 1226 emitMovw(B25 | B24, Rd, ConstVal, SetFlags, Cond); |
| 1175 return; | 1227 return; |
| 1176 | 1228 |
| 1177 // MOVW (immediate) - ARM section A8.8.102, encoding A1: | 1229 // MOVW (immediate) - ARM section A8.8.102, encoding A1: |
| 1178 // movw<c> <Rd>, #<RotatedImm8> | 1230 // movw<c> <Rd>, #<RotatedImm8> |
| 1179 // | 1231 // |
| 1180 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, s=SetFlags=0, | 1232 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, s=SetFlags=0, |
| 1181 // and iiiiiiiiiiii is a shift-rotated value defining RotatedImm8. | 1233 // and iiiiiiiiiiii is a shift-rotated value defining RotatedImm8. |
| 1182 } | 1234 } |
| 1183 | 1235 |
| 1184 void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc, | 1236 void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc, |
| 1185 CondARM32::Cond Cond) { | 1237 CondARM32::Cond Cond) { |
| 1186 IValueT Rd; | |
| 1187 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) | |
| 1188 return setNeedsTextFixup(); | |
| 1189 auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc); | |
| 1190 if (Src == nullptr) | |
| 1191 return setNeedsTextFixup(); | |
| 1192 // MOVT - ARM section A8.8.102, encoding A2: | 1238 // MOVT - ARM section A8.8.102, encoding A2: |
| 1193 // movt<c> <Rd>, #<imm16> | 1239 // movt<c> <Rd>, #<imm16> |
| 1194 // | 1240 // |
| 1195 // cccc00110100iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and | 1241 // cccc00110100iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and |
| 1196 // iiiiiiiiiiiiiiii=imm16. | 1242 // iiiiiiiiiiiiiiii=imm16. |
| 1197 if (!isConditionDefined(Cond)) | 1243 constexpr const char *MovtName = "movt"; |
| 1198 // Conditions of rule violated. | 1244 IValueT Rd = encodeRegister(OpRd, "Rd", MovtName); |
| 1245 auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc); | |
| 1246 if (!Src) | |
| 1247 // TODO(kschimpf) Figure out what else can appear here. | |
| 1199 return setNeedsTextFixup(); | 1248 return setNeedsTextFixup(); |
| 1249 verifyCondDefined(Cond, MovtName); | |
| 1200 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1250 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 1201 // Use 0 for the lower 16 bits of the relocatable, and add a fixup to | 1251 // Use 0 for the lower 16 bits of the relocatable, and add a fixup to |
| 1202 // install the correct bits. | 1252 // install the correct bits. |
| 1203 constexpr bool IsMovW = false; | 1253 constexpr bool IsMovW = false; |
| 1204 emitFixup(createMoveFixup(IsMovW, Src)); | 1254 emitFixup(createMoveFixup(IsMovW, Src)); |
| 1205 constexpr IValueT Imm16 = 0; | 1255 constexpr IValueT Imm16 = 0; |
| 1206 const IValueT Encoding = encodeCondition(Cond) << kConditionShift | B25 | | 1256 const IValueT Encoding = encodeCondition(Cond) << kConditionShift | B25 | |
| 1207 B24 | B22 | ((Imm16 >> 12) << 16) | Rd << kRdShift | | 1257 B24 | B22 | ((Imm16 >> 12) << 16) | Rd << kRdShift | |
| 1208 (Imm16 & 0xfff); | 1258 (Imm16 & 0xfff); |
| 1209 emitInst(Encoding); | 1259 emitInst(Encoding); |
| 1210 } | 1260 } |
| 1211 | 1261 |
| 1212 void AssemblerARM32::mvn(const Operand *OpRd, const Operand *OpSrc, | 1262 void AssemblerARM32::mvn(const Operand *OpRd, const Operand *OpSrc, |
| 1213 CondARM32::Cond Cond) { | 1263 CondARM32::Cond Cond) { |
| 1214 // MVN (immediate) - ARM section A8.8.115, encoding A1: | 1264 // MVN (immediate) - ARM section A8.8.115, encoding A1: |
| 1215 // mvn{s}<c> <Rd>, #<const> | 1265 // mvn{s}<c> <Rd>, #<const> |
| 1216 // | 1266 // |
| 1217 // cccc0011111s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags=0, dddd=Rd, | 1267 // cccc0011111s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags=0, dddd=Rd, |
| 1218 // and iiiiiiiiiiii=const | 1268 // and iiiiiiiiiiii=const |
| 1219 // | 1269 // |
| 1220 // MVN (register) - ARM section A8.8.116, encoding A1: | 1270 // MVN (register) - ARM section A8.8.116, encoding A1: |
| 1221 // mvn{s}<c> <Rd>, <Rm>{, <shift> | 1271 // mvn{s}<c> <Rd>, <Rm>{, <shift> |
| 1222 // | 1272 // |
| 1223 // cccc0001111s0000ddddiiiiitt0mmmm where cccc=Cond, s=SetFlags=0, dddd=Rd, | 1273 // cccc0001111s0000ddddiiiiitt0mmmm where cccc=Cond, s=SetFlags=0, dddd=Rd, |
| 1224 // mmmm=Rm, iiii defines shift constant, and tt=ShiftKind. | 1274 // mmmm=Rm, iiii defines shift constant, and tt=ShiftKind. |
| 1225 IValueT Rd; | 1275 constexpr const char *MvnName = "mvn"; |
| 1226 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) | 1276 IValueT Rd = encodeRegister(OpRd, "Rd", MvnName); |
| 1227 return setNeedsTextFixup(); | |
| 1228 constexpr IValueT MvnOpcode = B3 | B2 | B1 | B0; // i.e. 1111 | 1277 constexpr IValueT MvnOpcode = B3 | B2 | B1 | B0; // i.e. 1111 |
| 1229 constexpr IValueT Rn = 0; | 1278 constexpr IValueT Rn = 0; |
| 1230 constexpr bool SetFlags = false; | 1279 constexpr bool SetFlags = false; |
| 1231 emitType01(MvnOpcode, Rd, Rn, OpSrc, SetFlags, Cond, RdIsPcAndSetFlags); | 1280 emitType01(Cond, MvnOpcode, Rd, Rn, OpSrc, SetFlags, RdIsPcAndSetFlags, |
| 1281 MvnName); | |
| 1232 } | 1282 } |
| 1233 | 1283 |
| 1234 void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn, | 1284 void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn, |
| 1235 const Operand *OpSrc1, bool SetFlags, | 1285 const Operand *OpSrc1, bool SetFlags, |
| 1236 CondARM32::Cond Cond) { | 1286 CondARM32::Cond Cond) { |
| 1237 // SBC (register) - ARM section 18.8.162, encoding A1: | 1287 // SBC (register) - ARM section 18.8.162, encoding A1: |
| 1238 // sbc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} | 1288 // sbc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} |
| 1239 // | 1289 // |
| 1240 // cccc0000110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 1290 // cccc0000110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 1241 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. | 1291 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. |
| 1242 // | 1292 // |
| 1243 // SBC (Immediate) - ARM section A8.8.161, encoding A1: | 1293 // SBC (Immediate) - ARM section A8.8.161, encoding A1: |
| 1244 // sbc{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 1294 // sbc{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 1245 // | 1295 // |
| 1246 // cccc0010110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 1296 // cccc0010110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 1247 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 1297 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
| 1248 constexpr IValueT Sbc = B2 | B1; // 0110 | 1298 constexpr const char *SbcName = "sbc"; |
| 1249 emitType01(Sbc, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); | 1299 constexpr IValueT SbcOpcode = B2 | B1; // 0110 |
| 1300 emitType01(Cond, SbcOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, | |
| 1301 SbcName); | |
| 1250 } | 1302 } |
| 1251 | 1303 |
| 1252 void AssemblerARM32::sdiv(const Operand *OpRd, const Operand *OpRn, | 1304 void AssemblerARM32::sdiv(const Operand *OpRd, const Operand *OpRn, |
| 1253 const Operand *OpSrc1, CondARM32::Cond Cond) { | 1305 const Operand *OpSrc1, CondARM32::Cond Cond) { |
| 1254 // SDIV - ARM section A8.8.165, encoding A1. | 1306 // SDIV - ARM section A8.8.165, encoding A1. |
| 1255 // sdiv<c> <Rd>, <Rn>, <Rm> | 1307 // sdiv<c> <Rd>, <Rn>, <Rm> |
| 1256 // | 1308 // |
| 1257 // cccc01110001dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and | 1309 // cccc01110001dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and |
| 1258 // mmmm=Rm. | 1310 // mmmm=Rm. |
| 1259 IValueT Rd; | 1311 constexpr const char *SdivName = "sdiv"; |
| 1260 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) | 1312 IValueT Rd = encodeRegister(OpRd, "Rd", SdivName); |
| 1261 return setNeedsTextFixup(); | 1313 IValueT Rn = encodeRegister(OpRn, "Rn", SdivName); |
| 1262 IValueT Rn; | 1314 IValueT Rm = encodeRegister(OpSrc1, "Rm", SdivName); |
| 1263 if (encodeOperand(OpRn, Rn) != EncodedAsRegister) | 1315 verifyRegNotPc(Rd, "Rd", SdivName); |
| 1264 return setNeedsTextFixup(); | 1316 verifyRegNotPc(Rn, "Rn", SdivName); |
| 1265 IValueT Rm; | 1317 verifyRegNotPc(Rm, "Rm", SdivName); |
| 1266 if (encodeOperand(OpSrc1, Rm) != EncodedAsRegister) | |
| 1267 return setNeedsTextFixup(); | |
| 1268 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || | |
| 1269 Rm == RegARM32::Encoded_Reg_pc) | |
| 1270 llvm::report_fatal_error("Sdiv instruction unpredictable on pc"); | |
| 1271 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. | 1318 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. |
| 1272 constexpr IValueT Opcode = 0; | 1319 constexpr IValueT SdivOpcode = 0; |
| 1273 emitDivOp(Cond, Opcode, Rd, Rn, Rm); | 1320 emitDivOp(Cond, SdivOpcode, Rd, Rn, Rm, SdivName); |
| 1274 } | 1321 } |
| 1275 | 1322 |
| 1276 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, | 1323 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
| 1277 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 1324 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
| 1325 constexpr const char *StrName = "str"; | |
| 1278 constexpr bool IsLoad = false; | 1326 constexpr bool IsLoad = false; |
| 1279 IValueT Rt; | 1327 IValueT Rt = encodeRegister(OpRt, "Rt", StrName); |
| 1280 if (encodeOperand(OpRt, Rt) != EncodedAsRegister) | |
| 1281 return setNeedsTextFixup(); | |
| 1282 const Type Ty = OpRt->getType(); | 1328 const Type Ty = OpRt->getType(); |
| 1283 switch (typeWidthInBytesLog2(Ty)) { | 1329 switch (typeWidthInBytesLog2(Ty)) { |
| 1284 case 3: | 1330 case 3: |
| 1285 // STRD is not implemented because target lowering handles i64 and double by | 1331 // STRD is not implemented because target lowering handles i64 and double by |
| 1286 // using two (32-bit) store instructions. Note: Intenionally drop to | 1332 // using two (32-bit) store instructions. Note: Intenionally drop to |
| 1287 // default case. | 1333 // default case. |
| 1288 default: | 1334 default: |
| 1289 llvm::report_fatal_error(std::string("Type ") + typeString(Ty) + | 1335 llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) + |
| 1290 " not implementable using str\n"); | 1336 " not implemented"); |
| 1291 case 0: { | 1337 case 0: { |
| 1292 // Handles i1 and i8 stores. | 1338 // Handles i1 and i8 stores. |
| 1293 // | 1339 // |
| 1294 // STRB (immediate) - ARM section A8.8.207, encoding A1: | 1340 // STRB (immediate) - ARM section A8.8.207, encoding A1: |
| 1295 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1341 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 1296 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1342 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 1297 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1343 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 1298 // | 1344 // |
| 1299 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1345 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1300 // iiiiiiiiiiii=imm12, u=1 if +. | 1346 // iiiiiiiiiiii=imm12, u=1 if +. |
| 1301 constexpr bool IsByte = true; | 1347 constexpr bool IsByte = true; |
| 1302 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo); | 1348 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); |
| 1303 } | 1349 } |
| 1304 case 1: { | 1350 case 1: { |
| 1305 // Handles i16 stores. | 1351 // Handles i16 stores. |
| 1306 // | 1352 // |
| 1307 // STRH (immediate) - ARM section A8.*.217, encoding A1: | 1353 // STRH (immediate) - ARM section A8.*.217, encoding A1: |
| 1308 // strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] | 1354 // strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] |
| 1309 // strh<c> <Rt>, [<Rn>], #+/-<Imm8> | 1355 // strh<c> <Rt>, [<Rn>], #+/-<Imm8> |
| 1310 // strh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | 1356 // strh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
| 1311 // | 1357 // |
| 1312 // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1358 // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1313 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and | 1359 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and |
| 1314 // pu0w0nnnn0000iiiiiiiiiiii=Address. | 1360 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
| 1315 return emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo); | 1361 constexpr const char *Strh = "strh"; |
| 1362 return emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo, Strh); | |
| 1316 } | 1363 } |
| 1317 case 2: { | 1364 case 2: { |
| 1318 // Note: Handles i32 and float stores. Target lowering handles i64 and | 1365 // Note: Handles i32 and float stores. Target lowering handles i64 and |
| 1319 // double by using two (32 bit) store instructions. | 1366 // double by using two (32 bit) store instructions. |
| 1320 // | 1367 // |
| 1321 // STR (immediate) - ARM section A8.8.207, encoding A1: | 1368 // STR (immediate) - ARM section A8.8.207, encoding A1: |
| 1322 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1369 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 1323 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1370 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 1324 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1371 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 1325 // | 1372 // |
| 1326 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1373 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1327 // iiiiiiiiiiii=imm12, u=1 if +. | 1374 // iiiiiiiiiiii=imm12, u=1 if +. |
| 1328 constexpr bool IsByte = false; | 1375 constexpr bool IsByte = false; |
| 1329 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo); | 1376 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); |
| 1330 return setNeedsTextFixup(); | 1377 return setNeedsTextFixup(); |
| 1331 } | 1378 } |
| 1332 } | 1379 } |
| 1333 } | 1380 } |
| 1334 | 1381 |
| 1335 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, | 1382 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, |
| 1336 const Operand *OpSrc1, bool SetFlags, | 1383 const Operand *OpSrc1, bool SetFlags, |
| 1337 CondARM32::Cond Cond) { | 1384 CondARM32::Cond Cond) { |
| 1338 // ORR (register) - ARM Section A8.8.123, encoding A1: | 1385 // ORR (register) - ARM Section A8.8.123, encoding A1: |
| 1339 // orr{s}<c> <Rd>, <Rn>, <Rm> | 1386 // orr{s}<c> <Rd>, <Rn>, <Rm> |
| 1340 // | 1387 // |
| 1341 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 1388 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 1342 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. | 1389 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. |
| 1343 // | 1390 // |
| 1344 // ORR (register) - ARM Section A8.8.123, encoding A1: | 1391 // ORR (register) - ARM Section A8.8.123, encoding A1: |
| 1345 // orr{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 1392 // orr{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 1346 // | 1393 // |
| 1347 // cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 1394 // cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 1348 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 1395 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
| 1349 constexpr IValueT Orr = B3 | B2; // i.e. 1100 | 1396 constexpr const char *OrrName = "orr"; |
| 1350 emitType01(Orr, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); | 1397 constexpr IValueT OrrOpcode = B3 | B2; // i.e. 1100 |
| 1398 emitType01(Cond, OrrOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, | |
| 1399 OrrName); | |
| 1351 } | 1400 } |
| 1352 | 1401 |
| 1353 void AssemblerARM32::pop(const Operand *OpRt, CondARM32::Cond Cond) { | 1402 void AssemblerARM32::pop(const Operand *OpRt, CondARM32::Cond Cond) { |
| 1354 // POP - ARM section A8.8.132, encoding A2: | 1403 // POP - ARM section A8.8.132, encoding A2: |
| 1355 // pop<c> {Rt} | 1404 // pop<c> {Rt} |
| 1356 // | 1405 // |
| 1357 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. | 1406 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. |
| 1358 IValueT Rt; | 1407 constexpr const char *Pop = "pop"; |
| 1359 if (encodeOperand(OpRt, Rt) != EncodedAsRegister) | 1408 IValueT Rt = encodeRegister(OpRt, "Rt", Pop); |
| 1360 return setNeedsTextFixup(); | 1409 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Pop); |
| 1361 assert(Rt != RegARM32::Encoded_Reg_sp); | |
| 1362 // Same as load instruction. | 1410 // Same as load instruction. |
| 1363 constexpr bool IsLoad = true; | 1411 constexpr bool IsLoad = true; |
| 1364 constexpr bool IsByte = false; | 1412 constexpr bool IsByte = false; |
| 1365 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, | 1413 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, |
| 1366 OperandARM32Mem::PostIndex); | 1414 OperandARM32Mem::PostIndex); |
| 1367 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); | 1415 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address, Pop); |
| 1368 } | 1416 } |
| 1369 | 1417 |
| 1370 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { | 1418 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { |
| 1371 // POP - ARM section A8.*.131, encoding A1: | 1419 // POP - ARM section A8.*.131, encoding A1: |
| 1372 // pop<c> <registers> | 1420 // pop<c> <registers> |
| 1373 // | 1421 // |
| 1374 // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and | 1422 // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and |
| 1375 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). | 1423 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). |
| 1424 constexpr const char *PopListName = "pop {}"; | |
| 1376 constexpr bool IsLoad = true; | 1425 constexpr bool IsLoad = true; |
| 1377 emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); | 1426 emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers, |
| 1427 PopListName); | |
| 1378 } | 1428 } |
| 1379 | 1429 |
| 1380 void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) { | 1430 void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) { |
| 1381 // PUSH - ARM section A8.8.133, encoding A2: | 1431 // PUSH - ARM section A8.8.133, encoding A2: |
| 1382 // push<c> {Rt} | 1432 // push<c> {Rt} |
| 1383 // | 1433 // |
| 1384 // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond. | 1434 // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond. |
| 1385 IValueT Rt; | 1435 constexpr const char *Push = "push"; |
| 1386 if (encodeOperand(OpRt, Rt) != EncodedAsRegister) | 1436 IValueT Rt = encodeRegister(OpRt, "Rt", Push); |
| 1387 return setNeedsTextFixup(); | 1437 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Push); |
| 1388 assert(Rt != RegARM32::Encoded_Reg_sp); | |
| 1389 // Same as store instruction. | 1438 // Same as store instruction. |
| 1390 constexpr bool isLoad = false; | 1439 constexpr bool isLoad = false; |
| 1391 constexpr bool isByte = false; | 1440 constexpr bool isByte = false; |
| 1392 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, | 1441 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, |
| 1393 OperandARM32Mem::PreIndex); | 1442 OperandARM32Mem::PreIndex); |
| 1394 emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address); | 1443 emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address, Push); |
| 1395 } | 1444 } |
| 1396 | 1445 |
| 1397 void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) { | 1446 void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) { |
| 1398 // PUSH - ARM section A8.8.133, encoding A1: | 1447 // PUSH - ARM section A8.8.133, encoding A1: |
| 1399 // push<c> <Registers> | 1448 // push<c> <Registers> |
| 1400 // | 1449 // |
| 1401 // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and | 1450 // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and |
| 1402 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). | 1451 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). |
| 1452 constexpr const char *PushListName = "push {}"; | |
| 1403 constexpr bool IsLoad = false; | 1453 constexpr bool IsLoad = false; |
| 1404 emitMultiMemOp(Cond, DB_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); | 1454 emitMultiMemOp(Cond, DB_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers, |
| 1455 PushListName); | |
| 1405 } | 1456 } |
| 1406 | 1457 |
| 1407 void AssemblerARM32::mla(const Operand *OpRd, const Operand *OpRn, | 1458 void AssemblerARM32::mla(const Operand *OpRd, const Operand *OpRn, |
| 1408 const Operand *OpRm, const Operand *OpRa, | 1459 const Operand *OpRm, const Operand *OpRa, |
| 1409 CondARM32::Cond Cond) { | 1460 CondARM32::Cond Cond) { |
| 1410 IValueT Rd; | |
| 1411 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) | |
| 1412 return setNeedsTextFixup(); | |
| 1413 IValueT Rn; | |
| 1414 if (encodeOperand(OpRn, Rn) != EncodedAsRegister) | |
| 1415 return setNeedsTextFixup(); | |
| 1416 IValueT Rm; | |
| 1417 if (encodeOperand(OpRm, Rm) != EncodedAsRegister) | |
| 1418 return setNeedsTextFixup(); | |
| 1419 IValueT Ra; | |
| 1420 if (encodeOperand(OpRa, Ra) != EncodedAsRegister) | |
| 1421 return setNeedsTextFixup(); | |
| 1422 // MLA - ARM section A8.8.114, encoding A1. | 1461 // MLA - ARM section A8.8.114, encoding A1. |
| 1423 // mla{s}<c> <Rd>, <Rn>, <Rm>, <Ra> | 1462 // mla{s}<c> <Rd>, <Rn>, <Rm>, <Ra> |
| 1424 // | 1463 // |
| 1425 // cccc0000001sddddaaaammmm1001nnnn where cccc=Cond, s=SetFlags, dddd=Rd, | 1464 // cccc0000001sddddaaaammmm1001nnnn where cccc=Cond, s=SetFlags, dddd=Rd, |
| 1426 // aaaa=Ra, mmmm=Rm, and nnnn=Rn. | 1465 // aaaa=Ra, mmmm=Rm, and nnnn=Rn. |
| 1427 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || | 1466 constexpr const char *MlaName = "mla"; |
| 1428 Rm == RegARM32::Encoded_Reg_pc || Ra == RegARM32::Encoded_Reg_pc) | 1467 IValueT Rd = encodeRegister(OpRd, "Rd", MlaName); |
| 1429 llvm::report_fatal_error("Mul instruction unpredictable on pc"); | 1468 IValueT Rn = encodeRegister(OpRn, "Rn", MlaName); |
| 1469 IValueT Rm = encodeRegister(OpRm, "Rm", MlaName); | |
| 1470 IValueT Ra = encodeRegister(OpRa, "Ra", MlaName); | |
| 1471 verifyRegNotPc(Rd, "Rd", MlaName); | |
| 1472 verifyRegNotPc(Rn, "Rn", MlaName); | |
| 1473 verifyRegNotPc(Rm, "Rm", MlaName); | |
| 1474 verifyRegNotPc(Ra, "Ra", MlaName); | |
| 1430 constexpr IValueT MlaOpcode = B21; | 1475 constexpr IValueT MlaOpcode = B21; |
| 1431 constexpr bool SetFlags = false; | 1476 constexpr bool SetFlags = false; |
| 1432 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. | 1477 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. |
| 1433 emitMulOp(Cond, MlaOpcode, Ra, Rd, Rn, Rm, SetFlags); | 1478 emitMulOp(Cond, MlaOpcode, Ra, Rd, Rn, Rm, SetFlags, MlaName); |
| 1434 } | 1479 } |
| 1435 | 1480 |
| 1436 void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn, | 1481 void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn, |
| 1437 const Operand *OpSrc1, bool SetFlags, | 1482 const Operand *OpSrc1, bool SetFlags, |
| 1438 CondARM32::Cond Cond) { | 1483 CondARM32::Cond Cond) { |
| 1439 IValueT Rd; | |
| 1440 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) | |
| 1441 return setNeedsTextFixup(); | |
| 1442 IValueT Rn; | |
| 1443 if (encodeOperand(OpRn, Rn) != EncodedAsRegister) | |
| 1444 return setNeedsTextFixup(); | |
| 1445 IValueT Rm; | |
| 1446 if (encodeOperand(OpSrc1, Rm) != EncodedAsRegister) | |
| 1447 return setNeedsTextFixup(); | |
| 1448 // MUL - ARM section A8.8.114, encoding A1. | 1484 // MUL - ARM section A8.8.114, encoding A1. |
| 1449 // mul{s}<c> <Rd>, <Rn>, <Rm> | 1485 // mul{s}<c> <Rd>, <Rn>, <Rm> |
| 1450 // | 1486 // |
| 1451 // cccc0000000sdddd0000mmmm1001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, | 1487 // cccc0000000sdddd0000mmmm1001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 1452 // mmmm=Rm, and s=SetFlags. | 1488 // mmmm=Rm, and s=SetFlags. |
| 1453 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || | 1489 constexpr const char *MulName = "mul"; |
| 1454 Rm == RegARM32::Encoded_Reg_pc) | 1490 IValueT Rd = encodeRegister(OpRd, "Rd", MulName); |
| 1455 llvm::report_fatal_error("Mul instruction unpredictable on pc"); | 1491 IValueT Rn = encodeRegister(OpRn, "Rn", MulName); |
| 1492 IValueT Rm = encodeRegister(OpSrc1, "Rm", MulName); | |
| 1493 verifyRegNotPc(Rd, "Rd", MulName); | |
| 1494 verifyRegNotPc(Rn, "Rn", MulName); | |
| 1495 verifyRegNotPc(Rm, "Rm", MulName); | |
| 1456 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. | 1496 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. |
| 1457 constexpr IValueT MulOpcode = 0; | 1497 constexpr IValueT MulOpcode = 0; |
| 1458 emitMulOp(Cond, MulOpcode, RegARM32::Encoded_Reg_r0, Rd, Rn, Rm, SetFlags); | 1498 emitMulOp(Cond, MulOpcode, RegARM32::Encoded_Reg_r0, Rd, Rn, Rm, SetFlags, |
| 1499 MulName); | |
| 1459 } | 1500 } |
| 1460 | 1501 |
| 1461 void AssemblerARM32::udiv(const Operand *OpRd, const Operand *OpRn, | 1502 void AssemblerARM32::udiv(const Operand *OpRd, const Operand *OpRn, |
| 1462 const Operand *OpSrc1, CondARM32::Cond Cond) { | 1503 const Operand *OpSrc1, CondARM32::Cond Cond) { |
| 1463 // UDIV - ARM section A8.8.248, encoding A1. | 1504 // UDIV - ARM section A8.8.248, encoding A1. |
| 1464 // udiv<c> <Rd>, <Rn>, <Rm> | 1505 // udiv<c> <Rd>, <Rn>, <Rm> |
| 1465 // | 1506 // |
| 1466 // cccc01110011dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and | 1507 // cccc01110011dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and |
| 1467 // mmmm=Rm. | 1508 // mmmm=Rm. |
| 1468 IValueT Rd; | 1509 constexpr const char *UdivName = "udiv"; |
| 1469 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) | 1510 IValueT Rd = encodeRegister(OpRd, "Rd", UdivName); |
| 1470 return setNeedsTextFixup(); | 1511 IValueT Rn = encodeRegister(OpRn, "Rn", UdivName); |
| 1471 IValueT Rn; | 1512 IValueT Rm = encodeRegister(OpSrc1, "Rm", UdivName); |
| 1472 if (encodeOperand(OpRn, Rn) != EncodedAsRegister) | 1513 verifyRegNotPc(Rd, "Rd", UdivName); |
| 1473 return setNeedsTextFixup(); | 1514 verifyRegNotPc(Rn, "Rn", UdivName); |
| 1474 IValueT Rm; | 1515 verifyRegNotPc(Rm, "Rm", UdivName); |
| 1475 if (encodeOperand(OpSrc1, Rm) != EncodedAsRegister) | |
| 1476 return setNeedsTextFixup(); | |
| 1477 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || | |
| 1478 Rm == RegARM32::Encoded_Reg_pc) | |
| 1479 llvm::report_fatal_error("Udiv instruction unpredictable on pc"); | |
| 1480 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. | 1516 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. |
| 1481 constexpr IValueT Opcode = B21; | 1517 constexpr IValueT UdivOpcode = B21; |
| 1482 emitDivOp(Cond, Opcode, Rd, Rn, Rm); | 1518 emitDivOp(Cond, UdivOpcode, Rd, Rn, Rm, UdivName); |
| 1483 } | 1519 } |
| 1484 | 1520 |
| 1485 void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, | 1521 void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, |
| 1486 const Operand *OpSrc1, bool SetFlags, | 1522 const Operand *OpSrc1, bool SetFlags, |
| 1487 CondARM32::Cond Cond) { | 1523 CondARM32::Cond Cond) { |
| 1488 // SUB (register) - ARM section A8.8.223, encoding A1: | 1524 // SUB (register) - ARM section A8.8.223, encoding A1: |
| 1489 // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} | 1525 // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} |
| 1490 // SUB (SP minus register): See ARM section 8.8.226, encoding A1: | 1526 // SUB (SP minus register): See ARM section 8.8.226, encoding A1: |
| 1491 // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>} | 1527 // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>} |
| 1492 // | 1528 // |
| 1493 // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 1529 // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 1494 // mmmm=Rm, iiiiii=shift, tt=ShiftKind, and s=SetFlags. | 1530 // mmmm=Rm, iiiiii=shift, tt=ShiftKind, and s=SetFlags. |
| 1495 // | 1531 // |
| 1496 // Sub (Immediate) - ARM section A8.8.222, encoding A1: | 1532 // Sub (Immediate) - ARM section A8.8.222, encoding A1: |
| 1497 // sub{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 1533 // sub{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 1498 // Sub (Sp minus immediate) - ARM section A8.*.225, encoding A1: | 1534 // Sub (Sp minus immediate) - ARM section A8.*.225, encoding A1: |
| 1499 // sub{s}<c> sp, <Rn>, #<RotatedImm8> | 1535 // sub{s}<c> sp, <Rn>, #<RotatedImm8> |
| 1500 // | 1536 // |
| 1501 // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 1537 // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 1502 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8 | 1538 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8 |
| 1503 constexpr IValueT Sub = B1; // 0010 | 1539 constexpr const char *SubName = "sub"; |
| 1504 emitType01(Sub, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); | 1540 constexpr IValueT SubOpcode = B1; // 0010 |
| 1541 emitType01(Cond, SubOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, | |
| 1542 SubName); | |
| 1505 } | 1543 } |
| 1506 | 1544 |
| 1507 void AssemblerARM32::tst(const Operand *OpRn, const Operand *OpSrc1, | 1545 void AssemblerARM32::tst(const Operand *OpRn, const Operand *OpSrc1, |
| 1508 CondARM32::Cond Cond) { | 1546 CondARM32::Cond Cond) { |
| 1509 // TST (register) - ARM section A8.8.241, encoding A1: | 1547 // TST (register) - ARM section A8.8.241, encoding A1: |
| 1510 // tst<c> <Rn>, <Rm>(, <shift>} | 1548 // tst<c> <Rn>, <Rm>(, <shift>} |
| 1511 // | 1549 // |
| 1512 // cccc00010001nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, | 1550 // cccc00010001nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, |
| 1513 // iiiii=Shift, and tt=ShiftKind. | 1551 // iiiii=Shift, and tt=ShiftKind. |
| 1514 // | 1552 // |
| 1515 // TST (immediate) - ARM section A8.8.240, encoding A1: | 1553 // TST (immediate) - ARM section A8.8.240, encoding A1: |
| 1516 // tst<c> <Rn>, #<RotatedImm8> | 1554 // tst<c> <Rn>, #<RotatedImm8> |
| 1517 // | 1555 // |
| 1518 // cccc00110001nnnn0000iiiiiiiiiiii where cccc=Cond, nnnn=Rn, and | 1556 // cccc00110001nnnn0000iiiiiiiiiiii where cccc=Cond, nnnn=Rn, and |
| 1519 // iiiiiiiiiiii defines RotatedImm8. | 1557 // iiiiiiiiiiii defines RotatedImm8. |
| 1520 constexpr IValueT Opcode = B3; // ie. 1000 | 1558 constexpr const char *TstName = "tst"; |
| 1521 emitCompareOp(Opcode, OpRn, OpSrc1, Cond); | 1559 constexpr IValueT TstOpcode = B3; // ie. 1000 |
| 1560 emitCompareOp(Cond, TstOpcode, OpRn, OpSrc1, TstName); | |
| 1522 } | 1561 } |
| 1523 | 1562 |
| 1524 void AssemblerARM32::umull(const Operand *OpRdLo, const Operand *OpRdHi, | 1563 void AssemblerARM32::umull(const Operand *OpRdLo, const Operand *OpRdHi, |
| 1525 const Operand *OpRn, const Operand *OpRm, | 1564 const Operand *OpRn, const Operand *OpRm, |
| 1526 CondARM32::Cond Cond) { | 1565 CondARM32::Cond Cond) { |
| 1527 // UMULL - ARM section A8.8.257, encoding A1: | 1566 // UMULL - ARM section A8.8.257, encoding A1: |
| 1528 // umull<c> <RdLo>, <RdHi>, <Rn>, <Rm> | 1567 // umull<c> <RdLo>, <RdHi>, <Rn>, <Rm> |
| 1529 // | 1568 // |
| 1530 // cccc0000100shhhhllllmmmm1001nnnn where hhhh=RdHi, llll=RdLo, nnnn=Rn, | 1569 // cccc0000100shhhhllllmmmm1001nnnn where hhhh=RdHi, llll=RdLo, nnnn=Rn, |
| 1531 // mmmm=Rm, and s=SetFlags | 1570 // mmmm=Rm, and s=SetFlags |
| 1532 IValueT RdLo; | 1571 constexpr const char *UmullName = "umull"; |
| 1533 IValueT RdHi; | 1572 IValueT RdLo = encodeRegister(OpRdLo, "RdLo", UmullName); |
| 1534 IValueT Rn; | 1573 IValueT RdHi = encodeRegister(OpRdHi, "RdHi", UmullName); |
| 1535 IValueT Rm; | 1574 IValueT Rn = encodeRegister(OpRn, "Rn", UmullName); |
| 1536 if (encodeOperand(OpRdLo, RdLo) != EncodedAsRegister || | 1575 IValueT Rm = encodeRegister(OpRm, "Rm", UmullName); |
| 1537 encodeOperand(OpRdHi, RdHi) != EncodedAsRegister || | 1576 verifyRegNotPc(RdLo, "RdLo", UmullName); |
| 1538 encodeOperand(OpRn, Rn) != EncodedAsRegister || | 1577 verifyRegNotPc(RdHi, "RdHi", UmullName); |
| 1539 encodeOperand(OpRm, Rm) != EncodedAsRegister) | 1578 verifyRegNotPc(Rn, "Rn", UmullName); |
| 1540 return setNeedsTextFixup(); | 1579 verifyRegNotPc(Rm, "Rm", UmullName); |
| 1541 if (RdHi == RegARM32::Encoded_Reg_pc || RdLo == RegARM32::Encoded_Reg_pc || | 1580 verifyRegsNotEq(RdHi, "RdHi", RdLo, "RdLo", UmullName); |
| 1542 Rn == RegARM32::Encoded_Reg_pc || Rm == RegARM32::Encoded_Reg_pc || | 1581 constexpr IValueT UmullOpcode = B23; |
| 1543 RdHi == RdLo) | |
| 1544 llvm::report_fatal_error("Umull instruction unpredictable on pc"); | |
| 1545 constexpr bool SetFlags = false; | 1582 constexpr bool SetFlags = false; |
| 1546 emitMulOp(Cond, B23, RdLo, RdHi, Rn, Rm, SetFlags); | 1583 emitMulOp(Cond, UmullOpcode, RdLo, RdHi, Rn, Rm, SetFlags, UmullName); |
| 1547 } | 1584 } |
| 1548 | 1585 |
| 1549 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, | 1586 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, |
| 1550 CondARM32::Cond Cond) { | 1587 CondARM32::Cond Cond) { |
| 1551 IValueT Rd; | 1588 constexpr const char *UxtName = "uxt"; |
| 1552 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) | 1589 IValueT Rd = encodeRegister(OpRd, "Rd", UxtName); |
| 1553 return setNeedsTextFixup(); | 1590 IValueT Rm = encodeRegister(OpSrc0, "Rm", UxtName); |
| 1554 // Note: For the moment, we assume no rotation is specified. | 1591 // Note: For the moment, we assume no rotation is specified. |
| 1555 RotationValue Rotation = kRotateNone; | 1592 RotationValue Rotation = kRotateNone; |
| 1556 constexpr IValueT Rn = RegARM32::Encoded_Reg_pc; | 1593 constexpr IValueT Rn = RegARM32::Encoded_Reg_pc; |
| 1557 IValueT Rm; | |
| 1558 if (encodeOperand(OpSrc0, Rm) != EncodedAsRegister) | |
| 1559 return setNeedsTextFixup(); | |
| 1560 switch (typeWidthInBytes(OpSrc0->getType())) { | 1594 switch (typeWidthInBytes(OpSrc0->getType())) { |
| 1561 default: | 1595 default: |
| 1562 return setNeedsTextFixup(); | 1596 llvm::report_fatal_error("Type of Rm not understood: uxt"); |
| 1563 case 1: { | 1597 case 1: { |
| 1564 // UXTB - ARM section A8.8.274, encoding A1: | 1598 // UXTB - ARM section A8.8.274, encoding A1: |
| 1565 // uxtb<c> <Rd>, <Rm>{, <rotate>} | 1599 // uxtb<c> <Rd>, <Rm>{, <rotate>} |
| 1566 // | 1600 // |
| 1567 // cccc011011101111ddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and | 1601 // cccc011011101111ddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and |
| 1568 // rr defined (RotationValue) rotate. | 1602 // rr defined (RotationValue) rotate. |
| 1569 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21; | 1603 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; |
| 1570 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); | 1604 emitUxt(Cond, UxtOpcode, Rd, Rn, Rm, Rotation, UxtName); |
| 1571 return; | 1605 return; |
| 1572 } | 1606 } |
| 1573 case 2: { | 1607 case 2: { |
| 1574 // UXTH - ARM section A8.8.276, encoding A1: | 1608 // UXTH - ARM section A8.8.276, encoding A1: |
| 1575 // uxth<c> <Rd>< <Rm>{, <rotate>} | 1609 // uxth<c> <Rd>< <Rm>{, <rotate>} |
| 1576 // | 1610 // |
| 1577 // cccc01101111nnnnddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and | 1611 // cccc01101111nnnnddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and |
| 1578 // rr defined (RotationValue) rotate. | 1612 // rr defined (RotationValue) rotate. |
| 1579 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21 | B20; | 1613 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21 | B20; |
| 1580 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); | 1614 emitUxt(Cond, UxtOpcode, Rd, Rn, Rm, Rotation, UxtName); |
| 1581 return; | 1615 return; |
| 1582 } | 1616 } |
| 1583 } | 1617 } |
| 1584 } | 1618 } |
| 1585 | 1619 |
| 1586 } // end of namespace ARM32 | 1620 } // end of namespace ARM32 |
| 1587 } // end of namespace Ice | 1621 } // end of namespace Ice |
| OLD | NEW |