| 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 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 // Rn. | 196 // Rn. |
| 197 EncodedAsImmRegOffsetEnc3, | 197 EncodedAsImmRegOffsetEnc3, |
| 198 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, | 198 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, |
| 199 // mmmm is the index register Rm, iiiii is the shift amount, ss is the shift | 199 // mmmm is the index register Rm, iiiii is the shift amount, ss is the shift |
| 200 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if | 200 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if |
| 201 // writeback to Rn. | 201 // writeback to Rn. |
| 202 EncodedAsShiftRotateImm5, | 202 EncodedAsShiftRotateImm5, |
| 203 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value | 203 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value |
| 204 // to shift. | 204 // to shift. |
| 205 EncodedAsShiftImm5, | 205 EncodedAsShiftImm5, |
| 206 // i.e. iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift | 206 // Value=iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift |
| 207 // kind, and iiiii is the shift amount. | 207 // kind, and iiiii is the shift amount. |
| 208 EncodedAsShiftedRegister, | 208 EncodedAsShiftedRegister, |
| 209 // Value=ssss0tt1mmmm where mmmm=Rm, tt is an encoded ShiftKind, and ssss=Rms. |
| 210 EncodedAsRegShiftReg, |
| 209 // Value is 32bit integer constant. | 211 // Value is 32bit integer constant. |
| 210 EncodedAsConstI32 | 212 EncodedAsConstI32 |
| 211 }; | 213 }; |
| 212 | 214 |
| 213 // Sets Encoding to a rotated Imm8 encoding of Value, if possible. | 215 // Sets Encoding to a rotated Imm8 encoding of Value, if possible. |
| 214 IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) { | 216 IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) { |
| 215 assert(RotateAmt < (1 << kRotateBits)); | 217 assert(RotateAmt < (1 << kRotateBits)); |
| 216 assert(Immed8 < (1 << kImmed8Bits)); | 218 assert(Immed8 < (1 << kImmed8Bits)); |
| 217 return (RotateAmt << kRotateShift) | (Immed8 << kImmed8Shift); | 219 return (RotateAmt << kRotateShift) | (Immed8 << kImmed8Shift); |
| 218 } | 220 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 return CantEncode; | 252 return CantEncode; |
| 251 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); | 253 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); |
| 252 return EncodedAsRotatedImm8; | 254 return EncodedAsRotatedImm8; |
| 253 } | 255 } |
| 254 if (const auto *Const = llvm::dyn_cast<ConstantInteger32>(Opnd)) { | 256 if (const auto *Const = llvm::dyn_cast<ConstantInteger32>(Opnd)) { |
| 255 Value = Const->getValue(); | 257 Value = Const->getValue(); |
| 256 return EncodedAsConstI32; | 258 return EncodedAsConstI32; |
| 257 } | 259 } |
| 258 if (const auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Opnd)) { | 260 if (const auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Opnd)) { |
| 259 Operand *Amt = FlexReg->getShiftAmt(); | 261 Operand *Amt = FlexReg->getShiftAmt(); |
| 260 if (const auto *Imm5 = llvm::dyn_cast<OperandARM32ShAmtImm>(Amt)) { | 262 IValueT Rm; |
| 261 IValueT Rm; | 263 if (encodeOperand(FlexReg->getReg(), Rm) != EncodedAsRegister) |
| 262 if (encodeOperand(FlexReg->getReg(), Rm) != EncodedAsRegister) | 264 return CantEncode; |
| 265 if (const auto *Var = llvm::dyn_cast<Variable>(Amt)) { |
| 266 IValueT Rs; |
| 267 if (encodeOperand(Var, Rs) != EncodedAsRegister) |
| 263 return CantEncode; | 268 return CantEncode; |
| 264 Value = | 269 Value = encodeShiftRotateReg(Rm, FlexReg->getShiftOp(), Rs); |
| 265 encodeShiftRotateImm5(Rm, FlexReg->getShiftOp(), Imm5->getShAmtImm()); | 270 return EncodedAsRegShiftReg; |
| 266 return EncodedAsShiftedRegister; | |
| 267 } | 271 } |
| 268 // TODO(kschimpf): Handle case where Amt is a register? | 272 // If reached, the amount is a shifted amount by some 5-bit immediate. |
| 273 uint32_t Imm5; |
| 274 if (const auto *ShAmt = llvm::dyn_cast<OperandARM32ShAmtImm>(Amt)) { |
| 275 Imm5 = ShAmt->getShAmtImm(); |
| 276 } else if (const auto *IntConst = llvm::dyn_cast<ConstantInteger32>(Amt)) { |
| 277 int32_t Val = IntConst->getValue(); |
| 278 if (Val < 0) |
| 279 return CantEncode; |
| 280 Imm5 = static_cast<uint32_t>(Val); |
| 281 } else |
| 282 return CantEncode; |
| 283 Value = encodeShiftRotateImm5(Rm, FlexReg->getShiftOp(), Imm5); |
| 284 return EncodedAsShiftedRegister; |
| 269 } | 285 } |
| 270 if (const auto *ShImm = llvm::dyn_cast<OperandARM32ShAmtImm>(Opnd)) { | 286 if (const auto *ShImm = llvm::dyn_cast<OperandARM32ShAmtImm>(Opnd)) { |
| 271 const IValueT Immed5 = ShImm->getShAmtImm(); | 287 const IValueT Immed5 = ShImm->getShAmtImm(); |
| 272 assert(Immed5 < (1 << kShiftImmBits)); | 288 assert(Immed5 < (1 << kShiftImmBits)); |
| 273 Value = (Immed5 << kShiftImmShift); | 289 Value = (Immed5 << kShiftImmShift); |
| 274 return EncodedAsShiftImm5; | 290 return EncodedAsShiftImm5; |
| 275 } | 291 } |
| 276 return CantEncode; | 292 return CantEncode; |
| 277 } | 293 } |
| 278 | 294 |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 EmitChecks RuleChecks, const char *InstName) { | 604 EmitChecks RuleChecks, const char *InstName) { |
| 589 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); | 605 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); |
| 590 IValueT Rn = encodeRegister(OpRn, "Rn", InstName); | 606 IValueT Rn = encodeRegister(OpRn, "Rn", InstName); |
| 591 emitType01(Cond, Opcode, Rd, Rn, OpSrc1, SetFlags, RuleChecks, InstName); | 607 emitType01(Cond, Opcode, Rd, Rn, OpSrc1, SetFlags, RuleChecks, InstName); |
| 592 } | 608 } |
| 593 | 609 |
| 594 void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Opcode, | 610 void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Opcode, |
| 595 IValueT Rd, IValueT Rn, const Operand *OpSrc1, | 611 IValueT Rd, IValueT Rn, const Operand *OpSrc1, |
| 596 bool SetFlags, EmitChecks RuleChecks, | 612 bool SetFlags, EmitChecks RuleChecks, |
| 597 const char *InstName) { | 613 const char *InstName) { |
| 598 | |
| 599 IValueT Src1Value; | 614 IValueT Src1Value; |
| 600 // TODO(kschimpf) Other possible decodings of data operations. | 615 // TODO(kschimpf) Other possible decodings of data operations. |
| 601 switch (encodeOperand(OpSrc1, Src1Value)) { | 616 switch (encodeOperand(OpSrc1, Src1Value)) { |
| 602 default: | 617 default: |
| 603 // TODO(kschimpf): Figure out what additional cases need to be handled. | 618 llvm::report_fatal_error(std::string(InstName) + |
| 604 return setNeedsTextFixup(); | 619 ": Can't encode instruction"); |
| 620 return; |
| 605 case EncodedAsRegister: { | 621 case EncodedAsRegister: { |
| 606 // XXX (register) | 622 // XXX (register) |
| 607 // xxx{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} | 623 // xxx{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} |
| 608 // | 624 // |
| 609 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 625 // cccc000xxxxsnnnnddddiiiiitt0mmmm where cccc=Cond, xxxx=Opcode, dddd=Rd, |
| 610 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. | 626 // nnnn=Rn, mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. |
| 611 constexpr IValueT Imm5 = 0; | 627 constexpr IValueT Imm5 = 0; |
| 612 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Imm5); | 628 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Imm5); |
| 613 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, | 629 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, |
| 614 RuleChecks, InstName); | 630 RuleChecks, InstName); |
| 615 return; | 631 return; |
| 616 } | 632 } |
| 617 case EncodedAsShiftedRegister: { | 633 case EncodedAsShiftedRegister: { |
| 618 // Form is defined in case EncodedAsRegister. (i.e. XXX (register)). | 634 // Form is defined in case EncodedAsRegister. (i.e. XXX (register)). |
| 619 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, | 635 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, |
| 620 RuleChecks, InstName); | 636 RuleChecks, InstName); |
| 621 return; | 637 return; |
| 622 } | 638 } |
| 623 case EncodedAsConstI32: { | 639 case EncodedAsConstI32: { |
| 624 // See if we can convert this to an XXX (immediate). | 640 // See if we can convert this to an XXX (immediate). |
| 625 IValueT RotateAmt; | 641 IValueT RotateAmt; |
| 626 IValueT Imm8; | 642 IValueT Imm8; |
| 627 if (!OperandARM32FlexImm::canHoldImm(Src1Value, &RotateAmt, &Imm8)) | 643 if (!OperandARM32FlexImm::canHoldImm(Src1Value, &RotateAmt, &Imm8)) |
| 628 llvm::report_fatal_error(std::string(InstName) + | 644 llvm::report_fatal_error(std::string(InstName) + |
| 629 ": Immediate rotated constant not valid"); | 645 ": Immediate rotated constant not valid"); |
| 630 Src1Value = encodeRotatedImm8(RotateAmt, Imm8); | 646 Src1Value = encodeRotatedImm8(RotateAmt, Imm8); |
| 631 // Intentionally fall to next case! | 647 // Intentionally fall to next case! |
| 632 } | 648 } |
| 633 case EncodedAsRotatedImm8: { | 649 case EncodedAsRotatedImm8: { |
| 634 // XXX (Immediate) | 650 // XXX (Immediate) |
| 635 // xxx{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 651 // xxx{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 636 // | 652 // |
| 637 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 653 // cccc001xxxxsnnnnddddiiiiiiiiiiii where cccc=Cond, xxxx=Opcode, dddd=Rd, |
| 638 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 654 // nnnn=Rn, s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
| 639 emitType01(Cond, kInstTypeDataImmediate, Opcode, SetFlags, Rn, Rd, | 655 emitType01(Cond, kInstTypeDataImmediate, Opcode, SetFlags, Rn, Rd, |
| 640 Src1Value, RuleChecks, InstName); | 656 Src1Value, RuleChecks, InstName); |
| 641 return; | 657 return; |
| 642 } | 658 } |
| 659 case EncodedAsRegShiftReg: { |
| 660 // XXX (register-shifted reg) |
| 661 // xxx{s}<c> <Rd>, <Rn>, <Rm>, <type> <Rs> |
| 662 // |
| 663 // cccc000xxxxfnnnnddddssss0tt1mmmm where cccc=Cond, xxxx=Opcode, dddd=Rd, |
| 664 // nnnn=Rn, ssss=Rs, f=SetFlags, tt is encoding of type, and |
| 665 // Src1Value=ssss01tt1mmmm. |
| 666 emitType01(Cond, kInstTypeDataRegShift, Opcode, SetFlags, Rn, Rd, Src1Value, |
| 667 RuleChecks, InstName); |
| 668 return; |
| 669 } |
| 643 } | 670 } |
| 644 } | 671 } |
| 645 | 672 |
| 646 void AssemblerARM32::emitType05(CondARM32::Cond Cond, IOffsetT Offset, | 673 void AssemblerARM32::emitType05(CondARM32::Cond Cond, IOffsetT Offset, |
| 647 bool Link, const char *InstName) { | 674 bool Link, const char *InstName) { |
| 648 // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and | 675 // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and |
| 649 // iiiiiiiiiiiiiiiiiiiiiiii= | 676 // iiiiiiiiiiiiiiiiiiiiiiii= |
| 650 // EncodedBranchOffset(cccc101l000000000000000000000000, Offset); | 677 // EncodedBranchOffset(cccc101l000000000000000000000000, Offset); |
| 651 verifyCondDefined(Cond, InstName); | 678 verifyCondDefined(Cond, InstName); |
| 652 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 679 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| (...skipping 1098 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1751 | 1778 |
| 1752 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, | 1779 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, |
| 1753 CondARM32::Cond Cond) { | 1780 CondARM32::Cond Cond) { |
| 1754 constexpr const char *UxtName = "uxt"; | 1781 constexpr const char *UxtName = "uxt"; |
| 1755 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; | 1782 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; |
| 1756 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); | 1783 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); |
| 1757 } | 1784 } |
| 1758 | 1785 |
| 1759 } // end of namespace ARM32 | 1786 } // end of namespace ARM32 |
| 1760 } // end of namespace Ice | 1787 } // end of namespace Ice |
| OLD | NEW |