OLD | NEW |
1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// | 1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// |
2 // | 2 // |
3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
4 // for details. All rights reserved. Use of this source code is governed by a | 4 // for details. All rights reserved. Use of this source code is governed by a |
5 // BSD-style license that can be found in the LICENSE file. | 5 // BSD-style license that can be found in the LICENSE file. |
6 // | 6 // |
7 // Modified by the Subzero authors. | 7 // Modified by the Subzero authors. |
8 // | 8 // |
9 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// |
10 // | 10 // |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 // Extract out a Bit in Value. | 170 // Extract out a Bit in Value. |
171 inline bool isBitSet(IValueT Bit, IValueT Value) { | 171 inline bool isBitSet(IValueT Bit, IValueT Value) { |
172 return (Value & Bit) == Bit; | 172 return (Value & Bit) == Bit; |
173 } | 173 } |
174 | 174 |
175 // Returns the GPR register at given Shift in Value. | 175 // Returns the GPR register at given Shift in Value. |
176 inline RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { | 176 inline RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { |
177 return decodeGPRRegister((Value >> Shift) & 0xF); | 177 return decodeGPRRegister((Value >> Shift) & 0xF); |
178 } | 178 } |
179 | 179 |
180 // The way an operand was decoded in functions decodeOperand and decodeAddress | 180 // The way an operand is encoded into a sequence of bits in functions |
181 // below. | 181 // encodeOperand and encodeAddress below. |
182 enum DecodedResult { | 182 enum EncodedOperand { |
183 // Unable to decode, value left undefined. | 183 // Unable to encode, value left undefined. |
184 CantDecode = 0, | 184 CantEncode = 0, |
185 // Value is register found. | 185 // Value is register found. |
186 DecodedAsRegister, | 186 EncodedAsRegister, |
187 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 | 187 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 |
188 // value. | 188 // value. |
189 DecodedAsRotatedImm8, | 189 EncodedAsRotatedImm8, |
190 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, | 190 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, |
191 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to | 191 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to |
192 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. | 192 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. |
193 DecodedAsImmRegOffset, | 193 EncodedAsImmRegOffset, |
194 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 | 194 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 |
195 // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to | 195 // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to |
196 // Rn. | 196 // Rn. |
197 DecodedAsImmRegOffsetEnc3, | 197 EncodedAsImmRegOffsetEnc3, |
198 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, | 198 // 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 | 199 // 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 | 200 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if |
201 // writeback to Rn. | 201 // writeback to Rn. |
202 DecodedAsShiftRotateImm5, | 202 EncodedAsShiftRotateImm5, |
203 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value | 203 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value |
204 // to shift. | 204 // to shift. |
205 DecodedAsShiftImm5, | 205 EncodedAsShiftImm5, |
206 // i.e. iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift | 206 // i.e. iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift |
207 // kind, and iiiii is the shift amount. | 207 // kind, and iiiii is the shift amount. |
208 DecodedAsShiftedRegister, | 208 EncodedAsShiftedRegister, |
209 // Value is 32bit integer constant. | 209 // Value is 32bit integer constant. |
210 DecodedAsConstI32 | 210 EncodedAsConstI32 |
211 }; | 211 }; |
212 | 212 |
213 // Sets Encoding to a rotated Imm8 encoding of Value, if possible. | 213 // Sets Encoding to a rotated Imm8 encoding of Value, if possible. |
214 inline IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) { | 214 inline IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) { |
215 assert(RotateAmt < (1 << kRotateBits)); | 215 assert(RotateAmt < (1 << kRotateBits)); |
216 assert(Immed8 < (1 << kImmed8Bits)); | 216 assert(Immed8 < (1 << kImmed8Bits)); |
217 return (RotateAmt << kRotateShift) | (Immed8 << kImmed8Shift); | 217 return (RotateAmt << kRotateShift) | (Immed8 << kImmed8Shift); |
218 } | 218 } |
219 | 219 |
220 // Encodes iiiiitt0mmmm for data-processing (2nd) operands where iiiii=Imm5, | 220 // Encodes iiiiitt0mmmm for data-processing (2nd) operands where iiiii=Imm5, |
221 // tt=Shift, and mmmm=Rm. | 221 // tt=Shift, and mmmm=Rm. |
222 IValueT encodeShiftRotateImm5(IValueT Rm, OperandARM32::ShiftKind Shift, | 222 IValueT encodeShiftRotateImm5(IValueT Rm, OperandARM32::ShiftKind Shift, |
223 IOffsetT imm5) { | 223 IOffsetT imm5) { |
224 (void)kShiftImmBits; | 224 (void)kShiftImmBits; |
225 assert(imm5 < (1 << kShiftImmBits)); | 225 assert(imm5 < (1 << kShiftImmBits)); |
226 return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm; | 226 return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm; |
227 } | 227 } |
228 | 228 |
229 // Encodes mmmmtt01ssss for data-processing operands where mmmm=Rm, ssss=Rs, and | 229 // Encodes mmmmtt01ssss for data-processing operands where mmmm=Rm, ssss=Rs, and |
230 // tt=Shift. | 230 // tt=Shift. |
231 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, | 231 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, |
232 IValueT Rs) { | 232 IValueT Rs) { |
233 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | | 233 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | |
234 (Rm << kRmShift); | 234 (Rm << kRmShift); |
235 } | 235 } |
236 | 236 |
237 DecodedResult decodeOperand(const Operand *Opnd, IValueT &Value) { | 237 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value) { |
238 Value = 0; // Make sure initialized. | 238 Value = 0; // Make sure initialized. |
239 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 239 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
240 if (Var->hasReg()) { | 240 if (Var->hasReg()) { |
241 Value = Var->getRegNum(); | 241 Value = Var->getRegNum(); |
242 return DecodedAsRegister; | 242 return EncodedAsRegister; |
243 } | 243 } |
244 return CantDecode; | 244 return CantEncode; |
245 } | 245 } |
246 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { | 246 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { |
247 const IValueT Immed8 = FlexImm->getImm(); | 247 const IValueT Immed8 = FlexImm->getImm(); |
248 const IValueT Rotate = FlexImm->getRotateAmt(); | 248 const IValueT Rotate = FlexImm->getRotateAmt(); |
249 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) | 249 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) |
250 return CantDecode; | 250 return CantEncode; |
251 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); | 251 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); |
252 return DecodedAsRotatedImm8; | 252 return EncodedAsRotatedImm8; |
253 } | 253 } |
254 if (const auto *Const = llvm::dyn_cast<ConstantInteger32>(Opnd)) { | 254 if (const auto *Const = llvm::dyn_cast<ConstantInteger32>(Opnd)) { |
255 Value = Const->getValue(); | 255 Value = Const->getValue(); |
256 return DecodedAsConstI32; | 256 return EncodedAsConstI32; |
257 } | 257 } |
258 if (const auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Opnd)) { | 258 if (const auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Opnd)) { |
259 Operand *Amt = FlexReg->getShiftAmt(); | 259 Operand *Amt = FlexReg->getShiftAmt(); |
260 if (const auto *Imm5 = llvm::dyn_cast<OperandARM32ShAmtImm>(Amt)) { | 260 if (const auto *Imm5 = llvm::dyn_cast<OperandARM32ShAmtImm>(Amt)) { |
261 IValueT Rm; | 261 IValueT Rm; |
262 if (decodeOperand(FlexReg->getReg(), Rm) != DecodedAsRegister) | 262 if (encodeOperand(FlexReg->getReg(), Rm) != EncodedAsRegister) |
263 return CantDecode; | 263 return CantEncode; |
264 Value = | 264 Value = |
265 encodeShiftRotateImm5(Rm, FlexReg->getShiftOp(), Imm5->getShAmtImm()); | 265 encodeShiftRotateImm5(Rm, FlexReg->getShiftOp(), Imm5->getShAmtImm()); |
266 return DecodedAsShiftedRegister; | 266 return EncodedAsShiftedRegister; |
267 } | 267 } |
268 // TODO(kschimpf): Handle case where Amt is a register? | 268 // TODO(kschimpf): Handle case where Amt is a register? |
269 } | 269 } |
270 if (const auto *ShImm = llvm::dyn_cast<OperandARM32ShAmtImm>(Opnd)) { | 270 if (const auto *ShImm = llvm::dyn_cast<OperandARM32ShAmtImm>(Opnd)) { |
271 const IValueT Immed5 = ShImm->getShAmtImm(); | 271 const IValueT Immed5 = ShImm->getShAmtImm(); |
272 assert(Immed5 < (1 << kShiftImmBits)); | 272 assert(Immed5 < (1 << kShiftImmBits)); |
273 Value = (Immed5 << kShiftImmShift); | 273 Value = (Immed5 << kShiftImmShift); |
274 return DecodedAsShiftImm5; | 274 return EncodedAsShiftImm5; |
275 } | 275 } |
276 return CantDecode; | 276 return CantEncode; |
277 } | 277 } |
278 | 278 |
279 IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset, | 279 IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset, |
280 OperandARM32Mem::AddrMode Mode) { | 280 OperandARM32Mem::AddrMode Mode) { |
281 IValueT Value = Mode | (Reg << kRnShift); | 281 IValueT Value = Mode | (Reg << kRnShift); |
282 if (Offset < 0) { | 282 if (Offset < 0) { |
283 Value = (Value ^ U) | -Offset; // Flip U to adjust sign. | 283 Value = (Value ^ U) | -Offset; // Flip U to adjust sign. |
284 } else { | 284 } else { |
285 Value |= Offset; | 285 Value |= Offset; |
286 } | 286 } |
(...skipping 15 matching lines...) Expand all Loading... |
302 | 302 |
303 // Defines alternate layouts of instruction operands, should the (common) | 303 // Defines alternate layouts of instruction operands, should the (common) |
304 // default pattern not be used. | 304 // default pattern not be used. |
305 enum OpEncoding { | 305 enum OpEncoding { |
306 // No alternate layout specified. | 306 // No alternate layout specified. |
307 DefaultOpEncoding, | 307 DefaultOpEncoding, |
308 // Alternate encoding 3. | 308 // Alternate encoding 3. |
309 OpEncoding3 | 309 OpEncoding3 |
310 }; | 310 }; |
311 | 311 |
312 // Decodes memory address Opnd, and encodes that information into Value, | 312 // Encodes memory address Opnd, and encodes that information into Value, based |
313 // based on how ARM represents the address. Returns how the value was encoded. | 313 // on how ARM represents the address. Returns how the value was encoded. |
314 DecodedResult decodeAddress(const Operand *Opnd, IValueT &Value, | 314 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, |
315 const AssemblerARM32::TargetInfo &TInfo, | 315 const AssemblerARM32::TargetInfo &TInfo, |
316 OpEncoding AddressEncoding = DefaultOpEncoding) { | 316 OpEncoding AddressEncoding = DefaultOpEncoding) { |
317 Value = 0; // Make sure initialized. | 317 Value = 0; // Make sure initialized. |
318 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 318 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
319 // Should be a stack variable, with an offset. | 319 // Should be a stack variable, with an offset. |
320 if (Var->hasReg()) | 320 if (Var->hasReg()) |
321 return CantDecode; | 321 return CantEncode; |
322 IOffsetT Offset = Var->getStackOffset(); | 322 IOffsetT Offset = Var->getStackOffset(); |
323 if (!Utils::IsAbsoluteUint(12, Offset)) | 323 if (!Utils::IsAbsoluteUint(12, Offset)) |
324 return CantDecode; | 324 return CantEncode; |
325 int32_t BaseRegNum = Var->getBaseRegNum(); | 325 int32_t BaseRegNum = Var->getBaseRegNum(); |
326 if (BaseRegNum == Variable::NoRegister) | 326 if (BaseRegNum == Variable::NoRegister) |
327 BaseRegNum = TInfo.FrameOrStackReg; | 327 BaseRegNum = TInfo.FrameOrStackReg; |
328 Value = encodeImmRegOffset(BaseRegNum, Offset, OperandARM32Mem::Offset); | 328 Value = encodeImmRegOffset(BaseRegNum, Offset, OperandARM32Mem::Offset); |
329 return DecodedAsImmRegOffset; | 329 return EncodedAsImmRegOffset; |
330 } | 330 } |
331 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { | 331 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { |
332 Variable *Var = Mem->getBase(); | 332 Variable *Var = Mem->getBase(); |
333 if (!Var->hasReg()) | 333 if (!Var->hasReg()) |
334 return CantDecode; | 334 return CantEncode; |
335 IValueT Rn = Var->getRegNum(); | 335 IValueT Rn = Var->getRegNum(); |
336 if (Mem->isRegReg()) { | 336 if (Mem->isRegReg()) { |
337 const Variable *Index = Mem->getIndex(); | 337 const Variable *Index = Mem->getIndex(); |
338 if (Var == nullptr) | 338 if (Var == nullptr) |
339 return CantDecode; | 339 return CantEncode; |
340 Value = (Rn << kRnShift) | Mem->getAddrMode() | | 340 Value = (Rn << kRnShift) | Mem->getAddrMode() | |
341 encodeShiftRotateImm5(Index->getRegNum(), Mem->getShiftOp(), | 341 encodeShiftRotateImm5(Index->getRegNum(), Mem->getShiftOp(), |
342 Mem->getShiftAmt()); | 342 Mem->getShiftAmt()); |
343 return DecodedAsShiftRotateImm5; | 343 return EncodedAsShiftRotateImm5; |
344 } | 344 } |
345 // Decoded as immediate register offset. | 345 // Encoded as immediate register offset. |
346 ConstantInteger32 *Offset = Mem->getOffset(); | 346 ConstantInteger32 *Offset = Mem->getOffset(); |
347 switch (AddressEncoding) { | 347 switch (AddressEncoding) { |
348 case DefaultOpEncoding: | 348 case DefaultOpEncoding: |
349 Value = encodeImmRegOffset(Rn, Offset->getValue(), Mem->getAddrMode()); | 349 Value = encodeImmRegOffset(Rn, Offset->getValue(), Mem->getAddrMode()); |
350 return DecodedAsImmRegOffset; | 350 return EncodedAsImmRegOffset; |
351 case OpEncoding3: | 351 case OpEncoding3: |
352 Value = | 352 Value = |
353 encodeImmRegOffsetEnc3(Rn, Offset->getValue(), Mem->getAddrMode()); | 353 encodeImmRegOffsetEnc3(Rn, Offset->getValue(), Mem->getAddrMode()); |
354 return DecodedAsImmRegOffsetEnc3; | 354 return EncodedAsImmRegOffsetEnc3; |
355 } | 355 } |
356 } | 356 } |
357 return CantDecode; | 357 return CantEncode; |
358 } | 358 } |
359 | 359 |
360 // Checks that Offset can fit in imm24 constant of branch (b) instruction. | 360 // Checks that Offset can fit in imm24 constant of branch (b) instruction. |
361 bool canEncodeBranchOffset(IOffsetT Offset) { | 361 bool canEncodeBranchOffset(IOffsetT Offset) { |
362 return Utils::IsAligned(Offset, 4) && | 362 return Utils::IsAligned(Offset, 4) && |
363 Utils::IsInt(kBranchOffsetBits, Offset >> 2); | 363 Utils::IsInt(kBranchOffsetBits, Offset >> 2); |
364 } | 364 } |
365 | 365 |
366 } // end of anonymous namespace | 366 } // end of anonymous namespace |
367 | 367 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 assert(IsGoodOffset); | 454 assert(IsGoodOffset); |
455 // Note: Following cast is for MINIMAL build. | 455 // Note: Following cast is for MINIMAL build. |
456 (void)IsGoodOffset; | 456 (void)IsGoodOffset; |
457 | 457 |
458 // Properly preserve only the bits supported in the instruction. | 458 // Properly preserve only the bits supported in the instruction. |
459 Offset >>= 2; | 459 Offset >>= 2; |
460 Offset &= kBranchOffsetMask; | 460 Offset &= kBranchOffsetMask; |
461 return (Inst & ~kBranchOffsetMask) | Offset; | 461 return (Inst & ~kBranchOffsetMask) | Offset; |
462 } | 462 } |
463 | 463 |
| 464 // Pull out offset from branch Inst. |
464 IOffsetT AssemblerARM32::decodeBranchOffset(IValueT Inst) { | 465 IOffsetT AssemblerARM32::decodeBranchOffset(IValueT Inst) { |
465 // Sign-extend, left-shift by 2, and adjust to the way ARM CPUs read PC. | 466 // Sign-extend, left-shift by 2, and adjust to the way ARM CPUs read PC. |
466 IOffsetT Offset = static_cast<IOffsetT>((Inst & kBranchOffsetMask) << 8); | 467 IOffsetT Offset = static_cast<IOffsetT>((Inst & kBranchOffsetMask) << 8); |
467 return (Offset >> 6) + kPCReadOffset; | 468 return (Offset >> 6) + kPCReadOffset; |
468 } | 469 } |
469 | 470 |
470 void AssemblerARM32::bind(Label *L) { | 471 void AssemblerARM32::bind(Label *L) { |
471 IOffsetT BoundPc = Buffer.size(); | 472 IOffsetT BoundPc = Buffer.size(); |
472 assert(!L->isBound()); // Labels can only be bound once. | 473 assert(!L->isBound()); // Labels can only be bound once. |
473 while (L->isLinked()) { | 474 while (L->isLinked()) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 (encodeBool(SetFlags) << kSShift) | | 512 (encodeBool(SetFlags) << kSShift) | |
512 (Rn << kRnShift) | (Rd << kRdShift) | Imm12; | 513 (Rn << kRnShift) | (Rd << kRdShift) | Imm12; |
513 emitInst(Encoding); | 514 emitInst(Encoding); |
514 } | 515 } |
515 | 516 |
516 void AssemblerARM32::emitType01(IValueT Opcode, const Operand *OpRd, | 517 void AssemblerARM32::emitType01(IValueT Opcode, const Operand *OpRd, |
517 const Operand *OpRn, const Operand *OpSrc1, | 518 const Operand *OpRn, const Operand *OpSrc1, |
518 bool SetFlags, CondARM32::Cond Cond, | 519 bool SetFlags, CondARM32::Cond Cond, |
519 EmitChecks RuleChecks) { | 520 EmitChecks RuleChecks) { |
520 IValueT Rd; | 521 IValueT Rd; |
521 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 522 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) |
522 return setNeedsTextFixup(); | 523 return setNeedsTextFixup(); |
523 IValueT Rn; | 524 IValueT Rn; |
524 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 525 if (encodeOperand(OpRn, Rn) != EncodedAsRegister) |
525 return setNeedsTextFixup(); | 526 return setNeedsTextFixup(); |
526 emitType01(Opcode, Rd, Rn, OpSrc1, SetFlags, Cond, RuleChecks); | 527 emitType01(Opcode, Rd, Rn, OpSrc1, SetFlags, Cond, RuleChecks); |
527 } | 528 } |
528 | 529 |
529 void AssemblerARM32::emitType01(IValueT Opcode, IValueT Rd, IValueT Rn, | 530 void AssemblerARM32::emitType01(IValueT Opcode, IValueT Rd, IValueT Rn, |
530 const Operand *OpSrc1, bool SetFlags, | 531 const Operand *OpSrc1, bool SetFlags, |
531 CondARM32::Cond Cond, EmitChecks RuleChecks) { | 532 CondARM32::Cond Cond, EmitChecks RuleChecks) { |
532 | 533 |
533 IValueT Src1Value; | 534 IValueT Src1Value; |
534 // TODO(kschimpf) Other possible decodings of data operations. | 535 // TODO(kschimpf) Other possible decodings of data operations. |
535 switch (decodeOperand(OpSrc1, Src1Value)) { | 536 switch (encodeOperand(OpSrc1, Src1Value)) { |
536 default: | 537 default: |
537 return setNeedsTextFixup(); | 538 return setNeedsTextFixup(); |
538 case DecodedAsRegister: { | 539 case EncodedAsRegister: { |
539 // XXX (register) | 540 // XXX (register) |
540 // xxx{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} | 541 // xxx{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} |
541 // | 542 // |
542 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 543 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
543 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. | 544 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. |
544 constexpr IValueT Imm5 = 0; | 545 constexpr IValueT Imm5 = 0; |
545 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Imm5); | 546 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Imm5); |
546 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, | 547 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, |
547 RuleChecks); | 548 RuleChecks); |
548 return; | 549 return; |
549 } | 550 } |
550 case DecodedAsShiftedRegister: { | 551 case EncodedAsShiftedRegister: { |
551 // Form is defined in case DecodedAsRegister. (i.e. XXX (register)). | 552 // Form is defined in case EncodedAsRegister. (i.e. XXX (register)). |
552 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, | 553 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, |
553 RuleChecks); | 554 RuleChecks); |
554 return; | 555 return; |
555 } | 556 } |
556 case DecodedAsConstI32: { | 557 case EncodedAsConstI32: { |
557 // See if we can convert this to an XXX (immediate). | 558 // See if we can convert this to an XXX (immediate). |
558 IValueT RotateAmt; | 559 IValueT RotateAmt; |
559 IValueT Imm8; | 560 IValueT Imm8; |
560 if (!OperandARM32FlexImm::canHoldImm(Src1Value, &RotateAmt, &Imm8)) | 561 if (!OperandARM32FlexImm::canHoldImm(Src1Value, &RotateAmt, &Imm8)) |
561 return setNeedsTextFixup(); | 562 return setNeedsTextFixup(); |
562 Src1Value = encodeRotatedImm8(RotateAmt, Imm8); | 563 Src1Value = encodeRotatedImm8(RotateAmt, Imm8); |
563 // Intentionally fall to next case! | 564 // Intentionally fall to next case! |
564 } | 565 } |
565 case DecodedAsRotatedImm8: { | 566 case EncodedAsRotatedImm8: { |
566 // XXX (Immediate) | 567 // XXX (Immediate) |
567 // xxx{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 568 // xxx{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
568 // | 569 // |
569 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 570 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
570 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 571 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
571 emitType01(Cond, kInstTypeDataImmediate, Opcode, SetFlags, Rn, Rd, | 572 emitType01(Cond, kInstTypeDataImmediate, Opcode, SetFlags, Rn, Rd, |
572 Src1Value, RuleChecks); | 573 Src1Value, RuleChecks); |
573 return; | 574 return; |
574 } | 575 } |
575 } | 576 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 // | 616 // |
616 // XXX (immediate) | 617 // XXX (immediate) |
617 // XXX<c> <Rn>, #<RotatedImm8> | 618 // XXX<c> <Rn>, #<RotatedImm8> |
618 // | 619 // |
619 // ccccyyyxxxx1nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 620 // ccccyyyxxxx1nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
620 // yyy=kInstTypeDataImmdiate, xxxx=Opcode, and iiiiiiiiiiii=Src1Value | 621 // yyy=kInstTypeDataImmdiate, xxxx=Opcode, and iiiiiiiiiiii=Src1Value |
621 // defining RotatedImm8. | 622 // defining RotatedImm8. |
622 constexpr bool SetFlags = true; | 623 constexpr bool SetFlags = true; |
623 constexpr IValueT Rd = RegARM32::Encoded_Reg_r0; | 624 constexpr IValueT Rd = RegARM32::Encoded_Reg_r0; |
624 IValueT Rn; | 625 IValueT Rn; |
625 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 626 if (encodeOperand(OpRn, Rn) != EncodedAsRegister) |
626 return setNeedsTextFixup(); | 627 return setNeedsTextFixup(); |
627 emitType01(Opcode, Rd, Rn, OpSrc1, SetFlags, Cond, NoChecks); | 628 emitType01(Opcode, Rd, Rn, OpSrc1, SetFlags, Cond, NoChecks); |
628 } | 629 } |
629 | 630 |
630 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType, | 631 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType, |
631 bool IsLoad, bool IsByte, IValueT Rt, | 632 bool IsLoad, bool IsByte, IValueT Rt, |
632 IValueT Address) { | 633 IValueT Address) { |
633 if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond)) | 634 if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond)) |
634 return setNeedsTextFixup(); | 635 return setNeedsTextFixup(); |
635 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 636 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
636 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | | 637 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | |
637 (InstType << kTypeShift) | (IsLoad ? L : 0) | | 638 (InstType << kTypeShift) | (IsLoad ? L : 0) | |
638 (IsByte ? B : 0) | (Rt << kRdShift) | Address; | 639 (IsByte ? B : 0) | (Rt << kRdShift) | Address; |
639 emitInst(Encoding); | 640 emitInst(Encoding); |
640 } | 641 } |
641 | 642 |
642 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, | 643 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, |
643 IValueT Rt, const Operand *OpAddress, | 644 IValueT Rt, const Operand *OpAddress, |
644 const TargetInfo &TInfo) { | 645 const TargetInfo &TInfo) { |
645 IValueT Address; | 646 IValueT Address; |
646 switch (decodeAddress(OpAddress, Address, TInfo)) { | 647 switch (encodeAddress(OpAddress, Address, TInfo)) { |
647 default: | 648 default: |
648 return setNeedsTextFixup(); | 649 return setNeedsTextFixup(); |
649 case DecodedAsImmRegOffset: { | 650 case EncodedAsImmRegOffset: { |
650 // XXX{B} (immediate): | 651 // XXX{B} (immediate): |
651 // xxx{b}<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 652 // xxx{b}<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
652 // xxx{b}<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 653 // xxx{b}<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
653 // xxx{b}<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 654 // xxx{b}<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
654 // | 655 // |
655 // cccc010pubwlnnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 656 // cccc010pubwlnnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
656 // iiiiiiiiiiii=imm12, b=IsByte, pu0w<<21 is a BlockAddr, l=IsLoad, and | 657 // iiiiiiiiiiii=imm12, b=IsByte, pu0w<<21 is a BlockAddr, l=IsLoad, and |
657 // pu0w0nnnn0000iiiiiiiiiiii=Address. | 658 // pu0w0nnnn0000iiiiiiiiiiii=Address. |
658 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); | 659 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); |
659 | 660 |
660 // Check if conditions of rules violated. | 661 // Check if conditions of rules violated. |
661 if (Rn == RegARM32::Encoded_Reg_pc) | 662 if (Rn == RegARM32::Encoded_Reg_pc) |
662 return setNeedsTextFixup(); | 663 return setNeedsTextFixup(); |
663 if (!isBitSet(P, Address) && isBitSet(W, Address)) | 664 if (!isBitSet(P, Address) && isBitSet(W, Address)) |
664 return setNeedsTextFixup(); | 665 return setNeedsTextFixup(); |
665 if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) && | 666 if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) && |
666 isBitSet(U, Address) & !isBitSet(W, Address) && | 667 isBitSet(U, Address) & !isBitSet(W, Address) && |
667 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) | 668 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) |
668 return setNeedsTextFixup(); | 669 return setNeedsTextFixup(); |
669 | 670 |
670 return emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); | 671 return emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); |
671 } | 672 } |
672 case DecodedAsShiftRotateImm5: { | 673 case EncodedAsShiftRotateImm5: { |
673 // XXX{B} (register) | 674 // XXX{B} (register) |
674 // xxx{b}<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} | 675 // xxx{b}<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} |
675 // xxx{b}<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} | 676 // xxx{b}<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} |
676 // | 677 // |
677 // cccc011pubwlnnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, | 678 // cccc011pubwlnnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, |
678 // b=IsByte, U=1 if +, pu0b is a BlockAddr, l=IsLoad, and | 679 // b=IsByte, U=1 if +, pu0b is a BlockAddr, l=IsLoad, and |
679 // pu0w0nnnn0000iiiiiss0mmmm=Address. | 680 // pu0w0nnnn0000iiiiiss0mmmm=Address. |
680 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); | 681 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); |
681 RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address); | 682 RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address); |
682 | 683 |
(...skipping 15 matching lines...) Expand all Loading... |
698 | 699 |
699 return emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address); | 700 return emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address); |
700 } | 701 } |
701 } | 702 } |
702 } | 703 } |
703 | 704 |
704 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, | 705 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, |
705 IValueT Rt, const Operand *OpAddress, | 706 IValueT Rt, const Operand *OpAddress, |
706 const TargetInfo &TInfo) { | 707 const TargetInfo &TInfo) { |
707 IValueT Address; | 708 IValueT Address; |
708 switch (decodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { | 709 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { |
709 default: | 710 default: |
710 return setNeedsTextFixup(); | 711 return setNeedsTextFixup(); |
711 case DecodedAsImmRegOffsetEnc3: { | 712 case EncodedAsImmRegOffsetEnc3: { |
712 // XXXH (immediate) | 713 // XXXH (immediate) |
713 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] | 714 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] |
714 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] | 715 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] |
715 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | 716 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
716 // | 717 // |
717 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, | 718 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, |
718 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, | 719 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, |
719 // and pu0w0nnnn0000iiii0000jjjj=Address. | 720 // and pu0w0nnnn0000iiii0000jjjj=Address. |
720 if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond)) | 721 if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond)) |
721 return setNeedsTextFixup(); | 722 return setNeedsTextFixup(); |
722 if (!isBitSet(P, Address) && isBitSet(W, Address)) | 723 if (!isBitSet(P, Address) && isBitSet(W, Address)) |
723 return setNeedsTextFixup(); | 724 return setNeedsTextFixup(); |
724 if ((Rt == RegARM32::Encoded_Reg_pc) || | 725 if ((Rt == RegARM32::Encoded_Reg_pc) || |
725 (isBitSet(W, Address) && | 726 (isBitSet(W, Address) && |
726 (getGPRReg(kRnShift, Address) == decodeGPRRegister(Rt)))) | 727 (getGPRReg(kRnShift, Address) == decodeGPRRegister(Rt)))) |
727 return setNeedsTextFixup(); | 728 return setNeedsTextFixup(); |
728 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | | 729 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | |
729 Opcode | (Rt << kRdShift) | Address; | 730 Opcode | (Rt << kRdShift) | Address; |
730 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 731 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
731 return emitInst(Encoding); | 732 return emitInst(Encoding); |
732 } | 733 } |
733 case DecodedAsShiftRotateImm5: { | 734 case EncodedAsShiftRotateImm5: { |
734 // XXXH (register) | 735 // XXXH (register) |
735 // xxxh<c> <Rt>, [<Rn>, +/-<Rm>]{!} | 736 // xxxh<c> <Rt>, [<Rn>, +/-<Rm>]{!} |
736 // xxxh<c> <Rt>, [<Rn>], +/-<Rm> | 737 // xxxh<c> <Rt>, [<Rn>], +/-<Rm> |
737 // | 738 // |
738 // cccc000pu0wxnnnntttt00001011mmmm where cccc=Cond, tttt=Rt, nnnn=Rn, | 739 // cccc000pu0wxnnnntttt00001011mmmm where cccc=Cond, tttt=Rt, nnnn=Rn, |
739 // mmmm=Rm, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, and | 740 // mmmm=Rm, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, and |
740 // pu0w0nnnn000000000000mmmm=Address. | 741 // pu0w0nnnn000000000000mmmm=Address. |
741 if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond)) | 742 if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond)) |
742 return setNeedsTextFixup(); | 743 return setNeedsTextFixup(); |
743 if (!isBitSet(P, Address) && isBitSet(W, Address)) | 744 if (!isBitSet(P, Address) && isBitSet(W, Address)) |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
914 // and iiiiiiiiiiiiiiiiiiiiiiii is the (encoded) Target to branch to. | 915 // and iiiiiiiiiiiiiiiiiiiiiiii is the (encoded) Target to branch to. |
915 emitFixup(createBlFixup(Target)); | 916 emitFixup(createBlFixup(Target)); |
916 constexpr CondARM32::Cond Cond = CondARM32::AL; | 917 constexpr CondARM32::Cond Cond = CondARM32::AL; |
917 constexpr IValueT Immed = 0; | 918 constexpr IValueT Immed = 0; |
918 constexpr bool Link = true; | 919 constexpr bool Link = true; |
919 emitType05(Cond, Immed, Link); | 920 emitType05(Cond, Immed, Link); |
920 } | 921 } |
921 | 922 |
922 void AssemblerARM32::blx(const Operand *Target) { | 923 void AssemblerARM32::blx(const Operand *Target) { |
923 IValueT Rm; | 924 IValueT Rm; |
924 if (decodeOperand(Target, Rm) != DecodedAsRegister) | 925 if (encodeOperand(Target, Rm) != EncodedAsRegister) |
925 return setNeedsTextFixup(); | 926 return setNeedsTextFixup(); |
926 // BLX (register) - ARM section A8.8.26, encoding A1: | 927 // BLX (register) - ARM section A8.8.26, encoding A1: |
927 // blx<c> <Rm> | 928 // blx<c> <Rm> |
928 // | 929 // |
929 // cccc000100101111111111110011mmmm where cccc=Cond (not currently allowed) | 930 // cccc000100101111111111110011mmmm where cccc=Cond (not currently allowed) |
930 // and mmmm=Rm. | 931 // and mmmm=Rm. |
931 if (Rm == RegARM32::Encoded_Reg_pc) | 932 if (Rm == RegARM32::Encoded_Reg_pc) |
932 // Unpredictable. | 933 // Unpredictable. |
933 return setNeedsTextFixup(); | 934 return setNeedsTextFixup(); |
934 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 935 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
984 // cccc0010001snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 985 // cccc0010001snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
985 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 986 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
986 constexpr IValueT Eor = B0; // 0001 | 987 constexpr IValueT Eor = B0; // 0001 |
987 emitType01(Eor, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); | 988 emitType01(Eor, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); |
988 } | 989 } |
989 | 990 |
990 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, | 991 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, |
991 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 992 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
992 constexpr bool IsLoad = true; | 993 constexpr bool IsLoad = true; |
993 IValueT Rt; | 994 IValueT Rt; |
994 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 995 if (encodeOperand(OpRt, Rt) != EncodedAsRegister) |
995 return setNeedsTextFixup(); | 996 return setNeedsTextFixup(); |
996 const Type Ty = OpRt->getType(); | 997 const Type Ty = OpRt->getType(); |
997 switch (typeWidthInBytesLog2(Ty)) { | 998 switch (typeWidthInBytesLog2(Ty)) { |
998 case 3: | 999 case 3: |
999 // LDRD is not implemented because target lowering handles i64 and double by | 1000 // LDRD is not implemented because target lowering handles i64 and double by |
1000 // using two (32-bit) load instructions. Note: Intenionally drop to default | 1001 // using two (32-bit) load instructions. Note: Intenionally drop to default |
1001 // case. | 1002 // case. |
1002 default: | 1003 default: |
1003 llvm::report_fatal_error(std::string("Type ") + typeString(Ty) + | 1004 llvm::report_fatal_error(std::string("Type ") + typeString(Ty) + |
1004 " not implementable using ldr\n"); | 1005 " not implementable using ldr\n"); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 } | 1060 } |
1060 } | 1061 } |
1061 } | 1062 } |
1062 | 1063 |
1063 void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm, | 1064 void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm, |
1064 const Operand *OpSrc1, bool SetFlags, | 1065 const Operand *OpSrc1, bool SetFlags, |
1065 CondARM32::Cond Cond) { | 1066 CondARM32::Cond Cond) { |
1066 constexpr IValueT Lsl = B3 | B2 | B0; // 1101 | 1067 constexpr IValueT Lsl = B3 | B2 | B0; // 1101 |
1067 constexpr IValueT Rn = 0; // Rn field is not used. | 1068 constexpr IValueT Rn = 0; // Rn field is not used. |
1068 IValueT Rd; | 1069 IValueT Rd; |
1069 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 1070 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) |
1070 return setNeedsTextFixup(); | 1071 return setNeedsTextFixup(); |
1071 IValueT Rm; | 1072 IValueT Rm; |
1072 if (decodeOperand(OpRm, Rm) != DecodedAsRegister) | 1073 if (encodeOperand(OpRm, Rm) != EncodedAsRegister) |
1073 return setNeedsTextFixup(); | 1074 return setNeedsTextFixup(); |
1074 IValueT Value; | 1075 IValueT Value; |
1075 switch (decodeOperand(OpSrc1, Value)) { | 1076 switch (encodeOperand(OpSrc1, Value)) { |
1076 default: | 1077 default: |
1077 return setNeedsTextFixup(); | 1078 return setNeedsTextFixup(); |
1078 case DecodedAsShiftImm5: { | 1079 case EncodedAsShiftImm5: { |
1079 // LSL (immediate) - ARM section A8.8.94, encoding A1: | 1080 // LSL (immediate) - ARM section A8.8.94, encoding A1: |
1080 // lsl{s}<c> <Rd>, <Rm>, #imm5 | 1081 // lsl{s}<c> <Rd>, <Rm>, #imm5 |
1081 // | 1082 // |
1082 // cccc0001101s0000ddddiiiii000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, | 1083 // cccc0001101s0000ddddiiiii000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, |
1083 // iiiii=imm5, and mmmm=Rm. | 1084 // iiiii=imm5, and mmmm=Rm. |
1084 Value = Value | (Rm << kRmShift); | 1085 Value = Value | (Rm << kRmShift); |
1085 emitType01(Cond, kInstTypeDataRegShift, Lsl, SetFlags, Rn, Rd, Value, | 1086 emitType01(Cond, kInstTypeDataRegShift, Lsl, SetFlags, Rn, Rd, Value, |
1086 RdIsPcAndSetFlags); | 1087 RdIsPcAndSetFlags); |
1087 return; | 1088 return; |
1088 } | 1089 } |
1089 case DecodedAsRegister: { | 1090 case EncodedAsRegister: { |
1090 // LSL (register) - ARM section A8.8.95, encoding A1: | 1091 // LSL (register) - ARM section A8.8.95, encoding A1: |
1091 // lsl{S}<c> <Rd>, <Rm>, <Rs> | 1092 // lsl{S}<c> <Rd>, <Rm>, <Rs> |
1092 // | 1093 // |
1093 // cccc0001101s0000ddddssss0001mmmm where cccc=Cond, s=SetFlags, dddd=Rd, | 1094 // cccc0001101s0000ddddssss0001mmmm where cccc=Cond, s=SetFlags, dddd=Rd, |
1094 // mmmm=Rm, and ssss=Rs. | 1095 // mmmm=Rm, and ssss=Rs. |
1095 IValueT Rs; | 1096 IValueT Rs; |
1096 if (decodeOperand(OpSrc1, Rs) != DecodedAsRegister) | 1097 if (encodeOperand(OpSrc1, Rs) != EncodedAsRegister) |
1097 return setNeedsTextFixup(); | 1098 return setNeedsTextFixup(); |
1098 if ((Rd == RegARM32::Encoded_Reg_pc) || (Rm == RegARM32::Encoded_Reg_pc) || | 1099 if ((Rd == RegARM32::Encoded_Reg_pc) || (Rm == RegARM32::Encoded_Reg_pc) || |
1099 (Rs == RegARM32::Encoded_Reg_pc)) | 1100 (Rs == RegARM32::Encoded_Reg_pc)) |
1100 setNeedsTextFixup(); | 1101 setNeedsTextFixup(); |
1101 emitType01(Cond, kInstTypeDataRegShift, Lsl, SetFlags, Rn, Rd, | 1102 emitType01(Cond, kInstTypeDataRegShift, Lsl, SetFlags, Rn, Rd, |
1102 encodeShiftRotateReg(Rm, OperandARM32::kNoShift, Rs), NoChecks); | 1103 encodeShiftRotateReg(Rm, OperandARM32::kNoShift, Rs), NoChecks); |
1103 return; | 1104 return; |
1104 } | 1105 } |
1105 } | 1106 } |
1106 } | 1107 } |
1107 | 1108 |
1108 void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, | 1109 void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |
1109 CondARM32::Cond Cond) { | 1110 CondARM32::Cond Cond) { |
1110 // MOV (register) - ARM section A8.8.104, encoding A1: | 1111 // MOV (register) - ARM section A8.8.104, encoding A1: |
1111 // mov{S}<c> <Rd>, <Rn> | 1112 // mov{S}<c> <Rd>, <Rn> |
1112 // | 1113 // |
1113 // cccc0001101s0000dddd00000000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, | 1114 // cccc0001101s0000dddd00000000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, |
1114 // and nnnn=Rn. | 1115 // and nnnn=Rn. |
1115 // | 1116 // |
1116 // MOV (immediate) - ARM section A8.8.102, encoding A1: | 1117 // MOV (immediate) - ARM section A8.8.102, encoding A1: |
1117 // mov{S}<c> <Rd>, #<RotatedImm8> | 1118 // mov{S}<c> <Rd>, #<RotatedImm8> |
1118 // | 1119 // |
1119 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, | 1120 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, |
1120 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this | 1121 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this |
1121 // assembler. | 1122 // assembler. |
1122 IValueT Rd; | 1123 IValueT Rd; |
1123 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 1124 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) |
1124 return setNeedsTextFixup(); | 1125 return setNeedsTextFixup(); |
1125 constexpr bool SetFlags = false; | 1126 constexpr bool SetFlags = false; |
1126 constexpr IValueT Rn = 0; | 1127 constexpr IValueT Rn = 0; |
1127 constexpr IValueT Mov = B3 | B2 | B0; // 1101. | 1128 constexpr IValueT Mov = B3 | B2 | B0; // 1101. |
1128 emitType01(Mov, Rd, Rn, OpSrc, SetFlags, Cond, RdIsPcAndSetFlags); | 1129 emitType01(Mov, Rd, Rn, OpSrc, SetFlags, Cond, RdIsPcAndSetFlags); |
1129 } | 1130 } |
1130 | 1131 |
1131 void AssemblerARM32::emitMovw(IValueT Opcode, IValueT Rd, IValueT Imm16, | 1132 void AssemblerARM32::emitMovw(IValueT Opcode, IValueT Rd, IValueT Imm16, |
1132 bool SetFlags, CondARM32::Cond Cond) { | 1133 bool SetFlags, CondARM32::Cond Cond) { |
1133 if (!isConditionDefined(Cond) || !Utils::IsAbsoluteUint(16, Imm16)) | 1134 if (!isConditionDefined(Cond) || !Utils::IsAbsoluteUint(16, Imm16)) |
1134 return setNeedsTextFixup(); | 1135 return setNeedsTextFixup(); |
1135 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1136 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
1136 const IValueT Encoding = encodeCondition(Cond) << kConditionShift | Opcode | | 1137 const IValueT Encoding = encodeCondition(Cond) << kConditionShift | Opcode | |
1137 (encodeBool(SetFlags) << kSShift) | | 1138 (encodeBool(SetFlags) << kSShift) | |
1138 ((Imm16 >> 12) << 16) | Rd << kRdShift | | 1139 ((Imm16 >> 12) << 16) | Rd << kRdShift | |
1139 (Imm16 & 0xfff); | 1140 (Imm16 & 0xfff); |
1140 emitInst(Encoding); | 1141 emitInst(Encoding); |
1141 } | 1142 } |
1142 | 1143 |
1143 void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc, | 1144 void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc, |
1144 CondARM32::Cond Cond) { | 1145 CondARM32::Cond Cond) { |
1145 IValueT Rd; | 1146 IValueT Rd; |
1146 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 1147 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) |
1147 return setNeedsTextFixup(); | 1148 return setNeedsTextFixup(); |
1148 if (const auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc)) { | 1149 if (const auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc)) { |
1149 // MOVW (immediate) - ARM section A8.8.102, encoding A2: | 1150 // MOVW (immediate) - ARM section A8.8.102, encoding A2: |
1150 // movw<c> <Rd>, #<imm16> | 1151 // movw<c> <Rd>, #<imm16> |
1151 // | 1152 // |
1152 // cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and | 1153 // cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and |
1153 // iiiiiiiiiiiiiiii=imm16. | 1154 // iiiiiiiiiiiiiiii=imm16. |
1154 if (!isConditionDefined(Cond)) | 1155 if (!isConditionDefined(Cond)) |
1155 // Conditions of rule violated. | 1156 // Conditions of rule violated. |
1156 return setNeedsTextFixup(); | 1157 return setNeedsTextFixup(); |
1157 // Use 0 for the lower 16 bits of the relocatable, and add a fixup to | 1158 // Use 0 for the lower 16 bits of the relocatable, and add a fixup to |
1158 // install the correct bits. | 1159 // install the correct bits. |
1159 constexpr bool IsMovW = true; | 1160 constexpr bool IsMovW = true; |
1160 emitFixup(createMoveFixup(IsMovW, Src)); | 1161 emitFixup(createMoveFixup(IsMovW, Src)); |
1161 constexpr IValueT Imm16 = 0; | 1162 constexpr IValueT Imm16 = 0; |
1162 constexpr bool SetFlags = false; | 1163 constexpr bool SetFlags = false; |
1163 emitMovw(B25 | B24, Rd, Imm16, SetFlags, Cond); | 1164 emitMovw(B25 | B24, Rd, Imm16, SetFlags, Cond); |
1164 return; | 1165 return; |
1165 } | 1166 } |
1166 IValueT ConstVal; | 1167 IValueT ConstVal; |
1167 if (decodeOperand(OpSrc, ConstVal) != DecodedAsConstI32) | 1168 if (encodeOperand(OpSrc, ConstVal) != EncodedAsConstI32) |
1168 return setNeedsTextFixup(); | 1169 return setNeedsTextFixup(); |
1169 // TODO(kschimpf): Determine if we want to handle rotated immediate 8 values | 1170 // TODO(kschimpf): Determine if we want to handle rotated immediate 8 values |
1170 // to handle cases where the constant is greater than 16 bits (encoding A1 | 1171 // to handle cases where the constant is greater than 16 bits (encoding A1 |
1171 // below). For now, handle using encoding A2. | 1172 // below). For now, handle using encoding A2. |
1172 constexpr bool SetFlags = 0; | 1173 constexpr bool SetFlags = 0; |
1173 emitMovw(B25 | B24, Rd, ConstVal, SetFlags, Cond); | 1174 emitMovw(B25 | B24, Rd, ConstVal, SetFlags, Cond); |
1174 return; | 1175 return; |
1175 | 1176 |
1176 // MOVW (immediate) - ARM section A8.8.102, encoding A1: | 1177 // MOVW (immediate) - ARM section A8.8.102, encoding A1: |
1177 // movw<c> <Rd>, #<RotatedImm8> | 1178 // movw<c> <Rd>, #<RotatedImm8> |
1178 // | 1179 // |
1179 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, s=SetFlags=0, | 1180 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, s=SetFlags=0, |
1180 // and iiiiiiiiiiii is a shift-rotated value defining RotatedImm8. | 1181 // and iiiiiiiiiiii is a shift-rotated value defining RotatedImm8. |
1181 } | 1182 } |
1182 | 1183 |
1183 void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc, | 1184 void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc, |
1184 CondARM32::Cond Cond) { | 1185 CondARM32::Cond Cond) { |
1185 IValueT Rd; | 1186 IValueT Rd; |
1186 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 1187 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) |
1187 return setNeedsTextFixup(); | 1188 return setNeedsTextFixup(); |
1188 auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc); | 1189 auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc); |
1189 if (Src == nullptr) | 1190 if (Src == nullptr) |
1190 return setNeedsTextFixup(); | 1191 return setNeedsTextFixup(); |
1191 // MOVT - ARM section A8.8.102, encoding A2: | 1192 // MOVT - ARM section A8.8.102, encoding A2: |
1192 // movt<c> <Rd>, #<imm16> | 1193 // movt<c> <Rd>, #<imm16> |
1193 // | 1194 // |
1194 // cccc00110100iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and | 1195 // cccc00110100iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and |
1195 // iiiiiiiiiiiiiiii=imm16. | 1196 // iiiiiiiiiiiiiiii=imm16. |
1196 if (!isConditionDefined(Cond)) | 1197 if (!isConditionDefined(Cond)) |
(...skipping 18 matching lines...) Expand all Loading... |
1215 // | 1216 // |
1216 // cccc0011111s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags=0, dddd=Rd, | 1217 // cccc0011111s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags=0, dddd=Rd, |
1217 // and iiiiiiiiiiii=const | 1218 // and iiiiiiiiiiii=const |
1218 // | 1219 // |
1219 // MVN (register) - ARM section A8.8.116, encoding A1: | 1220 // MVN (register) - ARM section A8.8.116, encoding A1: |
1220 // mvn{s}<c> <Rd>, <Rm>{, <shift> | 1221 // mvn{s}<c> <Rd>, <Rm>{, <shift> |
1221 // | 1222 // |
1222 // cccc0001111s0000ddddiiiiitt0mmmm where cccc=Cond, s=SetFlags=0, dddd=Rd, | 1223 // cccc0001111s0000ddddiiiiitt0mmmm where cccc=Cond, s=SetFlags=0, dddd=Rd, |
1223 // mmmm=Rm, iiii defines shift constant, and tt=ShiftKind. | 1224 // mmmm=Rm, iiii defines shift constant, and tt=ShiftKind. |
1224 IValueT Rd; | 1225 IValueT Rd; |
1225 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 1226 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) |
1226 return setNeedsTextFixup(); | 1227 return setNeedsTextFixup(); |
1227 constexpr IValueT MvnOpcode = B3 | B2 | B1 | B0; // i.e. 1111 | 1228 constexpr IValueT MvnOpcode = B3 | B2 | B1 | B0; // i.e. 1111 |
1228 constexpr IValueT Rn = 0; | 1229 constexpr IValueT Rn = 0; |
1229 constexpr bool SetFlags = false; | 1230 constexpr bool SetFlags = false; |
1230 emitType01(MvnOpcode, Rd, Rn, OpSrc, SetFlags, Cond, RdIsPcAndSetFlags); | 1231 emitType01(MvnOpcode, Rd, Rn, OpSrc, SetFlags, Cond, RdIsPcAndSetFlags); |
1231 } | 1232 } |
1232 | 1233 |
1233 void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn, | 1234 void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn, |
1234 const Operand *OpSrc1, bool SetFlags, | 1235 const Operand *OpSrc1, bool SetFlags, |
1235 CondARM32::Cond Cond) { | 1236 CondARM32::Cond Cond) { |
(...skipping 13 matching lines...) Expand all Loading... |
1249 } | 1250 } |
1250 | 1251 |
1251 void AssemblerARM32::sdiv(const Operand *OpRd, const Operand *OpRn, | 1252 void AssemblerARM32::sdiv(const Operand *OpRd, const Operand *OpRn, |
1252 const Operand *OpSrc1, CondARM32::Cond Cond) { | 1253 const Operand *OpSrc1, CondARM32::Cond Cond) { |
1253 // SDIV - ARM section A8.8.165, encoding A1. | 1254 // SDIV - ARM section A8.8.165, encoding A1. |
1254 // sdiv<c> <Rd>, <Rn>, <Rm> | 1255 // sdiv<c> <Rd>, <Rn>, <Rm> |
1255 // | 1256 // |
1256 // cccc01110001dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and | 1257 // cccc01110001dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and |
1257 // mmmm=Rm. | 1258 // mmmm=Rm. |
1258 IValueT Rd; | 1259 IValueT Rd; |
1259 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 1260 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) |
1260 return setNeedsTextFixup(); | 1261 return setNeedsTextFixup(); |
1261 IValueT Rn; | 1262 IValueT Rn; |
1262 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 1263 if (encodeOperand(OpRn, Rn) != EncodedAsRegister) |
1263 return setNeedsTextFixup(); | 1264 return setNeedsTextFixup(); |
1264 IValueT Rm; | 1265 IValueT Rm; |
1265 if (decodeOperand(OpSrc1, Rm) != DecodedAsRegister) | 1266 if (encodeOperand(OpSrc1, Rm) != EncodedAsRegister) |
1266 return setNeedsTextFixup(); | 1267 return setNeedsTextFixup(); |
1267 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || | 1268 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || |
1268 Rm == RegARM32::Encoded_Reg_pc) | 1269 Rm == RegARM32::Encoded_Reg_pc) |
1269 llvm::report_fatal_error("Sdiv instruction unpredictable on pc"); | 1270 llvm::report_fatal_error("Sdiv instruction unpredictable on pc"); |
1270 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. | 1271 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. |
1271 constexpr IValueT Opcode = 0; | 1272 constexpr IValueT Opcode = 0; |
1272 emitDivOp(Cond, Opcode, Rd, Rn, Rm); | 1273 emitDivOp(Cond, Opcode, Rd, Rn, Rm); |
1273 } | 1274 } |
1274 | 1275 |
1275 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, | 1276 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
1276 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 1277 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
1277 constexpr bool IsLoad = false; | 1278 constexpr bool IsLoad = false; |
1278 IValueT Rt; | 1279 IValueT Rt; |
1279 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 1280 if (encodeOperand(OpRt, Rt) != EncodedAsRegister) |
1280 return setNeedsTextFixup(); | 1281 return setNeedsTextFixup(); |
1281 const Type Ty = OpRt->getType(); | 1282 const Type Ty = OpRt->getType(); |
1282 switch (typeWidthInBytesLog2(Ty)) { | 1283 switch (typeWidthInBytesLog2(Ty)) { |
1283 case 3: | 1284 case 3: |
1284 // STRD is not implemented because target lowering handles i64 and double by | 1285 // STRD is not implemented because target lowering handles i64 and double by |
1285 // using two (32-bit) store instructions. Note: Intenionally drop to | 1286 // using two (32-bit) store instructions. Note: Intenionally drop to |
1286 // default case. | 1287 // default case. |
1287 default: | 1288 default: |
1288 llvm::report_fatal_error(std::string("Type ") + typeString(Ty) + | 1289 llvm::report_fatal_error(std::string("Type ") + typeString(Ty) + |
1289 " not implementable using str\n"); | 1290 " not implementable using str\n"); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 constexpr IValueT Orr = B3 | B2; // i.e. 1100 | 1349 constexpr IValueT Orr = B3 | B2; // i.e. 1100 |
1349 emitType01(Orr, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); | 1350 emitType01(Orr, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags); |
1350 } | 1351 } |
1351 | 1352 |
1352 void AssemblerARM32::pop(const Operand *OpRt, CondARM32::Cond Cond) { | 1353 void AssemblerARM32::pop(const Operand *OpRt, CondARM32::Cond Cond) { |
1353 // POP - ARM section A8.8.132, encoding A2: | 1354 // POP - ARM section A8.8.132, encoding A2: |
1354 // pop<c> {Rt} | 1355 // pop<c> {Rt} |
1355 // | 1356 // |
1356 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. | 1357 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. |
1357 IValueT Rt; | 1358 IValueT Rt; |
1358 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 1359 if (encodeOperand(OpRt, Rt) != EncodedAsRegister) |
1359 return setNeedsTextFixup(); | 1360 return setNeedsTextFixup(); |
1360 assert(Rt != RegARM32::Encoded_Reg_sp); | 1361 assert(Rt != RegARM32::Encoded_Reg_sp); |
1361 // Same as load instruction. | 1362 // Same as load instruction. |
1362 constexpr bool IsLoad = true; | 1363 constexpr bool IsLoad = true; |
1363 constexpr bool IsByte = false; | 1364 constexpr bool IsByte = false; |
1364 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, | 1365 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, |
1365 OperandARM32Mem::PostIndex); | 1366 OperandARM32Mem::PostIndex); |
1366 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); | 1367 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); |
1367 } | 1368 } |
1368 | 1369 |
1369 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { | 1370 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { |
1370 // POP - ARM section A8.*.131, encoding A1: | 1371 // POP - ARM section A8.*.131, encoding A1: |
1371 // pop<c> <registers> | 1372 // pop<c> <registers> |
1372 // | 1373 // |
1373 // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and | 1374 // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and |
1374 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). | 1375 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). |
1375 constexpr bool IsLoad = true; | 1376 constexpr bool IsLoad = true; |
1376 emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); | 1377 emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); |
1377 } | 1378 } |
1378 | 1379 |
1379 void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) { | 1380 void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) { |
1380 // PUSH - ARM section A8.8.133, encoding A2: | 1381 // PUSH - ARM section A8.8.133, encoding A2: |
1381 // push<c> {Rt} | 1382 // push<c> {Rt} |
1382 // | 1383 // |
1383 // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond. | 1384 // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond. |
1384 IValueT Rt; | 1385 IValueT Rt; |
1385 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 1386 if (encodeOperand(OpRt, Rt) != EncodedAsRegister) |
1386 return setNeedsTextFixup(); | 1387 return setNeedsTextFixup(); |
1387 assert(Rt != RegARM32::Encoded_Reg_sp); | 1388 assert(Rt != RegARM32::Encoded_Reg_sp); |
1388 // Same as store instruction. | 1389 // Same as store instruction. |
1389 constexpr bool isLoad = false; | 1390 constexpr bool isLoad = false; |
1390 constexpr bool isByte = false; | 1391 constexpr bool isByte = false; |
1391 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, | 1392 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, |
1392 OperandARM32Mem::PreIndex); | 1393 OperandARM32Mem::PreIndex); |
1393 emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address); | 1394 emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address); |
1394 } | 1395 } |
1395 | 1396 |
1396 void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) { | 1397 void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) { |
1397 // PUSH - ARM section A8.8.133, encoding A1: | 1398 // PUSH - ARM section A8.8.133, encoding A1: |
1398 // push<c> <Registers> | 1399 // push<c> <Registers> |
1399 // | 1400 // |
1400 // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and | 1401 // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and |
1401 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). | 1402 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). |
1402 constexpr bool IsLoad = false; | 1403 constexpr bool IsLoad = false; |
1403 emitMultiMemOp(Cond, DB_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); | 1404 emitMultiMemOp(Cond, DB_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); |
1404 } | 1405 } |
1405 | 1406 |
1406 void AssemblerARM32::mla(const Operand *OpRd, const Operand *OpRn, | 1407 void AssemblerARM32::mla(const Operand *OpRd, const Operand *OpRn, |
1407 const Operand *OpRm, const Operand *OpRa, | 1408 const Operand *OpRm, const Operand *OpRa, |
1408 CondARM32::Cond Cond) { | 1409 CondARM32::Cond Cond) { |
1409 IValueT Rd; | 1410 IValueT Rd; |
1410 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 1411 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) |
1411 return setNeedsTextFixup(); | 1412 return setNeedsTextFixup(); |
1412 IValueT Rn; | 1413 IValueT Rn; |
1413 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 1414 if (encodeOperand(OpRn, Rn) != EncodedAsRegister) |
1414 return setNeedsTextFixup(); | 1415 return setNeedsTextFixup(); |
1415 IValueT Rm; | 1416 IValueT Rm; |
1416 if (decodeOperand(OpRm, Rm) != DecodedAsRegister) | 1417 if (encodeOperand(OpRm, Rm) != EncodedAsRegister) |
1417 return setNeedsTextFixup(); | 1418 return setNeedsTextFixup(); |
1418 IValueT Ra; | 1419 IValueT Ra; |
1419 if (decodeOperand(OpRa, Ra) != DecodedAsRegister) | 1420 if (encodeOperand(OpRa, Ra) != EncodedAsRegister) |
1420 return setNeedsTextFixup(); | 1421 return setNeedsTextFixup(); |
1421 // MLA - ARM section A8.8.114, encoding A1. | 1422 // MLA - ARM section A8.8.114, encoding A1. |
1422 // mla{s}<c> <Rd>, <Rn>, <Rm>, <Ra> | 1423 // mla{s}<c> <Rd>, <Rn>, <Rm>, <Ra> |
1423 // | 1424 // |
1424 // cccc0000001sddddaaaammmm1001nnnn where cccc=Cond, s=SetFlags, dddd=Rd, | 1425 // cccc0000001sddddaaaammmm1001nnnn where cccc=Cond, s=SetFlags, dddd=Rd, |
1425 // aaaa=Ra, mmmm=Rm, and nnnn=Rn. | 1426 // aaaa=Ra, mmmm=Rm, and nnnn=Rn. |
1426 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || | 1427 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || |
1427 Rm == RegARM32::Encoded_Reg_pc || Ra == RegARM32::Encoded_Reg_pc) | 1428 Rm == RegARM32::Encoded_Reg_pc || Ra == RegARM32::Encoded_Reg_pc) |
1428 llvm::report_fatal_error("Mul instruction unpredictable on pc"); | 1429 llvm::report_fatal_error("Mul instruction unpredictable on pc"); |
1429 constexpr IValueT MlaOpcode = B21; | 1430 constexpr IValueT MlaOpcode = B21; |
1430 constexpr bool SetFlags = false; | 1431 constexpr bool SetFlags = false; |
1431 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. | 1432 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. |
1432 emitMulOp(Cond, MlaOpcode, Ra, Rd, Rn, Rm, SetFlags); | 1433 emitMulOp(Cond, MlaOpcode, Ra, Rd, Rn, Rm, SetFlags); |
1433 } | 1434 } |
1434 | 1435 |
1435 void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn, | 1436 void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn, |
1436 const Operand *OpSrc1, bool SetFlags, | 1437 const Operand *OpSrc1, bool SetFlags, |
1437 CondARM32::Cond Cond) { | 1438 CondARM32::Cond Cond) { |
1438 IValueT Rd; | 1439 IValueT Rd; |
1439 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 1440 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) |
1440 return setNeedsTextFixup(); | 1441 return setNeedsTextFixup(); |
1441 IValueT Rn; | 1442 IValueT Rn; |
1442 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 1443 if (encodeOperand(OpRn, Rn) != EncodedAsRegister) |
1443 return setNeedsTextFixup(); | 1444 return setNeedsTextFixup(); |
1444 IValueT Rm; | 1445 IValueT Rm; |
1445 if (decodeOperand(OpSrc1, Rm) != DecodedAsRegister) | 1446 if (encodeOperand(OpSrc1, Rm) != EncodedAsRegister) |
1446 return setNeedsTextFixup(); | 1447 return setNeedsTextFixup(); |
1447 // MUL - ARM section A8.8.114, encoding A1. | 1448 // MUL - ARM section A8.8.114, encoding A1. |
1448 // mul{s}<c> <Rd>, <Rn>, <Rm> | 1449 // mul{s}<c> <Rd>, <Rn>, <Rm> |
1449 // | 1450 // |
1450 // cccc0000000sdddd0000mmmm1001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, | 1451 // cccc0000000sdddd0000mmmm1001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, |
1451 // mmmm=Rm, and s=SetFlags. | 1452 // mmmm=Rm, and s=SetFlags. |
1452 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || | 1453 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || |
1453 Rm == RegARM32::Encoded_Reg_pc) | 1454 Rm == RegARM32::Encoded_Reg_pc) |
1454 llvm::report_fatal_error("Mul instruction unpredictable on pc"); | 1455 llvm::report_fatal_error("Mul instruction unpredictable on pc"); |
1455 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. | 1456 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. |
1456 constexpr IValueT MulOpcode = 0; | 1457 constexpr IValueT MulOpcode = 0; |
1457 emitMulOp(Cond, MulOpcode, RegARM32::Encoded_Reg_r0, Rd, Rn, Rm, SetFlags); | 1458 emitMulOp(Cond, MulOpcode, RegARM32::Encoded_Reg_r0, Rd, Rn, Rm, SetFlags); |
1458 } | 1459 } |
1459 | 1460 |
1460 void AssemblerARM32::udiv(const Operand *OpRd, const Operand *OpRn, | 1461 void AssemblerARM32::udiv(const Operand *OpRd, const Operand *OpRn, |
1461 const Operand *OpSrc1, CondARM32::Cond Cond) { | 1462 const Operand *OpSrc1, CondARM32::Cond Cond) { |
1462 // UDIV - ARM section A8.8.248, encoding A1. | 1463 // UDIV - ARM section A8.8.248, encoding A1. |
1463 // udiv<c> <Rd>, <Rn>, <Rm> | 1464 // udiv<c> <Rd>, <Rn>, <Rm> |
1464 // | 1465 // |
1465 // cccc01110011dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and | 1466 // cccc01110011dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and |
1466 // mmmm=Rm. | 1467 // mmmm=Rm. |
1467 IValueT Rd; | 1468 IValueT Rd; |
1468 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 1469 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) |
1469 return setNeedsTextFixup(); | 1470 return setNeedsTextFixup(); |
1470 IValueT Rn; | 1471 IValueT Rn; |
1471 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 1472 if (encodeOperand(OpRn, Rn) != EncodedAsRegister) |
1472 return setNeedsTextFixup(); | 1473 return setNeedsTextFixup(); |
1473 IValueT Rm; | 1474 IValueT Rm; |
1474 if (decodeOperand(OpSrc1, Rm) != DecodedAsRegister) | 1475 if (encodeOperand(OpSrc1, Rm) != EncodedAsRegister) |
1475 return setNeedsTextFixup(); | 1476 return setNeedsTextFixup(); |
1476 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || | 1477 if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || |
1477 Rm == RegARM32::Encoded_Reg_pc) | 1478 Rm == RegARM32::Encoded_Reg_pc) |
1478 llvm::report_fatal_error("Udiv instruction unpredictable on pc"); | 1479 llvm::report_fatal_error("Udiv instruction unpredictable on pc"); |
1479 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. | 1480 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. |
1480 constexpr IValueT Opcode = B21; | 1481 constexpr IValueT Opcode = B21; |
1481 emitDivOp(Cond, Opcode, Rd, Rn, Rm); | 1482 emitDivOp(Cond, Opcode, Rd, Rn, Rm); |
1482 } | 1483 } |
1483 | 1484 |
1484 void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, | 1485 void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1525 CondARM32::Cond Cond) { | 1526 CondARM32::Cond Cond) { |
1526 // UMULL - ARM section A8.8.257, encoding A1: | 1527 // UMULL - ARM section A8.8.257, encoding A1: |
1527 // umull<c> <RdLo>, <RdHi>, <Rn>, <Rm> | 1528 // umull<c> <RdLo>, <RdHi>, <Rn>, <Rm> |
1528 // | 1529 // |
1529 // cccc0000100shhhhllllmmmm1001nnnn where hhhh=RdHi, llll=RdLo, nnnn=Rn, | 1530 // cccc0000100shhhhllllmmmm1001nnnn where hhhh=RdHi, llll=RdLo, nnnn=Rn, |
1530 // mmmm=Rm, and s=SetFlags | 1531 // mmmm=Rm, and s=SetFlags |
1531 IValueT RdLo; | 1532 IValueT RdLo; |
1532 IValueT RdHi; | 1533 IValueT RdHi; |
1533 IValueT Rn; | 1534 IValueT Rn; |
1534 IValueT Rm; | 1535 IValueT Rm; |
1535 if (decodeOperand(OpRdLo, RdLo) != DecodedAsRegister || | 1536 if (encodeOperand(OpRdLo, RdLo) != EncodedAsRegister || |
1536 decodeOperand(OpRdHi, RdHi) != DecodedAsRegister || | 1537 encodeOperand(OpRdHi, RdHi) != EncodedAsRegister || |
1537 decodeOperand(OpRn, Rn) != DecodedAsRegister || | 1538 encodeOperand(OpRn, Rn) != EncodedAsRegister || |
1538 decodeOperand(OpRm, Rm) != DecodedAsRegister) | 1539 encodeOperand(OpRm, Rm) != EncodedAsRegister) |
1539 return setNeedsTextFixup(); | 1540 return setNeedsTextFixup(); |
1540 if (RdHi == RegARM32::Encoded_Reg_pc || RdLo == RegARM32::Encoded_Reg_pc || | 1541 if (RdHi == RegARM32::Encoded_Reg_pc || RdLo == RegARM32::Encoded_Reg_pc || |
1541 Rn == RegARM32::Encoded_Reg_pc || Rm == RegARM32::Encoded_Reg_pc || | 1542 Rn == RegARM32::Encoded_Reg_pc || Rm == RegARM32::Encoded_Reg_pc || |
1542 RdHi == RdLo) | 1543 RdHi == RdLo) |
1543 llvm::report_fatal_error("Umull instruction unpredictable on pc"); | 1544 llvm::report_fatal_error("Umull instruction unpredictable on pc"); |
1544 constexpr bool SetFlags = false; | 1545 constexpr bool SetFlags = false; |
1545 emitMulOp(Cond, B23, RdLo, RdHi, Rn, Rm, SetFlags); | 1546 emitMulOp(Cond, B23, RdLo, RdHi, Rn, Rm, SetFlags); |
1546 } | 1547 } |
1547 | 1548 |
1548 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, | 1549 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, |
1549 CondARM32::Cond Cond) { | 1550 CondARM32::Cond Cond) { |
1550 IValueT Rd; | 1551 IValueT Rd; |
1551 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 1552 if (encodeOperand(OpRd, Rd) != EncodedAsRegister) |
1552 return setNeedsTextFixup(); | 1553 return setNeedsTextFixup(); |
1553 // Note: For the moment, we assume no rotation is specified. | 1554 // Note: For the moment, we assume no rotation is specified. |
1554 RotationValue Rotation = kRotateNone; | 1555 RotationValue Rotation = kRotateNone; |
1555 constexpr IValueT Rn = RegARM32::Encoded_Reg_pc; | 1556 constexpr IValueT Rn = RegARM32::Encoded_Reg_pc; |
1556 IValueT Rm; | 1557 IValueT Rm; |
1557 if (decodeOperand(OpSrc0, Rm) != DecodedAsRegister) | 1558 if (encodeOperand(OpSrc0, Rm) != EncodedAsRegister) |
1558 return setNeedsTextFixup(); | 1559 return setNeedsTextFixup(); |
1559 switch (typeWidthInBytes(OpSrc0->getType())) { | 1560 switch (typeWidthInBytes(OpSrc0->getType())) { |
1560 default: | 1561 default: |
1561 return setNeedsTextFixup(); | 1562 return setNeedsTextFixup(); |
1562 case 1: { | 1563 case 1: { |
1563 // UXTB - ARM section A8.8.274, encoding A1: | 1564 // UXTB - ARM section A8.8.274, encoding A1: |
1564 // uxtb<c> <Rd>, <Rm>{, <rotate>} | 1565 // uxtb<c> <Rd>, <Rm>{, <rotate>} |
1565 // | 1566 // |
1566 // cccc011011101111ddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and | 1567 // cccc011011101111ddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and |
1567 // rr defined (RotationValue) rotate. | 1568 // rr defined (RotationValue) rotate. |
1568 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21; | 1569 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21; |
1569 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); | 1570 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); |
1570 return; | 1571 return; |
1571 } | 1572 } |
1572 case 2: { | 1573 case 2: { |
1573 // UXTH - ARM section A8.8.276, encoding A1: | 1574 // UXTH - ARM section A8.8.276, encoding A1: |
1574 // uxth<c> <Rd>< <Rm>{, <rotate>} | 1575 // uxth<c> <Rd>< <Rm>{, <rotate>} |
1575 // | 1576 // |
1576 // cccc01101111nnnnddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and | 1577 // cccc01101111nnnnddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and |
1577 // rr defined (RotationValue) rotate. | 1578 // rr defined (RotationValue) rotate. |
1578 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21 | B20; | 1579 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21 | B20; |
1579 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); | 1580 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); |
1580 return; | 1581 return; |
1581 } | 1582 } |
1582 } | 1583 } |
1583 } | 1584 } |
1584 | 1585 |
1585 } // end of namespace ARM32 | 1586 } // end of namespace ARM32 |
1586 } // end of namespace Ice | 1587 } // end of namespace Ice |
OLD | NEW |