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 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 (typeWidthInBytes(Ty)) { |
| 844 return setNeedsTextFixup(); | |
| 845 const bool IsByte = isByteSizedType(Ty); | |
| 846 IValueT Address; | |
| 847 switch (decodeAddress(OpAddress, Address, TInfo)) { | |
| 848 default: | 998 default: |
|
Jim Stichnoth
2015/12/01 22:45:33
Should "case 8" and "case 16" be explicitly called
Karl
2015/12/02 18:24:44
I'm not sure what you mean? 1 byte corresponds to
| |
| 849 return setNeedsTextFixup(); | 999 return setNeedsTextFixup(); |
| 850 case DecodedAsImmRegOffset: { | 1000 case 1: { |
| 1001 // LDRB (immediate) - ARM section A8.8.68, encoding A1: | |
| 1002 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | |
| 1003 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | |
| 1004 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | |
| 1005 // | |
| 1006 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | |
| 1007 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and | |
| 1008 // pu0w0nnnn0000iiiiiiiiiiii=Address. | |
| 1009 // | |
| 1010 // LDRB (register) - ARM section A8.8.66, encoding A1: | |
| 1011 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | |
| 1012 // ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} | |
| 1013 // | |
| 1014 // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b | |
| 1015 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. | |
| 1016 constexpr bool IsByte = true; | |
| 1017 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo); | |
| 1018 } | |
| 1019 case 2: { | |
| 1020 // LDRH (immediate) - ARM section A8.8.80, encoding A1: | |
| 1021 // ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] | |
| 1022 // ldrh<c> <Rt>, [<Rn>], #+/-<Imm8> | |
| 1023 // ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | |
| 1024 // | |
| 1025 // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, | |
| 1026 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and | |
| 1027 // pu0w0nnnn0000iiiiiiiiiiii=Address. | |
| 1028 return emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo); | |
| 1029 } | |
| 1030 case 4: { | |
| 851 // LDR (immediate) - ARM section A8.8.63, encoding A1: | 1031 // LDR (immediate) - ARM section A8.8.63, encoding A1: |
| 852 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1032 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 853 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1033 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 854 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1034 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 855 // | 1035 // |
| 856 // LDRB (immediate) - ARM section A8.8.68, encoding A1: | 1036 // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 857 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1037 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and |
| 858 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | |
| 859 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | |
| 860 // | 1038 // |
| 861 // cccc010pubw1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1039 // LDR (register) - ARM section A8.8.70, encoding A1: |
| 862 // iiiiiiiiiiii=imm12, b=1 if LDRB, u=1 if +, pu0w is a BlockAddr, and | |
| 863 // pu0w0nnnn0000iiiiiiiiiiii=Address. | |
| 864 | |
| 865 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); | |
| 866 | |
| 867 // Check if conditions of rules violated. | |
| 868 if (Rn == RegARM32::Encoded_Reg_pc) | |
| 869 return setNeedsTextFixup(); | |
| 870 if (!isBitSet(P, Address) && isBitSet(W, Address)) | |
| 871 return setNeedsTextFixup(); | |
| 872 if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) && | |
| 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 } | |
| 879 case DecodedAsShiftRotateImm5: { | |
| 880 // LDR (register) - ARM section A8.8.66, encoding A1: | |
| 881 // ldr<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | |
| 882 // ldr<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} | |
| 883 // | |
| 884 // LDRB (register) - ARM section A8.8.70, encoding A1: | |
| 885 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | 1040 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
| 886 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>} | 1041 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>} |
| 887 // | 1042 // |
| 888 // cccc011pubw1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, | 1043 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b |
| 889 // b=1 if LDRB, U=1 if +, pu0b is a BlockAddr, and | 1044 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. |
| 890 // pu0w0nnnn0000iiiiiss0mmmm=Address. | 1045 constexpr bool IsByte = false; |
| 891 | 1046 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 } | 1047 } |
| 913 } | 1048 } |
| 914 } | 1049 } |
| 915 | 1050 |
| 916 void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm, | 1051 void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm, |
| 917 const Operand *OpSrc1, bool SetFlags, | 1052 const Operand *OpSrc1, bool SetFlags, |
| 918 CondARM32::Cond Cond) { | 1053 CondARM32::Cond Cond) { |
| 919 constexpr IValueT Lsl = B3 | B2 | B0; // 1101 | 1054 constexpr IValueT Lsl = B3 | B2 | B0; // 1101 |
| 920 constexpr IValueT Rn = 0; // Rn field is not used. | 1055 constexpr IValueT Rn = 0; // Rn field is not used. |
| 921 IValueT Rd; | 1056 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 || | 1255 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || |
| 1121 Rm == RegARM32::Encoded_Reg_pc) | 1256 Rm == RegARM32::Encoded_Reg_pc) |
| 1122 llvm::report_fatal_error("Sdiv instruction unpredictable on pc"); | 1257 llvm::report_fatal_error("Sdiv instruction unpredictable on pc"); |
| 1123 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. | 1258 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. |
| 1124 constexpr IValueT Opcode = 0; | 1259 constexpr IValueT Opcode = 0; |
| 1125 emitDivOp(Cond, Opcode, Rd, Rn, Rm); | 1260 emitDivOp(Cond, Opcode, Rd, Rn, Rm); |
| 1126 } | 1261 } |
| 1127 | 1262 |
| 1128 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, | 1263 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
| 1129 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 1264 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
| 1265 constexpr bool IsLoad = false; | |
| 1130 IValueT Rt; | 1266 IValueT Rt; |
| 1131 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 1267 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
| 1132 return setNeedsTextFixup(); | 1268 return setNeedsTextFixup(); |
| 1133 IValueT Address; | 1269 const Type Ty = OpRt->getType(); |
| 1134 if (decodeAddress(OpAddress, Address, TInfo) != DecodedAsImmRegOffset) | 1270 switch (typeWidthInBytes(Ty)) { |
| 1271 default: | |
| 1135 return setNeedsTextFixup(); | 1272 return setNeedsTextFixup(); |
| 1136 // STR (immediate) - ARM section A8.8.204, encoding A1: | 1273 case 1: { |
| 1137 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1274 // STRB (immediate) - ARM section A8.8.207, encoding A1: |
| 1138 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1275 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 1139 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1276 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 1140 // STRB (immediate) - ARM section A8.8.207, encoding A1: | 1277 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 1141 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1278 // |
| 1142 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1279 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1143 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1280 // iiiiiiiiiiii=imm12, u=1 if +. |
| 1144 // | 1281 constexpr bool IsByte = true; |
| 1145 // cccc010pubw0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1282 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo); |
| 1146 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. | 1283 } |
| 1147 constexpr bool IsLoad = false; | 1284 case 2: { |
| 1148 const Type Ty = OpRt->getType(); | 1285 // STRH (immediate) - ARM section A8.*.217, encoding A1: |
| 1149 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | 1286 // strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] |
| 1287 // strh<c> <Rt>, [<Rn>], #+/-<Imm8> | |
| 1288 // strh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | |
| 1289 // | |
| 1290 // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, | |
| 1291 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and | |
| 1292 // pu0w0nnnn0000iiiiiiiiiiii=Address. | |
| 1293 return emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo); | |
| 1294 } | |
| 1295 case 4: { | |
| 1296 // STR (immediate) - ARM section A8.8.207, encoding A1: | |
| 1297 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | |
| 1298 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | |
| 1299 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | |
| 1300 // | |
| 1301 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | |
| 1302 // iiiiiiiiiiii=imm12, u=1 if +. | |
| 1303 constexpr bool IsByte = false; | |
| 1304 return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo); | |
| 1150 return setNeedsTextFixup(); | 1305 return setNeedsTextFixup(); |
| 1151 const bool IsByte = isByteSizedType(Ty); | 1306 } |
| 1152 // Check for rule violations. | 1307 } |
| 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 } | 1308 } |
| 1163 | 1309 |
| 1164 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, | 1310 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, |
| 1165 const Operand *OpSrc1, bool SetFlags, | 1311 const Operand *OpSrc1, bool SetFlags, |
| 1166 CondARM32::Cond Cond) { | 1312 CondARM32::Cond Cond) { |
| 1167 // ORR (register) - ARM Section A8.8.123, encoding A1: | 1313 // ORR (register) - ARM Section A8.8.123, encoding A1: |
| 1168 // orr{s}<c> <Rd>, <Rn>, <Rm> | 1314 // orr{s}<c> <Rd>, <Rn>, <Rm> |
| 1169 // | 1315 // |
| 1170 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 1316 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 1171 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. | 1317 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1184 // pop<c> {Rt} | 1330 // pop<c> {Rt} |
| 1185 // | 1331 // |
| 1186 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. | 1332 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. |
| 1187 IValueT Rt; | 1333 IValueT Rt; |
| 1188 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 1334 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
| 1189 return setNeedsTextFixup(); | 1335 return setNeedsTextFixup(); |
| 1190 assert(Rt != RegARM32::Encoded_Reg_sp); | 1336 assert(Rt != RegARM32::Encoded_Reg_sp); |
| 1191 // Same as load instruction. | 1337 // Same as load instruction. |
| 1192 constexpr bool IsLoad = true; | 1338 constexpr bool IsLoad = true; |
| 1193 constexpr bool IsByte = false; | 1339 constexpr bool IsByte = false; |
| 1194 IValueT Address = decodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, | 1340 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, |
| 1195 OperandARM32Mem::PostIndex); | 1341 OperandARM32Mem::PostIndex); |
| 1196 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); | 1342 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); |
| 1197 } | 1343 } |
| 1198 | 1344 |
| 1199 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { | 1345 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { |
| 1200 // POP - ARM section A8.*.131, encoding A1: | 1346 // POP - ARM section A8.*.131, encoding A1: |
| 1201 // pop<c> <registers> | 1347 // pop<c> <registers> |
| 1202 // | 1348 // |
| 1203 // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and | 1349 // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and |
| 1204 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). | 1350 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). |
| 1205 constexpr bool IsLoad = true; | 1351 constexpr bool IsLoad = true; |
| 1206 emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); | 1352 emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); |
| 1207 } | 1353 } |
| 1208 | 1354 |
| 1209 void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) { | 1355 void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) { |
| 1210 // PUSH - ARM section A8.8.133, encoding A2: | 1356 // PUSH - ARM section A8.8.133, encoding A2: |
| 1211 // push<c> {Rt} | 1357 // push<c> {Rt} |
| 1212 // | 1358 // |
| 1213 // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond. | 1359 // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond. |
| 1214 IValueT Rt; | 1360 IValueT Rt; |
| 1215 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 1361 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
| 1216 return setNeedsTextFixup(); | 1362 return setNeedsTextFixup(); |
| 1217 assert(Rt != RegARM32::Encoded_Reg_sp); | 1363 assert(Rt != RegARM32::Encoded_Reg_sp); |
| 1218 // Same as store instruction. | 1364 // Same as store instruction. |
| 1219 constexpr bool isLoad = false; | 1365 constexpr bool isLoad = false; |
| 1220 constexpr bool isByte = false; | 1366 constexpr bool isByte = false; |
| 1221 IValueT Address = decodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, | 1367 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, |
| 1222 OperandARM32Mem::PreIndex); | 1368 OperandARM32Mem::PreIndex); |
| 1223 emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address); | 1369 emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address); |
| 1224 } | 1370 } |
| 1225 | 1371 |
| 1226 void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) { | 1372 void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) { |
| 1227 // PUSH - ARM section A8.8.133, encoding A1: | 1373 // PUSH - ARM section A8.8.133, encoding A1: |
| 1228 // push<c> <Registers> | 1374 // push<c> <Registers> |
| 1229 // | 1375 // |
| 1230 // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and | 1376 // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and |
| 1231 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). | 1377 // 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. | 1553 // rr defined (RotationValue) rotate. |
| 1408 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21 | B20; | 1554 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21 | B20; |
| 1409 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); | 1555 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); |
| 1410 return; | 1556 return; |
| 1411 } | 1557 } |
| 1412 } | 1558 } |
| 1413 } | 1559 } |
| 1414 | 1560 |
| 1415 } // end of namespace ARM32 | 1561 } // end of namespace ARM32 |
| 1416 } // end of namespace Ice | 1562 } // end of namespace Ice |
| OLD | NEW |