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

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: Update Dart files and fix nits. 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
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 23 matching lines...) Expand all
34 34
35 // The following define individual bits. 35 // The following define individual bits.
36 static constexpr IValueT B0 = 1; 36 static constexpr IValueT B0 = 1;
37 static constexpr IValueT B1 = 1 << 1; 37 static constexpr IValueT B1 = 1 << 1;
38 static constexpr IValueT B2 = 1 << 2; 38 static constexpr IValueT B2 = 1 << 2;
39 static constexpr IValueT B3 = 1 << 3; 39 static constexpr IValueT B3 = 1 << 3;
40 static constexpr IValueT B4 = 1 << 4; 40 static constexpr IValueT B4 = 1 << 4;
41 static constexpr IValueT B5 = 1 << 5; 41 static constexpr IValueT B5 = 1 << 5;
42 static constexpr IValueT B6 = 1 << 6; 42 static constexpr IValueT B6 = 1 << 6;
43 static constexpr IValueT B7 = 1 << 7; 43 static constexpr IValueT B7 = 1 << 7;
44 static constexpr IValueT B8 = 1 << 8;
45 static constexpr IValueT B9 = 1 << 9;
46 static constexpr IValueT B10 = 1 << 10;
47 static constexpr IValueT B11 = 1 << 11;
44 static constexpr IValueT B12 = 1 << 12; 48 static constexpr IValueT B12 = 1 << 12;
45 static constexpr IValueT B13 = 1 << 13; 49 static constexpr IValueT B13 = 1 << 13;
46 static constexpr IValueT B14 = 1 << 14; 50 static constexpr IValueT B14 = 1 << 14;
47 static constexpr IValueT B15 = 1 << 15; 51 static constexpr IValueT B15 = 1 << 15;
48 static constexpr IValueT B16 = 1 << 16; 52 static constexpr IValueT B16 = 1 << 16;
49 static constexpr IValueT B17 = 1 << 17; 53 static constexpr IValueT B17 = 1 << 17;
50 static constexpr IValueT B18 = 1 << 18; 54 static constexpr IValueT B18 = 1 << 18;
51 static constexpr IValueT B19 = 1 << 19; 55 static constexpr IValueT B19 = 1 << 19;
52 static constexpr IValueT B20 = 1 << 20; 56 static constexpr IValueT B20 = 1 << 20;
53 static constexpr IValueT B21 = 1 << 21; 57 static constexpr IValueT B21 = 1 << 21;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 // Shift instruction register fields encodings. 93 // Shift instruction register fields encodings.
90 static constexpr IValueT kShiftImmShift = 7; 94 static constexpr IValueT kShiftImmShift = 7;
91 static constexpr IValueT kShiftImmBits = 5; 95 static constexpr IValueT kShiftImmBits = 5;
92 static constexpr IValueT kShiftShift = 5; 96 static constexpr IValueT kShiftShift = 5;
93 static constexpr IValueT kImmed12Bits = 12; 97 static constexpr IValueT kImmed12Bits = 12;
94 static constexpr IValueT kImm12Shift = 0; 98 static constexpr IValueT kImm12Shift = 0;
95 99
96 // Rotation instructions (uxtb etc.). 100 // Rotation instructions (uxtb etc.).
97 static constexpr IValueT kRotationShift = 10; 101 static constexpr IValueT kRotationShift = 10;
98 102
103 // MemEx instructions.
104 static constexpr IValueT kMemExOpcodeShift = 20;
105
99 // Div instruction register field encodings. 106 // Div instruction register field encodings.
100 static constexpr IValueT kDivRdShift = 16; 107 static constexpr IValueT kDivRdShift = 16;
101 static constexpr IValueT kDivRmShift = 8; 108 static constexpr IValueT kDivRmShift = 8;
102 static constexpr IValueT kDivRnShift = 0; 109 static constexpr IValueT kDivRnShift = 0;
103 110
104 // 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
105 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000 112 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000
106 static constexpr IValueT kInstTypeDataRegShift = 0; // i.e. 000 113 static constexpr IValueT kInstTypeDataRegShift = 0; // i.e. 000
107 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001 114 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001
108 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
166 } 173 }
167 174
168 // Extract out a Bit in Value. 175 // Extract out a Bit in Value.
169 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; } 176 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; }
170 177
171 // Returns the GPR register at given Shift in Value. 178 // Returns the GPR register at given Shift in Value.
172 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { 179 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) {
173 return decodeGPRRegister((Value >> Shift) & 0xF); 180 return decodeGPRRegister((Value >> Shift) & 0xF);
174 } 181 }
175 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 getVarRegNum(const Variable *Var) {
Jim Stichnoth 2015/12/11 17:24:57 This function name should be changed, to reflect t
Karl 2015/12/11 18:05:08 Changed to getEncodedGPRegNum.
197 int32_t Reg = Var->getRegNum();
198 return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg)
199 : RegARM32::getEncodedGPR(Reg);
200 }
201
176 // 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
177 // encodeOperand and encodeAddress below. 203 // encodeOperand and encodeAddress below.
178 enum EncodedOperand { 204 enum EncodedOperand {
179 // Unable to encode, value left undefined. 205 // Unable to encode, value left undefined.
180 CantEncode = 0, 206 CantEncode = 0,
181 // Value is register found. 207 // Value is register found.
182 EncodedAsRegister, 208 EncodedAsRegister,
183 // 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
184 // value. 210 // value.
185 EncodedAsRotatedImm8, 211 EncodedAsRotatedImm8,
212 // EncodedAsImmRegOffset is a memory operand that can take three forms, based
213 // on OpEncoding:
214 //
215 // case DefaultOpEncoding:
Jim Stichnoth 2015/12/11 17:24:57 This style of comment made me think you had some s
Karl 2015/12/11 18:05:08 Ok. Done.
216 //
186 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, 217 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn,
187 // 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
188 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. 219 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value.
189 EncodedAsImmRegOffset, 220 //
221 // case OpEncoding3:
222 //
190 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 223 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1
191 // 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
192 // Rn. 225 // Rn.
193 EncodedAsImmRegOffsetEnc3, 226 //
227 // case OpEncodingMemEx:
228 //
229 // Value=000000000000nnnn0000000000000000 where nnnn=Rn.
230 EncodedAsImmRegOffset,
194 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, 231 // 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 232 // 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 233 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if
197 // writeback to Rn. 234 // writeback to Rn.
198 EncodedAsShiftRotateImm5, 235 EncodedAsShiftRotateImm5,
199 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value 236 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value
200 // to shift. 237 // to shift.
201 EncodedAsShiftImm5, 238 EncodedAsShiftImm5,
202 // i.e. iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift 239 // i.e. iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift
203 // kind, and iiiii is the shift amount. 240 // kind, and iiiii is the shift amount.
(...skipping 23 matching lines...) Expand all
227 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, 264 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift,
228 IValueT Rs) { 265 IValueT Rs) {
229 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | 266 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 |
230 (Rm << kRmShift); 267 (Rm << kRmShift);
231 } 268 }
232 269
233 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value) { 270 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value) {
234 Value = 0; // Make sure initialized. 271 Value = 0; // Make sure initialized.
235 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { 272 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
236 if (Var->hasReg()) { 273 if (Var->hasReg()) {
237 Value = Var->getRegNum(); 274 Value = getVarRegNum(Var);
238 return EncodedAsRegister; 275 return EncodedAsRegister;
239 } 276 }
240 return CantEncode; 277 return CantEncode;
241 } 278 }
242 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { 279 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) {
243 const IValueT Immed8 = FlexImm->getImm(); 280 const IValueT Immed8 = FlexImm->getImm();
244 const IValueT Rotate = FlexImm->getRotateAmt(); 281 const IValueT Rotate = FlexImm->getRotateAmt();
245 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) 282 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))))
246 return CantEncode; 283 return CantEncode;
247 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); 284 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 IValueT Value = Mode | (Rn << kRnShift); 326 IValueT Value = Mode | (Rn << kRnShift);
290 if (Imm8 < 0) { 327 if (Imm8 < 0) {
291 Imm8 = -Imm8; 328 Imm8 = -Imm8;
292 Value = (Value ^ U); 329 Value = (Value ^ U);
293 } 330 }
294 assert(Imm8 < (1 << 8)); 331 assert(Imm8 < (1 << 8));
295 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); 332 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f);
296 return Value; 333 return Value;
297 } 334 }
298 335
299 // Defines alternate layouts of instruction operands, should the (common) 336 IValueT encodeImmRegOffset(OpEncoding AddressEncoding, IValueT Reg,
300 // default pattern not be used. 337 IOffsetT Offset, OperandARM32Mem::AddrMode Mode) {
301 enum OpEncoding { 338 switch (AddressEncoding) {
302 // No alternate layout specified. 339 case DefaultOpEncoding:
303 DefaultOpEncoding, 340 return encodeImmRegOffset(Reg, Offset, Mode);
304 // Alternate encoding 3. 341 case OpEncoding3:
305 OpEncoding3 342 return encodeImmRegOffsetEnc3(Reg, Offset, Mode);
306 }; 343 case OpEncodingMemEx:
344 assert(Offset == 0);
345 assert(Mode == OperandARM32Mem::Offset);
346 return Reg << kRnShift;
347 }
348 }
307 349
308 // Encodes memory address Opnd, and encodes that information into Value, based 350 // Encodes memory address Opnd, and encodes that information into Value, based
309 // on how ARM represents the address. Returns how the value was encoded. 351 // on how ARM represents the address. Returns how the value was encoded.
310 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, 352 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value,
311 const AssemblerARM32::TargetInfo &TInfo, 353 const AssemblerARM32::TargetInfo &TInfo,
312 OpEncoding AddressEncoding = DefaultOpEncoding) { 354 OpEncoding AddressEncoding = DefaultOpEncoding) {
313 Value = 0; // Make sure initialized. 355 Value = 0; // Make sure initialized.
314 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { 356 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
315 // Should be a stack variable, with an offset. 357 // Should be a stack variable, with an offset.
316 if (Var->hasReg()) 358 if (Var->hasReg())
317 return CantEncode; 359 return CantEncode;
318 IOffsetT Offset = Var->getStackOffset(); 360 IOffsetT Offset = Var->getStackOffset();
319 if (!Utils::IsAbsoluteUint(12, Offset)) 361 if (!Utils::IsAbsoluteUint(12, Offset))
320 return CantEncode; 362 return CantEncode;
321 int32_t BaseRegNum = Var->getBaseRegNum(); 363 int32_t BaseRegNum = Var->getBaseRegNum();
322 if (BaseRegNum == Variable::NoRegister) 364 if (BaseRegNum == Variable::NoRegister)
323 BaseRegNum = TInfo.FrameOrStackReg; 365 BaseRegNum = TInfo.FrameOrStackReg;
324 Value = encodeImmRegOffset(BaseRegNum, Offset, OperandARM32Mem::Offset); 366 Value = encodeImmRegOffset(AddressEncoding, BaseRegNum, Offset,
367 OperandARM32Mem::Offset);
325 return EncodedAsImmRegOffset; 368 return EncodedAsImmRegOffset;
326 } 369 }
327 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { 370 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) {
328 Variable *Var = Mem->getBase(); 371 Variable *Var = Mem->getBase();
329 if (!Var->hasReg()) 372 if (!Var->hasReg())
330 return CantEncode; 373 return CantEncode;
331 IValueT Rn = Var->getRegNum(); 374 IValueT Rn = getVarRegNum(Var);
332 if (Mem->isRegReg()) { 375 if (Mem->isRegReg()) {
333 const Variable *Index = Mem->getIndex(); 376 const Variable *Index = Mem->getIndex();
334 if (Var == nullptr) 377 if (Var == nullptr)
335 return CantEncode; 378 return CantEncode;
336 Value = (Rn << kRnShift) | Mem->getAddrMode() | 379 Value = (Rn << kRnShift) | Mem->getAddrMode() |
337 encodeShiftRotateImm5(Index->getRegNum(), Mem->getShiftOp(), 380 encodeShiftRotateImm5(getVarRegNum(Index), Mem->getShiftOp(),
338 Mem->getShiftAmt()); 381 Mem->getShiftAmt());
339 return EncodedAsShiftRotateImm5; 382 return EncodedAsShiftRotateImm5;
340 } 383 }
341 // Encoded as immediate register offset. 384 // Encoded as immediate register offset.
342 ConstantInteger32 *Offset = Mem->getOffset(); 385 ConstantInteger32 *Offset = Mem->getOffset();
343 switch (AddressEncoding) { 386 Value = encodeImmRegOffset(AddressEncoding, Rn, Offset->getValue(),
344 case DefaultOpEncoding: 387 Mem->getAddrMode());
345 Value = encodeImmRegOffset(Rn, Offset->getValue(), Mem->getAddrMode()); 388 return EncodedAsImmRegOffset;
346 return EncodedAsImmRegOffset;
347 case OpEncoding3:
348 Value =
349 encodeImmRegOffsetEnc3(Rn, Offset->getValue(), Mem->getAddrMode());
350 return EncodedAsImmRegOffsetEnc3;
351 }
352 } 389 }
353 return CantEncode; 390 return CantEncode;
354 } 391 }
355 392
356 // Checks that Offset can fit in imm24 constant of branch (b) instruction. 393 // Checks that Offset can fit in imm24 constant of branch (b) instruction.
357 bool canEncodeBranchOffset(IOffsetT Offset) { 394 bool canEncodeBranchOffset(IOffsetT Offset) {
358 return Utils::IsAligned(Offset, 4) && 395 return Utils::IsAligned(Offset, 4) &&
359 Utils::IsInt(kBranchOffsetBits, Offset >> 2); 396 Utils::IsInt(kBranchOffsetBits, Offset >> 2);
360 } 397 }
361 398
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 798
762 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, 799 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode,
763 IValueT Rt, const Operand *OpAddress, 800 IValueT Rt, const Operand *OpAddress,
764 const TargetInfo &TInfo, 801 const TargetInfo &TInfo,
765 const char *InstName) { 802 const char *InstName) {
766 IValueT Address; 803 IValueT Address;
767 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { 804 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) {
768 default: 805 default:
769 llvm::report_fatal_error(std::string(InstName) + 806 llvm::report_fatal_error(std::string(InstName) +
770 ": Memory address not understood"); 807 ": Memory address not understood");
771 case EncodedAsImmRegOffsetEnc3: { 808 case EncodedAsImmRegOffset: {
772 // XXXH (immediate) 809 // XXXH (immediate)
773 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] 810 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}]
774 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] 811 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]
775 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! 812 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]!
776 // 813 //
777 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, 814 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt,
778 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, 815 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode,
779 // and pu0w0nnnn0000iiii0000jjjj=Address. 816 // and pu0w0nnnn0000iiii0000jjjj=Address.
780 verifyRegDefined(Rt, "Rt", InstName); 817 verifyRegDefined(Rt, "Rt", InstName);
781 verifyCondDefined(Cond, InstName); 818 verifyCondDefined(Cond, InstName);
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
1132 constexpr bool IsLoad = true; 1169 constexpr bool IsLoad = true;
1133 IValueT Rt = encodeRegister(OpRt, "Rt", LdrName); 1170 IValueT Rt = encodeRegister(OpRt, "Rt", LdrName);
1134 const Type Ty = OpRt->getType(); 1171 const Type Ty = OpRt->getType();
1135 switch (typeWidthInBytesLog2(Ty)) { 1172 switch (typeWidthInBytesLog2(Ty)) {
1136 case 3: 1173 case 3:
1137 // LDRD is not implemented because target lowering handles i64 and double by 1174 // LDRD is not implemented because target lowering handles i64 and double by
1138 // using two (32-bit) load instructions. Note: Intenionally drop to default 1175 // using two (32-bit) load instructions. Note: Intenionally drop to default
1139 // case. 1176 // case.
1140 default: 1177 default:
1141 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) + 1178 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) +
1142 " not implementable\n"); 1179 " not implementable");
1143 case 0: { 1180 case 0: {
1144 // Handles i1 and i8 loads. 1181 // Handles i1 and i8 loads.
1145 // 1182 //
1146 // LDRB (immediate) - ARM section A8.8.68, encoding A1: 1183 // LDRB (immediate) - ARM section A8.8.68, encoding A1:
1147 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 1184 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
1148 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 1185 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
1149 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 1186 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
1150 // 1187 //
1151 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1188 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1152 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and 1189 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1195 // 1232 //
1196 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b 1233 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b
1197 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. 1234 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address.
1198 constexpr bool IsByte = false; 1235 constexpr bool IsByte = false;
1199 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); 1236 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName);
1200 return; 1237 return;
1201 } 1238 }
1202 } 1239 }
1203 } 1240 }
1204 1241
1242 void AssemblerARM32::emitMemExOp(CondARM32::Cond Cond, Type Ty, bool IsLoad,
1243 const Operand *OpRd, IValueT Rt,
1244 const Operand *OpAddress,
1245 const TargetInfo &TInfo,
1246 const char *InstName) {
1247 IValueT Rd = encodeRegister(OpRd, "Rd", InstName);
1248 IValueT MemExOpcode = IsLoad ? B0 : 0;
1249 switch (typeWidthInBytesLog2(Ty)) {
John 2015/12/11 16:59:09 Why did you switch on the type width? can you swit
Karl 2015/12/11 18:05:08 I did it this way for the following reasons: 1) I
John 2015/12/11 18:10:46 IceType_i[8|16|32|64] are declared sequentially in
Karl 2015/12/11 21:00:12 OK, I'll change it, but you are slightly incorrect
1250 default:
1251 llvm::report_fatal_error(std::string(InstName) + ": Type " +
1252 typeString(Ty) + " not implementable");
1253 case 0:
1254 MemExOpcode |= B2;
1255 break;
1256 case 1:
1257 MemExOpcode |= B2 | B1;
1258 break;
1259 case 2:
1260 break;
1261 case 3:
1262 MemExOpcode |= B1;
1263 }
1264 // emitMemExOp(Cond, MemExOpcode, Rd, Rt, OpAddress, TInfo, InstName);
Jim Stichnoth 2015/12/11 17:24:57 Remove this comment?
Karl 2015/12/11 18:05:08 Really? I like useless comments. Removing...
1265 IValueT AddressRn;
1266 if (encodeAddress(OpAddress, AddressRn, TInfo, OpEncodingMemEx) !=
1267 EncodedAsImmRegOffset)
1268 llvm::report_fatal_error(std::string(InstName) +
1269 ": Can't extract Rn from address");
1270 assert(Utils::IsAbsoluteUint(3, MemExOpcode));
1271 verifyRegDefined(Rd, "Rd", InstName);
1272 verifyRegDefined(Rt, "Rt", InstName);
1273 verifyCondDefined(Cond, InstName);
1274 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1275 IValueT Encoding = (Cond << kConditionShift) | B24 | B23 | B11 | B10 | B9 |
1276 B8 | B7 | B4 | (MemExOpcode << kMemExOpcodeShift) |
1277 AddressRn | (Rd << kRdShift) | (Rt << kRmShift);
1278 emitInst(Encoding);
1279 return;
1280 }
1281
1282 void AssemblerARM32::ldrex(const Operand *OpRt, const Operand *OpAddress,
1283 CondARM32::Cond Cond, const TargetInfo &TInfo) {
1284 // LDREXB - ARM section A8.8.76, encoding A1:
1285 // ldrexb<c> <Rt>, [<Rn>]
1286 //
1287 // cccc00011101nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1288 //
1289 // LDREXH - ARM section A8.8.78, encoding A1:
1290 // ldrexh<c> <Rt>, [<Rn>]
1291 //
1292 // cccc00011111nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1293 //
1294 // LDREX - ARM section A8.8.75, encoding A1:
1295 // ldrex<c> <Rt>, [<Rn>]
1296 //
1297 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1298 //
1299 // LDREXD - ARM section A8.
1300 // ldrexd<c> <Rt>, [<Rn>]
1301 //
1302 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1303 constexpr const char *LdrexName = "ldrex";
1304 const Type Ty = OpRt->getType();
1305 constexpr bool IsLoad = true;
1306 constexpr IValueT Rm = RegARM32::Encoded_Reg_pc;
1307 emitMemExOp(Cond, Ty, IsLoad, OpRt, Rm, OpAddress, TInfo, LdrexName);
1308 }
1309
1205 void AssemblerARM32::emitShift(const CondARM32::Cond Cond, 1310 void AssemblerARM32::emitShift(const CondARM32::Cond Cond,
1206 const OperandARM32::ShiftKind Shift, 1311 const OperandARM32::ShiftKind Shift,
1207 const Operand *OpRd, const Operand *OpRm, 1312 const Operand *OpRd, const Operand *OpRm,
1208 const Operand *OpSrc1, const bool SetFlags, 1313 const Operand *OpSrc1, const bool SetFlags,
1209 const char *InstName) { 1314 const char *InstName) {
1210 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101 1315 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101
1211 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); 1316 IValueT Rd = encodeRegister(OpRd, "Rd", InstName);
1212 IValueT Rm = encodeRegister(OpRm, "Rm", InstName); 1317 IValueT Rm = encodeRegister(OpRm, "Rm", InstName);
1213 IValueT Value; 1318 IValueT Value;
1214 switch (encodeOperand(OpSrc1, Value)) { 1319 switch (encodeOperand(OpSrc1, Value)) {
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
1464 // 1569 //
1465 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1570 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1466 // iiiiiiiiiiii=imm12, u=1 if +. 1571 // iiiiiiiiiiii=imm12, u=1 if +.
1467 constexpr bool IsByte = false; 1572 constexpr bool IsByte = false;
1468 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); 1573 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName);
1469 return; 1574 return;
1470 } 1575 }
1471 } 1576 }
1472 } 1577 }
1473 1578
1579 void AssemblerARM32::strex(const Operand *OpRd, const Operand *OpRt,
1580 const Operand *OpAddress, CondARM32::Cond Cond,
1581 const TargetInfo &TInfo) {
1582 // STREXB - ARM section A8.8.213, encoding A1:
1583 // strexb<c> <Rd>, <Rt>, [<Rn>]
1584 //
1585 // cccc00011100nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1586 // nnnn=Rn.
1587 //
1588 // STREXH - ARM section A8.8.215, encoding A1:
1589 // strexh<c> <Rd>, <Rt>, [<Rn>]
1590 //
1591 // cccc00011110nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1592 // nnnn=Rn.
1593 //
1594 // STREX - ARM section A8.8.212, encoding A1:
1595 // strex<c> <Rd>, <Rt>, [<Rn>]
1596 //
1597 // cccc00011000nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1598 // nnnn=Rn.
1599 //
1600 // STREXD - ARM section A8.8.214, encoding A1:
1601 // strexd<c> <Rd>, <Rt>, [<Rn>]
1602 //
1603 // cccc00011010nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1604 // nnnn=Rn.
1605 constexpr const char *StrexName = "strex";
1606 // Note: Rt uses Rm shift in encoding.
1607 IValueT Rt = encodeRegister(OpRt, "Rt", StrexName);
1608 const Type Ty = OpRt->getType();
1609 constexpr bool IsLoad = true;
1610 emitMemExOp(Cond, Ty, !IsLoad, OpRd, Rt, OpAddress, TInfo, StrexName);
1611 return;
Jim Stichnoth 2015/12/11 17:24:57 Remove this explicit return.
Karl 2015/12/11 18:05:08 Done.
1612 }
1613
1474 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, 1614 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn,
1475 const Operand *OpSrc1, bool SetFlags, 1615 const Operand *OpSrc1, bool SetFlags,
1476 CondARM32::Cond Cond) { 1616 CondARM32::Cond Cond) {
1477 // ORR (register) - ARM Section A8.8.123, encoding A1: 1617 // ORR (register) - ARM Section A8.8.123, encoding A1:
1478 // orr{s}<c> <Rd>, <Rn>, <Rm> 1618 // orr{s}<c> <Rd>, <Rn>, <Rm>
1479 // 1619 //
1480 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 1620 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1481 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. 1621 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags.
1482 // 1622 //
1483 // ORR (register) - ARM Section A8.8.123, encoding A1: 1623 // ORR (register) - ARM Section A8.8.123, encoding A1:
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1704 1844
1705 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, 1845 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0,
1706 CondARM32::Cond Cond) { 1846 CondARM32::Cond Cond) {
1707 constexpr const char *UxtName = "uxt"; 1847 constexpr const char *UxtName = "uxt";
1708 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; 1848 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21;
1709 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); 1849 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName);
1710 } 1850 }
1711 1851
1712 } // end of namespace ARM32 1852 } // end of namespace ARM32
1713 } // end of namespace Ice 1853 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698