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