Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/IceAssemblerARM32.cpp

Issue 1516863003: Add various forms of LDREX/STREX to ARM integrated assembler. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix latest issues. Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceAssemblerARM32.h ('k') | src/IceInstARM32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 // Shift instruction register fields encodings. 93 // Shift instruction register fields encodings.
94 static constexpr IValueT kShiftImmShift = 7; 94 static constexpr IValueT kShiftImmShift = 7;
95 static constexpr IValueT kShiftImmBits = 5; 95 static constexpr IValueT kShiftImmBits = 5;
96 static constexpr IValueT kShiftShift = 5; 96 static constexpr IValueT kShiftShift = 5;
97 static constexpr IValueT kImmed12Bits = 12; 97 static constexpr IValueT kImmed12Bits = 12;
98 static constexpr IValueT kImm12Shift = 0; 98 static constexpr IValueT kImm12Shift = 0;
99 99
100 // Rotation instructions (uxtb etc.). 100 // Rotation instructions (uxtb etc.).
101 static constexpr IValueT kRotationShift = 10; 101 static constexpr IValueT kRotationShift = 10;
102 102
103 // MemEx instructions.
104 static constexpr IValueT kMemExOpcodeShift = 20;
105
103 // Div instruction register field encodings. 106 // Div instruction register field encodings.
104 static constexpr IValueT kDivRdShift = 16; 107 static constexpr IValueT kDivRdShift = 16;
105 static constexpr IValueT kDivRmShift = 8; 108 static constexpr IValueT kDivRmShift = 8;
106 static constexpr IValueT kDivRnShift = 0; 109 static constexpr IValueT kDivRnShift = 0;
107 110
108 // Type of instruction encoding (bits 25-27). See ARM section A5.1 111 // Type of instruction encoding (bits 25-27). See ARM section A5.1
109 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000 112 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000
110 static constexpr IValueT kInstTypeDataRegShift = 0; // i.e. 000 113 static constexpr IValueT kInstTypeDataRegShift = 0; // i.e. 000
111 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001 114 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001
112 static constexpr IValueT kInstTypeMemImmediate = 2; // i.e. 010 115 static constexpr IValueT kInstTypeMemImmediate = 2; // i.e. 010
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 } 173 }
171 174
172 // Extract out a Bit in Value. 175 // Extract out a Bit in Value.
173 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; } 176 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; }
174 177
175 // Returns the GPR register at given Shift in Value. 178 // Returns the GPR register at given Shift in Value.
176 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { 179 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) {
177 return decodeGPRRegister((Value >> Shift) & 0xF); 180 return decodeGPRRegister((Value >> Shift) & 0xF);
178 } 181 }
179 182
183 // Defines alternate layouts of instruction operands, should the (common)
184 // default pattern not be used.
185 enum OpEncoding {
186 // No alternate layout specified.
187 DefaultOpEncoding,
188 // Alternate encoding 3 for memory operands (like in strb, strh, ldrb, and
189 // ldrh.
190 OpEncoding3,
191 // Alternate encoding for memory operands for ldrex and strex, which only
192 // actually expect a register.
193 OpEncodingMemEx
194 };
195
196 IValueT getEncodedGPRegNum(const Variable *Var) {
197 int32_t Reg = Var->getRegNum();
198 return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg)
199 : RegARM32::getEncodedGPR(Reg);
200 }
201
180 // The way an operand is encoded into a sequence of bits in functions 202 // The way an operand is encoded into a sequence of bits in functions
181 // encodeOperand and encodeAddress below. 203 // encodeOperand and encodeAddress below.
182 enum EncodedOperand { 204 enum EncodedOperand {
183 // Unable to encode, value left undefined. 205 // Unable to encode, value left undefined.
184 CantEncode = 0, 206 CantEncode = 0,
185 // Value is register found. 207 // Value is register found.
186 EncodedAsRegister, 208 EncodedAsRegister,
187 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 209 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8
188 // value. 210 // value.
189 EncodedAsRotatedImm8, 211 EncodedAsRotatedImm8,
212 // EncodedAsImmRegOffset is a memory operand that can take three forms, based
213 // on OpEncoding:
214 //
215 // ***** DefaultOpEncoding *****
216 //
190 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, 217 // 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 218 // 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. 219 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value.
193 EncodedAsImmRegOffset, 220 //
221 // ***** OpEncoding3 *****
222 //
194 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 223 // 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 224 // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to
196 // Rn. 225 // Rn.
197 EncodedAsImmRegOffsetEnc3, 226 //
227 // ***** OpEncodingMemEx *****
228 //
229 // Value=000000000000nnnn0000000000000000 where nnnn=Rn.
230 EncodedAsImmRegOffset,
198 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, 231 // 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 232 // 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 233 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if
201 // writeback to Rn. 234 // writeback to Rn.
202 EncodedAsShiftRotateImm5, 235 EncodedAsShiftRotateImm5,
203 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value 236 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value
204 // to shift. 237 // to shift.
205 EncodedAsShiftImm5, 238 EncodedAsShiftImm5,
206 // Value=iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift 239 // Value=iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift
207 // kind, and iiiii is the shift amount. 240 // kind, and iiiii is the shift amount.
(...skipping 25 matching lines...) Expand all
233 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, 266 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift,
234 IValueT Rs) { 267 IValueT Rs) {
235 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | 268 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 |
236 (Rm << kRmShift); 269 (Rm << kRmShift);
237 } 270 }
238 271
239 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value) { 272 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value) {
240 Value = 0; // Make sure initialized. 273 Value = 0; // Make sure initialized.
241 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { 274 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
242 if (Var->hasReg()) { 275 if (Var->hasReg()) {
243 Value = Var->getRegNum(); 276 Value = getEncodedGPRegNum(Var);
244 return EncodedAsRegister; 277 return EncodedAsRegister;
245 } 278 }
246 return CantEncode; 279 return CantEncode;
247 } 280 }
248 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { 281 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) {
249 const IValueT Immed8 = FlexImm->getImm(); 282 const IValueT Immed8 = FlexImm->getImm();
250 const IValueT Rotate = FlexImm->getRotateAmt(); 283 const IValueT Rotate = FlexImm->getRotateAmt();
251 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) 284 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))))
252 return CantEncode; 285 return CantEncode;
253 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); 286 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 IValueT Value = Mode | (Rn << kRnShift); 342 IValueT Value = Mode | (Rn << kRnShift);
310 if (Imm8 < 0) { 343 if (Imm8 < 0) {
311 Imm8 = -Imm8; 344 Imm8 = -Imm8;
312 Value = (Value ^ U); 345 Value = (Value ^ U);
313 } 346 }
314 assert(Imm8 < (1 << 8)); 347 assert(Imm8 < (1 << 8));
315 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); 348 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f);
316 return Value; 349 return Value;
317 } 350 }
318 351
319 // Defines alternate layouts of instruction operands, should the (common) 352 IValueT encodeImmRegOffset(OpEncoding AddressEncoding, IValueT Reg,
320 // default pattern not be used. 353 IOffsetT Offset, OperandARM32Mem::AddrMode Mode) {
321 enum OpEncoding { 354 switch (AddressEncoding) {
322 // No alternate layout specified. 355 case DefaultOpEncoding:
323 DefaultOpEncoding, 356 return encodeImmRegOffset(Reg, Offset, Mode);
324 // Alternate encoding 3. 357 case OpEncoding3:
325 OpEncoding3 358 return encodeImmRegOffsetEnc3(Reg, Offset, Mode);
326 }; 359 case OpEncodingMemEx:
360 assert(Offset == 0);
361 assert(Mode == OperandARM32Mem::Offset);
362 return Reg << kRnShift;
363 }
364 }
327 365
328 // Encodes memory address Opnd, and encodes that information into Value, based 366 // Encodes memory address Opnd, and encodes that information into Value, based
329 // on how ARM represents the address. Returns how the value was encoded. 367 // on how ARM represents the address. Returns how the value was encoded.
330 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, 368 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value,
331 const AssemblerARM32::TargetInfo &TInfo, 369 const AssemblerARM32::TargetInfo &TInfo,
332 OpEncoding AddressEncoding = DefaultOpEncoding) { 370 OpEncoding AddressEncoding = DefaultOpEncoding) {
333 Value = 0; // Make sure initialized. 371 Value = 0; // Make sure initialized.
334 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { 372 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
335 // Should be a stack variable, with an offset. 373 // Should be a stack variable, with an offset.
336 if (Var->hasReg()) 374 if (Var->hasReg())
337 return CantEncode; 375 return CantEncode;
338 IOffsetT Offset = Var->getStackOffset(); 376 IOffsetT Offset = Var->getStackOffset();
339 if (!Utils::IsAbsoluteUint(12, Offset)) 377 if (!Utils::IsAbsoluteUint(12, Offset))
340 return CantEncode; 378 return CantEncode;
341 int32_t BaseRegNum = Var->getBaseRegNum(); 379 int32_t BaseRegNum = Var->getBaseRegNum();
342 if (BaseRegNum == Variable::NoRegister) 380 if (BaseRegNum == Variable::NoRegister)
343 BaseRegNum = TInfo.FrameOrStackReg; 381 BaseRegNum = TInfo.FrameOrStackReg;
344 Value = encodeImmRegOffset(BaseRegNum, Offset, OperandARM32Mem::Offset); 382 Value = encodeImmRegOffset(AddressEncoding, BaseRegNum, Offset,
383 OperandARM32Mem::Offset);
345 return EncodedAsImmRegOffset; 384 return EncodedAsImmRegOffset;
346 } 385 }
347 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { 386 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) {
348 Variable *Var = Mem->getBase(); 387 Variable *Var = Mem->getBase();
349 if (!Var->hasReg()) 388 if (!Var->hasReg())
350 return CantEncode; 389 return CantEncode;
351 IValueT Rn = Var->getRegNum(); 390 IValueT Rn = getEncodedGPRegNum(Var);
352 if (Mem->isRegReg()) { 391 if (Mem->isRegReg()) {
353 const Variable *Index = Mem->getIndex(); 392 const Variable *Index = Mem->getIndex();
354 if (Var == nullptr) 393 if (Var == nullptr)
355 return CantEncode; 394 return CantEncode;
356 Value = (Rn << kRnShift) | Mem->getAddrMode() | 395 Value = (Rn << kRnShift) | Mem->getAddrMode() |
357 encodeShiftRotateImm5(Index->getRegNum(), Mem->getShiftOp(), 396 encodeShiftRotateImm5(getEncodedGPRegNum(Index),
358 Mem->getShiftAmt()); 397 Mem->getShiftOp(), Mem->getShiftAmt());
359 return EncodedAsShiftRotateImm5; 398 return EncodedAsShiftRotateImm5;
360 } 399 }
361 // Encoded as immediate register offset. 400 // Encoded as immediate register offset.
362 ConstantInteger32 *Offset = Mem->getOffset(); 401 ConstantInteger32 *Offset = Mem->getOffset();
363 switch (AddressEncoding) { 402 Value = encodeImmRegOffset(AddressEncoding, Rn, Offset->getValue(),
364 case DefaultOpEncoding: 403 Mem->getAddrMode());
365 Value = encodeImmRegOffset(Rn, Offset->getValue(), Mem->getAddrMode()); 404 return EncodedAsImmRegOffset;
366 return EncodedAsImmRegOffset;
367 case OpEncoding3:
368 Value =
369 encodeImmRegOffsetEnc3(Rn, Offset->getValue(), Mem->getAddrMode());
370 return EncodedAsImmRegOffsetEnc3;
371 }
372 } 405 }
373 return CantEncode; 406 return CantEncode;
374 } 407 }
375 408
376 // Checks that Offset can fit in imm24 constant of branch (b) instruction. 409 // Checks that Offset can fit in imm24 constant of branch (b) instruction.
377 bool canEncodeBranchOffset(IOffsetT Offset) { 410 bool canEncodeBranchOffset(IOffsetT Offset) {
378 return Utils::IsAligned(Offset, 4) && 411 return Utils::IsAligned(Offset, 4) &&
379 Utils::IsInt(kBranchOffsetBits, Offset >> 2); 412 Utils::IsInt(kBranchOffsetBits, Offset >> 2);
380 } 413 }
381 414
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 825
793 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, 826 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode,
794 IValueT Rt, const Operand *OpAddress, 827 IValueT Rt, const Operand *OpAddress,
795 const TargetInfo &TInfo, 828 const TargetInfo &TInfo,
796 const char *InstName) { 829 const char *InstName) {
797 IValueT Address; 830 IValueT Address;
798 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { 831 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) {
799 default: 832 default:
800 llvm::report_fatal_error(std::string(InstName) + 833 llvm::report_fatal_error(std::string(InstName) +
801 ": Memory address not understood"); 834 ": Memory address not understood");
802 case EncodedAsImmRegOffsetEnc3: { 835 case EncodedAsImmRegOffset: {
803 // XXXH (immediate) 836 // XXXH (immediate)
804 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] 837 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}]
805 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] 838 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]
806 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! 839 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]!
807 // 840 //
808 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, 841 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt,
809 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, 842 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode,
810 // and pu0w0nnnn0000iiii0000jjjj=Address. 843 // and pu0w0nnnn0000iiii0000jjjj=Address.
811 verifyRegDefined(Rt, "Rt", InstName); 844 verifyRegDefined(Rt, "Rt", InstName);
812 verifyCondDefined(Cond, InstName); 845 verifyCondDefined(Cond, InstName);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
899 } 932 }
900 933
901 void AssemblerARM32::emitSignExtend(CondARM32::Cond Cond, IValueT Opcode, 934 void AssemblerARM32::emitSignExtend(CondARM32::Cond Cond, IValueT Opcode,
902 const Operand *OpRd, const Operand *OpSrc0, 935 const Operand *OpRd, const Operand *OpSrc0,
903 const char *InstName) { 936 const char *InstName) {
904 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); 937 IValueT Rd = encodeRegister(OpRd, "Rd", InstName);
905 IValueT Rm = encodeRegister(OpSrc0, "Rm", InstName); 938 IValueT Rm = encodeRegister(OpSrc0, "Rm", InstName);
906 // Note: For the moment, we assume no rotation is specified. 939 // Note: For the moment, we assume no rotation is specified.
907 RotationValue Rotation = kRotateNone; 940 RotationValue Rotation = kRotateNone;
908 constexpr IValueT Rn = RegARM32::Encoded_Reg_pc; 941 constexpr IValueT Rn = RegARM32::Encoded_Reg_pc;
909 switch (typeWidthInBytes(OpSrc0->getType())) { 942 const Type Ty = OpSrc0->getType();
943 switch (Ty) {
910 default: 944 default:
911 llvm::report_fatal_error(std::string(InstName) + 945 llvm::report_fatal_error(std::string(InstName) + ": Type " +
912 ": Type of Rm not understood"); 946 typeString(Ty) + " not allowed");
913 break; 947 break;
914 case 1: { 948 case IceType_i1:
949 case IceType_i8: {
915 // SXTB/UXTB - Arm sections A8.8.233 and A8.8.274, encoding A1: 950 // SXTB/UXTB - Arm sections A8.8.233 and A8.8.274, encoding A1:
916 // sxtb<c> <Rd>, <Rm>{, <rotate>} 951 // sxtb<c> <Rd>, <Rm>{, <rotate>}
917 // uxtb<c> <Rd>, <Rm>{, <rotate>} 952 // uxtb<c> <Rd>, <Rm>{, <rotate>}
918 // 953 //
919 // ccccxxxxxxxx1111ddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode, 954 // ccccxxxxxxxx1111ddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode,
920 // dddd=Rd, mmmm=Rm, and rr defined (RotationValue) rotate. 955 // dddd=Rd, mmmm=Rm, and rr defined (RotationValue) rotate.
921 break; 956 break;
922 } 957 }
923 case 2: { 958 case IceType_i16: {
924 // SXTH/UXTH - ARM sections A8.8.235 and A8.8.276, encoding A1: 959 // SXTH/UXTH - ARM sections A8.8.235 and A8.8.276, encoding A1:
925 // uxth<c> <Rd>< <Rm>{, <rotate>} 960 // uxth<c> <Rd>< <Rm>{, <rotate>}
926 // 961 //
927 // cccc01101111nnnnddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and 962 // cccc01101111nnnnddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and
928 // rr defined (RotationValue) rotate. 963 // rr defined (RotationValue) rotate.
929 Opcode |= B20; 964 Opcode |= B20;
930 break; 965 break;
931 } 966 }
932 } 967 }
933 968
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1156 emitType01(Cond, EorOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, 1191 emitType01(Cond, EorOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1157 EorName); 1192 EorName);
1158 } 1193 }
1159 1194
1160 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, 1195 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
1161 CondARM32::Cond Cond, const TargetInfo &TInfo) { 1196 CondARM32::Cond Cond, const TargetInfo &TInfo) {
1162 constexpr const char *LdrName = "ldr"; 1197 constexpr const char *LdrName = "ldr";
1163 constexpr bool IsLoad = true; 1198 constexpr bool IsLoad = true;
1164 IValueT Rt = encodeRegister(OpRt, "Rt", LdrName); 1199 IValueT Rt = encodeRegister(OpRt, "Rt", LdrName);
1165 const Type Ty = OpRt->getType(); 1200 const Type Ty = OpRt->getType();
1166 switch (typeWidthInBytesLog2(Ty)) { 1201 switch (Ty) {
1167 case 3: 1202 case IceType_i64:
1168 // LDRD is not implemented because target lowering handles i64 and double by 1203 // LDRD is not implemented because target lowering handles i64 and double by
1169 // using two (32-bit) load instructions. Note: Intenionally drop to default 1204 // using two (32-bit) load instructions. Note: Intentionally drop to default
1170 // case. 1205 // case.
1206 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) +
1207 " not implemented");
1171 default: 1208 default:
1172 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) + 1209 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) +
1173 " not implementable\n"); 1210 " not allowed");
1174 case 0: { 1211 case IceType_i1:
1175 // Handles i1 and i8 loads. 1212 case IceType_i8: {
1176 //
1177 // LDRB (immediate) - ARM section A8.8.68, encoding A1: 1213 // LDRB (immediate) - ARM section A8.8.68, encoding A1:
1178 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 1214 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
1179 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 1215 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
1180 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 1216 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
1181 // 1217 //
1182 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1218 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1183 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and 1219 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and
1184 // pu0w0nnnn0000iiiiiiiiiiii=Address. 1220 // pu0w0nnnn0000iiiiiiiiiiii=Address.
1185 // 1221 //
1186 // LDRB (register) - ARM section A8.8.66, encoding A1: 1222 // LDRB (register) - ARM section A8.8.66, encoding A1:
1187 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} 1223 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
1188 // ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} 1224 // ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
1189 // 1225 //
1190 // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b 1226 // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b
1191 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. 1227 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address.
1192 constexpr bool IsByte = true; 1228 constexpr bool IsByte = true;
1193 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); 1229 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName);
1194 return; 1230 return;
1195 } 1231 }
1196 case 1: { 1232 case IceType_i16: {
1197 // Handles i16 loads.
1198 //
1199 // LDRH (immediate) - ARM section A8.8.80, encoding A1: 1233 // LDRH (immediate) - ARM section A8.8.80, encoding A1:
1200 // ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] 1234 // ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}]
1201 // ldrh<c> <Rt>, [<Rn>], #+/-<Imm8> 1235 // ldrh<c> <Rt>, [<Rn>], #+/-<Imm8>
1202 // ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]! 1236 // ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]!
1203 // 1237 //
1204 // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1238 // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1205 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and 1239 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and
1206 // pu0w0nnnn0000iiiiiiiiiiii=Address. 1240 // pu0w0nnnn0000iiiiiiiiiiii=Address.
1207 constexpr const char *Ldrh = "ldrh"; 1241 constexpr const char *Ldrh = "ldrh";
1208 emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo, Ldrh); 1242 emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo, Ldrh);
1209 return; 1243 return;
1210 } 1244 }
1211 case 2: { 1245 case IceType_i32: {
1212 // Note: Handles i32 and float loads. Target lowering handles i64 and
1213 // double by using two (32 bit) load instructions.
1214 //
1215 // LDR (immediate) - ARM section A8.8.63, encoding A1: 1246 // LDR (immediate) - ARM section A8.8.63, encoding A1:
1216 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 1247 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
1217 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 1248 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
1218 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 1249 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
1219 // 1250 //
1220 // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1251 // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1221 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and 1252 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and
1222 // 1253 //
1223 // LDR (register) - ARM section A8.8.70, encoding A1: 1254 // LDR (register) - ARM section A8.8.70, encoding A1:
1224 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} 1255 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
1225 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>} 1256 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>}
1226 // 1257 //
1227 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b 1258 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b
1228 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. 1259 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address.
1229 constexpr bool IsByte = false; 1260 constexpr bool IsByte = false;
1230 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); 1261 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName);
1231 return; 1262 return;
1232 } 1263 }
1233 } 1264 }
1234 } 1265 }
1235 1266
1267 void AssemblerARM32::emitMemExOp(CondARM32::Cond Cond, Type Ty, bool IsLoad,
1268 const Operand *OpRd, IValueT Rt,
1269 const Operand *OpAddress,
1270 const TargetInfo &TInfo,
1271 const char *InstName) {
1272 IValueT Rd = encodeRegister(OpRd, "Rd", InstName);
1273 IValueT MemExOpcode = IsLoad ? B0 : 0;
1274 switch (Ty) {
1275 default:
1276 llvm::report_fatal_error(std::string(InstName) + ": Type " +
1277 typeString(Ty) + " not allowed");
1278 case IceType_i1:
1279 case IceType_i8:
1280 MemExOpcode |= B2;
1281 break;
1282 case IceType_i16:
1283 MemExOpcode |= B2 | B1;
1284 break;
1285 case IceType_i32:
1286 break;
1287 case IceType_i64:
1288 MemExOpcode |= B1;
1289 }
1290 IValueT AddressRn;
1291 if (encodeAddress(OpAddress, AddressRn, TInfo, OpEncodingMemEx) !=
1292 EncodedAsImmRegOffset)
1293 llvm::report_fatal_error(std::string(InstName) +
1294 ": Can't extract Rn from address");
1295 assert(Utils::IsAbsoluteUint(3, MemExOpcode));
1296 verifyRegDefined(Rd, "Rd", InstName);
1297 verifyRegDefined(Rt, "Rt", InstName);
1298 verifyCondDefined(Cond, InstName);
1299 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1300 IValueT Encoding = (Cond << kConditionShift) | B24 | B23 | B11 | B10 | B9 |
1301 B8 | B7 | B4 | (MemExOpcode << kMemExOpcodeShift) |
1302 AddressRn | (Rd << kRdShift) | (Rt << kRmShift);
1303 emitInst(Encoding);
1304 return;
1305 }
1306
1307 void AssemblerARM32::ldrex(const Operand *OpRt, const Operand *OpAddress,
1308 CondARM32::Cond Cond, const TargetInfo &TInfo) {
1309 // LDREXB - ARM section A8.8.76, encoding A1:
1310 // ldrexb<c> <Rt>, [<Rn>]
1311 //
1312 // cccc00011101nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1313 //
1314 // LDREXH - ARM section A8.8.78, encoding A1:
1315 // ldrexh<c> <Rt>, [<Rn>]
1316 //
1317 // cccc00011111nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1318 //
1319 // LDREX - ARM section A8.8.75, encoding A1:
1320 // ldrex<c> <Rt>, [<Rn>]
1321 //
1322 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1323 //
1324 // LDREXD - ARM section A8.
1325 // ldrexd<c> <Rt>, [<Rn>]
1326 //
1327 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1328 constexpr const char *LdrexName = "ldrex";
1329 const Type Ty = OpRt->getType();
1330 constexpr bool IsLoad = true;
1331 constexpr IValueT Rm = RegARM32::Encoded_Reg_pc;
1332 emitMemExOp(Cond, Ty, IsLoad, OpRt, Rm, OpAddress, TInfo, LdrexName);
1333 }
1334
1236 void AssemblerARM32::emitShift(const CondARM32::Cond Cond, 1335 void AssemblerARM32::emitShift(const CondARM32::Cond Cond,
1237 const OperandARM32::ShiftKind Shift, 1336 const OperandARM32::ShiftKind Shift,
1238 const Operand *OpRd, const Operand *OpRm, 1337 const Operand *OpRd, const Operand *OpRm,
1239 const Operand *OpSrc1, const bool SetFlags, 1338 const Operand *OpSrc1, const bool SetFlags,
1240 const char *InstName) { 1339 const char *InstName) {
1241 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101 1340 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101
1242 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); 1341 IValueT Rd = encodeRegister(OpRd, "Rd", InstName);
1243 IValueT Rm = encodeRegister(OpRm, "Rm", InstName); 1342 IValueT Rm = encodeRegister(OpRm, "Rm", InstName);
1244 IValueT Value; 1343 IValueT Value;
1245 switch (encodeOperand(OpSrc1, Value)) { 1344 switch (encodeOperand(OpSrc1, Value)) {
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1440 constexpr IValueT SdivOpcode = 0; 1539 constexpr IValueT SdivOpcode = 0;
1441 emitDivOp(Cond, SdivOpcode, Rd, Rn, Rm, SdivName); 1540 emitDivOp(Cond, SdivOpcode, Rd, Rn, Rm, SdivName);
1442 } 1541 }
1443 1542
1444 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, 1543 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress,
1445 CondARM32::Cond Cond, const TargetInfo &TInfo) { 1544 CondARM32::Cond Cond, const TargetInfo &TInfo) {
1446 constexpr const char *StrName = "str"; 1545 constexpr const char *StrName = "str";
1447 constexpr bool IsLoad = false; 1546 constexpr bool IsLoad = false;
1448 IValueT Rt = encodeRegister(OpRt, "Rt", StrName); 1547 IValueT Rt = encodeRegister(OpRt, "Rt", StrName);
1449 const Type Ty = OpRt->getType(); 1548 const Type Ty = OpRt->getType();
1450 switch (typeWidthInBytesLog2(Ty)) { 1549 switch (Ty) {
1451 case 3: 1550 case IceType_i64:
1452 // STRD is not implemented because target lowering handles i64 and double by 1551 // STRD is not implemented because target lowering handles i64 and double by
1453 // using two (32-bit) store instructions. Note: Intenionally drop to 1552 // using two (32-bit) store instructions. Note: Intentionally drop to
1454 // default case. 1553 // default case.
1554 llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) +
1555 " not implemented");
1455 default: 1556 default:
1456 llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) + 1557 llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) +
1457 " not implemented"); 1558 " not allowed");
1458 case 0: { 1559 case IceType_i1:
1459 // Handles i1 and i8 stores. 1560 case IceType_i8: {
1460 //
1461 // STRB (immediate) - ARM section A8.8.207, encoding A1: 1561 // STRB (immediate) - ARM section A8.8.207, encoding A1:
1462 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 1562 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
1463 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 1563 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
1464 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 1564 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
1465 // 1565 //
1466 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1566 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1467 // iiiiiiiiiiii=imm12, u=1 if +. 1567 // iiiiiiiiiiii=imm12, u=1 if +.
1468 constexpr bool IsByte = true; 1568 constexpr bool IsByte = true;
1469 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); 1569 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName);
1470 return; 1570 return;
1471 } 1571 }
1472 case 1: { 1572 case IceType_i16: {
1473 // Handles i16 stores.
1474 //
1475 // STRH (immediate) - ARM section A8.*.217, encoding A1: 1573 // STRH (immediate) - ARM section A8.*.217, encoding A1:
1476 // strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] 1574 // strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}]
1477 // strh<c> <Rt>, [<Rn>], #+/-<Imm8> 1575 // strh<c> <Rt>, [<Rn>], #+/-<Imm8>
1478 // strh<c> <Rt>, [<Rn>, #+/-<Imm8>]! 1576 // strh<c> <Rt>, [<Rn>, #+/-<Imm8>]!
1479 // 1577 //
1480 // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1578 // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1481 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and 1579 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and
1482 // pu0w0nnnn0000iiiiiiiiiiii=Address. 1580 // pu0w0nnnn0000iiiiiiiiiiii=Address.
1483 constexpr const char *Strh = "strh"; 1581 constexpr const char *Strh = "strh";
1484 emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo, Strh); 1582 emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo, Strh);
1485 return; 1583 return;
1486 } 1584 }
1487 case 2: { 1585 case IceType_i32: {
1488 // Note: Handles i32 and float stores. Target lowering handles i64 and 1586 // Note: Handles i32 and float stores. Target lowering handles i64 and
1489 // double by using two (32 bit) store instructions. 1587 // double by using two (32 bit) store instructions.
1490 // 1588 //
1491 // STR (immediate) - ARM section A8.8.207, encoding A1: 1589 // STR (immediate) - ARM section A8.8.207, encoding A1:
1492 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 1590 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
1493 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 1591 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
1494 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 1592 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
1495 // 1593 //
1496 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1594 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1497 // iiiiiiiiiiii=imm12, u=1 if +. 1595 // iiiiiiiiiiii=imm12, u=1 if +.
1498 constexpr bool IsByte = false; 1596 constexpr bool IsByte = false;
1499 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); 1597 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName);
1500 return; 1598 return;
1501 } 1599 }
1502 } 1600 }
1503 } 1601 }
1504 1602
1603 void AssemblerARM32::strex(const Operand *OpRd, const Operand *OpRt,
1604 const Operand *OpAddress, CondARM32::Cond Cond,
1605 const TargetInfo &TInfo) {
1606 // STREXB - ARM section A8.8.213, encoding A1:
1607 // strexb<c> <Rd>, <Rt>, [<Rn>]
1608 //
1609 // cccc00011100nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1610 // nnnn=Rn.
1611 //
1612 // STREXH - ARM section A8.8.215, encoding A1:
1613 // strexh<c> <Rd>, <Rt>, [<Rn>]
1614 //
1615 // cccc00011110nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1616 // nnnn=Rn.
1617 //
1618 // STREX - ARM section A8.8.212, encoding A1:
1619 // strex<c> <Rd>, <Rt>, [<Rn>]
1620 //
1621 // cccc00011000nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1622 // nnnn=Rn.
1623 //
1624 // STREXD - ARM section A8.8.214, encoding A1:
1625 // strexd<c> <Rd>, <Rt>, [<Rn>]
1626 //
1627 // cccc00011010nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1628 // nnnn=Rn.
1629 constexpr const char *StrexName = "strex";
1630 // Note: Rt uses Rm shift in encoding.
1631 IValueT Rt = encodeRegister(OpRt, "Rt", StrexName);
1632 const Type Ty = OpRt->getType();
1633 constexpr bool IsLoad = true;
1634 emitMemExOp(Cond, Ty, !IsLoad, OpRd, Rt, OpAddress, TInfo, StrexName);
1635 }
1636
1505 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, 1637 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn,
1506 const Operand *OpSrc1, bool SetFlags, 1638 const Operand *OpSrc1, bool SetFlags,
1507 CondARM32::Cond Cond) { 1639 CondARM32::Cond Cond) {
1508 // ORR (register) - ARM Section A8.8.123, encoding A1: 1640 // ORR (register) - ARM Section A8.8.123, encoding A1:
1509 // orr{s}<c> <Rd>, <Rn>, <Rm> 1641 // orr{s}<c> <Rd>, <Rn>, <Rm>
1510 // 1642 //
1511 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 1643 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1512 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. 1644 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags.
1513 // 1645 //
1514 // ORR (register) - ARM Section A8.8.123, encoding A1: 1646 // ORR (register) - ARM Section A8.8.123, encoding A1:
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1778 1910
1779 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, 1911 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0,
1780 CondARM32::Cond Cond) { 1912 CondARM32::Cond Cond) {
1781 constexpr const char *UxtName = "uxt"; 1913 constexpr const char *UxtName = "uxt";
1782 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; 1914 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21;
1783 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); 1915 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName);
1784 } 1916 }
1785 1917
1786 } // end of namespace ARM32 1918 } // end of namespace ARM32
1787 } // end of namespace Ice 1919 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceAssemblerARM32.h ('k') | src/IceInstARM32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698