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