| 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 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 CantDecode = 0, | 184 CantDecode = 0, |
| 185 // Value is register found. | 185 // Value is register found. |
| 186 DecodedAsRegister, | 186 DecodedAsRegister, |
| 187 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 | 187 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 |
| 188 // value. | 188 // value. |
| 189 DecodedAsRotatedImm8, | 189 DecodedAsRotatedImm8, |
| 190 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, | 190 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, |
| 191 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to | 191 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to |
| 192 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. | 192 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. |
| 193 DecodedAsImmRegOffset, | 193 DecodedAsImmRegOffset, |
| 194 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 |
| 195 // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to |
| 196 // Rn. |
| 197 DecodedAsImmRegOffsetEnc3, |
| 194 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, | 198 // 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 | 199 // 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 | 200 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if |
| 197 // writeback to Rn. | 201 // writeback to Rn. |
| 198 DecodedAsShiftRotateImm5, | 202 DecodedAsShiftRotateImm5, |
| 199 // Value=000000000000000000000iiiii0000000 iiii defines the Imm5 value to | 203 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value |
| 200 // shift. | 204 // to shift. |
| 201 DecodedAsShiftImm5, | 205 DecodedAsShiftImm5, |
| 202 // i.e. iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift | 206 // i.e. iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift |
| 203 // kind, and iiiii is the shift amount. | 207 // kind, and iiiii is the shift amount. |
| 204 DecodedAsShiftedRegister, | 208 DecodedAsShiftedRegister, |
| 205 // Value is 32bit integer constant. | 209 // Value is 32bit integer constant. |
| 206 DecodedAsConstI32 | 210 DecodedAsConstI32 |
| 207 }; | 211 }; |
| 208 | 212 |
| 209 // Sets Encoding to a rotated Imm8 encoding of Value, if possible. | 213 // Sets Encoding to a rotated Imm8 encoding of Value, if possible. |
| 210 inline IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) { | 214 inline IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 } | 269 } |
| 266 if (const auto *ShImm = llvm::dyn_cast<OperandARM32ShAmtImm>(Opnd)) { | 270 if (const auto *ShImm = llvm::dyn_cast<OperandARM32ShAmtImm>(Opnd)) { |
| 267 const IValueT Immed5 = ShImm->getShAmtImm(); | 271 const IValueT Immed5 = ShImm->getShAmtImm(); |
| 268 assert(Immed5 < (1 << kShiftImmBits)); | 272 assert(Immed5 < (1 << kShiftImmBits)); |
| 269 Value = (Immed5 << kShiftImmShift); | 273 Value = (Immed5 << kShiftImmShift); |
| 270 return DecodedAsShiftImm5; | 274 return DecodedAsShiftImm5; |
| 271 } | 275 } |
| 272 return CantDecode; | 276 return CantDecode; |
| 273 } | 277 } |
| 274 | 278 |
| 275 IValueT decodeImmRegOffset(RegARM32::GPRRegister Reg, IOffsetT Offset, | 279 IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset, |
| 276 OperandARM32Mem::AddrMode Mode) { | 280 OperandARM32Mem::AddrMode Mode) { |
| 277 IValueT Value = Mode | (encodeGPRRegister(Reg) << kRnShift); | 281 IValueT Value = Mode | (Reg << kRnShift); |
| 278 if (Offset < 0) { | 282 if (Offset < 0) { |
| 279 Value = (Value ^ U) | -Offset; // Flip U to adjust sign. | 283 Value = (Value ^ U) | -Offset; // Flip U to adjust sign. |
| 280 } else { | 284 } else { |
| 281 Value |= Offset; | 285 Value |= Offset; |
| 282 } | 286 } |
| 283 return Value; | 287 return Value; |
| 284 } | 288 } |
| 285 | 289 |
| 290 // Encodes immediate register offset using encoding 3. |
| 291 IValueT encodeImmRegOffsetEnc3(IValueT Rn, IOffsetT Imm8, |
| 292 OperandARM32Mem::AddrMode Mode) { |
| 293 IValueT Value = Mode | (Rn << kRnShift); |
| 294 if (Imm8 < 0) { |
| 295 Imm8 = -Imm8; |
| 296 Value = (Value ^ U); |
| 297 } |
| 298 assert(Imm8 < (1 << 8)); |
| 299 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); |
| 300 return Value; |
| 301 } |
| 302 |
| 303 // Defines alternate layouts of instruction operands, should the (common) |
| 304 // default pattern not be used. |
| 305 enum OpEncoding { |
| 306 // No alternate layout specified. |
| 307 DefaultOpEncoding, |
| 308 // Alternate encoding 3. |
| 309 OpEncoding3 |
| 310 }; |
| 311 |
| 286 // Decodes memory address Opnd, and encodes that information into Value, | 312 // Decodes memory address Opnd, and encodes that information into Value, |
| 287 // based on how ARM represents the address. Returns how the value was encoded. | 313 // based on how ARM represents the address. Returns how the value was encoded. |
| 288 DecodedResult decodeAddress(const Operand *Opnd, IValueT &Value, | 314 DecodedResult decodeAddress(const Operand *Opnd, IValueT &Value, |
| 289 const AssemblerARM32::TargetInfo &TInfo) { | 315 const AssemblerARM32::TargetInfo &TInfo, |
| 316 OpEncoding AddressEncoding = DefaultOpEncoding) { |
| 290 Value = 0; // Make sure initialized. | 317 Value = 0; // Make sure initialized. |
| 291 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 318 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
| 292 // Should be a stack variable, with an offset. | 319 // Should be a stack variable, with an offset. |
| 293 if (Var->hasReg()) | 320 if (Var->hasReg()) |
| 294 return CantDecode; | 321 return CantDecode; |
| 295 IOffsetT Offset = Var->getStackOffset(); | 322 IOffsetT Offset = Var->getStackOffset(); |
| 296 if (!Utils::IsAbsoluteUint(12, Offset)) | 323 if (!Utils::IsAbsoluteUint(12, Offset)) |
| 297 return CantDecode; | 324 return CantDecode; |
| 298 int32_t BaseRegNum = Var->getBaseRegNum(); | 325 int32_t BaseRegNum = Var->getBaseRegNum(); |
| 299 if (BaseRegNum == Variable::NoRegister) | 326 if (BaseRegNum == Variable::NoRegister) |
| 300 BaseRegNum = TInfo.FrameOrStackReg; | 327 BaseRegNum = TInfo.FrameOrStackReg; |
| 301 Value = decodeImmRegOffset(decodeGPRRegister(BaseRegNum), Offset, | 328 Value = encodeImmRegOffset(BaseRegNum, Offset, OperandARM32Mem::Offset); |
| 302 OperandARM32Mem::Offset); | |
| 303 return DecodedAsImmRegOffset; | 329 return DecodedAsImmRegOffset; |
| 304 } | 330 } |
| 305 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { | 331 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { |
| 306 Variable *Var = Mem->getBase(); | 332 Variable *Var = Mem->getBase(); |
| 307 if (!Var->hasReg()) | 333 if (!Var->hasReg()) |
| 308 return CantDecode; | 334 return CantDecode; |
| 309 IValueT Rn = Var->getRegNum(); | 335 IValueT Rn = Var->getRegNum(); |
| 310 if (Mem->isRegReg()) { | 336 if (Mem->isRegReg()) { |
| 311 const Variable *Index = Mem->getIndex(); | 337 const Variable *Index = Mem->getIndex(); |
| 312 if (Var == nullptr) | 338 if (Var == nullptr) |
| 313 return CantDecode; | 339 return CantDecode; |
| 314 Value = (Rn << kRnShift) | Mem->getAddrMode() | | 340 Value = (Rn << kRnShift) | Mem->getAddrMode() | |
| 315 encodeShiftRotateImm5(Index->getRegNum(), Mem->getShiftOp(), | 341 encodeShiftRotateImm5(Index->getRegNum(), Mem->getShiftOp(), |
| 316 Mem->getShiftAmt()); | 342 Mem->getShiftAmt()); |
| 317 return DecodedAsShiftRotateImm5; | 343 return DecodedAsShiftRotateImm5; |
| 318 } | 344 } |
| 319 // Decoded as immediate register offset. | 345 // Decoded as immediate register offset. |
| 320 ConstantInteger32 *Offset = Mem->getOffset(); | 346 ConstantInteger32 *Offset = Mem->getOffset(); |
| 321 Value = decodeImmRegOffset(decodeGPRRegister(Rn), Offset->getValue(), | 347 switch (AddressEncoding) { |
| 322 Mem->getAddrMode()); | 348 case DefaultOpEncoding: |
| 323 return DecodedAsImmRegOffset; | 349 Value = encodeImmRegOffset(Rn, Offset->getValue(), Mem->getAddrMode()); |
| 350 return DecodedAsImmRegOffset; |
| 351 case OpEncoding3: |
| 352 Value = |
| 353 encodeImmRegOffsetEnc3(Rn, Offset->getValue(), Mem->getAddrMode()); |
| 354 return DecodedAsImmRegOffsetEnc3; |
| 355 } |
| 324 } | 356 } |
| 325 return CantDecode; | 357 return CantDecode; |
| 326 } | 358 } |
| 327 | 359 |
| 328 // Checks that Offset can fit in imm24 constant of branch (b) instruction. | 360 // Checks that Offset can fit in imm24 constant of branch (b) instruction. |
| 329 bool canEncodeBranchOffset(IOffsetT Offset) { | 361 bool canEncodeBranchOffset(IOffsetT Offset) { |
| 330 return Utils::IsAligned(Offset, 4) && | 362 return Utils::IsAligned(Offset, 4) && |
| 331 Utils::IsInt(kBranchOffsetBits, Offset >> 2); | 363 Utils::IsInt(kBranchOffsetBits, Offset >> 2); |
| 332 } | 364 } |
| 333 | 365 |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 IValueT Address) { | 632 IValueT Address) { |
| 601 if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond)) | 633 if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond)) |
| 602 return setNeedsTextFixup(); | 634 return setNeedsTextFixup(); |
| 603 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 635 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 604 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | | 636 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | |
| 605 (InstType << kTypeShift) | (IsLoad ? L : 0) | | 637 (InstType << kTypeShift) | (IsLoad ? L : 0) | |
| 606 (IsByte ? B : 0) | (Rt << kRdShift) | Address; | 638 (IsByte ? B : 0) | (Rt << kRdShift) | Address; |
| 607 emitInst(Encoding); | 639 emitInst(Encoding); |
| 608 } | 640 } |
| 609 | 641 |
| 642 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, |
| 643 IValueT Rt, const Operand *OpAddress, |
| 644 const TargetInfo &TInfo) { |
| 645 IValueT Address; |
| 646 switch (decodeAddress(OpAddress, Address, TInfo)) { |
| 647 default: |
| 648 return setNeedsTextFixup(); |
| 649 case DecodedAsImmRegOffset: { |
| 650 // XXX{B} (immediate): |
| 651 // xxx{b}<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 652 // xxx{b}<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 653 // xxx{b}<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 654 // |
| 655 // cccc010pubwlnnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 656 // iiiiiiiiiiii=imm12, b=IsByte, pu0w<<21 is a BlockAddr, l=IsLoad, and |
| 657 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
| 658 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); |
| 659 |
| 660 // Check if conditions of rules violated. |
| 661 if (Rn == RegARM32::Encoded_Reg_pc) |
| 662 return setNeedsTextFixup(); |
| 663 if (!isBitSet(P, Address) && isBitSet(W, Address)) |
| 664 return setNeedsTextFixup(); |
| 665 if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) && |
| 666 isBitSet(U, Address) & !isBitSet(W, Address) && |
| 667 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) |
| 668 return setNeedsTextFixup(); |
| 669 |
| 670 return emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); |
| 671 } |
| 672 case DecodedAsShiftRotateImm5: { |
| 673 // XXX{B} (register) |
| 674 // xxx{b}<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
| 675 // xxx{b}<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} |
| 676 // |
| 677 // cccc011pubwlnnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, |
| 678 // b=IsByte, U=1 if +, pu0b is a BlockAddr, l=IsLoad, and |
| 679 // pu0w0nnnn0000iiiiiss0mmmm=Address. |
| 680 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); |
| 681 RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address); |
| 682 |
| 683 // Check if conditions of rules violated. |
| 684 if (isBitSet(P, Address) && isBitSet(W, Address)) |
| 685 // Instruction XXXBT! |
| 686 return setNeedsTextFixup(); |
| 687 if (IsByte && |
| 688 ((Rt == RegARM32::Encoded_Reg_pc) || (Rm == RegARM32::Encoded_Reg_pc))) |
| 689 // Unpredictable. |
| 690 return setNeedsTextFixup(); |
| 691 if (!IsByte && Rm == RegARM32::Encoded_Reg_pc) |
| 692 // Unpredictable. |
| 693 return setNeedsTextFixup(); |
| 694 if (isBitSet(W, Address) && |
| 695 ((Rn == RegARM32::Encoded_Reg_pc) || encodeGPRRegister(Rn) == Rt)) |
| 696 // Unpredictable |
| 697 return setNeedsTextFixup(); |
| 698 |
| 699 return emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address); |
| 700 } |
| 701 } |
| 702 } |
| 703 |
| 704 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, |
| 705 IValueT Rt, const Operand *OpAddress, |
| 706 const TargetInfo &TInfo) { |
| 707 IValueT Address; |
| 708 switch (decodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { |
| 709 default: |
| 710 return setNeedsTextFixup(); |
| 711 case DecodedAsImmRegOffsetEnc3: { |
| 712 // XXXH (immediate) |
| 713 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] |
| 714 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] |
| 715 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
| 716 // |
| 717 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, |
| 718 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, |
| 719 // and pu0w0nnnn0000iiii0000jjjj=Address. |
| 720 if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond)) |
| 721 return setNeedsTextFixup(); |
| 722 if (!isBitSet(P, Address) && isBitSet(W, Address)) |
| 723 return setNeedsTextFixup(); |
| 724 if ((Rt == RegARM32::Encoded_Reg_pc) || |
| 725 (isBitSet(W, Address) && |
| 726 (getGPRReg(kRnShift, Address) == decodeGPRRegister(Rt)))) |
| 727 return setNeedsTextFixup(); |
| 728 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | |
| 729 Opcode | (Rt << kRdShift) | Address; |
| 730 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 731 return emitInst(Encoding); |
| 732 } |
| 733 case DecodedAsShiftRotateImm5: { |
| 734 // XXXH (register) |
| 735 // xxxh<c> <Rt>, [<Rn>, +/-<Rm>]{!} |
| 736 // xxxh<c> <Rt>, [<Rn>], +/-<Rm> |
| 737 // |
| 738 // cccc000pu0wxnnnntttt00001011mmmm where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 739 // mmmm=Rm, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, and |
| 740 // pu0w0nnnn000000000000mmmm=Address. |
| 741 if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond)) |
| 742 return setNeedsTextFixup(); |
| 743 if (!isBitSet(P, Address) && isBitSet(W, Address)) |
| 744 return setNeedsTextFixup(); |
| 745 if (Rt == RegARM32::Encoded_Reg_pc) |
| 746 return setNeedsTextFixup(); |
| 747 if (getGPRReg(kRmShift, Address) == RegARM32::Encoded_Reg_pc) |
| 748 return setNeedsTextFixup(); |
| 749 const RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); |
| 750 if (isBitSet(W, Address) && |
| 751 ((Rn == RegARM32::Encoded_Reg_pc) || (encodeGPRRegister(Rn) == Rt))) |
| 752 return setNeedsTextFixup(); |
| 753 if (mask(Address, kShiftImmShift, 5) != 0) |
| 754 // For encoding 3, no shift is allowed. |
| 755 return setNeedsTextFixup(); |
| 756 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | |
| 757 Opcode | (Rt << kRdShift) | Address; |
| 758 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 759 return emitInst(Encoding); |
| 760 } |
| 761 } |
| 762 } |
| 763 |
| 610 void AssemblerARM32::emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, | 764 void AssemblerARM32::emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, |
| 611 IValueT Rn, IValueT Rm) { | 765 IValueT Rn, IValueT Rm) { |
| 612 if (!isGPRRegisterDefined(Rd) || !isGPRRegisterDefined(Rn) || | 766 if (!isGPRRegisterDefined(Rd) || !isGPRRegisterDefined(Rn) || |
| 613 !isGPRRegisterDefined(Rm) || !isConditionDefined(Cond)) | 767 !isGPRRegisterDefined(Rm) || !isConditionDefined(Cond)) |
| 614 return setNeedsTextFixup(); | 768 return setNeedsTextFixup(); |
| 615 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 769 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 616 const IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | | 770 const IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | |
| 617 (Rn << kDivRnShift) | (Rd << kDivRdShift) | B26 | | 771 (Rn << kDivRnShift) | (Rd << kDivRdShift) | B26 | |
| 618 B25 | B24 | B20 | B15 | B14 | B13 | B12 | B4 | | 772 B25 | B24 | B20 | B15 | B14 | B13 | B12 | B4 | |
| 619 (Rm << kDivRmShift); | 773 (Rm << kDivRmShift); |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 833 emitType01(Eor, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); | 987 emitType01(Eor, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); |
| 834 } | 988 } |
| 835 | 989 |
| 836 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, | 990 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, |
| 837 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 991 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
| 838 constexpr bool IsLoad = true; | 992 constexpr bool IsLoad = true; |
| 839 IValueT Rt; | 993 IValueT Rt; |
| 840 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 994 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
| 841 return setNeedsTextFixup(); | 995 return setNeedsTextFixup(); |
| 842 const Type Ty = OpRt->getType(); | 996 const Type Ty = OpRt->getType(); |
| 843 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | 997 switch (typeWidthInBytesLog2(Ty)) { |
| 844 return setNeedsTextFixup(); | 998 case 3: |
| 845 const bool IsByte = isByteSizedType(Ty); | 999 // LDRD is not implemented because target lowering handles i64 and double by |
| 846 IValueT Address; | 1000 // using two (32-bit) load instructions. Note: Intenionally drop to default |
| 847 switch (decodeAddress(OpAddress, Address, TInfo)) { | 1001 // case. |
| 848 default: | 1002 default: |
| 849 return setNeedsTextFixup(); | 1003 llvm::report_fatal_error(std::string("Type ") + typeString(Ty) + |
| 850 case DecodedAsImmRegOffset: { | 1004 " not implementable using ldr\n"); |
| 851 // LDR (immediate) - ARM section A8.8.63, encoding A1: | 1005 case 0: { |
| 852 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1006 // Handles i1 and i8 loads. |
| 853 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | |
| 854 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | |
| 855 // | 1007 // |
| 856 // LDRB (immediate) - ARM section A8.8.68, encoding A1: | 1008 // LDRB (immediate) - ARM section A8.8.68, encoding A1: |
| 857 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1009 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 858 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1010 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 859 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1011 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 860 // | 1012 // |
| 861 // cccc010pubw1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1013 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 862 // iiiiiiiiiiii=imm12, b=1 if LDRB, u=1 if +, pu0w is a BlockAddr, and | 1014 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and |
| 863 // pu0w0nnnn0000iiiiiiiiiiii=Address. | 1015 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
| 864 | 1016 // |
| 865 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); | 1017 // LDRB (register) - ARM section A8.8.66, encoding A1: |
| 866 | 1018 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
| 867 // Check if conditions of rules violated. | 1019 // ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} |
| 868 if (Rn == RegARM32::Encoded_Reg_pc) | 1020 // |
| 869 return setNeedsTextFixup(); | 1021 // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b |
| 870 if (!isBitSet(P, Address) && isBitSet(W, Address)) | 1022 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. |
| 871 return setNeedsTextFixup(); | 1023 constexpr bool IsByte = true; |
| 872 if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) && | 1024 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo); |
| 873 isBitSet(U, Address) & !isBitSet(W, Address) && | |
| 874 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) | |
| 875 return setNeedsTextFixup(); | |
| 876 | |
| 877 return emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); | |
| 878 } | 1025 } |
| 879 case DecodedAsShiftRotateImm5: { | 1026 case 1: { |
| 880 // LDR (register) - ARM section A8.8.66, encoding A1: | 1027 // Handles i16 loads. |
| 881 // ldr<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | |
| 882 // ldr<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} | |
| 883 // | 1028 // |
| 884 // LDRB (register) - ARM section A8.8.70, encoding A1: | 1029 // LDRH (immediate) - ARM section A8.8.80, encoding A1: |
| 1030 // ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] |
| 1031 // ldrh<c> <Rt>, [<Rn>], #+/-<Imm8> |
| 1032 // ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
| 1033 // |
| 1034 // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1035 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and |
| 1036 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
| 1037 return emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo); |
| 1038 } |
| 1039 case 2: { |
| 1040 // Note: Handles i32 and float loads. Target lowering handles i64 and |
| 1041 // double by using two (32 bit) load instructions. |
| 1042 // |
| 1043 // LDR (immediate) - ARM section A8.8.63, encoding A1: |
| 1044 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 1045 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 1046 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 1047 // |
| 1048 // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1049 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and |
| 1050 // |
| 1051 // LDR (register) - ARM section A8.8.70, encoding A1: |
| 885 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | 1052 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
| 886 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>} | 1053 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>} |
| 887 // | 1054 // |
| 888 // cccc011pubw1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, | 1055 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b |
| 889 // b=1 if LDRB, U=1 if +, pu0b is a BlockAddr, and | 1056 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. |
| 890 // pu0w0nnnn0000iiiiiss0mmmm=Address. | 1057 constexpr bool IsByte = false; |
| 891 | 1058 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo); |
| 892 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); | |
| 893 RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address); | |
| 894 | |
| 895 // Check if conditions of rules violated. | |
| 896 if (isBitSet(P, Address) && isBitSet(W, Address)) | |
| 897 // Instruction LDRBT! | |
| 898 return setNeedsTextFixup(); | |
| 899 if (IsByte && | |
| 900 ((Rt == RegARM32::Encoded_Reg_pc) || (Rm == RegARM32::Encoded_Reg_pc))) | |
| 901 // Unpredictable. | |
| 902 return setNeedsTextFixup(); | |
| 903 if (!IsByte && Rm == RegARM32::Encoded_Reg_pc) | |
| 904 // Unpredictable. | |
| 905 return setNeedsTextFixup(); | |
| 906 if (isBitSet(W, Address) && | |
| 907 ((Rn == RegARM32::Encoded_Reg_pc) || encodeGPRRegister(Rn) == Rt)) | |
| 908 // Unpredictable | |
| 909 return setNeedsTextFixup(); | |
| 910 | |
| 911 return emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address); | |
| 912 } | 1059 } |
| 913 } | 1060 } |
| 914 } | 1061 } |
| 915 | 1062 |
| 916 void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm, | 1063 void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm, |
| 917 const Operand *OpSrc1, bool SetFlags, | 1064 const Operand *OpSrc1, bool SetFlags, |
| 918 CondARM32::Cond Cond) { | 1065 CondARM32::Cond Cond) { |
| 919 constexpr IValueT Lsl = B3 | B2 | B0; // 1101 | 1066 constexpr IValueT Lsl = B3 | B2 | B0; // 1101 |
| 920 constexpr IValueT Rn = 0; // Rn field is not used. | 1067 constexpr IValueT Rn = 0; // Rn field is not used. |
| 921 IValueT Rd; | 1068 IValueT Rd; |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1120 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || | 1267 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || |
| 1121 Rm == RegARM32::Encoded_Reg_pc) | 1268 Rm == RegARM32::Encoded_Reg_pc) |
| 1122 llvm::report_fatal_error("Sdiv instruction unpredictable on pc"); | 1269 llvm::report_fatal_error("Sdiv instruction unpredictable on pc"); |
| 1123 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. | 1270 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. |
| 1124 constexpr IValueT Opcode = 0; | 1271 constexpr IValueT Opcode = 0; |
| 1125 emitDivOp(Cond, Opcode, Rd, Rn, Rm); | 1272 emitDivOp(Cond, Opcode, Rd, Rn, Rm); |
| 1126 } | 1273 } |
| 1127 | 1274 |
| 1128 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, | 1275 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
| 1129 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 1276 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
| 1277 constexpr bool IsLoad = false; |
| 1130 IValueT Rt; | 1278 IValueT Rt; |
| 1131 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 1279 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
| 1132 return setNeedsTextFixup(); | 1280 return setNeedsTextFixup(); |
| 1133 IValueT Address; | 1281 const Type Ty = OpRt->getType(); |
| 1134 if (decodeAddress(OpAddress, Address, TInfo) != DecodedAsImmRegOffset) | 1282 switch (typeWidthInBytesLog2(Ty)) { |
| 1283 case 3: |
| 1284 // STRD is not implemented because target lowering handles i64 and double by |
| 1285 // using two (32-bit) store instructions. Note: Intenionally drop to |
| 1286 // default case. |
| 1287 default: |
| 1288 llvm::report_fatal_error(std::string("Type ") + typeString(Ty) + |
| 1289 " not implementable using str\n"); |
| 1290 case 0: { |
| 1291 // Handles i1 and i8 stores. |
| 1292 // |
| 1293 // STRB (immediate) - ARM section A8.8.207, encoding A1: |
| 1294 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 1295 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 1296 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 1297 // |
| 1298 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1299 // iiiiiiiiiiii=imm12, u=1 if +. |
| 1300 constexpr bool IsByte = true; |
| 1301 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo); |
| 1302 } |
| 1303 case 1: { |
| 1304 // Handles i16 stores. |
| 1305 // |
| 1306 // STRH (immediate) - ARM section A8.*.217, encoding A1: |
| 1307 // strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] |
| 1308 // strh<c> <Rt>, [<Rn>], #+/-<Imm8> |
| 1309 // strh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
| 1310 // |
| 1311 // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1312 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and |
| 1313 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
| 1314 return emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo); |
| 1315 } |
| 1316 case 2: { |
| 1317 // Note: Handles i32 and float stores. Target lowering handles i64 and |
| 1318 // double by using two (32 bit) store instructions. |
| 1319 // |
| 1320 // STR (immediate) - ARM section A8.8.207, encoding A1: |
| 1321 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 1322 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 1323 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 1324 // |
| 1325 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1326 // iiiiiiiiiiii=imm12, u=1 if +. |
| 1327 constexpr bool IsByte = false; |
| 1328 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo); |
| 1135 return setNeedsTextFixup(); | 1329 return setNeedsTextFixup(); |
| 1136 // STR (immediate) - ARM section A8.8.204, encoding A1: | 1330 } |
| 1137 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1331 } |
| 1138 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | |
| 1139 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | |
| 1140 // STRB (immediate) - ARM section A8.8.207, encoding A1: | |
| 1141 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | |
| 1142 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | |
| 1143 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | |
| 1144 // | |
| 1145 // cccc010pubw0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | |
| 1146 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. | |
| 1147 constexpr bool IsLoad = false; | |
| 1148 const Type Ty = OpRt->getType(); | |
| 1149 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | |
| 1150 return setNeedsTextFixup(); | |
| 1151 const bool IsByte = isByteSizedType(Ty); | |
| 1152 // Check for rule violations. | |
| 1153 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc)) | |
| 1154 return setNeedsTextFixup(); | |
| 1155 if (!isBitSet(P, Address) && isBitSet(W, Address)) | |
| 1156 return setNeedsTextFixup(); | |
| 1157 if (!IsByte && (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | |
| 1158 isBitSet(P, Address) && !isBitSet(U, Address) && isBitSet(W, Address) && | |
| 1159 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) | |
| 1160 return setNeedsTextFixup(); | |
| 1161 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); | |
| 1162 } | 1332 } |
| 1163 | 1333 |
| 1164 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, | 1334 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, |
| 1165 const Operand *OpSrc1, bool SetFlags, | 1335 const Operand *OpSrc1, bool SetFlags, |
| 1166 CondARM32::Cond Cond) { | 1336 CondARM32::Cond Cond) { |
| 1167 // ORR (register) - ARM Section A8.8.123, encoding A1: | 1337 // ORR (register) - ARM Section A8.8.123, encoding A1: |
| 1168 // orr{s}<c> <Rd>, <Rn>, <Rm> | 1338 // orr{s}<c> <Rd>, <Rn>, <Rm> |
| 1169 // | 1339 // |
| 1170 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 1340 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 1171 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. | 1341 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1184 // pop<c> {Rt} | 1354 // pop<c> {Rt} |
| 1185 // | 1355 // |
| 1186 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. | 1356 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. |
| 1187 IValueT Rt; | 1357 IValueT Rt; |
| 1188 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 1358 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
| 1189 return setNeedsTextFixup(); | 1359 return setNeedsTextFixup(); |
| 1190 assert(Rt != RegARM32::Encoded_Reg_sp); | 1360 assert(Rt != RegARM32::Encoded_Reg_sp); |
| 1191 // Same as load instruction. | 1361 // Same as load instruction. |
| 1192 constexpr bool IsLoad = true; | 1362 constexpr bool IsLoad = true; |
| 1193 constexpr bool IsByte = false; | 1363 constexpr bool IsByte = false; |
| 1194 IValueT Address = decodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, | 1364 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, |
| 1195 OperandARM32Mem::PostIndex); | 1365 OperandARM32Mem::PostIndex); |
| 1196 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); | 1366 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); |
| 1197 } | 1367 } |
| 1198 | 1368 |
| 1199 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { | 1369 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { |
| 1200 // POP - ARM section A8.*.131, encoding A1: | 1370 // POP - ARM section A8.*.131, encoding A1: |
| 1201 // pop<c> <registers> | 1371 // pop<c> <registers> |
| 1202 // | 1372 // |
| 1203 // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and | 1373 // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and |
| 1204 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). | 1374 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). |
| 1205 constexpr bool IsLoad = true; | 1375 constexpr bool IsLoad = true; |
| 1206 emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); | 1376 emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); |
| 1207 } | 1377 } |
| 1208 | 1378 |
| 1209 void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) { | 1379 void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) { |
| 1210 // PUSH - ARM section A8.8.133, encoding A2: | 1380 // PUSH - ARM section A8.8.133, encoding A2: |
| 1211 // push<c> {Rt} | 1381 // push<c> {Rt} |
| 1212 // | 1382 // |
| 1213 // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond. | 1383 // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond. |
| 1214 IValueT Rt; | 1384 IValueT Rt; |
| 1215 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 1385 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
| 1216 return setNeedsTextFixup(); | 1386 return setNeedsTextFixup(); |
| 1217 assert(Rt != RegARM32::Encoded_Reg_sp); | 1387 assert(Rt != RegARM32::Encoded_Reg_sp); |
| 1218 // Same as store instruction. | 1388 // Same as store instruction. |
| 1219 constexpr bool isLoad = false; | 1389 constexpr bool isLoad = false; |
| 1220 constexpr bool isByte = false; | 1390 constexpr bool isByte = false; |
| 1221 IValueT Address = decodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, | 1391 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, |
| 1222 OperandARM32Mem::PreIndex); | 1392 OperandARM32Mem::PreIndex); |
| 1223 emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address); | 1393 emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address); |
| 1224 } | 1394 } |
| 1225 | 1395 |
| 1226 void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) { | 1396 void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) { |
| 1227 // PUSH - ARM section A8.8.133, encoding A1: | 1397 // PUSH - ARM section A8.8.133, encoding A1: |
| 1228 // push<c> <Registers> | 1398 // push<c> <Registers> |
| 1229 // | 1399 // |
| 1230 // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and | 1400 // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and |
| 1231 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). | 1401 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1407 // rr defined (RotationValue) rotate. | 1577 // rr defined (RotationValue) rotate. |
| 1408 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21 | B20; | 1578 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21 | B20; |
| 1409 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); | 1579 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); |
| 1410 return; | 1580 return; |
| 1411 } | 1581 } |
| 1412 } | 1582 } |
| 1413 } | 1583 } |
| 1414 | 1584 |
| 1415 } // end of namespace ARM32 | 1585 } // end of namespace ARM32 |
| 1416 } // end of namespace Ice | 1586 } // end of namespace Ice |
| OLD | NEW |