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

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 issues raised in previous patch. 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), Mem->getShiftOp() ,
358 Mem->getShiftAmt()); 397 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 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
1159 1192
1160 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, 1193 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
1161 CondARM32::Cond Cond, const TargetInfo &TInfo) { 1194 CondARM32::Cond Cond, const TargetInfo &TInfo) {
1162 constexpr const char *LdrName = "ldr"; 1195 constexpr const char *LdrName = "ldr";
1163 constexpr bool IsLoad = true; 1196 constexpr bool IsLoad = true;
1164 IValueT Rt = encodeRegister(OpRt, "Rt", LdrName); 1197 IValueT Rt = encodeRegister(OpRt, "Rt", LdrName);
1165 const Type Ty = OpRt->getType(); 1198 const Type Ty = OpRt->getType();
1166 switch (typeWidthInBytesLog2(Ty)) { 1199 switch (typeWidthInBytesLog2(Ty)) {
1167 case 3: 1200 case 3:
1168 // LDRD is not implemented because target lowering handles i64 and double by 1201 // LDRD is not implemented because target lowering handles i64 and double by
1169 // using two (32-bit) load instructions. Note: Intenionally drop to default 1202 // using two (32-bit) load instructions. Note: Intenionally drop to default
Jim Stichnoth 2015/12/11 20:17:25 Intentionally
Karl 2015/12/11 21:00:12 Done.
1170 // case. 1203 // case.
1171 default: 1204 default:
1172 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) + 1205 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) +
1173 " not implementable\n"); 1206 " not implementable");
1174 case 0: { 1207 case 0: {
1175 // Handles i1 and i8 loads. 1208 // Handles i1 and i8 loads.
1176 // 1209 //
1177 // LDRB (immediate) - ARM section A8.8.68, encoding A1: 1210 // LDRB (immediate) - ARM section A8.8.68, encoding A1:
1178 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 1211 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
1179 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 1212 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
1180 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 1213 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
1181 // 1214 //
1182 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1215 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1183 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and 1216 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1226 // 1259 //
1227 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b 1260 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b
1228 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. 1261 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address.
1229 constexpr bool IsByte = false; 1262 constexpr bool IsByte = false;
1230 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); 1263 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName);
1231 return; 1264 return;
1232 } 1265 }
1233 } 1266 }
1234 } 1267 }
1235 1268
1269 void AssemblerARM32::emitMemExOp(CondARM32::Cond Cond, Type Ty, bool IsLoad,
1270 const Operand *OpRd, IValueT Rt,
1271 const Operand *OpAddress,
1272 const TargetInfo &TInfo,
1273 const char *InstName) {
1274 IValueT Rd = encodeRegister(OpRd, "Rd", InstName);
1275 IValueT MemExOpcode = IsLoad ? B0 : 0;
1276 switch (typeWidthInBytesLog2(Ty)) {
1277 default:
1278 llvm::report_fatal_error(std::string(InstName) + ": Type " +
1279 typeString(Ty) + " not implementable");
1280 case 0:
1281 MemExOpcode |= B2;
1282 break;
1283 case 1:
1284 MemExOpcode |= B2 | B1;
1285 break;
1286 case 2:
1287 break;
1288 case 3:
1289 MemExOpcode |= B1;
1290 }
1291 IValueT AddressRn;
1292 if (encodeAddress(OpAddress, AddressRn, TInfo, OpEncodingMemEx) !=
1293 EncodedAsImmRegOffset)
1294 llvm::report_fatal_error(std::string(InstName) +
1295 ": Can't extract Rn from address");
1296 assert(Utils::IsAbsoluteUint(3, MemExOpcode));
1297 verifyRegDefined(Rd, "Rd", InstName);
1298 verifyRegDefined(Rt, "Rt", InstName);
1299 verifyCondDefined(Cond, InstName);
1300 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1301 IValueT Encoding = (Cond << kConditionShift) | B24 | B23 | B11 | B10 | B9 |
1302 B8 | B7 | B4 | (MemExOpcode << kMemExOpcodeShift) |
1303 AddressRn | (Rd << kRdShift) | (Rt << kRmShift);
1304 emitInst(Encoding);
1305 return;
1306 }
1307
1308 void AssemblerARM32::ldrex(const Operand *OpRt, const Operand *OpAddress,
1309 CondARM32::Cond Cond, const TargetInfo &TInfo) {
1310 // LDREXB - ARM section A8.8.76, encoding A1:
1311 // ldrexb<c> <Rt>, [<Rn>]
1312 //
1313 // cccc00011101nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1314 //
1315 // LDREXH - ARM section A8.8.78, encoding A1:
1316 // ldrexh<c> <Rt>, [<Rn>]
1317 //
1318 // cccc00011111nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1319 //
1320 // LDREX - ARM section A8.8.75, encoding A1:
1321 // ldrex<c> <Rt>, [<Rn>]
1322 //
1323 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1324 //
1325 // LDREXD - ARM section A8.
1326 // ldrexd<c> <Rt>, [<Rn>]
1327 //
1328 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1329 constexpr const char *LdrexName = "ldrex";
1330 const Type Ty = OpRt->getType();
1331 constexpr bool IsLoad = true;
1332 constexpr IValueT Rm = RegARM32::Encoded_Reg_pc;
1333 emitMemExOp(Cond, Ty, IsLoad, OpRt, Rm, OpAddress, TInfo, LdrexName);
1334 }
1335
1236 void AssemblerARM32::emitShift(const CondARM32::Cond Cond, 1336 void AssemblerARM32::emitShift(const CondARM32::Cond Cond,
1237 const OperandARM32::ShiftKind Shift, 1337 const OperandARM32::ShiftKind Shift,
1238 const Operand *OpRd, const Operand *OpRm, 1338 const Operand *OpRd, const Operand *OpRm,
1239 const Operand *OpSrc1, const bool SetFlags, 1339 const Operand *OpSrc1, const bool SetFlags,
1240 const char *InstName) { 1340 const char *InstName) {
1241 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101 1341 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101
1242 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); 1342 IValueT Rd = encodeRegister(OpRd, "Rd", InstName);
1243 IValueT Rm = encodeRegister(OpRm, "Rm", InstName); 1343 IValueT Rm = encodeRegister(OpRm, "Rm", InstName);
1244 IValueT Value; 1344 IValueT Value;
1245 switch (encodeOperand(OpSrc1, Value)) { 1345 switch (encodeOperand(OpSrc1, Value)) {
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
1443 1543
1444 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, 1544 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress,
1445 CondARM32::Cond Cond, const TargetInfo &TInfo) { 1545 CondARM32::Cond Cond, const TargetInfo &TInfo) {
1446 constexpr const char *StrName = "str"; 1546 constexpr const char *StrName = "str";
1447 constexpr bool IsLoad = false; 1547 constexpr bool IsLoad = false;
1448 IValueT Rt = encodeRegister(OpRt, "Rt", StrName); 1548 IValueT Rt = encodeRegister(OpRt, "Rt", StrName);
1449 const Type Ty = OpRt->getType(); 1549 const Type Ty = OpRt->getType();
1450 switch (typeWidthInBytesLog2(Ty)) { 1550 switch (typeWidthInBytesLog2(Ty)) {
1451 case 3: 1551 case 3:
1452 // STRD is not implemented because target lowering handles i64 and double by 1552 // STRD is not implemented because target lowering handles i64 and double by
1453 // using two (32-bit) store instructions. Note: Intenionally drop to 1553 // using two (32-bit) store instructions. Note: Intenionally drop to
Jim Stichnoth 2015/12/11 20:17:25 Intentionally
Karl 2015/12/11 21:00:12 Done.
1454 // default case. 1554 // default case.
1455 default: 1555 default:
1456 llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) + 1556 llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) +
1457 " not implemented"); 1557 " not implemented");
1458 case 0: { 1558 case 0: {
1459 // Handles i1 and i8 stores. 1559 // Handles i1 and i8 stores.
1460 // 1560 //
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
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1495 // 1595 //
1496 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1596 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1497 // iiiiiiiiiiii=imm12, u=1 if +. 1597 // iiiiiiiiiiii=imm12, u=1 if +.
1498 constexpr bool IsByte = false; 1598 constexpr bool IsByte = false;
1499 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); 1599 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName);
1500 return; 1600 return;
1501 } 1601 }
1502 } 1602 }
1503 } 1603 }
1504 1604
1605 void AssemblerARM32::strex(const Operand *OpRd, const Operand *OpRt,
1606 const Operand *OpAddress, CondARM32::Cond Cond,
1607 const TargetInfo &TInfo) {
1608 // STREXB - ARM section A8.8.213, encoding A1:
1609 // strexb<c> <Rd>, <Rt>, [<Rn>]
1610 //
1611 // cccc00011100nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1612 // nnnn=Rn.
1613 //
1614 // STREXH - ARM section A8.8.215, encoding A1:
1615 // strexh<c> <Rd>, <Rt>, [<Rn>]
1616 //
1617 // cccc00011110nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1618 // nnnn=Rn.
1619 //
1620 // STREX - ARM section A8.8.212, encoding A1:
1621 // strex<c> <Rd>, <Rt>, [<Rn>]
1622 //
1623 // cccc00011000nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1624 // nnnn=Rn.
1625 //
1626 // STREXD - ARM section A8.8.214, encoding A1:
1627 // strexd<c> <Rd>, <Rt>, [<Rn>]
1628 //
1629 // cccc00011010nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1630 // nnnn=Rn.
1631 constexpr const char *StrexName = "strex";
1632 // Note: Rt uses Rm shift in encoding.
1633 IValueT Rt = encodeRegister(OpRt, "Rt", StrexName);
1634 const Type Ty = OpRt->getType();
1635 constexpr bool IsLoad = true;
1636 emitMemExOp(Cond, Ty, !IsLoad, OpRd, Rt, OpAddress, TInfo, StrexName);
1637 }
1638
1505 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, 1639 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn,
1506 const Operand *OpSrc1, bool SetFlags, 1640 const Operand *OpSrc1, bool SetFlags,
1507 CondARM32::Cond Cond) { 1641 CondARM32::Cond Cond) {
1508 // ORR (register) - ARM Section A8.8.123, encoding A1: 1642 // ORR (register) - ARM Section A8.8.123, encoding A1:
1509 // orr{s}<c> <Rd>, <Rn>, <Rm> 1643 // orr{s}<c> <Rd>, <Rn>, <Rm>
1510 // 1644 //
1511 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 1645 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1512 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. 1646 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags.
1513 // 1647 //
1514 // ORR (register) - ARM Section A8.8.123, encoding A1: 1648 // ORR (register) - ARM Section A8.8.123, encoding A1:
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1778 1912
1779 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, 1913 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0,
1780 CondARM32::Cond Cond) { 1914 CondARM32::Cond Cond) {
1781 constexpr const char *UxtName = "uxt"; 1915 constexpr const char *UxtName = "uxt";
1782 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; 1916 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21;
1783 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); 1917 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName);
1784 } 1918 }
1785 1919
1786 } // end of namespace ARM32 1920 } // end of namespace ARM32
1787 } // end of namespace Ice 1921 } // 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