• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===//
2 //
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
5 // BSD-style license that can be found in the LICENSE file.
6 //
7 // Modified by the Subzero authors.
8 //
9 //===----------------------------------------------------------------------===//
10 //
11 //                        The Subzero Code Generator
12 //
13 // This file is distributed under the University of Illinois Open Source
14 // License. See LICENSE.TXT for details.
15 //
16 //===----------------------------------------------------------------------===//
17 ///
18 /// \file
19 /// \brief Implements the Assembler class for ARM32.
20 ///
21 //===----------------------------------------------------------------------===//
22 
23 #include "IceAssemblerARM32.h"
24 #include "IceCfgNode.h"
25 #include "IceUtils.h"
26 
27 namespace {
28 
29 using namespace Ice;
30 using namespace Ice::ARM32;
31 
32 using WordType = uint32_t;
33 static constexpr IValueT kWordSize = sizeof(WordType);
34 
35 // The following define individual bits.
36 static constexpr IValueT B0 = 1;
37 static constexpr IValueT B1 = 1 << 1;
38 static constexpr IValueT B2 = 1 << 2;
39 static constexpr IValueT B3 = 1 << 3;
40 static constexpr IValueT B4 = 1 << 4;
41 static constexpr IValueT B5 = 1 << 5;
42 static constexpr IValueT B6 = 1 << 6;
43 static constexpr IValueT B7 = 1 << 7;
44 static constexpr IValueT B8 = 1 << 8;
45 static constexpr IValueT B9 = 1 << 9;
46 static constexpr IValueT B10 = 1 << 10;
47 static constexpr IValueT B11 = 1 << 11;
48 static constexpr IValueT B12 = 1 << 12;
49 static constexpr IValueT B13 = 1 << 13;
50 static constexpr IValueT B14 = 1 << 14;
51 static constexpr IValueT B15 = 1 << 15;
52 static constexpr IValueT B16 = 1 << 16;
53 static constexpr IValueT B17 = 1 << 17;
54 static constexpr IValueT B18 = 1 << 18;
55 static constexpr IValueT B19 = 1 << 19;
56 static constexpr IValueT B20 = 1 << 20;
57 static constexpr IValueT B21 = 1 << 21;
58 static constexpr IValueT B22 = 1 << 22;
59 static constexpr IValueT B23 = 1 << 23;
60 static constexpr IValueT B24 = 1 << 24;
61 static constexpr IValueT B25 = 1 << 25;
62 static constexpr IValueT B26 = 1 << 26;
63 static constexpr IValueT B27 = 1 << 27;
64 
65 // Constants used for the decoding or encoding of the individual fields of
66 // instructions. Based on ARM section A5.1.
67 static constexpr IValueT L = 1 << 20; // load (or store)
68 static constexpr IValueT W = 1 << 21; // writeback base register
69                                       // (or leave unchanged)
70 static constexpr IValueT B = 1 << 22; // unsigned byte (or word)
71 static constexpr IValueT U = 1 << 23; // positive (or negative)
72                                       // offset/index
73 static constexpr IValueT P = 1 << 24; // offset/pre-indexed
74                                       // addressing (or
75                                       // post-indexed addressing)
76 
77 static constexpr IValueT kConditionShift = 28;
78 static constexpr IValueT kLinkShift = 24;
79 static constexpr IValueT kOpcodeShift = 21;
80 static constexpr IValueT kRdShift = 12;
81 static constexpr IValueT kRmShift = 0;
82 static constexpr IValueT kRnShift = 16;
83 static constexpr IValueT kRsShift = 8;
84 static constexpr IValueT kSShift = 20;
85 static constexpr IValueT kTypeShift = 25;
86 
87 // Immediate instruction fields encoding.
88 static constexpr IValueT kImmed8Bits = 8;
89 static constexpr IValueT kImmed8Shift = 0;
90 static constexpr IValueT kRotateBits = 4;
91 static constexpr IValueT kRotateShift = 8;
92 
93 // Shift instruction register fields encodings.
94 static constexpr IValueT kShiftImmShift = 7;
95 static constexpr IValueT kShiftImmBits = 5;
96 static constexpr IValueT kShiftShift = 5;
97 static constexpr IValueT kImmed12Bits = 12;
98 static constexpr IValueT kImm12Shift = 0;
99 
100 // Rotation instructions (uxtb etc.).
101 static constexpr IValueT kRotationShift = 10;
102 
103 // MemEx instructions.
104 static constexpr IValueT kMemExOpcodeShift = 20;
105 
106 // Div instruction register field encodings.
107 static constexpr IValueT kDivRdShift = 16;
108 static constexpr IValueT kDivRmShift = 8;
109 static constexpr IValueT kDivRnShift = 0;
110 
111 // Type of instruction encoding (bits 25-27). See ARM section A5.1
112 static constexpr IValueT kInstTypeDataRegister = 0;  // i.e. 000
113 static constexpr IValueT kInstTypeDataRegShift = 0;  // i.e. 000
114 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001
115 static constexpr IValueT kInstTypeMemImmediate = 2;  // i.e. 010
116 static constexpr IValueT kInstTypeRegisterShift = 3; // i.e. 011
117 
118 // Limit on number of registers in a vpush/vpop.
119 static constexpr SizeT VpushVpopMaxConsecRegs = 16;
120 
121 // Offset modifier to current PC for next instruction.  The offset is off by 8
122 // due to the way the ARM CPUs read PC.
123 static constexpr IOffsetT kPCReadOffset = 8;
124 
125 // Mask to pull out PC offset from branch (b) instruction.
126 static constexpr int kBranchOffsetBits = 24;
127 static constexpr IOffsetT kBranchOffsetMask = 0x00ffffff;
128 
encodeBool(bool B)129 IValueT encodeBool(bool B) { return B ? 1 : 0; }
130 
encodeRotation(ARM32::AssemblerARM32::RotationValue Value)131 IValueT encodeRotation(ARM32::AssemblerARM32::RotationValue Value) {
132   return static_cast<IValueT>(Value);
133 }
134 
encodeGPRRegister(RegARM32::GPRRegister Rn)135 IValueT encodeGPRRegister(RegARM32::GPRRegister Rn) {
136   return static_cast<IValueT>(Rn);
137 }
138 
decodeGPRRegister(IValueT R)139 RegARM32::GPRRegister decodeGPRRegister(IValueT R) {
140   return static_cast<RegARM32::GPRRegister>(R);
141 }
142 
encodeCondition(CondARM32::Cond Cond)143 IValueT encodeCondition(CondARM32::Cond Cond) {
144   return static_cast<IValueT>(Cond);
145 }
146 
encodeShift(OperandARM32::ShiftKind Shift)147 IValueT encodeShift(OperandARM32::ShiftKind Shift) {
148   // Follows encoding in ARM section A8.4.1 "Constant shifts".
149   switch (Shift) {
150   case OperandARM32::kNoShift:
151   case OperandARM32::LSL:
152     return 0; // 0b00
153   case OperandARM32::LSR:
154     return 1; // 0b01
155   case OperandARM32::ASR:
156     return 2; // 0b10
157   case OperandARM32::ROR:
158   case OperandARM32::RRX:
159     return 3; // 0b11
160   }
161   llvm::report_fatal_error("Unknown Shift value");
162   return 0;
163 }
164 
165 // Returns the bits in the corresponding masked value.
mask(IValueT Value,IValueT Shift,IValueT Bits)166 IValueT mask(IValueT Value, IValueT Shift, IValueT Bits) {
167   return (Value >> Shift) & ((1 << Bits) - 1);
168 }
169 
170 // Extract out a Bit in Value.
isBitSet(IValueT Bit,IValueT Value)171 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; }
172 
173 // Returns the GPR register at given Shift in Value.
getGPRReg(IValueT Shift,IValueT Value)174 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) {
175   return decodeGPRRegister((Value >> Shift) & 0xF);
176 }
177 
getEncodedGPRegNum(const Variable * Var)178 IValueT getEncodedGPRegNum(const Variable *Var) {
179   assert(Var->hasReg());
180   const auto Reg = Var->getRegNum();
181   return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg)
182                                         : RegARM32::getEncodedGPR(Reg);
183 }
184 
getEncodedSRegNum(const Variable * Var)185 IValueT getEncodedSRegNum(const Variable *Var) {
186   assert(Var->hasReg());
187   return RegARM32::getEncodedSReg(Var->getRegNum());
188 }
189 
getEncodedDRegNum(const Variable * Var)190 IValueT getEncodedDRegNum(const Variable *Var) {
191   return RegARM32::getEncodedDReg(Var->getRegNum());
192 }
193 
getEncodedQRegNum(const Variable * Var)194 IValueT getEncodedQRegNum(const Variable *Var) {
195   return RegARM32::getEncodedQReg(Var->getRegNum());
196 }
197 
mapQRegToDReg(IValueT EncodedQReg)198 IValueT mapQRegToDReg(IValueT EncodedQReg) {
199   IValueT DReg = EncodedQReg << 1;
200   assert(DReg < RegARM32::getNumDRegs());
201   return DReg;
202 }
203 
mapQRegToSReg(IValueT EncodedQReg)204 IValueT mapQRegToSReg(IValueT EncodedQReg) {
205   IValueT SReg = EncodedQReg << 2;
206   assert(SReg < RegARM32::getNumSRegs());
207   return SReg;
208 }
209 
getYInRegXXXXY(IValueT RegXXXXY)210 IValueT getYInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY & 0x1; }
211 
getXXXXInRegXXXXY(IValueT RegXXXXY)212 IValueT getXXXXInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY >> 1; }
213 
getYInRegYXXXX(IValueT RegYXXXX)214 IValueT getYInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX >> 4; }
215 
getXXXXInRegYXXXX(IValueT RegYXXXX)216 IValueT getXXXXInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX & 0x0f; }
217 
218 // Figures out Op/Cmode values for given Value. Returns true if able to encode.
encodeAdvSIMDExpandImm(IValueT Value,Type ElmtTy,IValueT & Op,IValueT & Cmode,IValueT & Imm8)219 bool encodeAdvSIMDExpandImm(IValueT Value, Type ElmtTy, IValueT &Op,
220                             IValueT &Cmode, IValueT &Imm8) {
221   // TODO(kschimpf): Handle other shifted 8-bit values.
222   constexpr IValueT Imm8Mask = 0xFF;
223   if ((Value & IValueT(~Imm8Mask)) != 0)
224     return false;
225   Imm8 = Value;
226   switch (ElmtTy) {
227   case IceType_i8:
228     Op = 0;
229     Cmode = 14; // 0b1110
230     return true;
231   case IceType_i16:
232     Op = 0;
233     Cmode = 8; // 0b1000
234     return true;
235   case IceType_i32:
236     Op = 0;
237     Cmode = 0; // 0b0000
238     return true;
239   default:
240     return false;
241   }
242 }
243 
244 // Defines layouts of an operand representing a (register) memory address,
245 // possibly modified by an immediate value.
246 enum EncodedImmAddress {
247   // Address modified by a rotated immediate 8-bit value.
248   RotatedImm8Address,
249 
250   // Alternate encoding for RotatedImm8Address, where the offset is divided by 4
251   // before encoding.
252   RotatedImm8Div4Address,
253 
254   // Address modified by an immediate 12-bit value.
255   Imm12Address,
256 
257   // Alternate encoding 3, for an address modified by a rotated immediate 8-bit
258   // value.
259   RotatedImm8Enc3Address,
260 
261   // Encoding where no immediate offset is used.
262   NoImmOffsetAddress
263 };
264 
265 // The way an operand is encoded into a sequence of bits in functions
266 // encodeOperand and encodeAddress below.
267 enum EncodedOperand {
268   // Unable to encode, value left undefined.
269   CantEncode = 0,
270 
271   // Value is register found.
272   EncodedAsRegister,
273 
274   // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8
275   // value.
276   EncodedAsRotatedImm8,
277 
278   // EncodedAsImmRegOffset is a memory operand that can take three forms, based
279   // on type EncodedImmAddress:
280   //
281   // ***** RotatedImm8Address *****
282   //
283   // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn,
284   // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to
285   // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value.
286   //
287   // ***** RotatedImm8Div4Address *****
288   //
289   // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1
290   // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to
291   // Rn.
292   //
293   // ***** Imm12Address *****
294   //
295   // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn,
296   // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to
297   // Rn should be used, and iiiiiiiiiiii defines the immediate 12-bit value.
298   //
299   // ***** NoImmOffsetAddress *****
300   //
301   // Value=000000001000nnnn0000000000000000 where nnnn=Rn.
302   EncodedAsImmRegOffset,
303 
304   // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn,
305   // mmmm is the index register Rm, iiiii is the shift amount, ss is the shift
306   // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if
307   // writeback to Rn.
308   EncodedAsShiftRotateImm5,
309 
310   // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value
311   // to shift.
312   EncodedAsShiftImm5,
313 
314   // Value=iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift
315   // kind, and iiiii is the shift amount.
316   EncodedAsShiftedRegister,
317 
318   // Value=ssss0tt1mmmm where mmmm=Rm, tt is an encoded ShiftKind, and ssss=Rms.
319   EncodedAsRegShiftReg,
320 
321   // Value is 32bit integer constant.
322   EncodedAsConstI32
323 };
324 
325 // Sets Encoding to a rotated Imm8 encoding of Value, if possible.
encodeRotatedImm8(IValueT RotateAmt,IValueT Immed8)326 IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) {
327   assert(RotateAmt < (1 << kRotateBits));
328   assert(Immed8 < (1 << kImmed8Bits));
329   return (RotateAmt << kRotateShift) | (Immed8 << kImmed8Shift);
330 }
331 
332 // Encodes iiiiitt0mmmm for data-processing (2nd) operands where iiiii=Imm5,
333 // tt=Shift, and mmmm=Rm.
encodeShiftRotateImm5(IValueT Rm,OperandARM32::ShiftKind Shift,IOffsetT imm5)334 IValueT encodeShiftRotateImm5(IValueT Rm, OperandARM32::ShiftKind Shift,
335                               IOffsetT imm5) {
336   (void)kShiftImmBits;
337   assert(imm5 < (1 << kShiftImmBits));
338   return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm;
339 }
340 
341 // Encodes mmmmtt01ssss for data-processing operands where mmmm=Rm, ssss=Rs, and
342 // tt=Shift.
encodeShiftRotateReg(IValueT Rm,OperandARM32::ShiftKind Shift,IValueT Rs)343 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift,
344                              IValueT Rs) {
345   return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 |
346          (Rm << kRmShift);
347 }
348 
349 // Defines the set of registers expected in an operand.
350 enum RegSetWanted { WantGPRegs, WantSRegs, WantDRegs, WantQRegs };
351 
encodeOperand(const Operand * Opnd,IValueT & Value,RegSetWanted WantedRegSet)352 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value,
353                              RegSetWanted WantedRegSet) {
354   Value = 0; // Make sure initialized.
355   if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
356     if (Var->hasReg()) {
357       switch (WantedRegSet) {
358       case WantGPRegs:
359         Value = getEncodedGPRegNum(Var);
360         break;
361       case WantSRegs:
362         Value = getEncodedSRegNum(Var);
363         break;
364       case WantDRegs:
365         Value = getEncodedDRegNum(Var);
366         break;
367       case WantQRegs:
368         Value = getEncodedQRegNum(Var);
369         break;
370       }
371       return EncodedAsRegister;
372     }
373     return CantEncode;
374   }
375   if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) {
376     const IValueT Immed8 = FlexImm->getImm();
377     const IValueT Rotate = FlexImm->getRotateAmt();
378     if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))))
379       return CantEncode;
380     Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift);
381     return EncodedAsRotatedImm8;
382   }
383   if (const auto *Const = llvm::dyn_cast<ConstantInteger32>(Opnd)) {
384     Value = Const->getValue();
385     return EncodedAsConstI32;
386   }
387   if (const auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Opnd)) {
388     Operand *Amt = FlexReg->getShiftAmt();
389     IValueT Rm;
390     if (encodeOperand(FlexReg->getReg(), Rm, WantGPRegs) != EncodedAsRegister)
391       return CantEncode;
392     if (const auto *Var = llvm::dyn_cast<Variable>(Amt)) {
393       IValueT Rs;
394       if (encodeOperand(Var, Rs, WantGPRegs) != EncodedAsRegister)
395         return CantEncode;
396       Value = encodeShiftRotateReg(Rm, FlexReg->getShiftOp(), Rs);
397       return EncodedAsRegShiftReg;
398     }
399     // If reached, the amount is a shifted amount by some 5-bit immediate.
400     uint32_t Imm5;
401     if (const auto *ShAmt = llvm::dyn_cast<OperandARM32ShAmtImm>(Amt)) {
402       Imm5 = ShAmt->getShAmtImm();
403     } else if (const auto *IntConst = llvm::dyn_cast<ConstantInteger32>(Amt)) {
404       int32_t Val = IntConst->getValue();
405       if (Val < 0)
406         return CantEncode;
407       Imm5 = static_cast<uint32_t>(Val);
408     } else
409       return CantEncode;
410     Value = encodeShiftRotateImm5(Rm, FlexReg->getShiftOp(), Imm5);
411     return EncodedAsShiftedRegister;
412   }
413   if (const auto *ShImm = llvm::dyn_cast<OperandARM32ShAmtImm>(Opnd)) {
414     const IValueT Immed5 = ShImm->getShAmtImm();
415     assert(Immed5 < (1 << kShiftImmBits));
416     Value = (Immed5 << kShiftImmShift);
417     return EncodedAsShiftImm5;
418   }
419   return CantEncode;
420 }
421 
encodeImmRegOffset(IValueT Reg,IOffsetT Offset,OperandARM32Mem::AddrMode Mode,IOffsetT MaxOffset,IValueT OffsetShift)422 IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset,
423                            OperandARM32Mem::AddrMode Mode, IOffsetT MaxOffset,
424                            IValueT OffsetShift) {
425   IValueT Value = Mode | (Reg << kRnShift);
426   if (Offset < 0) {
427     Offset = -Offset;
428     Value ^= U; // Flip U to adjust sign.
429   }
430   assert(Offset <= MaxOffset);
431   (void)MaxOffset;
432   return Value | (Offset >> OffsetShift);
433 }
434 
435 // Encodes immediate register offset using encoding 3.
encodeImmRegOffsetEnc3(IValueT Rn,IOffsetT Imm8,OperandARM32Mem::AddrMode Mode)436 IValueT encodeImmRegOffsetEnc3(IValueT Rn, IOffsetT Imm8,
437                                OperandARM32Mem::AddrMode Mode) {
438   IValueT Value = Mode | (Rn << kRnShift);
439   if (Imm8 < 0) {
440     Imm8 = -Imm8;
441     Value = (Value ^ U);
442   }
443   assert(Imm8 < (1 << 8));
444   Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f);
445   return Value;
446 }
447 
encodeImmRegOffset(EncodedImmAddress ImmEncoding,IValueT Reg,IOffsetT Offset,OperandARM32Mem::AddrMode Mode)448 IValueT encodeImmRegOffset(EncodedImmAddress ImmEncoding, IValueT Reg,
449                            IOffsetT Offset, OperandARM32Mem::AddrMode Mode) {
450   switch (ImmEncoding) {
451   case RotatedImm8Address: {
452     constexpr IOffsetT MaxOffset = (1 << 8) - 1;
453     constexpr IValueT NoRightShift = 0;
454     return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, NoRightShift);
455   }
456   case RotatedImm8Div4Address: {
457     assert((Offset & 0x3) == 0);
458     constexpr IOffsetT MaxOffset = (1 << 8) - 1;
459     constexpr IValueT RightShift2 = 2;
460     return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, RightShift2);
461   }
462   case Imm12Address: {
463     constexpr IOffsetT MaxOffset = (1 << 12) - 1;
464     constexpr IValueT NoRightShift = 0;
465     return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, NoRightShift);
466   }
467   case RotatedImm8Enc3Address:
468     return encodeImmRegOffsetEnc3(Reg, Offset, Mode);
469   case NoImmOffsetAddress: {
470     assert(Offset == 0);
471     assert(Mode == OperandARM32Mem::Offset);
472     return Reg << kRnShift;
473   }
474   }
475   llvm_unreachable("(silence g++ warning)");
476 }
477 
478 // Encodes memory address Opnd, and encodes that information into Value, based
479 // on how ARM represents the address. Returns how the value was encoded.
encodeAddress(const Operand * Opnd,IValueT & Value,const AssemblerARM32::TargetInfo & TInfo,EncodedImmAddress ImmEncoding)480 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value,
481                              const AssemblerARM32::TargetInfo &TInfo,
482                              EncodedImmAddress ImmEncoding) {
483   Value = 0; // Make sure initialized.
484   if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
485     // Should be a stack variable, with an offset.
486     if (Var->hasReg())
487       return CantEncode;
488     IOffsetT Offset = Var->getStackOffset();
489     if (!Utils::IsAbsoluteUint(12, Offset))
490       return CantEncode;
491     const auto BaseRegNum =
492         Var->hasReg() ? Var->getBaseRegNum() : TInfo.FrameOrStackReg;
493     Value = encodeImmRegOffset(ImmEncoding, BaseRegNum, Offset,
494                                OperandARM32Mem::Offset);
495     return EncodedAsImmRegOffset;
496   }
497   if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) {
498     Variable *Var = Mem->getBase();
499     if (!Var->hasReg())
500       return CantEncode;
501     IValueT Rn = getEncodedGPRegNum(Var);
502     if (Mem->isRegReg()) {
503       const Variable *Index = Mem->getIndex();
504       if (Var == nullptr)
505         return CantEncode;
506       Value = (Rn << kRnShift) | Mem->getAddrMode() |
507               encodeShiftRotateImm5(getEncodedGPRegNum(Index),
508                                     Mem->getShiftOp(), Mem->getShiftAmt());
509       return EncodedAsShiftRotateImm5;
510     }
511     // Encoded as immediate register offset.
512     ConstantInteger32 *Offset = Mem->getOffset();
513     Value = encodeImmRegOffset(ImmEncoding, Rn, Offset->getValue(),
514                                Mem->getAddrMode());
515     return EncodedAsImmRegOffset;
516   }
517   return CantEncode;
518 }
519 
520 // Checks that Offset can fit in imm24 constant of branch (b) instruction.
assertCanEncodeBranchOffset(IOffsetT Offset)521 void assertCanEncodeBranchOffset(IOffsetT Offset) {
522   (void)Offset;
523   (void)kBranchOffsetBits;
524   assert(Utils::IsAligned(Offset, 4) &&
525          Utils::IsInt(kBranchOffsetBits, Offset >> 2));
526 }
527 
encodeBranchOffset(IOffsetT Offset,IValueT Inst)528 IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) {
529   // Adjust offset to the way ARM CPUs read PC.
530   Offset -= kPCReadOffset;
531 
532   assertCanEncodeBranchOffset(Offset);
533 
534   // Properly preserve only the bits supported in the instruction.
535   Offset >>= 2;
536   Offset &= kBranchOffsetMask;
537   return (Inst & ~kBranchOffsetMask) | Offset;
538 }
539 
encodeRegister(const Operand * OpReg,RegSetWanted WantedRegSet,const char * RegName,const char * InstName)540 IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet,
541                        const char *RegName, const char *InstName) {
542   IValueT Reg = 0;
543   if (encodeOperand(OpReg, Reg, WantedRegSet) != EncodedAsRegister)
544     llvm::report_fatal_error(std::string(InstName) + ": Can't find register " +
545                              RegName);
546   return Reg;
547 }
548 
encodeGPRegister(const Operand * OpReg,const char * RegName,const char * InstName)549 IValueT encodeGPRegister(const Operand *OpReg, const char *RegName,
550                          const char *InstName) {
551   return encodeRegister(OpReg, WantGPRegs, RegName, InstName);
552 }
553 
encodeSRegister(const Operand * OpReg,const char * RegName,const char * InstName)554 IValueT encodeSRegister(const Operand *OpReg, const char *RegName,
555                         const char *InstName) {
556   return encodeRegister(OpReg, WantSRegs, RegName, InstName);
557 }
558 
encodeDRegister(const Operand * OpReg,const char * RegName,const char * InstName)559 IValueT encodeDRegister(const Operand *OpReg, const char *RegName,
560                         const char *InstName) {
561   return encodeRegister(OpReg, WantDRegs, RegName, InstName);
562 }
563 
encodeQRegister(const Operand * OpReg,const char * RegName,const char * InstName)564 IValueT encodeQRegister(const Operand *OpReg, const char *RegName,
565                         const char *InstName) {
566   return encodeRegister(OpReg, WantQRegs, RegName, InstName);
567 }
568 
verifyPOrNotW(IValueT Address,const char * InstName)569 void verifyPOrNotW(IValueT Address, const char *InstName) {
570   if (BuildDefs::minimal())
571     return;
572   if (!isBitSet(P, Address) && isBitSet(W, Address))
573     llvm::report_fatal_error(std::string(InstName) +
574                              ": P=0 when W=1 not allowed");
575 }
576 
verifyRegsNotEq(IValueT Reg1,const char * Reg1Name,IValueT Reg2,const char * Reg2Name,const char * InstName)577 void verifyRegsNotEq(IValueT Reg1, const char *Reg1Name, IValueT Reg2,
578                      const char *Reg2Name, const char *InstName) {
579   if (BuildDefs::minimal())
580     return;
581   if (Reg1 == Reg2)
582     llvm::report_fatal_error(std::string(InstName) + ": " + Reg1Name + "=" +
583                              Reg2Name + " not allowed");
584 }
585 
verifyRegNotPc(IValueT Reg,const char * RegName,const char * InstName)586 void verifyRegNotPc(IValueT Reg, const char *RegName, const char *InstName) {
587   verifyRegsNotEq(Reg, RegName, RegARM32::Encoded_Reg_pc, "pc", InstName);
588 }
589 
verifyAddrRegNotPc(IValueT RegShift,IValueT Address,const char * RegName,const char * InstName)590 void verifyAddrRegNotPc(IValueT RegShift, IValueT Address, const char *RegName,
591                         const char *InstName) {
592   if (BuildDefs::minimal())
593     return;
594   if (getGPRReg(RegShift, Address) == RegARM32::Encoded_Reg_pc)
595     llvm::report_fatal_error(std::string(InstName) + ": " + RegName +
596                              "=pc not allowed");
597 }
598 
verifyRegNotPcWhenSetFlags(IValueT Reg,bool SetFlags,const char * InstName)599 void verifyRegNotPcWhenSetFlags(IValueT Reg, bool SetFlags,
600                                 const char *InstName) {
601   if (BuildDefs::minimal())
602     return;
603   if (SetFlags && (Reg == RegARM32::Encoded_Reg_pc))
604     llvm::report_fatal_error(std::string(InstName) + ": " +
605                              RegARM32::getRegName(RegARM32::Reg_pc) +
606                              "=pc not allowed when CC=1");
607 }
608 
609 } // end of anonymous namespace
610 
611 namespace Ice {
612 namespace ARM32 {
613 
emit(GlobalContext * Ctx,const Assembler & Asm) const614 size_t MoveRelocatableFixup::emit(GlobalContext *Ctx,
615                                   const Assembler &Asm) const {
616   if (!BuildDefs::dump())
617     return InstARM32::InstSize;
618   Ostream &Str = Ctx->getStrEmit();
619   IValueT Inst = Asm.load<IValueT>(position());
620   const bool IsMovw = kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ||
621                       kind() == llvm::ELF::R_ARM_MOVW_PREL_NC;
622   const auto Symbol = symbol().toString();
623   const bool NeedsPCRelSuffix =
624       (Asm.fixupIsPCRel(kind()) || Symbol == GlobalOffsetTable);
625   Str << "\t"
626          "mov" << (IsMovw ? "w" : "t") << "\t"
627       << RegARM32::getRegName(RegNumT::fixme((Inst >> kRdShift) & 0xF))
628       << ", #:" << (IsMovw ? "lower" : "upper") << "16:" << Symbol
629       << (NeedsPCRelSuffix ? " - ." : "") << "\t@ .word "
630       // TODO(jpp): This is broken, it also needs to add a magic constant.
631       << llvm::format_hex_no_prefix(Inst, 8) << "\n";
632   return InstARM32::InstSize;
633 }
634 
encodeElmtType(Type ElmtTy)635 IValueT AssemblerARM32::encodeElmtType(Type ElmtTy) {
636   switch (ElmtTy) {
637   case IceType_i8:
638     return 0;
639   case IceType_i16:
640     return 1;
641   case IceType_i32:
642   case IceType_f32:
643     return 2;
644   case IceType_i64:
645     return 3;
646   default:
647     llvm::report_fatal_error("SIMD op: Don't understand element type " +
648                              typeStdString(ElmtTy));
649   }
650 }
651 
652 // This fixup points to an ARM32 instruction with the following format:
emitOffset(Assembler * Asm) const653 void MoveRelocatableFixup::emitOffset(Assembler *Asm) const {
654   // cccc00110T00iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd,
655   // iiiiiiiiiiiiiiii = Imm16, and T=1 for movt.
656 
657   const IValueT Inst = Asm->load<IValueT>(position());
658   constexpr IValueT Imm16Mask = 0x000F0FFF;
659   const IValueT Imm16 = offset() & 0xffff;
660   Asm->store(position(),
661              (Inst & ~Imm16Mask) | ((Imm16 >> 12) << 16) | (Imm16 & 0xfff));
662 }
663 
createMoveFixup(bool IsMovW,const Constant * Value)664 MoveRelocatableFixup *AssemblerARM32::createMoveFixup(bool IsMovW,
665                                                       const Constant *Value) {
666   MoveRelocatableFixup *F =
667       new (allocate<MoveRelocatableFixup>()) MoveRelocatableFixup();
668   F->set_kind(IsMovW ? (IsNonsfi ? llvm::ELF::R_ARM_MOVW_PREL_NC
669                                  : llvm::ELF::R_ARM_MOVW_ABS_NC)
670                      : (IsNonsfi ? llvm::ELF::R_ARM_MOVT_PREL
671                                  : llvm::ELF::R_ARM_MOVT_ABS));
672   F->set_value(Value);
673   Buffer.installFixup(F);
674   return F;
675 }
676 
emit(GlobalContext * Ctx,const Assembler & Asm) const677 size_t BlRelocatableFixup::emit(GlobalContext *Ctx,
678                                 const Assembler &Asm) const {
679   if (!BuildDefs::dump())
680     return InstARM32::InstSize;
681   Ostream &Str = Ctx->getStrEmit();
682   IValueT Inst = Asm.load<IValueT>(position());
683   Str << "\t"
684          "bl\t" << symbol() << "\t@ .word "
685       << llvm::format_hex_no_prefix(Inst, 8) << "\n";
686   return InstARM32::InstSize;
687 }
688 
emitOffset(Assembler * Asm) const689 void BlRelocatableFixup::emitOffset(Assembler *Asm) const {
690   // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and
691   // iiiiiiiiiiiiiiiiiiiiiiii=
692   // EncodedBranchOffset(cccc101l000000000000000000000000, Offset);
693   const IValueT Inst = Asm->load<IValueT>(position());
694   constexpr IValueT OffsetMask = 0x00FFFFFF;
695   Asm->store(position(), encodeBranchOffset(offset(), Inst & ~OffsetMask));
696 }
697 
padWithNop(intptr_t Padding)698 void AssemblerARM32::padWithNop(intptr_t Padding) {
699   constexpr intptr_t InstWidth = sizeof(IValueT);
700   assert(Padding % InstWidth == 0 &&
701          "Padding not multiple of instruction size");
702   for (intptr_t i = 0; i < Padding; i += InstWidth)
703     nop();
704 }
705 
706 BlRelocatableFixup *
createBlFixup(const ConstantRelocatable * BlTarget)707 AssemblerARM32::createBlFixup(const ConstantRelocatable *BlTarget) {
708   BlRelocatableFixup *F =
709       new (allocate<BlRelocatableFixup>()) BlRelocatableFixup();
710   F->set_kind(llvm::ELF::R_ARM_CALL);
711   F->set_value(BlTarget);
712   Buffer.installFixup(F);
713   return F;
714 }
715 
bindCfgNodeLabel(const CfgNode * Node)716 void AssemblerARM32::bindCfgNodeLabel(const CfgNode *Node) {
717   if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) {
718     // Generate label name so that branches can find it.
719     constexpr SizeT InstSize = 0;
720     emitTextInst(Node->getAsmName() + ":", InstSize);
721   }
722   SizeT NodeNumber = Node->getIndex();
723   assert(!getPreliminary());
724   Label *L = getOrCreateCfgNodeLabel(NodeNumber);
725   this->bind(L);
726 }
727 
getOrCreateLabel(SizeT Number,LabelVector & Labels)728 Label *AssemblerARM32::getOrCreateLabel(SizeT Number, LabelVector &Labels) {
729   Label *L = nullptr;
730   if (Number == Labels.size()) {
731     L = new (this->allocate<Label>()) Label();
732     Labels.push_back(L);
733     return L;
734   }
735   if (Number > Labels.size()) {
736     Labels.resize(Number + 1);
737   }
738   L = Labels[Number];
739   if (!L) {
740     L = new (this->allocate<Label>()) Label();
741     Labels[Number] = L;
742   }
743   return L;
744 }
745 
746 // Pull out offset from branch Inst.
decodeBranchOffset(IValueT Inst)747 IOffsetT AssemblerARM32::decodeBranchOffset(IValueT Inst) {
748   // Sign-extend, left-shift by 2, and adjust to the way ARM CPUs read PC.
749   const IOffsetT Offset = (Inst & kBranchOffsetMask) << 8;
750   return (Offset >> 6) + kPCReadOffset;
751 }
752 
bind(Label * L)753 void AssemblerARM32::bind(Label *L) {
754   IOffsetT BoundPc = Buffer.size();
755   assert(!L->isBound()); // Labels can only be bound once.
756   while (L->isLinked()) {
757     IOffsetT Position = L->getLinkPosition();
758     IOffsetT Dest = BoundPc - Position;
759     IValueT Inst = Buffer.load<IValueT>(Position);
760     Buffer.store<IValueT>(Position, encodeBranchOffset(Dest, Inst));
761     L->setPosition(decodeBranchOffset(Inst));
762   }
763   L->bindTo(BoundPc);
764 }
765 
emitTextInst(const std::string & Text,SizeT InstSize)766 void AssemblerARM32::emitTextInst(const std::string &Text, SizeT InstSize) {
767   AssemblerFixup *F = createTextFixup(Text, InstSize);
768   emitFixup(F);
769   for (SizeT I = 0; I < InstSize; ++I) {
770     AssemblerBuffer::EnsureCapacity ensured(&Buffer);
771     Buffer.emit<char>(0);
772   }
773 }
774 
emitType01(CondARM32::Cond Cond,IValueT InstType,IValueT Opcode,bool SetFlags,IValueT Rn,IValueT Rd,IValueT Imm12,EmitChecks RuleChecks,const char * InstName)775 void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT InstType,
776                                 IValueT Opcode, bool SetFlags, IValueT Rn,
777                                 IValueT Rd, IValueT Imm12,
778                                 EmitChecks RuleChecks, const char *InstName) {
779   switch (RuleChecks) {
780   case NoChecks:
781     break;
782   case RdIsPcAndSetFlags:
783     verifyRegNotPcWhenSetFlags(Rd, SetFlags, InstName);
784     break;
785   }
786   assert(Rd < RegARM32::getNumGPRegs());
787   assert(CondARM32::isDefined(Cond));
788   const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
789                            (InstType << kTypeShift) | (Opcode << kOpcodeShift) |
790                            (encodeBool(SetFlags) << kSShift) |
791                            (Rn << kRnShift) | (Rd << kRdShift) | Imm12;
792   emitInst(Encoding);
793 }
794 
emitType01(CondARM32::Cond Cond,IValueT Opcode,const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,EmitChecks RuleChecks,const char * InstName)795 void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Opcode,
796                                 const Operand *OpRd, const Operand *OpRn,
797                                 const Operand *OpSrc1, bool SetFlags,
798                                 EmitChecks RuleChecks, const char *InstName) {
799   IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName);
800   IValueT Rn = encodeGPRegister(OpRn, "Rn", InstName);
801   emitType01(Cond, Opcode, Rd, Rn, OpSrc1, SetFlags, RuleChecks, InstName);
802 }
803 
emitType01(CondARM32::Cond Cond,IValueT Opcode,IValueT Rd,IValueT Rn,const Operand * OpSrc1,bool SetFlags,EmitChecks RuleChecks,const char * InstName)804 void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Opcode,
805                                 IValueT Rd, IValueT Rn, const Operand *OpSrc1,
806                                 bool SetFlags, EmitChecks RuleChecks,
807                                 const char *InstName) {
808   IValueT Src1Value;
809   // TODO(kschimpf) Other possible decodings of data operations.
810   switch (encodeOperand(OpSrc1, Src1Value, WantGPRegs)) {
811   default:
812     llvm::report_fatal_error(std::string(InstName) +
813                              ": Can't encode instruction");
814     return;
815   case EncodedAsRegister: {
816     // XXX (register)
817     //   xxx{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>}
818     //
819     // cccc000xxxxsnnnnddddiiiiitt0mmmm where cccc=Cond, xxxx=Opcode, dddd=Rd,
820     // nnnn=Rn, mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
821     constexpr IValueT Imm5 = 0;
822     Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Imm5);
823     emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value,
824                RuleChecks, InstName);
825     return;
826   }
827   case EncodedAsShiftedRegister: {
828     // Form is defined in case EncodedAsRegister. (i.e. XXX (register)).
829     emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value,
830                RuleChecks, InstName);
831     return;
832   }
833   case EncodedAsConstI32: {
834     // See if we can convert this to an XXX (immediate).
835     IValueT RotateAmt;
836     IValueT Imm8;
837     if (!OperandARM32FlexImm::canHoldImm(Src1Value, &RotateAmt, &Imm8))
838       llvm::report_fatal_error(std::string(InstName) +
839                                ": Immediate rotated constant not valid");
840     Src1Value = encodeRotatedImm8(RotateAmt, Imm8);
841     // Intentionally fall to next case!
842   }
843   case EncodedAsRotatedImm8: {
844     // XXX (Immediate)
845     //   xxx{s}<c> <Rd>, <Rn>, #<RotatedImm8>
846     //
847     // cccc001xxxxsnnnnddddiiiiiiiiiiii where cccc=Cond, xxxx=Opcode, dddd=Rd,
848     // nnnn=Rn, s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
849     emitType01(Cond, kInstTypeDataImmediate, Opcode, SetFlags, Rn, Rd,
850                Src1Value, RuleChecks, InstName);
851     return;
852   }
853   case EncodedAsRegShiftReg: {
854     // XXX (register-shifted reg)
855     //   xxx{s}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
856     //
857     // cccc000xxxxfnnnnddddssss0tt1mmmm where cccc=Cond, xxxx=Opcode, dddd=Rd,
858     // nnnn=Rn, ssss=Rs, f=SetFlags, tt is encoding of type, and
859     // Src1Value=ssss01tt1mmmm.
860     emitType01(Cond, kInstTypeDataRegShift, Opcode, SetFlags, Rn, Rd, Src1Value,
861                RuleChecks, InstName);
862     return;
863   }
864   }
865 }
866 
emitType05(CondARM32::Cond Cond,IOffsetT Offset,bool Link)867 void AssemblerARM32::emitType05(CondARM32::Cond Cond, IOffsetT Offset,
868                                 bool Link) {
869   // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and
870   // iiiiiiiiiiiiiiiiiiiiiiii=
871   // EncodedBranchOffset(cccc101l000000000000000000000000, Offset);
872   assert(CondARM32::isDefined(Cond));
873   IValueT Encoding = static_cast<int32_t>(Cond) << kConditionShift |
874                      5 << kTypeShift | (Link ? 1 : 0) << kLinkShift;
875   Encoding = encodeBranchOffset(Offset, Encoding);
876   emitInst(Encoding);
877 }
878 
emitBranch(Label * L,CondARM32::Cond Cond,bool Link)879 void AssemblerARM32::emitBranch(Label *L, CondARM32::Cond Cond, bool Link) {
880   // TODO(kschimpf): Handle far jumps.
881   if (L->isBound()) {
882     const int32_t Dest = L->getPosition() - Buffer.size();
883     emitType05(Cond, Dest, Link);
884     return;
885   }
886   const IOffsetT Position = Buffer.size();
887   // Use the offset field of the branch instruction for linking the sites.
888   emitType05(Cond, L->getEncodedPosition(), Link);
889   L->linkTo(*this, Position);
890 }
891 
emitCompareOp(CondARM32::Cond Cond,IValueT Opcode,const Operand * OpRn,const Operand * OpSrc1,const char * InstName)892 void AssemblerARM32::emitCompareOp(CondARM32::Cond Cond, IValueT Opcode,
893                                    const Operand *OpRn, const Operand *OpSrc1,
894                                    const char *InstName) {
895   // XXX (register)
896   //   XXX<c> <Rn>, <Rm>{, <shift>}
897   //
898   // ccccyyyxxxx1nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, iiiii
899   // defines shift constant, tt=ShiftKind, yyy=kInstTypeDataRegister, and
900   // xxxx=Opcode.
901   //
902   // XXX (immediate)
903   //  XXX<c> <Rn>, #<RotatedImm8>
904   //
905   // ccccyyyxxxx1nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
906   // yyy=kInstTypeDataImmdiate, xxxx=Opcode, and iiiiiiiiiiii=Src1Value
907   // defining RotatedImm8.
908   constexpr bool SetFlags = true;
909   constexpr IValueT Rd = RegARM32::Encoded_Reg_r0;
910   IValueT Rn = encodeGPRegister(OpRn, "Rn", InstName);
911   emitType01(Cond, Opcode, Rd, Rn, OpSrc1, SetFlags, NoChecks, InstName);
912 }
913 
emitMemOp(CondARM32::Cond Cond,IValueT InstType,bool IsLoad,bool IsByte,IValueT Rt,IValueT Address)914 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType,
915                                bool IsLoad, bool IsByte, IValueT Rt,
916                                IValueT Address) {
917   assert(Rt < RegARM32::getNumGPRegs());
918   assert(CondARM32::isDefined(Cond));
919   const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
920                            (InstType << kTypeShift) | (IsLoad ? L : 0) |
921                            (IsByte ? B : 0) | (Rt << kRdShift) | Address;
922   emitInst(Encoding);
923 }
924 
emitMemOp(CondARM32::Cond Cond,bool IsLoad,bool IsByte,IValueT Rt,const Operand * OpAddress,const TargetInfo & TInfo,const char * InstName)925 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte,
926                                IValueT Rt, const Operand *OpAddress,
927                                const TargetInfo &TInfo, const char *InstName) {
928   IValueT Address;
929   switch (encodeAddress(OpAddress, Address, TInfo, Imm12Address)) {
930   default:
931     llvm::report_fatal_error(std::string(InstName) +
932                              ": Memory address not understood");
933   case EncodedAsImmRegOffset: {
934     // XXX{B} (immediate):
935     //   xxx{b}<c> <Rt>, [<Rn>{, #+/-<imm12>}]      ; p=1, w=0
936     //   xxx{b}<c> <Rt>, [<Rn>], #+/-<imm12>        ; p=1, w=1
937     //   xxx{b}<c> <Rt>, [<Rn>, #+/-<imm12>]!       ; p=0, w=1
938     //
939     // cccc010pubwlnnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
940     // iiiiiiiiiiii=imm12, b=IsByte, pu0w<<21 is a BlockAddr, l=IsLoad, and
941     // pu0w0nnnn0000iiiiiiiiiiii=Address.
942     RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address);
943 
944     // Check if conditions of rules violated.
945     verifyRegNotPc(Rn, "Rn", InstName);
946     verifyPOrNotW(Address, InstName);
947     if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) &&
948         isBitSet(U, Address) && !isBitSet(W, Address) &&
949         (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))
950       llvm::report_fatal_error(std::string(InstName) +
951                                ": Use push/pop instead");
952 
953     emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address);
954     return;
955   }
956   case EncodedAsShiftRotateImm5: {
957     // XXX{B} (register)
958     //   xxx{b}<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
959     //   xxx{b}<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
960     //
961     // cccc011pubwlnnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt,
962     // b=IsByte, U=1 if +, pu0b is a BlockAddr, l=IsLoad, and
963     // pu0w0nnnn0000iiiiiss0mmmm=Address.
964     RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address);
965     RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address);
966 
967     // Check if conditions of rules violated.
968     verifyPOrNotW(Address, InstName);
969     verifyRegNotPc(Rm, "Rm", InstName);
970     if (IsByte)
971       verifyRegNotPc(Rt, "Rt", InstName);
972     if (isBitSet(W, Address)) {
973       verifyRegNotPc(Rn, "Rn", InstName);
974       verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName);
975     }
976     emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address);
977     return;
978   }
979   }
980 }
981 
emitMemOpEnc3(CondARM32::Cond Cond,IValueT Opcode,IValueT Rt,const Operand * OpAddress,const TargetInfo & TInfo,const char * InstName)982 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode,
983                                    IValueT Rt, const Operand *OpAddress,
984                                    const TargetInfo &TInfo,
985                                    const char *InstName) {
986   IValueT Address;
987   switch (encodeAddress(OpAddress, Address, TInfo, RotatedImm8Enc3Address)) {
988   default:
989     llvm::report_fatal_error(std::string(InstName) +
990                              ": Memory address not understood");
991   case EncodedAsImmRegOffset: {
992     // XXXH (immediate)
993     //   xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}]
994     //   xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]
995     //   xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]!
996     //
997     // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt,
998     // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode,
999     // and pu0w0nnnn0000iiii0000jjjj=Address.
1000     assert(Rt < RegARM32::getNumGPRegs());
1001     assert(CondARM32::isDefined(Cond));
1002     verifyPOrNotW(Address, InstName);
1003     verifyRegNotPc(Rt, "Rt", InstName);
1004     if (isBitSet(W, Address))
1005       verifyRegsNotEq(getGPRReg(kRnShift, Address), "Rn", Rt, "Rt", InstName);
1006     const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
1007                              Opcode | (Rt << kRdShift) | Address;
1008     emitInst(Encoding);
1009     return;
1010   }
1011   case EncodedAsShiftRotateImm5: {
1012     // XXXH (register)
1013     //   xxxh<c> <Rt>, [<Rn>, +/-<Rm>]{!}
1014     //   xxxh<c> <Rt>, [<Rn>], +/-<Rm>
1015     //
1016     // cccc000pu0wxnnnntttt00001011mmmm where cccc=Cond, tttt=Rt, nnnn=Rn,
1017     // mmmm=Rm, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, and
1018     // pu0w0nnnn000000000000mmmm=Address.
1019     assert(Rt < RegARM32::getNumGPRegs());
1020     assert(CondARM32::isDefined(Cond));
1021     verifyPOrNotW(Address, InstName);
1022     verifyRegNotPc(Rt, "Rt", InstName);
1023     verifyAddrRegNotPc(kRmShift, Address, "Rm", InstName);
1024     const RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address);
1025     if (isBitSet(W, Address)) {
1026       verifyRegNotPc(Rn, "Rn", InstName);
1027       verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName);
1028     }
1029     if (mask(Address, kShiftImmShift, 5) != 0)
1030       // For encoding 3, no shift is allowed.
1031       llvm::report_fatal_error(std::string(InstName) +
1032                                ": Shift constant not allowed");
1033     const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
1034                              Opcode | (Rt << kRdShift) | Address;
1035     emitInst(Encoding);
1036     return;
1037   }
1038   }
1039 }
1040 
emitDivOp(CondARM32::Cond Cond,IValueT Opcode,IValueT Rd,IValueT Rn,IValueT Rm)1041 void AssemblerARM32::emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
1042                                IValueT Rn, IValueT Rm) {
1043   assert(Rd < RegARM32::getNumGPRegs());
1044   assert(Rn < RegARM32::getNumGPRegs());
1045   assert(Rm < RegARM32::getNumGPRegs());
1046   assert(CondARM32::isDefined(Cond));
1047   const IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) |
1048                            (Rn << kDivRnShift) | (Rd << kDivRdShift) | B26 |
1049                            B25 | B24 | B20 | B15 | B14 | B13 | B12 | B4 |
1050                            (Rm << kDivRmShift);
1051   emitInst(Encoding);
1052 }
1053 
emitInsertExtractInt(CondARM32::Cond Cond,const Operand * OpQn,uint32_t Index,const Operand * OpRt,bool IsExtract,const char * InstName)1054 void AssemblerARM32::emitInsertExtractInt(CondARM32::Cond Cond,
1055                                           const Operand *OpQn, uint32_t Index,
1056                                           const Operand *OpRt, bool IsExtract,
1057                                           const char *InstName) {
1058   const IValueT Rt = encodeGPRegister(OpRt, "Rt", InstName);
1059   IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", InstName));
1060   assert(Rt != RegARM32::Encoded_Reg_pc);
1061   assert(Rt != RegARM32::Encoded_Reg_sp);
1062   assert(CondARM32::isDefined(Cond));
1063   const uint32_t BitSize = typeWidthInBytes(OpRt->getType()) * CHAR_BIT;
1064   IValueT Opcode1 = 0;
1065   IValueT Opcode2 = 0;
1066   switch (BitSize) {
1067   default:
1068     llvm::report_fatal_error(std::string(InstName) +
1069                              ": Unable to process type " +
1070                              typeStdString(OpRt->getType()));
1071   case 8:
1072     assert(Index < 16);
1073     Dn = Dn | mask(Index, 3, 1);
1074     Opcode1 = B1 | mask(Index, 2, 1);
1075     Opcode2 = mask(Index, 0, 2);
1076     break;
1077   case 16:
1078     assert(Index < 8);
1079     Dn = Dn | mask(Index, 2, 1);
1080     Opcode1 = mask(Index, 1, 1);
1081     Opcode2 = (mask(Index, 0, 1) << 1) | B0;
1082     break;
1083   case 32:
1084     assert(Index < 4);
1085     Dn = Dn | mask(Index, 1, 1);
1086     Opcode1 = mask(Index, 0, 1);
1087     break;
1088   }
1089   const IValueT Encoding = B27 | B26 | B25 | B11 | B9 | B8 | B4 |
1090                            (encodeCondition(Cond) << kConditionShift) |
1091                            (Opcode1 << 21) |
1092                            (getXXXXInRegYXXXX(Dn) << kRnShift) | (Rt << 12) |
1093                            (encodeBool(IsExtract) << 20) |
1094                            (getYInRegYXXXX(Dn) << 7) | (Opcode2 << 5);
1095   emitInst(Encoding);
1096 }
1097 
emitMoveSS(CondARM32::Cond Cond,IValueT Sd,IValueT Sm)1098 void AssemblerARM32::emitMoveSS(CondARM32::Cond Cond, IValueT Sd, IValueT Sm) {
1099   // VMOV (register) - ARM section A8.8.340, encoding A2:
1100   //   vmov<c>.f32 <Sd>, <Sm>
1101   //
1102   // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
1103   constexpr IValueT VmovssOpcode = B23 | B21 | B20 | B6;
1104   constexpr IValueT S0 = 0;
1105   emitVFPsss(Cond, VmovssOpcode, Sd, S0, Sm);
1106 }
1107 
emitMulOp(CondARM32::Cond Cond,IValueT Opcode,IValueT Rd,IValueT Rn,IValueT Rm,IValueT Rs,bool SetFlags)1108 void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
1109                                IValueT Rn, IValueT Rm, IValueT Rs,
1110                                bool SetFlags) {
1111   assert(Rd < RegARM32::getNumGPRegs());
1112   assert(Rn < RegARM32::getNumGPRegs());
1113   assert(Rm < RegARM32::getNumGPRegs());
1114   assert(Rs < RegARM32::getNumGPRegs());
1115   assert(CondARM32::isDefined(Cond));
1116   IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) |
1117                      (encodeBool(SetFlags) << kSShift) | (Rn << kRnShift) |
1118                      (Rd << kRdShift) | (Rs << kRsShift) | B7 | B4 |
1119                      (Rm << kRmShift);
1120   emitInst(Encoding);
1121 }
1122 
emitMultiMemOp(CondARM32::Cond Cond,BlockAddressMode AddressMode,bool IsLoad,IValueT BaseReg,IValueT Registers)1123 void AssemblerARM32::emitMultiMemOp(CondARM32::Cond Cond,
1124                                     BlockAddressMode AddressMode, bool IsLoad,
1125                                     IValueT BaseReg, IValueT Registers) {
1126   assert(CondARM32::isDefined(Cond));
1127   assert(BaseReg < RegARM32::getNumGPRegs());
1128   assert(Registers < (1 << RegARM32::getNumGPRegs()));
1129   IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 |
1130                      AddressMode | (IsLoad ? L : 0) | (BaseReg << kRnShift) |
1131                      Registers;
1132   emitInst(Encoding);
1133 }
1134 
emitSignExtend(CondARM32::Cond Cond,IValueT Opcode,const Operand * OpRd,const Operand * OpSrc0,const char * InstName)1135 void AssemblerARM32::emitSignExtend(CondARM32::Cond Cond, IValueT Opcode,
1136                                     const Operand *OpRd, const Operand *OpSrc0,
1137                                     const char *InstName) {
1138   IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName);
1139   IValueT Rm = encodeGPRegister(OpSrc0, "Rm", InstName);
1140   // Note: For the moment, we assume no rotation is specified.
1141   RotationValue Rotation = kRotateNone;
1142   constexpr IValueT Rn = RegARM32::Encoded_Reg_pc;
1143   const Type Ty = OpSrc0->getType();
1144   switch (Ty) {
1145   default:
1146     llvm::report_fatal_error(std::string(InstName) + ": Type " +
1147                              typeString(Ty) + " not allowed");
1148     break;
1149   case IceType_i1:
1150   case IceType_i8: {
1151     // SXTB/UXTB - Arm sections A8.8.233 and A8.8.274, encoding A1:
1152     //   sxtb<c> <Rd>, <Rm>{, <rotate>}
1153     //   uxtb<c> <Rd>, <Rm>{, <rotate>}
1154     //
1155     // ccccxxxxxxxx1111ddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode,
1156     // dddd=Rd, mmmm=Rm, and rr defined (RotationValue) rotate.
1157     break;
1158   }
1159   case IceType_i16: {
1160     // SXTH/UXTH - ARM sections A8.8.235 and A8.8.276, encoding A1:
1161     //   uxth<c> <Rd>< <Rm>{, <rotate>}
1162     //
1163     // cccc01101111nnnnddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and
1164     // rr defined (RotationValue) rotate.
1165     Opcode |= B20;
1166     break;
1167   }
1168   }
1169 
1170   assert(CondARM32::isDefined(Cond));
1171   IValueT Rot = encodeRotation(Rotation);
1172   if (!Utils::IsUint(2, Rot))
1173     llvm::report_fatal_error(std::string(InstName) +
1174                              ": Illegal rotation value");
1175   IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | Opcode |
1176                      (Rn << kRnShift) | (Rd << kRdShift) |
1177                      (Rot << kRotationShift) | B6 | B5 | B4 | (Rm << kRmShift);
1178   emitInst(Encoding);
1179 }
1180 
emitSIMDBase(IValueT Opcode,IValueT Dd,IValueT Dn,IValueT Dm,bool UseQRegs,bool IsFloatTy)1181 void AssemblerARM32::emitSIMDBase(IValueT Opcode, IValueT Dd, IValueT Dn,
1182                                   IValueT Dm, bool UseQRegs, bool IsFloatTy) {
1183   const IValueT Encoding =
1184       Opcode | B25 | (encodeCondition(CondARM32::kNone) << kConditionShift) |
1185       (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) |
1186       (getXXXXInRegYXXXX(Dd) << 12) | (IsFloatTy ? B10 : 0) |
1187       (getYInRegYXXXX(Dn) << 7) | (encodeBool(UseQRegs) << 6) |
1188       (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm);
1189   emitInst(Encoding);
1190 }
1191 
emitSIMD(IValueT Opcode,Type ElmtTy,IValueT Dd,IValueT Dn,IValueT Dm,bool UseQRegs)1192 void AssemblerARM32::emitSIMD(IValueT Opcode, Type ElmtTy, IValueT Dd,
1193                               IValueT Dn, IValueT Dm, bool UseQRegs) {
1194   constexpr IValueT ElmtShift = 20;
1195   const IValueT ElmtSize = encodeElmtType(ElmtTy);
1196   assert(Utils::IsUint(2, ElmtSize));
1197   emitSIMDBase(Opcode | (ElmtSize << ElmtShift), Dd, Dn, Dm, UseQRegs,
1198                isFloatingType(ElmtTy));
1199 }
1200 
emitSIMDqqqBase(IValueT Opcode,const Operand * OpQd,const Operand * OpQn,const Operand * OpQm,bool IsFloatTy,const char * OpcodeName)1201 void AssemblerARM32::emitSIMDqqqBase(IValueT Opcode, const Operand *OpQd,
1202                                      const Operand *OpQn, const Operand *OpQm,
1203                                      bool IsFloatTy, const char *OpcodeName) {
1204   const IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName);
1205   const IValueT Qn = encodeQRegister(OpQn, "Qn", OpcodeName);
1206   const IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName);
1207   constexpr bool UseQRegs = true;
1208   emitSIMDBase(Opcode, mapQRegToDReg(Qd), mapQRegToDReg(Qn), mapQRegToDReg(Qm),
1209                UseQRegs, IsFloatTy);
1210 }
1211 
emitSIMDqqq(IValueT Opcode,Type ElmtTy,const Operand * OpQd,const Operand * OpQn,const Operand * OpQm,const char * OpcodeName)1212 void AssemblerARM32::emitSIMDqqq(IValueT Opcode, Type ElmtTy,
1213                                  const Operand *OpQd, const Operand *OpQn,
1214                                  const Operand *OpQm, const char *OpcodeName) {
1215   constexpr IValueT ElmtShift = 20;
1216   const IValueT ElmtSize = encodeElmtType(ElmtTy);
1217   assert(Utils::IsUint(2, ElmtSize));
1218   emitSIMDqqqBase(Opcode | (ElmtSize << ElmtShift), OpQd, OpQn, OpQm,
1219                   isFloatingType(ElmtTy), OpcodeName);
1220 }
1221 
emitSIMDShiftqqc(IValueT Opcode,const Operand * OpQd,const Operand * OpQm,const IValueT Imm6,const char * OpcodeName)1222 void AssemblerARM32::emitSIMDShiftqqc(IValueT Opcode, const Operand *OpQd,
1223                                       const Operand *OpQm, const IValueT Imm6,
1224                                       const char *OpcodeName) {
1225   const IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName);
1226   const IValueT Qn = 0;
1227   const IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName);
1228   constexpr bool UseQRegs = true;
1229   constexpr bool IsFloatTy = false;
1230   constexpr IValueT ElmtShift = 16;
1231   emitSIMDBase(Opcode | (Imm6 << ElmtShift), mapQRegToDReg(Qd),
1232                mapQRegToDReg(Qn), mapQRegToDReg(Qm), UseQRegs, IsFloatTy);
1233 }
1234 
emitSIMDCvtqq(IValueT Opcode,const Operand * OpQd,const Operand * OpQm,const char * OpcodeName)1235 void AssemblerARM32::emitSIMDCvtqq(IValueT Opcode, const Operand *OpQd,
1236                                    const Operand *OpQm,
1237                                    const char *OpcodeName) {
1238   const IValueT SIMDOpcode =
1239       B24 | B23 | B21 | B20 | B19 | B17 | B16 | B10 | B9 | Opcode;
1240   constexpr bool UseQRegs = true;
1241   constexpr bool IsFloatTy = false;
1242   const IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName);
1243   constexpr IValueT Qn = 0;
1244   const IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName);
1245   emitSIMDBase(SIMDOpcode, mapQRegToDReg(Qd), mapQRegToDReg(Qn),
1246                mapQRegToDReg(Qm), UseQRegs, IsFloatTy);
1247 }
1248 
emitVFPddd(CondARM32::Cond Cond,IValueT Opcode,IValueT Dd,IValueT Dn,IValueT Dm)1249 void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode,
1250                                 IValueT Dd, IValueT Dn, IValueT Dm) {
1251   assert(Dd < RegARM32::getNumDRegs());
1252   assert(Dn < RegARM32::getNumDRegs());
1253   assert(Dm < RegARM32::getNumDRegs());
1254   assert(CondARM32::isDefined(Cond));
1255   constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9 | B8;
1256   const IValueT Encoding =
1257       Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
1258       (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) |
1259       (getXXXXInRegYXXXX(Dd) << 12) | (getYInRegYXXXX(Dn) << 7) |
1260       (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm);
1261   emitInst(Encoding);
1262 }
1263 
emitVFPddd(CondARM32::Cond Cond,IValueT Opcode,const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,const char * InstName)1264 void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode,
1265                                 const Operand *OpDd, const Operand *OpDn,
1266                                 const Operand *OpDm, const char *InstName) {
1267   IValueT Dd = encodeDRegister(OpDd, "Dd", InstName);
1268   IValueT Dn = encodeDRegister(OpDn, "Dn", InstName);
1269   IValueT Dm = encodeDRegister(OpDm, "Dm", InstName);
1270   emitVFPddd(Cond, Opcode, Dd, Dn, Dm);
1271 }
1272 
emitVFPsss(CondARM32::Cond Cond,IValueT Opcode,IValueT Sd,IValueT Sn,IValueT Sm)1273 void AssemblerARM32::emitVFPsss(CondARM32::Cond Cond, IValueT Opcode,
1274                                 IValueT Sd, IValueT Sn, IValueT Sm) {
1275   assert(Sd < RegARM32::getNumSRegs());
1276   assert(Sn < RegARM32::getNumSRegs());
1277   assert(Sm < RegARM32::getNumSRegs());
1278   assert(CondARM32::isDefined(Cond));
1279   constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9;
1280   const IValueT Encoding =
1281       Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
1282       (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sn) << 16) |
1283       (getXXXXInRegXXXXY(Sd) << 12) | (getYInRegXXXXY(Sn) << 7) |
1284       (getYInRegXXXXY(Sm) << 5) | getXXXXInRegXXXXY(Sm);
1285   emitInst(Encoding);
1286 }
1287 
emitVFPsss(CondARM32::Cond Cond,IValueT Opcode,const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,const char * InstName)1288 void AssemblerARM32::emitVFPsss(CondARM32::Cond Cond, IValueT Opcode,
1289                                 const Operand *OpSd, const Operand *OpSn,
1290                                 const Operand *OpSm, const char *InstName) {
1291   const IValueT Sd = encodeSRegister(OpSd, "Sd", InstName);
1292   const IValueT Sn = encodeSRegister(OpSn, "Sn", InstName);
1293   const IValueT Sm = encodeSRegister(OpSm, "Sm", InstName);
1294   emitVFPsss(Cond, Opcode, Sd, Sn, Sm);
1295 }
1296 
adc(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1297 void AssemblerARM32::adc(const Operand *OpRd, const Operand *OpRn,
1298                          const Operand *OpSrc1, bool SetFlags,
1299                          CondARM32::Cond Cond) {
1300   // ADC (register) - ARM section 18.8.2, encoding A1:
1301   //   adc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
1302   //
1303   // cccc0000101snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1304   // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
1305   //
1306   // ADC (Immediate) - ARM section A8.8.1, encoding A1:
1307   //   adc{s}<c> <Rd>, <Rn>, #<RotatedImm8>
1308   //
1309   // cccc0010101snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1310   // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1311   constexpr const char *AdcName = "adc";
1312   constexpr IValueT AdcOpcode = B2 | B0; // 0101
1313   emitType01(Cond, AdcOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1314              AdcName);
1315 }
1316 
add(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1317 void AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn,
1318                          const Operand *OpSrc1, bool SetFlags,
1319                          CondARM32::Cond Cond) {
1320   // ADD (register) - ARM section A8.8.7, encoding A1:
1321   //   add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>}
1322   // ADD (Sp plus register) - ARM section A8.8.11, encoding A1:
1323   //   add{s}<c> sp, <Rn>, <Rm>{, <shiff>}
1324   //
1325   // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1326   // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
1327   //
1328   // ADD (Immediate) - ARM section A8.8.5, encoding A1:
1329   //   add{s}<c> <Rd>, <Rn>, #<RotatedImm8>
1330   // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1.
1331   //   add{s}<c> <Rd>, sp, #<RotatedImm8>
1332   //
1333   // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1334   // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1335   constexpr const char *AddName = "add";
1336   constexpr IValueT Add = B2; // 0100
1337   emitType01(Cond, Add, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1338              AddName);
1339 }
1340 
and_(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1341 void AssemblerARM32::and_(const Operand *OpRd, const Operand *OpRn,
1342                           const Operand *OpSrc1, bool SetFlags,
1343                           CondARM32::Cond Cond) {
1344   // AND (register) - ARM section A8.8.14, encoding A1:
1345   //   and{s}<c> <Rd>, <Rn>{, <shift>}
1346   //
1347   // cccc0000000snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1348   // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
1349   //
1350   // AND (Immediate) - ARM section A8.8.13, encoding A1:
1351   //   and{s}<c> <Rd>, <Rn>, #<RotatedImm8>
1352   //
1353   // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1354   // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1355   constexpr const char *AndName = "and";
1356   constexpr IValueT And = 0; // 0000
1357   emitType01(Cond, And, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1358              AndName);
1359 }
1360 
b(Label * L,CondARM32::Cond Cond)1361 void AssemblerARM32::b(Label *L, CondARM32::Cond Cond) {
1362   emitBranch(L, Cond, false);
1363 }
1364 
bkpt(uint16_t Imm16)1365 void AssemblerARM32::bkpt(uint16_t Imm16) {
1366   // BKPT - ARM section A*.8.24 - encoding A1:
1367   //   bkpt #<Imm16>
1368   //
1369   // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and iiiiiiiiiiiiiiii=Imm16
1370   const IValueT Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 |
1371                            ((Imm16 >> 4) << 8) | B6 | B5 | B4 | (Imm16 & 0xf);
1372   emitInst(Encoding);
1373 }
1374 
bic(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1375 void AssemblerARM32::bic(const Operand *OpRd, const Operand *OpRn,
1376                          const Operand *OpSrc1, bool SetFlags,
1377                          CondARM32::Cond Cond) {
1378   // BIC (register) - ARM section A8.8.22, encoding A1:
1379   //   bic{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
1380   //
1381   // cccc0001110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1382   // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
1383   //
1384   // BIC (immediate) - ARM section A8.8.21, encoding A1:
1385   //   bic{s}<c> <Rd>, <Rn>, #<RotatedImm8>
1386   //
1387   // cccc0011110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rn, nnnn=Rn,
1388   // s=SetFlags, and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1389   constexpr const char *BicName = "bic";
1390   constexpr IValueT BicOpcode = B3 | B2 | B1; // i.e. 1110
1391   emitType01(Cond, BicOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1392              BicName);
1393 }
1394 
bl(const ConstantRelocatable * Target)1395 void AssemblerARM32::bl(const ConstantRelocatable *Target) {
1396   // BL (immediate) - ARM section A8.8.25, encoding A1:
1397   //   bl<c> <label>
1398   //
1399   // cccc1011iiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond (not currently allowed)
1400   // and iiiiiiiiiiiiiiiiiiiiiiii is the (encoded) Target to branch to.
1401   emitFixup(createBlFixup(Target));
1402   constexpr CondARM32::Cond Cond = CondARM32::AL;
1403   constexpr IValueT Immed = 0;
1404   constexpr bool Link = true;
1405   emitType05(Cond, Immed, Link);
1406 }
1407 
blx(const Operand * Target)1408 void AssemblerARM32::blx(const Operand *Target) {
1409   // BLX (register) - ARM section A8.8.26, encoding A1:
1410   //   blx<c> <Rm>
1411   //
1412   // cccc000100101111111111110011mmmm where cccc=Cond (not currently allowed)
1413   // and mmmm=Rm.
1414   constexpr const char *BlxName = "Blx";
1415   IValueT Rm = encodeGPRegister(Target, "Rm", BlxName);
1416   verifyRegNotPc(Rm, "Rm", BlxName);
1417   constexpr CondARM32::Cond Cond = CondARM32::AL;
1418   int32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | B21 |
1419                      (0xfff << 8) | B5 | B4 | (Rm << kRmShift);
1420   emitInst(Encoding);
1421 }
1422 
bx(RegARM32::GPRRegister Rm,CondARM32::Cond Cond)1423 void AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) {
1424   // BX - ARM section A8.8.27, encoding A1:
1425   //   bx<c> <Rm>
1426   //
1427   // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond.
1428   assert(CondARM32::isDefined(Cond));
1429   const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B24 |
1430                            B21 | (0xfff << 8) | B4 |
1431                            (encodeGPRRegister(Rm) << kRmShift);
1432   emitInst(Encoding);
1433 }
1434 
clz(const Operand * OpRd,const Operand * OpSrc,CondARM32::Cond Cond)1435 void AssemblerARM32::clz(const Operand *OpRd, const Operand *OpSrc,
1436                          CondARM32::Cond Cond) {
1437   // CLZ - ARM section A8.8.33, encoding A1:
1438   //   clz<c> <Rd> <Rm>
1439   //
1440   // cccc000101101111dddd11110001mmmm where cccc=Cond, dddd=Rd, and mmmm=Rm.
1441   constexpr const char *ClzName = "clz";
1442   constexpr const char *RdName = "Rd";
1443   constexpr const char *RmName = "Rm";
1444   IValueT Rd = encodeGPRegister(OpRd, RdName, ClzName);
1445   assert(Rd < RegARM32::getNumGPRegs());
1446   verifyRegNotPc(Rd, RdName, ClzName);
1447   IValueT Rm = encodeGPRegister(OpSrc, RmName, ClzName);
1448   assert(Rm < RegARM32::getNumGPRegs());
1449   verifyRegNotPc(Rm, RmName, ClzName);
1450   assert(CondARM32::isDefined(Cond));
1451   constexpr IValueT PredefinedBits =
1452       B24 | B22 | B21 | (0xF << 16) | (0xf << 8) | B4;
1453   const IValueT Encoding = PredefinedBits | (Cond << kConditionShift) |
1454                            (Rd << kRdShift) | (Rm << kRmShift);
1455   emitInst(Encoding);
1456 }
1457 
cmn(const Operand * OpRn,const Operand * OpSrc1,CondARM32::Cond Cond)1458 void AssemblerARM32::cmn(const Operand *OpRn, const Operand *OpSrc1,
1459                          CondARM32::Cond Cond) {
1460   // CMN (immediate) - ARM section A8.8.34, encoding A1:
1461   //   cmn<c> <Rn>, #<RotatedImm8>
1462   //
1463   // cccc00110111nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1464   // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1465   //
1466   // CMN (register) - ARM section A8.8.35, encodeing A1:
1467   //   cmn<c> <Rn>, <Rm>{, <shift>}
1468   //
1469   // cccc00010111nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm,
1470   // iiiii=Shift, and tt=ShiftKind.
1471   constexpr const char *CmnName = "cmn";
1472   constexpr IValueT CmnOpcode = B3 | B1 | B0; // ie. 1011
1473   emitCompareOp(Cond, CmnOpcode, OpRn, OpSrc1, CmnName);
1474 }
1475 
cmp(const Operand * OpRn,const Operand * OpSrc1,CondARM32::Cond Cond)1476 void AssemblerARM32::cmp(const Operand *OpRn, const Operand *OpSrc1,
1477                          CondARM32::Cond Cond) {
1478   // CMP (register) - ARM section A8.8.38, encoding A1:
1479   //   cmp<c> <Rn>, <Rm>{, <shift>}
1480   //
1481   // cccc00010101nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm,
1482   // iiiii=Shift, and tt=ShiftKind.
1483   //
1484   // CMP (immediate) - ARM section A8.8.37
1485   //  cmp<c: <Rn>, #<RotatedImm8>
1486   //
1487   // cccc00110101nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1488   // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1489   constexpr const char *CmpName = "cmp";
1490   constexpr IValueT CmpOpcode = B3 | B1; // ie. 1010
1491   emitCompareOp(Cond, CmpOpcode, OpRn, OpSrc1, CmpName);
1492 }
1493 
dmb(IValueT Option)1494 void AssemblerARM32::dmb(IValueT Option) {
1495   // DMB - ARM section A8.8.43, encoding A1:
1496   //   dmb <option>
1497   //
1498   // 1111010101111111111100000101xxxx where xxxx=Option.
1499   assert(Utils::IsUint(4, Option) && "Bad dmb option");
1500   const IValueT Encoding =
1501       (encodeCondition(CondARM32::kNone) << kConditionShift) | B26 | B24 | B22 |
1502       B21 | B20 | B19 | B18 | B17 | B16 | B15 | B14 | B13 | B12 | B6 | B4 |
1503       Option;
1504   emitInst(Encoding);
1505 }
1506 
eor(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1507 void AssemblerARM32::eor(const Operand *OpRd, const Operand *OpRn,
1508                          const Operand *OpSrc1, bool SetFlags,
1509                          CondARM32::Cond Cond) {
1510   // EOR (register) - ARM section A*.8.47, encoding A1:
1511   //   eor{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
1512   //
1513   // cccc0000001snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1514   // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
1515   //
1516   // EOR (Immediate) - ARM section A8.*.46, encoding A1:
1517   //   eor{s}<c> <Rd>, <Rn>, #RotatedImm8
1518   //
1519   // cccc0010001snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1520   // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1521   constexpr const char *EorName = "eor";
1522   constexpr IValueT EorOpcode = B0; // 0001
1523   emitType01(Cond, EorOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1524              EorName);
1525 }
1526 
ldr(const Operand * OpRt,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)1527 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
1528                          CondARM32::Cond Cond, const TargetInfo &TInfo) {
1529   constexpr const char *LdrName = "ldr";
1530   constexpr bool IsLoad = true;
1531   IValueT Rt = encodeGPRegister(OpRt, "Rt", LdrName);
1532   const Type Ty = OpRt->getType();
1533   switch (Ty) {
1534   case IceType_i64:
1535     // LDRD is not implemented because target lowering handles i64 and double by
1536     // using two (32-bit) load instructions. Note: Intentionally drop to default
1537     // case.
1538     llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) +
1539                              " not implemented");
1540   default:
1541     llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) +
1542                              " not allowed");
1543   case IceType_i1:
1544   case IceType_i8: {
1545     // LDRB (immediate) - ARM section A8.8.68, encoding A1:
1546     //   ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}]     ; p=1, w=0
1547     //   ldrb<c> <Rt>, [<Rn>], #+/-<imm12>       ; p=1, w=1
1548     //   ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]!      ; p=0, w=1
1549     //
1550     // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1551     // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and
1552     // pu0w0nnnn0000iiiiiiiiiiii=Address.
1553     //
1554     // LDRB (register) - ARM section A8.8.66, encoding A1:
1555     //   ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
1556     //   ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
1557     //
1558     // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b
1559     // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address.
1560     constexpr bool IsByte = true;
1561     emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName);
1562     return;
1563   }
1564   case IceType_i16: {
1565     // LDRH (immediate) - ARM section A8.8.80, encoding A1:
1566     //   ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}]
1567     //   ldrh<c> <Rt>, [<Rn>], #+/-<Imm8>
1568     //   ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]!
1569     //
1570     // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1571     // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and
1572     // pu0w0nnnn0000iiiiiiiiiiii=Address.
1573     constexpr const char *Ldrh = "ldrh";
1574     emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo, Ldrh);
1575     return;
1576   }
1577   case IceType_i32: {
1578     // LDR (immediate) - ARM section A8.8.63, encoding A1:
1579     //   ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}]      ; p=1, w=0
1580     //   ldr<c> <Rt>, [<Rn>], #+/-<imm12>        ; p=1, w=1
1581     //   ldr<c> <Rt>, [<Rn>, #+/-<imm12>]!       ; p=0, w=1
1582     //
1583     // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1584     // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and
1585     //
1586     // LDR (register) - ARM section A8.8.70, encoding A1:
1587     //   ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
1588     //   ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>}
1589     //
1590     // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b
1591     // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address.
1592     constexpr bool IsByte = false;
1593     emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName);
1594     return;
1595   }
1596   }
1597 }
1598 
emitMemExOp(CondARM32::Cond Cond,Type Ty,bool IsLoad,const Operand * OpRd,IValueT Rt,const Operand * OpAddress,const TargetInfo & TInfo,const char * InstName)1599 void AssemblerARM32::emitMemExOp(CondARM32::Cond Cond, Type Ty, bool IsLoad,
1600                                  const Operand *OpRd, IValueT Rt,
1601                                  const Operand *OpAddress,
1602                                  const TargetInfo &TInfo,
1603                                  const char *InstName) {
1604   IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName);
1605   IValueT MemExOpcode = IsLoad ? B0 : 0;
1606   switch (Ty) {
1607   default:
1608     llvm::report_fatal_error(std::string(InstName) + ": Type " +
1609                              typeString(Ty) + " not allowed");
1610   case IceType_i1:
1611   case IceType_i8:
1612     MemExOpcode |= B2;
1613     break;
1614   case IceType_i16:
1615     MemExOpcode |= B2 | B1;
1616     break;
1617   case IceType_i32:
1618     break;
1619   case IceType_i64:
1620     MemExOpcode |= B1;
1621   }
1622   IValueT AddressRn;
1623   if (encodeAddress(OpAddress, AddressRn, TInfo, NoImmOffsetAddress) !=
1624       EncodedAsImmRegOffset)
1625     llvm::report_fatal_error(std::string(InstName) +
1626                              ": Can't extract Rn from address");
1627   assert(Utils::IsAbsoluteUint(3, MemExOpcode));
1628   assert(Rd < RegARM32::getNumGPRegs());
1629   assert(Rt < RegARM32::getNumGPRegs());
1630   assert(CondARM32::isDefined(Cond));
1631   IValueT Encoding = (Cond << kConditionShift) | B24 | B23 | B11 | B10 | B9 |
1632                      B8 | B7 | B4 | (MemExOpcode << kMemExOpcodeShift) |
1633                      AddressRn | (Rd << kRdShift) | (Rt << kRmShift);
1634   emitInst(Encoding);
1635   return;
1636 }
1637 
ldrex(const Operand * OpRt,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)1638 void AssemblerARM32::ldrex(const Operand *OpRt, const Operand *OpAddress,
1639                            CondARM32::Cond Cond, const TargetInfo &TInfo) {
1640   // LDREXB - ARM section A8.8.76, encoding A1:
1641   //   ldrexb<c> <Rt>, [<Rn>]
1642   //
1643   // cccc00011101nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1644   //
1645   // LDREXH - ARM section A8.8.78, encoding A1:
1646   //   ldrexh<c> <Rt>, [<Rn>]
1647   //
1648   // cccc00011111nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1649   //
1650   // LDREX - ARM section A8.8.75, encoding A1:
1651   //   ldrex<c> <Rt>, [<Rn>]
1652   //
1653   // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1654   //
1655   // LDREXD - ARM section A8.
1656   //   ldrexd<c> <Rt>, [<Rn>]
1657   //
1658   // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1659   constexpr const char *LdrexName = "ldrex";
1660   const Type Ty = OpRt->getType();
1661   constexpr bool IsLoad = true;
1662   constexpr IValueT Rm = RegARM32::Encoded_Reg_pc;
1663   emitMemExOp(Cond, Ty, IsLoad, OpRt, Rm, OpAddress, TInfo, LdrexName);
1664 }
1665 
emitShift(const CondARM32::Cond Cond,const OperandARM32::ShiftKind Shift,const Operand * OpRd,const Operand * OpRm,const Operand * OpSrc1,const bool SetFlags,const char * InstName)1666 void AssemblerARM32::emitShift(const CondARM32::Cond Cond,
1667                                const OperandARM32::ShiftKind Shift,
1668                                const Operand *OpRd, const Operand *OpRm,
1669                                const Operand *OpSrc1, const bool SetFlags,
1670                                const char *InstName) {
1671   constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101
1672   IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName);
1673   IValueT Rm = encodeGPRegister(OpRm, "Rm", InstName);
1674   IValueT Value;
1675   switch (encodeOperand(OpSrc1, Value, WantGPRegs)) {
1676   default:
1677     llvm::report_fatal_error(std::string(InstName) +
1678                              ": Last operand not understood");
1679   case EncodedAsShiftImm5: {
1680     // XXX (immediate)
1681     //   xxx{s}<c> <Rd>, <Rm>, #imm5
1682     //
1683     // cccc0001101s0000ddddiiiii000mmmm where cccc=Cond, s=SetFlags, dddd=Rd,
1684     // iiiii=imm5, and mmmm=Rm.
1685     constexpr IValueT Rn = 0; // Rn field is not used.
1686     Value = Value | (Rm << kRmShift) | (Shift << kShiftShift);
1687     emitType01(Cond, kInstTypeDataRegShift, ShiftOpcode, SetFlags, Rn, Rd,
1688                Value, RdIsPcAndSetFlags, InstName);
1689     return;
1690   }
1691   case EncodedAsRegister: {
1692     // XXX (register)
1693     //   xxx{S}<c> <Rd>, <Rm>, <Rs>
1694     //
1695     // cccc0001101s0000ddddssss0001mmmm where cccc=Cond, s=SetFlags, dddd=Rd,
1696     // mmmm=Rm, and ssss=Rs.
1697     constexpr IValueT Rn = 0; // Rn field is not used.
1698     IValueT Rs = encodeGPRegister(OpSrc1, "Rs", InstName);
1699     verifyRegNotPc(Rd, "Rd", InstName);
1700     verifyRegNotPc(Rm, "Rm", InstName);
1701     verifyRegNotPc(Rs, "Rs", InstName);
1702     emitType01(Cond, kInstTypeDataRegShift, ShiftOpcode, SetFlags, Rn, Rd,
1703                encodeShiftRotateReg(Rm, Shift, Rs), NoChecks, InstName);
1704     return;
1705   }
1706   }
1707 }
1708 
asr(const Operand * OpRd,const Operand * OpRm,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1709 void AssemblerARM32::asr(const Operand *OpRd, const Operand *OpRm,
1710                          const Operand *OpSrc1, bool SetFlags,
1711                          CondARM32::Cond Cond) {
1712   constexpr const char *AsrName = "asr";
1713   emitShift(Cond, OperandARM32::ASR, OpRd, OpRm, OpSrc1, SetFlags, AsrName);
1714 }
1715 
lsl(const Operand * OpRd,const Operand * OpRm,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1716 void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm,
1717                          const Operand *OpSrc1, bool SetFlags,
1718                          CondARM32::Cond Cond) {
1719   constexpr const char *LslName = "lsl";
1720   emitShift(Cond, OperandARM32::LSL, OpRd, OpRm, OpSrc1, SetFlags, LslName);
1721 }
1722 
lsr(const Operand * OpRd,const Operand * OpRm,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1723 void AssemblerARM32::lsr(const Operand *OpRd, const Operand *OpRm,
1724                          const Operand *OpSrc1, bool SetFlags,
1725                          CondARM32::Cond Cond) {
1726   constexpr const char *LsrName = "lsr";
1727   emitShift(Cond, OperandARM32::LSR, OpRd, OpRm, OpSrc1, SetFlags, LsrName);
1728 }
1729 
mov(const Operand * OpRd,const Operand * OpSrc,CondARM32::Cond Cond)1730 void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc,
1731                          CondARM32::Cond Cond) {
1732   // MOV (register) - ARM section A8.8.104, encoding A1:
1733   //   mov{S}<c> <Rd>, <Rn>
1734   //
1735   // cccc0001101s0000dddd00000000mmmm where cccc=Cond, s=SetFlags, dddd=Rd,
1736   // and nnnn=Rn.
1737   //
1738   // MOV (immediate) - ARM section A8.8.102, encoding A1:
1739   //   mov{S}<c> <Rd>, #<RotatedImm8>
1740   //
1741   // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd,
1742   // and iiiiiiiiiiii=RotatedImm8=Src.  Note: We don't use movs in this
1743   // assembler.
1744   constexpr const char *MovName = "mov";
1745   IValueT Rd = encodeGPRegister(OpRd, "Rd", MovName);
1746   constexpr bool SetFlags = false;
1747   constexpr IValueT Rn = 0;
1748   constexpr IValueT MovOpcode = B3 | B2 | B0; // 1101.
1749   emitType01(Cond, MovOpcode, Rd, Rn, OpSrc, SetFlags, RdIsPcAndSetFlags,
1750              MovName);
1751 }
1752 
emitMovwt(CondARM32::Cond Cond,bool IsMovW,const Operand * OpRd,const Operand * OpSrc,const char * MovName)1753 void AssemblerARM32::emitMovwt(CondARM32::Cond Cond, bool IsMovW,
1754                                const Operand *OpRd, const Operand *OpSrc,
1755                                const char *MovName) {
1756   IValueT Opcode = B25 | B24 | (IsMovW ? 0 : B22);
1757   IValueT Rd = encodeGPRegister(OpRd, "Rd", MovName);
1758   IValueT Imm16;
1759   if (const auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc)) {
1760     emitFixup(createMoveFixup(IsMovW, Src));
1761     // Use 0 for the lower 16 bits of the relocatable, and add a fixup to
1762     // install the correct bits.
1763     Imm16 = 0;
1764   } else if (encodeOperand(OpSrc, Imm16, WantGPRegs) != EncodedAsConstI32) {
1765     llvm::report_fatal_error(std::string(MovName) + ": Not i32 constant");
1766   }
1767   assert(CondARM32::isDefined(Cond));
1768   if (!Utils::IsAbsoluteUint(16, Imm16))
1769     llvm::report_fatal_error(std::string(MovName) + ": Constant not i16");
1770   const IValueT Encoding = encodeCondition(Cond) << kConditionShift | Opcode |
1771                            ((Imm16 >> 12) << 16) | Rd << kRdShift |
1772                            (Imm16 & 0xfff);
1773   emitInst(Encoding);
1774 }
1775 
movw(const Operand * OpRd,const Operand * OpSrc,CondARM32::Cond Cond)1776 void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc,
1777                           CondARM32::Cond Cond) {
1778   // MOV (immediate) - ARM section A8.8.102, encoding A2:
1779   //  movw<c> <Rd>, #<imm16>
1780   //
1781   // cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and
1782   // iiiiiiiiiiiiiiii=imm16.
1783   constexpr const char *MovwName = "movw";
1784   constexpr bool IsMovW = true;
1785   emitMovwt(Cond, IsMovW, OpRd, OpSrc, MovwName);
1786 }
1787 
movt(const Operand * OpRd,const Operand * OpSrc,CondARM32::Cond Cond)1788 void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc,
1789                           CondARM32::Cond Cond) {
1790   // MOVT - ARM section A8.8.106, encoding A1:
1791   //  movt<c> <Rd>, #<imm16>
1792   //
1793   // cccc00110100iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and
1794   // iiiiiiiiiiiiiiii=imm16.
1795   constexpr const char *MovtName = "movt";
1796   constexpr bool IsMovW = false;
1797   emitMovwt(Cond, IsMovW, OpRd, OpSrc, MovtName);
1798 }
1799 
mvn(const Operand * OpRd,const Operand * OpSrc,CondARM32::Cond Cond)1800 void AssemblerARM32::mvn(const Operand *OpRd, const Operand *OpSrc,
1801                          CondARM32::Cond Cond) {
1802   // MVN (immediate) - ARM section A8.8.115, encoding A1:
1803   //   mvn{s}<c> <Rd>, #<const>
1804   //
1805   // cccc0011111s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags=0, dddd=Rd,
1806   // and iiiiiiiiiiii=const
1807   //
1808   // MVN (register) - ARM section A8.8.116, encoding A1:
1809   //   mvn{s}<c> <Rd>, <Rm>{, <shift>
1810   //
1811   // cccc0001111s0000ddddiiiiitt0mmmm where cccc=Cond, s=SetFlags=0, dddd=Rd,
1812   // mmmm=Rm, iiii defines shift constant, and tt=ShiftKind.
1813   constexpr const char *MvnName = "mvn";
1814   IValueT Rd = encodeGPRegister(OpRd, "Rd", MvnName);
1815   constexpr IValueT MvnOpcode = B3 | B2 | B1 | B0; // i.e. 1111
1816   constexpr IValueT Rn = 0;
1817   constexpr bool SetFlags = false;
1818   emitType01(Cond, MvnOpcode, Rd, Rn, OpSrc, SetFlags, RdIsPcAndSetFlags,
1819              MvnName);
1820 }
1821 
nop()1822 void AssemblerARM32::nop() {
1823   // NOP - Section A8.8.119, encoding A1:
1824   //  nop<c>
1825   //
1826   // cccc0011001000001111000000000000 where cccc=Cond.
1827   constexpr CondARM32::Cond Cond = CondARM32::AL;
1828   const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B25 |
1829                            B24 | B21 | B15 | B14 | B13 | B12;
1830   emitInst(Encoding);
1831 }
1832 
sbc(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1833 void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn,
1834                          const Operand *OpSrc1, bool SetFlags,
1835                          CondARM32::Cond Cond) {
1836   // SBC (register) - ARM section 18.8.162, encoding A1:
1837   //   sbc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
1838   //
1839   // cccc0000110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1840   // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
1841   //
1842   // SBC (Immediate) - ARM section A8.8.161, encoding A1:
1843   //   sbc{s}<c> <Rd>, <Rn>, #<RotatedImm8>
1844   //
1845   // cccc0010110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1846   // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1847   constexpr const char *SbcName = "sbc";
1848   constexpr IValueT SbcOpcode = B2 | B1; // 0110
1849   emitType01(Cond, SbcOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1850              SbcName);
1851 }
1852 
sdiv(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,CondARM32::Cond Cond)1853 void AssemblerARM32::sdiv(const Operand *OpRd, const Operand *OpRn,
1854                           const Operand *OpSrc1, CondARM32::Cond Cond) {
1855   // SDIV - ARM section A8.8.165, encoding A1.
1856   //   sdiv<c> <Rd>, <Rn>, <Rm>
1857   //
1858   // cccc01110001dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and
1859   // mmmm=Rm.
1860   constexpr const char *SdivName = "sdiv";
1861   IValueT Rd = encodeGPRegister(OpRd, "Rd", SdivName);
1862   IValueT Rn = encodeGPRegister(OpRn, "Rn", SdivName);
1863   IValueT Rm = encodeGPRegister(OpSrc1, "Rm", SdivName);
1864   verifyRegNotPc(Rd, "Rd", SdivName);
1865   verifyRegNotPc(Rn, "Rn", SdivName);
1866   verifyRegNotPc(Rm, "Rm", SdivName);
1867   // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
1868   constexpr IValueT SdivOpcode = 0;
1869   emitDivOp(Cond, SdivOpcode, Rd, Rn, Rm);
1870 }
1871 
str(const Operand * OpRt,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)1872 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress,
1873                          CondARM32::Cond Cond, const TargetInfo &TInfo) {
1874   constexpr const char *StrName = "str";
1875   constexpr bool IsLoad = false;
1876   IValueT Rt = encodeGPRegister(OpRt, "Rt", StrName);
1877   const Type Ty = OpRt->getType();
1878   switch (Ty) {
1879   case IceType_i64:
1880     // STRD is not implemented because target lowering handles i64 and double by
1881     // using two (32-bit) store instructions.  Note: Intentionally drop to
1882     // default case.
1883     llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) +
1884                              " not implemented");
1885   default:
1886     llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) +
1887                              " not allowed");
1888   case IceType_i1:
1889   case IceType_i8: {
1890     // STRB (immediate) - ARM section A8.8.207, encoding A1:
1891     //   strb<c> <Rt>, [<Rn>{, #+/-<imm12>}]     ; p=1, w=0
1892     //   strb<c> <Rt>, [<Rn>], #+/-<imm12>       ; p=1, w=1
1893     //   strb<c> <Rt>, [<Rn>, #+/-<imm12>]!      ; p=0, w=1
1894     //
1895     // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1896     // iiiiiiiiiiii=imm12, u=1 if +.
1897     constexpr bool IsByte = true;
1898     emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName);
1899     return;
1900   }
1901   case IceType_i16: {
1902     // STRH (immediate) - ARM section A8.*.217, encoding A1:
1903     //   strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}]
1904     //   strh<c> <Rt>, [<Rn>], #+/-<Imm8>
1905     //   strh<c> <Rt>, [<Rn>, #+/-<Imm8>]!
1906     //
1907     // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1908     // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and
1909     // pu0w0nnnn0000iiiiiiiiiiii=Address.
1910     constexpr const char *Strh = "strh";
1911     emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo, Strh);
1912     return;
1913   }
1914   case IceType_i32: {
1915     // Note: Handles i32 and float stores. Target lowering handles i64 and
1916     // double by using two (32 bit) store instructions.
1917     //
1918     // STR (immediate) - ARM section A8.8.207, encoding A1:
1919     //   str<c> <Rt>, [<Rn>{, #+/-<imm12>}]     ; p=1, w=0
1920     //   str<c> <Rt>, [<Rn>], #+/-<imm12>       ; p=1, w=1
1921     //   str<c> <Rt>, [<Rn>, #+/-<imm12>]!      ; p=0, w=1
1922     //
1923     // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1924     // iiiiiiiiiiii=imm12, u=1 if +.
1925     constexpr bool IsByte = false;
1926     emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName);
1927     return;
1928   }
1929   }
1930 }
1931 
strex(const Operand * OpRd,const Operand * OpRt,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)1932 void AssemblerARM32::strex(const Operand *OpRd, const Operand *OpRt,
1933                            const Operand *OpAddress, CondARM32::Cond Cond,
1934                            const TargetInfo &TInfo) {
1935   // STREXB - ARM section A8.8.213, encoding A1:
1936   //   strexb<c> <Rd>, <Rt>, [<Rn>]
1937   //
1938   // cccc00011100nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1939   // nnnn=Rn.
1940   //
1941   // STREXH - ARM section A8.8.215, encoding A1:
1942   //   strexh<c> <Rd>, <Rt>, [<Rn>]
1943   //
1944   // cccc00011110nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1945   // nnnn=Rn.
1946   //
1947   // STREX - ARM section A8.8.212, encoding A1:
1948   //   strex<c> <Rd>, <Rt>, [<Rn>]
1949   //
1950   // cccc00011000nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1951   // nnnn=Rn.
1952   //
1953   // STREXD - ARM section A8.8.214, encoding A1:
1954   //   strexd<c> <Rd>, <Rt>, [<Rn>]
1955   //
1956   // cccc00011010nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1957   // nnnn=Rn.
1958   constexpr const char *StrexName = "strex";
1959   // Note: Rt uses Rm shift in encoding.
1960   IValueT Rt = encodeGPRegister(OpRt, "Rt", StrexName);
1961   const Type Ty = OpRt->getType();
1962   constexpr bool IsLoad = true;
1963   emitMemExOp(Cond, Ty, !IsLoad, OpRd, Rt, OpAddress, TInfo, StrexName);
1964 }
1965 
orr(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1966 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn,
1967                          const Operand *OpSrc1, bool SetFlags,
1968                          CondARM32::Cond Cond) {
1969   // ORR (register) - ARM Section A8.8.123, encoding A1:
1970   //   orr{s}<c> <Rd>, <Rn>, <Rm>
1971   //
1972   // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1973   // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags.
1974   //
1975   // ORR (register) - ARM Section A8.8.123, encoding A1:
1976   //   orr{s}<c> <Rd>, <Rn>,  #<RotatedImm8>
1977   //
1978   // cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1979   // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1980   constexpr const char *OrrName = "orr";
1981   constexpr IValueT OrrOpcode = B3 | B2; // i.e. 1100
1982   emitType01(Cond, OrrOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1983              OrrName);
1984 }
1985 
pop(const Variable * OpRt,CondARM32::Cond Cond)1986 void AssemblerARM32::pop(const Variable *OpRt, CondARM32::Cond Cond) {
1987   // POP - ARM section A8.8.132, encoding A2:
1988   //   pop<c> {Rt}
1989   //
1990   // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond.
1991   constexpr const char *Pop = "pop";
1992   IValueT Rt = encodeGPRegister(OpRt, "Rt", Pop);
1993   verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Pop);
1994   // Same as load instruction.
1995   constexpr bool IsLoad = true;
1996   constexpr bool IsByte = false;
1997   constexpr IOffsetT MaxOffset = (1 << 8) - 1;
1998   constexpr IValueT NoShiftRight = 0;
1999   IValueT Address =
2000       encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize,
2001                          OperandARM32Mem::PostIndex, MaxOffset, NoShiftRight);
2002   emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address);
2003 }
2004 
popList(const IValueT Registers,CondARM32::Cond Cond)2005 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) {
2006   // POP - ARM section A8.*.131, encoding A1:
2007   //   pop<c> <registers>
2008   //
2009   // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and
2010   // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register).
2011   constexpr bool IsLoad = true;
2012   emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers);
2013 }
2014 
push(const Operand * OpRt,CondARM32::Cond Cond)2015 void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) {
2016   // PUSH - ARM section A8.8.133, encoding A2:
2017   //   push<c> {Rt}
2018   //
2019   // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond.
2020   constexpr const char *Push = "push";
2021   IValueT Rt = encodeGPRegister(OpRt, "Rt", Push);
2022   verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Push);
2023   // Same as store instruction.
2024   constexpr bool isLoad = false;
2025   constexpr bool isByte = false;
2026   constexpr IOffsetT MaxOffset = (1 << 8) - 1;
2027   constexpr IValueT NoShiftRight = 0;
2028   IValueT Address =
2029       encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize,
2030                          OperandARM32Mem::PreIndex, MaxOffset, NoShiftRight);
2031   emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address);
2032 }
2033 
pushList(const IValueT Registers,CondARM32::Cond Cond)2034 void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) {
2035   // PUSH - ARM section A8.8.133, encoding A1:
2036   //   push<c> <Registers>
2037   //
2038   // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and
2039   // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register).
2040   constexpr bool IsLoad = false;
2041   emitMultiMemOp(Cond, DB_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers);
2042 }
2043 
mla(const Operand * OpRd,const Operand * OpRn,const Operand * OpRm,const Operand * OpRa,CondARM32::Cond Cond)2044 void AssemblerARM32::mla(const Operand *OpRd, const Operand *OpRn,
2045                          const Operand *OpRm, const Operand *OpRa,
2046                          CondARM32::Cond Cond) {
2047   // MLA - ARM section A8.8.114, encoding A1.
2048   //   mla{s}<c> <Rd>, <Rn>, <Rm>, <Ra>
2049   //
2050   // cccc0000001sddddaaaammmm1001nnnn where cccc=Cond, s=SetFlags, dddd=Rd,
2051   // aaaa=Ra, mmmm=Rm, and nnnn=Rn.
2052   constexpr const char *MlaName = "mla";
2053   IValueT Rd = encodeGPRegister(OpRd, "Rd", MlaName);
2054   IValueT Rn = encodeGPRegister(OpRn, "Rn", MlaName);
2055   IValueT Rm = encodeGPRegister(OpRm, "Rm", MlaName);
2056   IValueT Ra = encodeGPRegister(OpRa, "Ra", MlaName);
2057   verifyRegNotPc(Rd, "Rd", MlaName);
2058   verifyRegNotPc(Rn, "Rn", MlaName);
2059   verifyRegNotPc(Rm, "Rm", MlaName);
2060   verifyRegNotPc(Ra, "Ra", MlaName);
2061   constexpr IValueT MlaOpcode = B21;
2062   constexpr bool SetFlags = true;
2063   // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
2064   emitMulOp(Cond, MlaOpcode, Ra, Rd, Rn, Rm, !SetFlags);
2065 }
2066 
mls(const Operand * OpRd,const Operand * OpRn,const Operand * OpRm,const Operand * OpRa,CondARM32::Cond Cond)2067 void AssemblerARM32::mls(const Operand *OpRd, const Operand *OpRn,
2068                          const Operand *OpRm, const Operand *OpRa,
2069                          CondARM32::Cond Cond) {
2070   constexpr const char *MlsName = "mls";
2071   IValueT Rd = encodeGPRegister(OpRd, "Rd", MlsName);
2072   IValueT Rn = encodeGPRegister(OpRn, "Rn", MlsName);
2073   IValueT Rm = encodeGPRegister(OpRm, "Rm", MlsName);
2074   IValueT Ra = encodeGPRegister(OpRa, "Ra", MlsName);
2075   verifyRegNotPc(Rd, "Rd", MlsName);
2076   verifyRegNotPc(Rn, "Rn", MlsName);
2077   verifyRegNotPc(Rm, "Rm", MlsName);
2078   verifyRegNotPc(Ra, "Ra", MlsName);
2079   constexpr IValueT MlsOpcode = B22 | B21;
2080   constexpr bool SetFlags = true;
2081   // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
2082   emitMulOp(Cond, MlsOpcode, Ra, Rd, Rn, Rm, !SetFlags);
2083 }
2084 
mul(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)2085 void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn,
2086                          const Operand *OpSrc1, bool SetFlags,
2087                          CondARM32::Cond Cond) {
2088   // MUL - ARM section A8.8.114, encoding A1.
2089   //   mul{s}<c> <Rd>, <Rn>, <Rm>
2090   //
2091   // cccc0000000sdddd0000mmmm1001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn,
2092   // mmmm=Rm, and s=SetFlags.
2093   constexpr const char *MulName = "mul";
2094   IValueT Rd = encodeGPRegister(OpRd, "Rd", MulName);
2095   IValueT Rn = encodeGPRegister(OpRn, "Rn", MulName);
2096   IValueT Rm = encodeGPRegister(OpSrc1, "Rm", MulName);
2097   verifyRegNotPc(Rd, "Rd", MulName);
2098   verifyRegNotPc(Rn, "Rn", MulName);
2099   verifyRegNotPc(Rm, "Rm", MulName);
2100   // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
2101   constexpr IValueT MulOpcode = 0;
2102   emitMulOp(Cond, MulOpcode, RegARM32::Encoded_Reg_r0, Rd, Rn, Rm, SetFlags);
2103 }
2104 
emitRdRm(CondARM32::Cond Cond,IValueT Opcode,const Operand * OpRd,const Operand * OpRm,const char * InstName)2105 void AssemblerARM32::emitRdRm(CondARM32::Cond Cond, IValueT Opcode,
2106                               const Operand *OpRd, const Operand *OpRm,
2107                               const char *InstName) {
2108   IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName);
2109   IValueT Rm = encodeGPRegister(OpRm, "Rm", InstName);
2110   IValueT Encoding =
2111       (Cond << kConditionShift) | Opcode | (Rd << kRdShift) | (Rm << kRmShift);
2112   emitInst(Encoding);
2113 }
2114 
rbit(const Operand * OpRd,const Operand * OpRm,CondARM32::Cond Cond)2115 void AssemblerARM32::rbit(const Operand *OpRd, const Operand *OpRm,
2116                           CondARM32::Cond Cond) {
2117   // RBIT - ARM section A8.8.144, encoding A1:
2118   //   rbit<c> <Rd>, <Rm>
2119   //
2120   // cccc011011111111dddd11110011mmmm where cccc=Cond, dddd=Rn, and mmmm=Rm.
2121   constexpr const char *RbitName = "rev";
2122   constexpr IValueT RbitOpcode = B26 | B25 | B23 | B22 | B21 | B20 | B19 | B18 |
2123                                  B17 | B16 | B11 | B10 | B9 | B8 | B5 | B4;
2124   emitRdRm(Cond, RbitOpcode, OpRd, OpRm, RbitName);
2125 }
2126 
rev(const Operand * OpRd,const Operand * OpRm,CondARM32::Cond Cond)2127 void AssemblerARM32::rev(const Operand *OpRd, const Operand *OpRm,
2128                          CondARM32::Cond Cond) {
2129   // REV - ARM section A8.8.145, encoding A1:
2130   //   rev<c> <Rd>, <Rm>
2131   //
2132   // cccc011010111111dddd11110011mmmm where cccc=Cond, dddd=Rn, and mmmm=Rm.
2133   constexpr const char *RevName = "rev";
2134   constexpr IValueT RevOpcode = B26 | B25 | B23 | B21 | B20 | B19 | B18 | B17 |
2135                                 B16 | B11 | B10 | B9 | B8 | B5 | B4;
2136   emitRdRm(Cond, RevOpcode, OpRd, OpRm, RevName);
2137 }
2138 
rsb(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)2139 void AssemblerARM32::rsb(const Operand *OpRd, const Operand *OpRn,
2140                          const Operand *OpSrc1, bool SetFlags,
2141                          CondARM32::Cond Cond) {
2142   // RSB (immediate) - ARM section A8.8.152, encoding A1.
2143   //   rsb{s}<c> <Rd>, <Rn>, #<RotatedImm8>
2144   //
2145   // cccc0010011snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
2146   // s=setFlags and iiiiiiiiiiii defines the RotatedImm8 value.
2147   //
2148   // RSB (register) - ARM section A8.8.163, encoding A1.
2149   //   rsb{s}<c> <Rd>, <Rn>, <Rm>{, <Shift>}
2150   //
2151   // cccc0000011snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
2152   // mmmm=Rm, iiiii=shift, tt==ShiftKind, and s=SetFlags.
2153   constexpr const char *RsbName = "rsb";
2154   constexpr IValueT RsbOpcode = B1 | B0; // 0011
2155   emitType01(Cond, RsbOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
2156              RsbName);
2157 }
2158 
rsc(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)2159 void AssemblerARM32::rsc(const Operand *OpRd, const Operand *OpRn,
2160                          const Operand *OpSrc1, bool SetFlags,
2161                          CondARM32::Cond Cond) {
2162   // RSC (immediate) - ARM section A8.8.155, encoding A1:
2163   //   rsc{s}<c> <Rd>, <Rn>, #<RotatedImm8>
2164   //
2165   // cccc0010111snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
2166   // mmmm=Rm, iiiii=shift, tt=ShiftKind, and s=SetFlags.
2167   //
2168   // RSC (register) - ARM section A8.8.156, encoding A1:
2169   //   rsc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
2170   //
2171   // cccc0000111snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
2172   // mmmm=Rm, iiiii=shift, tt=ShiftKind, and s=SetFlags.
2173   //
2174   // RSC (register-shifted register) - ARM section A8.8.157, encoding A1:
2175   //   rsc{s}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
2176   //
2177   // cccc0000111fnnnnddddssss0tt1mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
2178   // mmmm=Rm, ssss=Rs, tt defined <type>, and f=SetFlags.
2179   constexpr const char *RscName = "rsc";
2180   constexpr IValueT RscOpcode = B2 | B1 | B0; // i.e. 0111.
2181   emitType01(Cond, RscOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
2182              RscName);
2183 }
2184 
sxt(const Operand * OpRd,const Operand * OpSrc0,CondARM32::Cond Cond)2185 void AssemblerARM32::sxt(const Operand *OpRd, const Operand *OpSrc0,
2186                          CondARM32::Cond Cond) {
2187   constexpr const char *SxtName = "sxt";
2188   constexpr IValueT SxtOpcode = B26 | B25 | B23 | B21;
2189   emitSignExtend(Cond, SxtOpcode, OpRd, OpSrc0, SxtName);
2190 }
2191 
sub(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)2192 void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn,
2193                          const Operand *OpSrc1, bool SetFlags,
2194                          CondARM32::Cond Cond) {
2195   // SUB (register) - ARM section A8.8.223, encoding A1:
2196   //   sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
2197   // SUB (SP minus register): See ARM section 8.8.226, encoding A1:
2198   //   sub{s}<c> <Rd>, sp, <Rm>{, <Shift>}
2199   //
2200   // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
2201   // mmmm=Rm, iiiii=shift, tt=ShiftKind, and s=SetFlags.
2202   //
2203   // Sub (Immediate) - ARM section A8.8.222, encoding A1:
2204   //    sub{s}<c> <Rd>, <Rn>, #<RotatedImm8>
2205   // Sub (Sp minus immediate) - ARM section A8.8.225, encoding A1:
2206   //    sub{s}<c> sp, <Rn>, #<RotatedImm8>
2207   //
2208   // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
2209   // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8
2210   constexpr const char *SubName = "sub";
2211   constexpr IValueT SubOpcode = B1; // 0010
2212   emitType01(Cond, SubOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
2213              SubName);
2214 }
2215 
2216 namespace {
2217 
2218 // Use a particular UDF encoding -- TRAPNaCl in LLVM: 0xE7FEDEF0
2219 // http://llvm.org/viewvc/llvm-project?view=revision&revision=173943
2220 const uint8_t TrapBytesRaw[] = {0xE7, 0xFE, 0xDE, 0xF0};
2221 
2222 const auto TrapBytes =
2223     llvm::ArrayRef<uint8_t>(TrapBytesRaw, llvm::array_lengthof(TrapBytesRaw));
2224 
2225 } // end of anonymous namespace
2226 
getNonExecBundlePadding() const2227 llvm::ArrayRef<uint8_t> AssemblerARM32::getNonExecBundlePadding() const {
2228   return TrapBytes;
2229 }
2230 
trap()2231 void AssemblerARM32::trap() {
2232   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2233   for (const uint8_t &Byte : reverse_range(TrapBytes))
2234     Buffer.emit<uint8_t>(Byte);
2235 }
2236 
tst(const Operand * OpRn,const Operand * OpSrc1,CondARM32::Cond Cond)2237 void AssemblerARM32::tst(const Operand *OpRn, const Operand *OpSrc1,
2238                          CondARM32::Cond Cond) {
2239   // TST (register) - ARM section A8.8.241, encoding A1:
2240   //   tst<c> <Rn>, <Rm>(, <shift>}
2241   //
2242   // cccc00010001nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm,
2243   // iiiii=Shift, and tt=ShiftKind.
2244   //
2245   // TST (immediate) - ARM section A8.8.240, encoding A1:
2246   //   tst<c> <Rn>, #<RotatedImm8>
2247   //
2248   // cccc00110001nnnn0000iiiiiiiiiiii where cccc=Cond, nnnn=Rn, and
2249   // iiiiiiiiiiii defines RotatedImm8.
2250   constexpr const char *TstName = "tst";
2251   constexpr IValueT TstOpcode = B3; // ie. 1000
2252   emitCompareOp(Cond, TstOpcode, OpRn, OpSrc1, TstName);
2253 }
2254 
udiv(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,CondARM32::Cond Cond)2255 void AssemblerARM32::udiv(const Operand *OpRd, const Operand *OpRn,
2256                           const Operand *OpSrc1, CondARM32::Cond Cond) {
2257   // UDIV - ARM section A8.8.248, encoding A1.
2258   //   udiv<c> <Rd>, <Rn>, <Rm>
2259   //
2260   // cccc01110011dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and
2261   // mmmm=Rm.
2262   constexpr const char *UdivName = "udiv";
2263   IValueT Rd = encodeGPRegister(OpRd, "Rd", UdivName);
2264   IValueT Rn = encodeGPRegister(OpRn, "Rn", UdivName);
2265   IValueT Rm = encodeGPRegister(OpSrc1, "Rm", UdivName);
2266   verifyRegNotPc(Rd, "Rd", UdivName);
2267   verifyRegNotPc(Rn, "Rn", UdivName);
2268   verifyRegNotPc(Rm, "Rm", UdivName);
2269   // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
2270   constexpr IValueT UdivOpcode = B21;
2271   emitDivOp(Cond, UdivOpcode, Rd, Rn, Rm);
2272 }
2273 
umull(const Operand * OpRdLo,const Operand * OpRdHi,const Operand * OpRn,const Operand * OpRm,CondARM32::Cond Cond)2274 void AssemblerARM32::umull(const Operand *OpRdLo, const Operand *OpRdHi,
2275                            const Operand *OpRn, const Operand *OpRm,
2276                            CondARM32::Cond Cond) {
2277   // UMULL - ARM section A8.8.257, encoding A1:
2278   //   umull<c> <RdLo>, <RdHi>, <Rn>, <Rm>
2279   //
2280   // cccc0000100shhhhllllmmmm1001nnnn where hhhh=RdHi, llll=RdLo, nnnn=Rn,
2281   // mmmm=Rm, and s=SetFlags
2282   constexpr const char *UmullName = "umull";
2283   IValueT RdLo = encodeGPRegister(OpRdLo, "RdLo", UmullName);
2284   IValueT RdHi = encodeGPRegister(OpRdHi, "RdHi", UmullName);
2285   IValueT Rn = encodeGPRegister(OpRn, "Rn", UmullName);
2286   IValueT Rm = encodeGPRegister(OpRm, "Rm", UmullName);
2287   verifyRegNotPc(RdLo, "RdLo", UmullName);
2288   verifyRegNotPc(RdHi, "RdHi", UmullName);
2289   verifyRegNotPc(Rn, "Rn", UmullName);
2290   verifyRegNotPc(Rm, "Rm", UmullName);
2291   verifyRegsNotEq(RdHi, "RdHi", RdLo, "RdLo", UmullName);
2292   constexpr IValueT UmullOpcode = B23;
2293   constexpr bool SetFlags = false;
2294   emitMulOp(Cond, UmullOpcode, RdLo, RdHi, Rn, Rm, SetFlags);
2295 }
2296 
uxt(const Operand * OpRd,const Operand * OpSrc0,CondARM32::Cond Cond)2297 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0,
2298                          CondARM32::Cond Cond) {
2299   constexpr const char *UxtName = "uxt";
2300   constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21;
2301   emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName);
2302 }
2303 
vabss(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)2304 void AssemblerARM32::vabss(const Operand *OpSd, const Operand *OpSm,
2305                            CondARM32::Cond Cond) {
2306   // VABS - ARM section A8.8.280, encoding A2:
2307   //   vabs<c>.f32 <Sd>, <Sm>
2308   //
2309   // cccc11101D110000dddd101011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
2310   constexpr const char *Vabss = "vabss";
2311   IValueT Sd = encodeSRegister(OpSd, "Sd", Vabss);
2312   IValueT Sm = encodeSRegister(OpSm, "Sm", Vabss);
2313   constexpr IValueT S0 = 0;
2314   constexpr IValueT VabssOpcode = B23 | B21 | B20 | B7 | B6;
2315   emitVFPsss(Cond, VabssOpcode, Sd, S0, Sm);
2316 }
2317 
vabsd(const Operand * OpDd,const Operand * OpDm,CondARM32::Cond Cond)2318 void AssemblerARM32::vabsd(const Operand *OpDd, const Operand *OpDm,
2319                            CondARM32::Cond Cond) {
2320   // VABS - ARM section A8.8.280, encoding A2:
2321   //   vabs<c>.f64 <Dd>, <Dm>
2322   //
2323   // cccc11101D110000dddd101111M0mmmm where cccc=Cond, Ddddd=Dd, and Mmmmm=Dm.
2324   constexpr const char *Vabsd = "vabsd";
2325   const IValueT Dd = encodeDRegister(OpDd, "Dd", Vabsd);
2326   const IValueT Dm = encodeDRegister(OpDm, "Dm", Vabsd);
2327   constexpr IValueT D0 = 0;
2328   constexpr IValueT VabsdOpcode = B23 | B21 | B20 | B7 | B6;
2329   emitVFPddd(Cond, VabsdOpcode, Dd, D0, Dm);
2330 }
2331 
vabsq(const Operand * OpQd,const Operand * OpQm)2332 void AssemblerARM32::vabsq(const Operand *OpQd, const Operand *OpQm) {
2333   // VABS - ARM section A8.8.280, encoding A1:
2334   //   vabs.<dt> <Qd>, <Qm>
2335   //
2336   // 111100111D11ss01ddd0f1101M0mmm0 where Dddd=OpQd, Mddd=OpQm, and
2337   // <dt> in {s8, s16, s32, f32} and ss is the encoding of <dt>.
2338   const Type ElmtTy = typeElementType(OpQd->getType());
2339   assert(ElmtTy != IceType_i64 && "vabsq doesn't allow i64!");
2340   constexpr const char *Vabsq = "vabsq";
2341   const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vabsq));
2342   const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vabsq));
2343   constexpr IValueT Dn = 0;
2344   const IValueT VabsqOpcode =
2345       B24 | B23 | B21 | B20 | B16 | B9 | B8 | (encodeElmtType(ElmtTy) << 18);
2346   constexpr bool UseQRegs = true;
2347   emitSIMDBase(VabsqOpcode, Dd, Dn, Dm, UseQRegs, isFloatingType(ElmtTy));
2348 }
2349 
vadds(const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,CondARM32::Cond Cond)2350 void AssemblerARM32::vadds(const Operand *OpSd, const Operand *OpSn,
2351                            const Operand *OpSm, CondARM32::Cond Cond) {
2352   // VADD (floating-point) - ARM section A8.8.283, encoding A2:
2353   //   vadd<c>.f32 <Sd>, <Sn>, <Sm>
2354   //
2355   // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn,
2356   // and mmmmM=Rm.
2357   constexpr const char *Vadds = "vadds";
2358   constexpr IValueT VaddsOpcode = B21 | B20;
2359   emitVFPsss(Cond, VaddsOpcode, OpSd, OpSn, OpSm, Vadds);
2360 }
2361 
vaddqi(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2362 void AssemblerARM32::vaddqi(Type ElmtTy, const Operand *OpQd,
2363                             const Operand *OpQm, const Operand *OpQn) {
2364   // VADD (integer) - ARM section A8.8.282, encoding A1:
2365   //   vadd.<dt> <Qd>, <Qn>, <Qm>
2366   //
2367   // 111100100Dssnnn0ddd01000N1M0mmm0 where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm,
2368   // and dt in [i8, i16, i32, i64] where ss is the index.
2369   assert(isScalarIntegerType(ElmtTy) &&
2370          "vaddqi expects vector with integer element type");
2371   constexpr const char *Vaddqi = "vaddqi";
2372   constexpr IValueT VaddqiOpcode = B11;
2373   emitSIMDqqq(VaddqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vaddqi);
2374 }
2375 
vaddqf(const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)2376 void AssemblerARM32::vaddqf(const Operand *OpQd, const Operand *OpQn,
2377                             const Operand *OpQm) {
2378   // VADD (floating-point) - ARM section A8.8.283, Encoding A1:
2379   //   vadd.f32 <Qd>, <Qn>, <Qm>
2380   //
2381   // 111100100D00nnn0ddd01101N1M0mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm.
2382   assert(OpQd->getType() == IceType_v4f32 && "vaddqf expects type <4 x float>");
2383   constexpr const char *Vaddqf = "vaddqf";
2384   constexpr IValueT VaddqfOpcode = B11 | B8;
2385   constexpr bool IsFloatTy = true;
2386   emitSIMDqqqBase(VaddqfOpcode, OpQd, OpQn, OpQm, IsFloatTy, Vaddqf);
2387 }
2388 
vaddd(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,CondARM32::Cond Cond)2389 void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn,
2390                            const Operand *OpDm, CondARM32::Cond Cond) {
2391   // VADD (floating-point) - ARM section A8.8.283, encoding A2:
2392   //   vadd<c>.f64 <Dd>, <Dn>, <Dm>
2393   //
2394   // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn,
2395   // and Mmmmm=Rm.
2396   constexpr const char *Vaddd = "vaddd";
2397   constexpr IValueT VadddOpcode = B21 | B20;
2398   emitVFPddd(Cond, VadddOpcode, OpDd, OpDn, OpDm, Vaddd);
2399 }
2400 
vandq(const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2401 void AssemblerARM32::vandq(const Operand *OpQd, const Operand *OpQm,
2402                            const Operand *OpQn) {
2403   // VAND (register) - ARM section A8.8.287, encoding A1:
2404   //   vand <Qd>, <Qn>, <Qm>
2405   //
2406   // 111100100D00nnn0ddd00001N1M1mmm0 where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm.
2407   constexpr const char *Vandq = "vandq";
2408   constexpr IValueT VandqOpcode = B8 | B4;
2409   constexpr Type ElmtTy = IceType_i8;
2410   emitSIMDqqq(VandqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vandq);
2411 }
2412 
vbslq(const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2413 void AssemblerARM32::vbslq(const Operand *OpQd, const Operand *OpQm,
2414                            const Operand *OpQn) {
2415   // VBSL (register) - ARM section A8.8.290, encoding A1:
2416   //   vbsl <Qd>, <Qn>, <Qm>
2417   //
2418   // 111100110D01nnn0ddd00001N1M1mmm0 where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm.
2419   constexpr const char *Vbslq = "vbslq";
2420   constexpr IValueT VbslqOpcode = B24 | B20 | B8 | B4;
2421   constexpr Type ElmtTy = IceType_i8; // emits sz=0
2422   emitSIMDqqq(VbslqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vbslq);
2423 }
2424 
vceqqi(const Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2425 void AssemblerARM32::vceqqi(const Type ElmtTy, const Operand *OpQd,
2426                             const Operand *OpQm, const Operand *OpQn) {
2427   // vceq (register) - ARM section A8.8.291, encoding A1:
2428   //   vceq.<st> <Qd>, <Qn>, <Qm>
2429   //
2430   // 111100110Dssnnnndddd1000NQM1mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, and
2431   // st in [i8, i16, i32] where ss is the index.
2432   constexpr const char *Vceq = "vceq";
2433   constexpr IValueT VceqOpcode = B24 | B11 | B4;
2434   emitSIMDqqq(VceqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vceq);
2435 }
2436 
vceqqs(const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2437 void AssemblerARM32::vceqqs(const Operand *OpQd, const Operand *OpQm,
2438                             const Operand *OpQn) {
2439   // vceq (register) - ARM section A8.8.291, encoding A2:
2440   //   vceq.f32 <Qd>, <Qn>, <Qm>
2441   //
2442   // 111100100D00nnnndddd1110NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm.
2443   constexpr const char *Vceq = "vceq";
2444   constexpr IValueT VceqOpcode = B11 | B10 | B9;
2445   constexpr Type ElmtTy = IceType_i8; // encoded as 0b00
2446   emitSIMDqqq(VceqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vceq);
2447 }
2448 
vcgeqi(const Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2449 void AssemblerARM32::vcgeqi(const Type ElmtTy, const Operand *OpQd,
2450                             const Operand *OpQm, const Operand *OpQn) {
2451   // vcge (register) - ARM section A8.8.293, encoding A1:
2452   //   vcge.<st> <Qd>, <Qn>, <Qm>
2453   //
2454   // 1111001U0Dssnnnndddd0011NQM1mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm,
2455   // 0=U, and st in [s8, s16, s32] where ss is the index.
2456   constexpr const char *Vcge = "vcge";
2457   constexpr IValueT VcgeOpcode = B9 | B8 | B4;
2458   emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge);
2459 }
2460 
vcugeqi(const Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2461 void AssemblerARM32::vcugeqi(const Type ElmtTy, const Operand *OpQd,
2462                              const Operand *OpQm, const Operand *OpQn) {
2463   // vcge (register) - ARM section A8.8.293, encoding A1:
2464   //   vcge.<st> <Qd>, <Qn>, <Qm>
2465   //
2466   // 1111001U0Dssnnnndddd0011NQM1mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm,
2467   // 1=U, and st in [u8, u16, u32] where ss is the index.
2468   constexpr const char *Vcge = "vcge";
2469   constexpr IValueT VcgeOpcode = B24 | B9 | B8 | B4;
2470   emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge);
2471 }
2472 
vcgeqs(const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2473 void AssemblerARM32::vcgeqs(const Operand *OpQd, const Operand *OpQm,
2474                             const Operand *OpQn) {
2475   // vcge (register) - ARM section A8.8.293, encoding A2:
2476   //   vcge.f32 <Qd>, <Qn>, <Qm>
2477   //
2478   // 111100110D00nnnndddd1110NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm.
2479   constexpr const char *Vcge = "vcge";
2480   constexpr IValueT VcgeOpcode = B24 | B11 | B10 | B9;
2481   constexpr Type ElmtTy = IceType_i8; // encoded as 0b00.
2482   emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge);
2483 }
2484 
vcgtqi(const Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2485 void AssemblerARM32::vcgtqi(const Type ElmtTy, const Operand *OpQd,
2486                             const Operand *OpQm, const Operand *OpQn) {
2487   // vcgt (register) - ARM section A8.8.295, encoding A1:
2488   //   vcgt.<st> <Qd>, <Qn>, <Qm>
2489   //
2490   // 1111001U0Dssnnnndddd0011NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm,
2491   // 0=U, and st in [s8, s16, s32] where ss is the index.
2492   constexpr const char *Vcge = "vcgt";
2493   constexpr IValueT VcgeOpcode = B9 | B8;
2494   emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge);
2495 }
2496 
vcugtqi(const Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2497 void AssemblerARM32::vcugtqi(const Type ElmtTy, const Operand *OpQd,
2498                              const Operand *OpQm, const Operand *OpQn) {
2499   // vcgt (register) - ARM section A8.8.295, encoding A1:
2500   //   vcgt.<st> <Qd>, <Qn>, <Qm>
2501   //
2502   // 111100110Dssnnnndddd0011NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm,
2503   // 1=U, and st in [u8, u16, u32] where ss is the index.
2504   constexpr const char *Vcge = "vcgt";
2505   constexpr IValueT VcgeOpcode = B24 | B9 | B8;
2506   emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge);
2507 }
2508 
vcgtqs(const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2509 void AssemblerARM32::vcgtqs(const Operand *OpQd, const Operand *OpQm,
2510                             const Operand *OpQn) {
2511   // vcgt (register) - ARM section A8.8.295, encoding A2:
2512   //   vcgt.f32 <Qd>, <Qn>, <Qm>
2513   //
2514   // 111100110D10nnnndddd1110NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm.
2515   constexpr const char *Vcge = "vcgt";
2516   constexpr IValueT VcgeOpcode = B24 | B21 | B11 | B10 | B9;
2517   constexpr Type ElmtTy = IceType_i8; // encoded as 0b00.
2518   emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge);
2519 }
2520 
vcmpd(const Operand * OpDd,const Operand * OpDm,CondARM32::Cond Cond)2521 void AssemblerARM32::vcmpd(const Operand *OpDd, const Operand *OpDm,
2522                            CondARM32::Cond Cond) {
2523   constexpr const char *Vcmpd = "vcmpd";
2524   IValueT Dd = encodeDRegister(OpDd, "Dd", Vcmpd);
2525   IValueT Dm = encodeDRegister(OpDm, "Dm", Vcmpd);
2526   constexpr IValueT VcmpdOpcode = B23 | B21 | B20 | B18 | B6;
2527   constexpr IValueT Dn = 0;
2528   emitVFPddd(Cond, VcmpdOpcode, Dd, Dn, Dm);
2529 }
2530 
vcmpdz(const Operand * OpDd,CondARM32::Cond Cond)2531 void AssemblerARM32::vcmpdz(const Operand *OpDd, CondARM32::Cond Cond) {
2532   constexpr const char *Vcmpdz = "vcmpdz";
2533   IValueT Dd = encodeDRegister(OpDd, "Dd", Vcmpdz);
2534   constexpr IValueT VcmpdzOpcode = B23 | B21 | B20 | B18 | B16 | B6;
2535   constexpr IValueT Dn = 0;
2536   constexpr IValueT Dm = 0;
2537   emitVFPddd(Cond, VcmpdzOpcode, Dd, Dn, Dm);
2538 }
2539 
vcmps(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)2540 void AssemblerARM32::vcmps(const Operand *OpSd, const Operand *OpSm,
2541                            CondARM32::Cond Cond) {
2542   constexpr const char *Vcmps = "vcmps";
2543   IValueT Sd = encodeSRegister(OpSd, "Sd", Vcmps);
2544   IValueT Sm = encodeSRegister(OpSm, "Sm", Vcmps);
2545   constexpr IValueT VcmpsOpcode = B23 | B21 | B20 | B18 | B6;
2546   constexpr IValueT Sn = 0;
2547   emitVFPsss(Cond, VcmpsOpcode, Sd, Sn, Sm);
2548 }
2549 
vcmpsz(const Operand * OpSd,CondARM32::Cond Cond)2550 void AssemblerARM32::vcmpsz(const Operand *OpSd, CondARM32::Cond Cond) {
2551   constexpr const char *Vcmpsz = "vcmps";
2552   IValueT Sd = encodeSRegister(OpSd, "Sd", Vcmpsz);
2553   constexpr IValueT VcmpszOpcode = B23 | B21 | B20 | B18 | B16 | B6;
2554   constexpr IValueT Sn = 0;
2555   constexpr IValueT Sm = 0;
2556   emitVFPsss(Cond, VcmpszOpcode, Sd, Sn, Sm);
2557 }
2558 
emitVFPsd(CondARM32::Cond Cond,IValueT Opcode,IValueT Sd,IValueT Dm)2559 void AssemblerARM32::emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd,
2560                                IValueT Dm) {
2561   assert(Sd < RegARM32::getNumSRegs());
2562   assert(Dm < RegARM32::getNumDRegs());
2563   assert(CondARM32::isDefined(Cond));
2564   constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9;
2565   const IValueT Encoding =
2566       Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
2567       (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) |
2568       (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm);
2569   emitInst(Encoding);
2570 }
2571 
vcvtdi(const Operand * OpDd,const Operand * OpSm,CondARM32::Cond Cond)2572 void AssemblerARM32::vcvtdi(const Operand *OpDd, const Operand *OpSm,
2573                             CondARM32::Cond Cond) {
2574   // VCVT (between floating-point and integer, Floating-point)
2575   //      - ARM Section A8.8.306, encoding A1:
2576   //   vcvt<c>.f64.s32 <Dd>, <Sm>
2577   //
2578   // cccc11101D111000dddd10111M0mmmm where cccc=Cond, Ddddd=Dd, and mmmmM=Sm.
2579   constexpr const char *Vcvtdi = "vcvtdi";
2580   IValueT Dd = encodeDRegister(OpDd, "Dd", Vcvtdi);
2581   IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtdi);
2582   constexpr IValueT VcvtdiOpcode = B23 | B21 | B20 | B19 | B8 | B7 | B6;
2583   emitVFPds(Cond, VcvtdiOpcode, Dd, Sm);
2584 }
2585 
vcvtdu(const Operand * OpDd,const Operand * OpSm,CondARM32::Cond Cond)2586 void AssemblerARM32::vcvtdu(const Operand *OpDd, const Operand *OpSm,
2587                             CondARM32::Cond Cond) {
2588   // VCVT (between floating-point and integer, Floating-point)
2589   //      - ARM Section A8.8.306, encoding A1:
2590   //   vcvt<c>.f64.u32 <Dd>, <Sm>
2591   //
2592   // cccc11101D111000dddd10101M0mmmm where cccc=Cond, Ddddd=Dd, and mmmmM=Sm.
2593   constexpr const char *Vcvtdu = "vcvtdu";
2594   IValueT Dd = encodeDRegister(OpDd, "Dd", Vcvtdu);
2595   IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtdu);
2596   constexpr IValueT VcvtduOpcode = B23 | B21 | B20 | B19 | B8 | B6;
2597   emitVFPds(Cond, VcvtduOpcode, Dd, Sm);
2598 }
2599 
vcvtsd(const Operand * OpSd,const Operand * OpDm,CondARM32::Cond Cond)2600 void AssemblerARM32::vcvtsd(const Operand *OpSd, const Operand *OpDm,
2601                             CondARM32::Cond Cond) {
2602   constexpr const char *Vcvtsd = "vcvtsd";
2603   IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtsd);
2604   IValueT Dm = encodeDRegister(OpDm, "Dm", Vcvtsd);
2605   constexpr IValueT VcvtsdOpcode =
2606       B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6;
2607   emitVFPsd(Cond, VcvtsdOpcode, Sd, Dm);
2608 }
2609 
vcvtis(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)2610 void AssemblerARM32::vcvtis(const Operand *OpSd, const Operand *OpSm,
2611                             CondARM32::Cond Cond) {
2612   // VCVT (between floating-point and integer, Floating-point)
2613   //      - ARM Section A8.8.306, encoding A1:
2614   //   vcvt<c>.s32.f32 <Sd>, <Sm>
2615   //
2616   // cccc11101D111101dddd10011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
2617   constexpr const char *Vcvtis = "vcvtis";
2618   IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtis);
2619   IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtis);
2620   constexpr IValueT VcvtisOpcode = B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6;
2621   constexpr IValueT S0 = 0;
2622   emitVFPsss(Cond, VcvtisOpcode, Sd, S0, Sm);
2623 }
2624 
vcvtid(const Operand * OpSd,const Operand * OpDm,CondARM32::Cond Cond)2625 void AssemblerARM32::vcvtid(const Operand *OpSd, const Operand *OpDm,
2626                             CondARM32::Cond Cond) {
2627   // VCVT (between floating-point and integer, Floating-point)
2628   //      - ARM Section A8.8.306, encoding A1:
2629   //   vcvt<c>.s32.f64 <Sd>, <Dm>
2630   //
2631   // cccc11101D111101dddd10111M0mmmm where cccc=Cond, ddddD=Sd, and Mmmmm=Dm.
2632   constexpr const char *Vcvtid = "vcvtid";
2633   IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtid);
2634   IValueT Dm = encodeDRegister(OpDm, "Dm", Vcvtid);
2635   constexpr IValueT VcvtidOpcode =
2636       B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6;
2637   emitVFPsd(Cond, VcvtidOpcode, Sd, Dm);
2638 }
2639 
vcvtsi(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)2640 void AssemblerARM32::vcvtsi(const Operand *OpSd, const Operand *OpSm,
2641                             CondARM32::Cond Cond) {
2642   // VCVT (between floating-point and integer, Floating-point)
2643   //      - ARM Section A8.8.306, encoding A1:
2644   //   vcvt<c>.f32.s32 <Sd>, <Sm>
2645   //
2646   // cccc11101D111000dddd10011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
2647   constexpr const char *Vcvtsi = "vcvtsi";
2648   IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtsi);
2649   IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtsi);
2650   constexpr IValueT VcvtsiOpcode = B23 | B21 | B20 | B19 | B7 | B6;
2651   constexpr IValueT S0 = 0;
2652   emitVFPsss(Cond, VcvtsiOpcode, Sd, S0, Sm);
2653 }
2654 
vcvtsu(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)2655 void AssemblerARM32::vcvtsu(const Operand *OpSd, const Operand *OpSm,
2656                             CondARM32::Cond Cond) {
2657   // VCVT (between floating-point and integer, Floating-point)
2658   //      - ARM Section A8.8.306, encoding A1:
2659   //   vcvt<c>.f32.u32 <Sd>, <Sm>
2660   //
2661   // cccc11101D111000dddd10001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
2662   constexpr const char *Vcvtsu = "vcvtsu";
2663   IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtsu);
2664   IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtsu);
2665   constexpr IValueT VcvtsuOpcode = B23 | B21 | B20 | B19 | B6;
2666   constexpr IValueT S0 = 0;
2667   emitVFPsss(Cond, VcvtsuOpcode, Sd, S0, Sm);
2668 }
2669 
vcvtud(const Operand * OpSd,const Operand * OpDm,CondARM32::Cond Cond)2670 void AssemblerARM32::vcvtud(const Operand *OpSd, const Operand *OpDm,
2671                             CondARM32::Cond Cond) {
2672   // VCVT (between floating-point and integer, Floating-point)
2673   //      - ARM Section A8.8.306, encoding A1:
2674   //   vcvt<c>.u32.f64 <Sd>, <Dm>
2675   //
2676   // cccc11101D111100dddd10111M0mmmm where cccc=Cond, ddddD=Sd, and Mmmmm=Dm.
2677   constexpr const char *Vcvtud = "vcvtud";
2678   IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtud);
2679   IValueT Dm = encodeDRegister(OpDm, "Dm", Vcvtud);
2680   constexpr IValueT VcvtudOpcode = B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6;
2681   emitVFPsd(Cond, VcvtudOpcode, Sd, Dm);
2682 }
2683 
vcvtus(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)2684 void AssemblerARM32::vcvtus(const Operand *OpSd, const Operand *OpSm,
2685                             CondARM32::Cond Cond) {
2686   // VCVT (between floating-point and integer, Floating-point)
2687   //      - ARM Section A8.8.306, encoding A1:
2688   //   vcvt<c>.u32.f32 <Sd>, <Sm>
2689   //
2690   // cccc11101D111100dddd10011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
2691   constexpr const char *Vcvtus = "vcvtus";
2692   IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtus);
2693   IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtus);
2694   constexpr IValueT VcvtsiOpcode = B23 | B21 | B20 | B19 | B18 | B7 | B6;
2695   constexpr IValueT S0 = 0;
2696   emitVFPsss(Cond, VcvtsiOpcode, Sd, S0, Sm);
2697 }
2698 
vcvtqsi(const Operand * OpQd,const Operand * OpQm)2699 void AssemblerARM32::vcvtqsi(const Operand *OpQd, const Operand *OpQm) {
2700   // VCVT (between floating-point and integer, Advanced SIMD)
2701   //      - ARM Section A8.8.305, encoding A1:
2702   //   vcvt<c>.f32.s32 <Qd>, <Qm>
2703   //
2704   // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 10=op.
2705   constexpr const char *Vcvtqsi = "vcvt.s32.f32";
2706   constexpr IValueT VcvtqsiOpcode = B8;
2707   emitSIMDCvtqq(VcvtqsiOpcode, OpQd, OpQm, Vcvtqsi);
2708 }
2709 
vcvtqsu(const Operand * OpQd,const Operand * OpQm)2710 void AssemblerARM32::vcvtqsu(const Operand *OpQd, const Operand *OpQm) {
2711   // VCVT (between floating-point and integer, Advanced SIMD)
2712   //      - ARM Section A8.8.305, encoding A1:
2713   //   vcvt<c>.f32.u32 <Qd>, <Qm>
2714   //
2715   // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 11=op.
2716   constexpr const char *Vcvtqsu = "vcvt.u32.f32";
2717   constexpr IValueT VcvtqsuOpcode = B8 | B7;
2718   emitSIMDCvtqq(VcvtqsuOpcode, OpQd, OpQm, Vcvtqsu);
2719 }
2720 
vcvtqis(const Operand * OpQd,const Operand * OpQm)2721 void AssemblerARM32::vcvtqis(const Operand *OpQd, const Operand *OpQm) {
2722   // VCVT (between floating-point and integer, Advanced SIMD)
2723   //      - ARM Section A8.8.305, encoding A1:
2724   //   vcvt<c>.f32.s32 <Qd>, <Qm>
2725   //
2726   // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 01=op.
2727   constexpr const char *Vcvtqis = "vcvt.f32.s32";
2728   constexpr IValueT VcvtqisOpcode = 0;
2729   emitSIMDCvtqq(VcvtqisOpcode, OpQd, OpQm, Vcvtqis);
2730 }
2731 
vcvtqus(const Operand * OpQd,const Operand * OpQm)2732 void AssemblerARM32::vcvtqus(const Operand *OpQd, const Operand *OpQm) {
2733   // VCVT (between floating-point and integer, Advanced SIMD)
2734   //      - ARM Section A8.8.305, encoding A1:
2735   //   vcvt<c>.f32.u32 <Qd>, <Qm>
2736   //
2737   // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 01=op.
2738   constexpr const char *Vcvtqus = "vcvt.f32.u32";
2739   constexpr IValueT VcvtqusOpcode = B7;
2740   emitSIMDCvtqq(VcvtqusOpcode, OpQd, OpQm, Vcvtqus);
2741 }
2742 
emitVFPds(CondARM32::Cond Cond,IValueT Opcode,IValueT Dd,IValueT Sm)2743 void AssemblerARM32::emitVFPds(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd,
2744                                IValueT Sm) {
2745   assert(Dd < RegARM32::getNumDRegs());
2746   assert(Sm < RegARM32::getNumSRegs());
2747   assert(CondARM32::isDefined(Cond));
2748   constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9;
2749   const IValueT Encoding =
2750       Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
2751       (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dd) << 12) |
2752       (getYInRegXXXXY(Sm) << 5) | getXXXXInRegXXXXY(Sm);
2753   emitInst(Encoding);
2754 }
2755 
vcvtds(const Operand * OpDd,const Operand * OpSm,CondARM32::Cond Cond)2756 void AssemblerARM32::vcvtds(const Operand *OpDd, const Operand *OpSm,
2757                             CondARM32::Cond Cond) {
2758   constexpr const char *Vcvtds = "Vctds";
2759   IValueT Dd = encodeDRegister(OpDd, "Dd", Vcvtds);
2760   IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtds);
2761   constexpr IValueT VcvtdsOpcode = B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6;
2762   emitVFPds(Cond, VcvtdsOpcode, Dd, Sm);
2763 }
2764 
vdivs(const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,CondARM32::Cond Cond)2765 void AssemblerARM32::vdivs(const Operand *OpSd, const Operand *OpSn,
2766                            const Operand *OpSm, CondARM32::Cond Cond) {
2767   // VDIV (floating-point) - ARM section A8.8.283, encoding A2:
2768   //   vdiv<c>.f32 <Sd>, <Sn>, <Sm>
2769   //
2770   // cccc11101D00nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn,
2771   // and mmmmM=Rm.
2772   constexpr const char *Vdivs = "vdivs";
2773   constexpr IValueT VdivsOpcode = B23;
2774   emitVFPsss(Cond, VdivsOpcode, OpSd, OpSn, OpSm, Vdivs);
2775 }
2776 
vdivd(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,CondARM32::Cond Cond)2777 void AssemblerARM32::vdivd(const Operand *OpDd, const Operand *OpDn,
2778                            const Operand *OpDm, CondARM32::Cond Cond) {
2779   // VDIV (floating-point) - ARM section A8.8.283, encoding A2:
2780   //   vdiv<c>.f64 <Dd>, <Dn>, <Dm>
2781   //
2782   // cccc11101D00nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn,
2783   // and Mmmmm=Rm.
2784   constexpr const char *Vdivd = "vdivd";
2785   constexpr IValueT VdivdOpcode = B23;
2786   emitVFPddd(Cond, VdivdOpcode, OpDd, OpDn, OpDm, Vdivd);
2787 }
2788 
veord(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm)2789 void AssemblerARM32::veord(const Operand *OpDd, const Operand *OpDn,
2790                            const Operand *OpDm) {
2791   // VEOR - ARM secdtion A8.8.315, encoding A1:
2792   //   veor<c> <Dd>, <Dn>, <Dm>
2793   //
2794   // 111100110D00nnnndddd0001N0M1mmmm where Ddddd=Dd, Nnnnn=Dn, and Mmmmm=Dm.
2795   constexpr const char *Veord = "veord";
2796   IValueT Dd = encodeDRegister(OpDd, "Dd", Veord);
2797   IValueT Dn = encodeDRegister(OpDn, "Dn", Veord);
2798   IValueT Dm = encodeDRegister(OpDm, "Dm", Veord);
2799   const IValueT Encoding =
2800       B25 | B24 | B8 | B4 |
2801       (encodeCondition(CondARM32::Cond::kNone) << kConditionShift) |
2802       (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) |
2803       (getXXXXInRegYXXXX(Dd) << 12) | (getYInRegYXXXX(Dn) << 7) |
2804       (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm);
2805   emitInst(Encoding);
2806 }
2807 
veorq(const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)2808 void AssemblerARM32::veorq(const Operand *OpQd, const Operand *OpQn,
2809                            const Operand *OpQm) {
2810   // VEOR - ARM section A8.8.316, encoding A1:
2811   //   veor <Qd>, <Qn>, <Qm>
2812   //
2813   // 111100110D00nnn0ddd00001N1M1mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm.
2814   constexpr const char *Veorq = "veorq";
2815   constexpr IValueT VeorqOpcode = B24 | B8 | B4;
2816   emitSIMDqqq(VeorqOpcode, IceType_i8, OpQd, OpQn, OpQm, Veorq);
2817 }
2818 
vldrd(const Operand * OpDd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)2819 void AssemblerARM32::vldrd(const Operand *OpDd, const Operand *OpAddress,
2820                            CondARM32::Cond Cond, const TargetInfo &TInfo) {
2821   // VLDR - ARM section A8.8.333, encoding A1.
2822   //   vldr<c> <Dd>, [<Rn>{, #+/-<imm>}]
2823   //
2824   // cccc1101UD01nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd,
2825   // iiiiiiii=abs(Imm >> 2), and U=1 if Opcode>=0.
2826   constexpr const char *Vldrd = "vldrd";
2827   IValueT Dd = encodeDRegister(OpDd, "Dd", Vldrd);
2828   assert(CondARM32::isDefined(Cond));
2829   IValueT Address;
2830   EncodedOperand AddressEncoding =
2831       encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address);
2832   (void)AddressEncoding;
2833   assert(AddressEncoding == EncodedAsImmRegOffset);
2834   IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | B8 |
2835                      (encodeCondition(Cond) << kConditionShift) |
2836                      (getYInRegYXXXX(Dd) << 22) |
2837                      (getXXXXInRegYXXXX(Dd) << 12) | Address;
2838   emitInst(Encoding);
2839 }
2840 
vldrs(const Operand * OpSd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)2841 void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress,
2842                            CondARM32::Cond Cond, const TargetInfo &TInfo) {
2843   // VDLR - ARM section A8.8.333, encoding A2.
2844   //   vldr<c> <Sd>, [<Rn>{, #+/-<imm>]]
2845   //
2846   // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd,
2847   // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0;
2848   constexpr const char *Vldrs = "vldrs";
2849   IValueT Sd = encodeSRegister(OpSd, "Sd", Vldrs);
2850   assert(CondARM32::isDefined(Cond));
2851   IValueT Address;
2852   EncodedOperand AddressEncoding =
2853       encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address);
2854   (void)AddressEncoding;
2855   assert(AddressEncoding == EncodedAsImmRegOffset);
2856   IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 |
2857                      (encodeCondition(Cond) << kConditionShift) |
2858                      (getYInRegXXXXY(Sd) << 22) |
2859                      (getXXXXInRegXXXXY(Sd) << 12) | Address;
2860   emitInst(Encoding);
2861 }
2862 
emitVMem1Op(IValueT Opcode,IValueT Dd,IValueT Rn,IValueT Rm,DRegListSize NumDRegs,size_t ElmtSize,IValueT Align,const char * InstName)2863 void AssemblerARM32::emitVMem1Op(IValueT Opcode, IValueT Dd, IValueT Rn,
2864                                  IValueT Rm, DRegListSize NumDRegs,
2865                                  size_t ElmtSize, IValueT Align,
2866                                  const char *InstName) {
2867   assert(Utils::IsAbsoluteUint(2, Align));
2868   IValueT EncodedElmtSize;
2869   switch (ElmtSize) {
2870   default: {
2871     std::string Buffer;
2872     llvm::raw_string_ostream StrBuf(Buffer);
2873     StrBuf << InstName << ": found invalid vector element size " << ElmtSize;
2874     llvm::report_fatal_error(StrBuf.str());
2875   }
2876   case 8:
2877     EncodedElmtSize = 0;
2878     break;
2879   case 16:
2880     EncodedElmtSize = 1;
2881     break;
2882   case 32:
2883     EncodedElmtSize = 2;
2884     break;
2885   case 64:
2886     EncodedElmtSize = 3;
2887   }
2888   const IValueT Encoding =
2889       Opcode | (encodeCondition(CondARM32::kNone) << kConditionShift) |
2890       (getYInRegYXXXX(Dd) << 22) | (Rn << kRnShift) |
2891       (getXXXXInRegYXXXX(Dd) << kRdShift) | (NumDRegs << 8) |
2892       (EncodedElmtSize << 6) | (Align << 4) | Rm;
2893   emitInst(Encoding);
2894 }
2895 
vld1qr(size_t ElmtSize,const Operand * OpQd,const Operand * OpAddress,const TargetInfo & TInfo)2896 void AssemblerARM32::vld1qr(size_t ElmtSize, const Operand *OpQd,
2897                             const Operand *OpAddress, const TargetInfo &TInfo) {
2898   // VLD1 (multiple single elements) - ARM section A8.8.320, encoding A1:
2899   //   vld1.<size> <Qd>, [<Rn>]
2900   //
2901   // 111101000D10nnnnddd0ttttssaammmm where tttt=DRegListSize2, Dddd=Qd,
2902   // nnnn=Rn, aa=0 (use default alignment), size=ElmtSize, and ss is the
2903   // encoding of ElmtSize.
2904   constexpr const char *Vld1qr = "vld1qr";
2905   const IValueT Qd = encodeQRegister(OpQd, "Qd", Vld1qr);
2906   const IValueT Dd = mapQRegToDReg(Qd);
2907   IValueT Address;
2908   if (encodeAddress(OpAddress, Address, TInfo, NoImmOffsetAddress) !=
2909       EncodedAsImmRegOffset)
2910     llvm::report_fatal_error(std::string(Vld1qr) + ": malform memory address");
2911   const IValueT Rn = mask(Address, kRnShift, 4);
2912   constexpr IValueT Rm = RegARM32::Reg_pc;
2913   constexpr IValueT Opcode = B26 | B21;
2914   constexpr IValueT Align = 0; // use default alignment.
2915   emitVMem1Op(Opcode, Dd, Rn, Rm, DRegListSize2, ElmtSize, Align, Vld1qr);
2916 }
2917 
vmovqc(const Operand * OpQd,const ConstantInteger32 * Imm)2918 bool AssemblerARM32::vmovqc(const Operand *OpQd, const ConstantInteger32 *Imm) {
2919   // VMOV (immediate) - ARM section A8.8.320, encoding A1:
2920   //   VMOV.<dt> <Qd>, #<Imm>
2921   // 1111001x1D000yyyddddcccc01p1zzzz where Qd=Ddddd, Imm=xyyyzzzz, cmode=cccc,
2922   // and Op=p.
2923   constexpr const char *Vmovc = "vmovc";
2924   const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vmovc));
2925   IValueT Value = Imm->getValue();
2926   const Type VecTy = OpQd->getType();
2927   if (!isVectorType(VecTy))
2928     return false;
2929 
2930   IValueT Op;
2931   IValueT Cmode;
2932   IValueT Imm8;
2933   if (!encodeAdvSIMDExpandImm(Value, typeElementType(VecTy), Op, Cmode, Imm8))
2934     return false;
2935   if (Op == 0 && mask(Cmode, 0, 1) == 1)
2936     return false;
2937   if (Op == 1 && Cmode != 13)
2938     return false;
2939   const IValueT Encoding =
2940       (0xF << kConditionShift) | B25 | B23 | B6 | B4 |
2941       (mask(Imm8, 7, 1) << 24) | (getYInRegYXXXX(Dd) << 22) |
2942       (mask(Imm8, 4, 3) << 16) | (getXXXXInRegYXXXX(Dd) << 12) | (Cmode << 8) |
2943       (Op << 5) | mask(Imm8, 0, 4);
2944   emitInst(Encoding);
2945   return true;
2946 }
2947 
vmovd(const Operand * OpDd,const OperandARM32FlexFpImm * OpFpImm,CondARM32::Cond Cond)2948 void AssemblerARM32::vmovd(const Operand *OpDd,
2949                            const OperandARM32FlexFpImm *OpFpImm,
2950                            CondARM32::Cond Cond) {
2951   // VMOV (immediate) - ARM section A8.8.339, encoding A2:
2952   //   vmov<c>.f64 <Dd>, #<imm>
2953   //
2954   // cccc11101D11xxxxdddd10110000yyyy where cccc=Cond, ddddD=Sn, xxxxyyyy=imm.
2955   constexpr const char *Vmovd = "vmovd";
2956   IValueT Dd = encodeSRegister(OpDd, "Dd", Vmovd);
2957   IValueT Imm8 = OpFpImm->getModifiedImm();
2958   assert(Imm8 < (1 << 8));
2959   constexpr IValueT VmovsOpcode = B23 | B21 | B20 | B8;
2960   IValueT OpcodePlusImm8 = VmovsOpcode | ((Imm8 >> 4) << 16) | (Imm8 & 0xf);
2961   constexpr IValueT D0 = 0;
2962   emitVFPddd(Cond, OpcodePlusImm8, Dd, D0, D0);
2963 }
2964 
vmovdd(const Operand * OpDd,const Variable * OpDm,CondARM32::Cond Cond)2965 void AssemblerARM32::vmovdd(const Operand *OpDd, const Variable *OpDm,
2966                             CondARM32::Cond Cond) {
2967   // VMOV (register) - ARM section A8.8.340, encoding A2:
2968   //   vmov<c>.f64 <Dd>, <Sm>
2969   //
2970   // cccc11101D110000dddd101101M0mmmm where cccc=Cond, Ddddd=Sd, and Mmmmm=Sm.
2971   constexpr const char *Vmovdd = "Vmovdd";
2972   IValueT Dd = encodeSRegister(OpDd, "Dd", Vmovdd);
2973   IValueT Dm = encodeSRegister(OpDm, "Dm", Vmovdd);
2974   constexpr IValueT VmovddOpcode = B23 | B21 | B20 | B6;
2975   constexpr IValueT D0 = 0;
2976   emitVFPddd(Cond, VmovddOpcode, Dd, D0, Dm);
2977 }
2978 
vmovdrr(const Operand * OpDm,const Operand * OpRt,const Operand * OpRt2,CondARM32::Cond Cond)2979 void AssemblerARM32::vmovdrr(const Operand *OpDm, const Operand *OpRt,
2980                              const Operand *OpRt2, CondARM32::Cond Cond) {
2981   // VMOV (between two ARM core registers and a doubleword extension register).
2982   // ARM section A8.8.345, encoding A1:
2983   //   vmov<c> <Dm>, <Rt>, <Rt2>
2984   //
2985   // cccc11000100xxxxyyyy101100M1mmmm where cccc=Cond, xxxx=Rt, yyyy=Rt2, and
2986   // Mmmmm=Dm.
2987   constexpr const char *Vmovdrr = "vmovdrr";
2988   IValueT Dm = encodeDRegister(OpDm, "Dm", Vmovdrr);
2989   IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovdrr);
2990   IValueT Rt2 = encodeGPRegister(OpRt2, "Rt", Vmovdrr);
2991   assert(Rt != RegARM32::Encoded_Reg_sp);
2992   assert(Rt != RegARM32::Encoded_Reg_pc);
2993   assert(Rt2 != RegARM32::Encoded_Reg_sp);
2994   assert(Rt2 != RegARM32::Encoded_Reg_pc);
2995   assert(Rt != Rt2);
2996   assert(CondARM32::isDefined(Cond));
2997   IValueT Encoding = B27 | B26 | B22 | B11 | B9 | B8 | B4 |
2998                      (encodeCondition(Cond) << kConditionShift) | (Rt2 << 16) |
2999                      (Rt << 12) | (getYInRegYXXXX(Dm) << 5) |
3000                      getXXXXInRegYXXXX(Dm);
3001   emitInst(Encoding);
3002 }
3003 
vmovqir(const Operand * OpQn,uint32_t Index,const Operand * OpRt,CondARM32::Cond Cond)3004 void AssemblerARM32::vmovqir(const Operand *OpQn, uint32_t Index,
3005                              const Operand *OpRt, CondARM32::Cond Cond) {
3006   // VMOV (ARM core register to scalar) - ARM section A8.8.341, encoding A1:
3007   //   vmov<c>.<size> <Dn[x]>, <Rt>
3008   constexpr const char *Vmovdr = "vmovdr";
3009   constexpr bool IsExtract = true;
3010   emitInsertExtractInt(Cond, OpQn, Index, OpRt, !IsExtract, Vmovdr);
3011 }
3012 
vmovqis(const Operand * OpQd,uint32_t Index,const Operand * OpSm,CondARM32::Cond Cond)3013 void AssemblerARM32::vmovqis(const Operand *OpQd, uint32_t Index,
3014                              const Operand *OpSm, CondARM32::Cond Cond) {
3015   constexpr const char *Vmovqis = "vmovqis";
3016   assert(Index < 4);
3017   IValueT Sd = mapQRegToSReg(encodeQRegister(OpQd, "Qd", Vmovqis)) + Index;
3018   IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovqis);
3019   emitMoveSS(Cond, Sd, Sm);
3020 }
3021 
vmovrqi(const Operand * OpRt,const Operand * OpQn,uint32_t Index,CondARM32::Cond Cond)3022 void AssemblerARM32::vmovrqi(const Operand *OpRt, const Operand *OpQn,
3023                              uint32_t Index, CondARM32::Cond Cond) {
3024   // VMOV (scalar to ARM core register) - ARM section A8.8.342, encoding A1:
3025   //   vmov<c>.<dt> <Rt>, <Dn[x]>
3026   constexpr const char *Vmovrd = "vmovrd";
3027   constexpr bool IsExtract = true;
3028   emitInsertExtractInt(Cond, OpQn, Index, OpRt, IsExtract, Vmovrd);
3029 }
3030 
vmovrrd(const Operand * OpRt,const Operand * OpRt2,const Operand * OpDm,CondARM32::Cond Cond)3031 void AssemblerARM32::vmovrrd(const Operand *OpRt, const Operand *OpRt2,
3032                              const Operand *OpDm, CondARM32::Cond Cond) {
3033   // VMOV (between two ARM core registers and a doubleword extension register).
3034   // ARM section A8.8.345, encoding A1:
3035   //   vmov<c> <Rt>, <Rt2>, <Dm>
3036   //
3037   // cccc11000101xxxxyyyy101100M1mmmm where cccc=Cond, xxxx=Rt, yyyy=Rt2, and
3038   // Mmmmm=Dm.
3039   constexpr const char *Vmovrrd = "vmovrrd";
3040   IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovrrd);
3041   IValueT Rt2 = encodeGPRegister(OpRt2, "Rt", Vmovrrd);
3042   IValueT Dm = encodeDRegister(OpDm, "Dm", Vmovrrd);
3043   assert(Rt != RegARM32::Encoded_Reg_sp);
3044   assert(Rt != RegARM32::Encoded_Reg_pc);
3045   assert(Rt2 != RegARM32::Encoded_Reg_sp);
3046   assert(Rt2 != RegARM32::Encoded_Reg_pc);
3047   assert(Rt != Rt2);
3048   assert(CondARM32::isDefined(Cond));
3049   IValueT Encoding = B27 | B26 | B22 | B20 | B11 | B9 | B8 | B4 |
3050                      (encodeCondition(Cond) << kConditionShift) | (Rt2 << 16) |
3051                      (Rt << 12) | (getYInRegYXXXX(Dm) << 5) |
3052                      getXXXXInRegYXXXX(Dm);
3053   emitInst(Encoding);
3054 }
3055 
vmovrs(const Operand * OpRt,const Operand * OpSn,CondARM32::Cond Cond)3056 void AssemblerARM32::vmovrs(const Operand *OpRt, const Operand *OpSn,
3057                             CondARM32::Cond Cond) {
3058   // VMOV (between ARM core register and single-precision register)
3059   //   ARM section A8.8.343, encoding A1.
3060   //
3061   //   vmov<c> <Rt>, <Sn>
3062   //
3063   // cccc11100001nnnntttt1010N0010000 where cccc=Cond, nnnnN = Sn, and tttt=Rt.
3064   constexpr const char *Vmovrs = "vmovrs";
3065   IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovrs);
3066   IValueT Sn = encodeSRegister(OpSn, "Sn", Vmovrs);
3067   assert(CondARM32::isDefined(Cond));
3068   IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 | B26 |
3069                      B25 | B20 | B11 | B9 | B4 | (getXXXXInRegXXXXY(Sn) << 16) |
3070                      (Rt << kRdShift) | (getYInRegXXXXY(Sn) << 7);
3071   emitInst(Encoding);
3072 }
3073 
vmovs(const Operand * OpSd,const OperandARM32FlexFpImm * OpFpImm,CondARM32::Cond Cond)3074 void AssemblerARM32::vmovs(const Operand *OpSd,
3075                            const OperandARM32FlexFpImm *OpFpImm,
3076                            CondARM32::Cond Cond) {
3077   // VMOV (immediate) - ARM section A8.8.339, encoding A2:
3078   //   vmov<c>.f32 <Sd>, #<imm>
3079   //
3080   // cccc11101D11xxxxdddd10100000yyyy where cccc=Cond, ddddD=Sn, xxxxyyyy=imm.
3081   constexpr const char *Vmovs = "vmovs";
3082   IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovs);
3083   IValueT Imm8 = OpFpImm->getModifiedImm();
3084   assert(Imm8 < (1 << 8));
3085   constexpr IValueT VmovsOpcode = B23 | B21 | B20;
3086   IValueT OpcodePlusImm8 = VmovsOpcode | ((Imm8 >> 4) << 16) | (Imm8 & 0xf);
3087   constexpr IValueT S0 = 0;
3088   emitVFPsss(Cond, OpcodePlusImm8, Sd, S0, S0);
3089 }
3090 
vmovss(const Operand * OpSd,const Variable * OpSm,CondARM32::Cond Cond)3091 void AssemblerARM32::vmovss(const Operand *OpSd, const Variable *OpSm,
3092                             CondARM32::Cond Cond) {
3093   constexpr const char *Vmovss = "Vmovss";
3094   IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovss);
3095   IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovss);
3096   emitMoveSS(Cond, Sd, Sm);
3097 }
3098 
vmovsqi(const Operand * OpSd,const Operand * OpQm,uint32_t Index,CondARM32::Cond Cond)3099 void AssemblerARM32::vmovsqi(const Operand *OpSd, const Operand *OpQm,
3100                              uint32_t Index, CondARM32::Cond Cond) {
3101   constexpr const char *Vmovsqi = "vmovsqi";
3102   const IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovsqi);
3103   assert(Index < 4);
3104   const IValueT Sm =
3105       mapQRegToSReg(encodeQRegister(OpQm, "Qm", Vmovsqi)) + Index;
3106   emitMoveSS(Cond, Sd, Sm);
3107 }
3108 
vmovsr(const Operand * OpSn,const Operand * OpRt,CondARM32::Cond Cond)3109 void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt,
3110                             CondARM32::Cond Cond) {
3111   // VMOV (between ARM core register and single-precision register)
3112   //   ARM section A8.8.343, encoding A1.
3113   //
3114   //   vmov<c> <Sn>, <Rt>
3115   //
3116   // cccc11100000nnnntttt1010N0010000 where cccc=Cond, nnnnN = Sn, and tttt=Rt.
3117   constexpr const char *Vmovsr = "vmovsr";
3118   IValueT Sn = encodeSRegister(OpSn, "Sn", Vmovsr);
3119   IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovsr);
3120   assert(Sn < RegARM32::getNumSRegs());
3121   assert(Rt < RegARM32::getNumGPRegs());
3122   assert(CondARM32::isDefined(Cond));
3123   IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 | B26 |
3124                      B25 | B11 | B9 | B4 | (getXXXXInRegXXXXY(Sn) << 16) |
3125                      (Rt << kRdShift) | (getYInRegXXXXY(Sn) << 7);
3126   emitInst(Encoding);
3127 }
3128 
vmlad(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,CondARM32::Cond Cond)3129 void AssemblerARM32::vmlad(const Operand *OpDd, const Operand *OpDn,
3130                            const Operand *OpDm, CondARM32::Cond Cond) {
3131   // VMLA, VMLS (floating-point), ARM section A8.8.337, encoding A2:
3132   //   vmla<c>.f64 <Dd>, <Dn>, <Dm>
3133   //
3134   // cccc11100d00nnnndddd1011n0M0mmmm where cccc=Cond, Ddddd=Dd, Nnnnn=Dn, and
3135   // Mmmmm=Dm
3136   constexpr const char *Vmlad = "vmlad";
3137   constexpr IValueT VmladOpcode = 0;
3138   emitVFPddd(Cond, VmladOpcode, OpDd, OpDn, OpDm, Vmlad);
3139 }
3140 
vmlas(const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,CondARM32::Cond Cond)3141 void AssemblerARM32::vmlas(const Operand *OpSd, const Operand *OpSn,
3142                            const Operand *OpSm, CondARM32::Cond Cond) {
3143   // VMLA, VMLS (floating-point), ARM section A8.8.337, encoding A2:
3144   //   vmla<c>.f32 <Sd>, <Sn>, <Sm>
3145   //
3146   // cccc11100d00nnnndddd1010n0M0mmmm where cccc=Cond, ddddD=Sd, nnnnN=Sn, and
3147   // mmmmM=Sm
3148   constexpr const char *Vmlas = "vmlas";
3149   constexpr IValueT VmlasOpcode = 0;
3150   emitVFPsss(Cond, VmlasOpcode, OpSd, OpSn, OpSm, Vmlas);
3151 }
3152 
vmlsd(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,CondARM32::Cond Cond)3153 void AssemblerARM32::vmlsd(const Operand *OpDd, const Operand *OpDn,
3154                            const Operand *OpDm, CondARM32::Cond Cond) {
3155   // VMLA, VMLS (floating-point), ARM section A8.8.337, encoding A2:
3156   //   vmls<c>.f64 <Dd>, <Dn>, <Dm>
3157   //
3158   // cccc11100d00nnnndddd1011n1M0mmmm where cccc=Cond, Ddddd=Dd, Nnnnn=Dn, and
3159   // Mmmmm=Dm
3160   constexpr const char *Vmlad = "vmlad";
3161   constexpr IValueT VmladOpcode = B6;
3162   emitVFPddd(Cond, VmladOpcode, OpDd, OpDn, OpDm, Vmlad);
3163 }
3164 
vmlss(const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,CondARM32::Cond Cond)3165 void AssemblerARM32::vmlss(const Operand *OpSd, const Operand *OpSn,
3166                            const Operand *OpSm, CondARM32::Cond Cond) {
3167   // VMLA, VMLS (floating-point), ARM section A8.8.337, encoding A2:
3168   //   vmls<c>.f32 <Sd>, <Sn>, <Sm>
3169   //
3170   // cccc11100d00nnnndddd1010n1M0mmmm where cccc=Cond, ddddD=Sd, nnnnN=Sn, and
3171   // mmmmM=Sm
3172   constexpr const char *Vmlas = "vmlas";
3173   constexpr IValueT VmlasOpcode = B6;
3174   emitVFPsss(Cond, VmlasOpcode, OpSd, OpSn, OpSm, Vmlas);
3175 }
3176 
vmrsAPSR_nzcv(CondARM32::Cond Cond)3177 void AssemblerARM32::vmrsAPSR_nzcv(CondARM32::Cond Cond) {
3178   // MVRS - ARM section A*.8.348, encoding A1:
3179   //   vmrs<c> APSR_nzcv, FPSCR
3180   //
3181   // cccc111011110001tttt101000010000 where tttt=0x15 (i.e. when Rt=pc, use
3182   // APSR_nzcv instead).
3183   assert(CondARM32::isDefined(Cond));
3184   IValueT Encoding = B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 | B15 | B14 |
3185                      B13 | B12 | B11 | B9 | B4 |
3186                      (encodeCondition(Cond) << kConditionShift);
3187   emitInst(Encoding);
3188 }
3189 
vmuls(const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,CondARM32::Cond Cond)3190 void AssemblerARM32::vmuls(const Operand *OpSd, const Operand *OpSn,
3191                            const Operand *OpSm, CondARM32::Cond Cond) {
3192   // VMUL (floating-point) - ARM section A8.8.351, encoding A2:
3193   //   vmul<c>.f32 <Sd>, <Sn>, <Sm>
3194   //
3195   // cccc11100D10nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn,
3196   // and mmmmM=Rm.
3197   constexpr const char *Vmuls = "vmuls";
3198   constexpr IValueT VmulsOpcode = B21;
3199   emitVFPsss(Cond, VmulsOpcode, OpSd, OpSn, OpSm, Vmuls);
3200 }
3201 
vmuld(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,CondARM32::Cond Cond)3202 void AssemblerARM32::vmuld(const Operand *OpDd, const Operand *OpDn,
3203                            const Operand *OpDm, CondARM32::Cond Cond) {
3204   // VMUL (floating-point) - ARM section A8.8.351, encoding A2:
3205   //   vmul<c>.f64 <Dd>, <Dn>, <Dm>
3206   //
3207   // cccc11100D10nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn,
3208   // and Mmmmm=Rm.
3209   constexpr const char *Vmuld = "vmuld";
3210   constexpr IValueT VmuldOpcode = B21;
3211   emitVFPddd(Cond, VmuldOpcode, OpDd, OpDn, OpDm, Vmuld);
3212 }
3213 
vmulqi(Type ElmtTy,const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)3214 void AssemblerARM32::vmulqi(Type ElmtTy, const Operand *OpQd,
3215                             const Operand *OpQn, const Operand *OpQm) {
3216   // VMUL, VMULL (integer and polynomial) - ARM section A8.8.350, encoding A1:
3217   //   vmul<c>.<dt> <Qd>, <Qn>, <Qm>
3218   //
3219   // 111100100Dssnnn0ddd01001NqM1mmm0 where Dddd=Qd, Nnnn=Qn, Mmmm=Qm, and
3220   // dt in [i8, i16, i32] where ss is the index.
3221   assert(isScalarIntegerType(ElmtTy) &&
3222          "vmulqi expects vector with integer element type");
3223   assert(ElmtTy != IceType_i64 && "vmulqi on i64 vector not allowed");
3224   constexpr const char *Vmulqi = "vmulqi";
3225   constexpr IValueT VmulqiOpcode = B11 | B8 | B4;
3226   emitSIMDqqq(VmulqiOpcode, ElmtTy, OpQd, OpQn, OpQm, Vmulqi);
3227 }
3228 
vmulqf(const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)3229 void AssemblerARM32::vmulqf(const Operand *OpQd, const Operand *OpQn,
3230                             const Operand *OpQm) {
3231   // VMUL (floating-point) - ARM section A8.8.351, encoding A1:
3232   //   vmul.f32 <Qd>, <Qn>, <Qm>
3233   //
3234   // 111100110D00nnn0ddd01101MqM1mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm.
3235   assert(OpQd->getType() == IceType_v4f32 && "vmulqf expects type <4 x float>");
3236   constexpr const char *Vmulqf = "vmulqf";
3237   constexpr IValueT VmulqfOpcode = B24 | B11 | B8 | B4;
3238   constexpr bool IsFloatTy = true;
3239   emitSIMDqqqBase(VmulqfOpcode, OpQd, OpQn, OpQm, IsFloatTy, Vmulqf);
3240 }
3241 
vmvnq(const Operand * OpQd,const Operand * OpQm)3242 void AssemblerARM32::vmvnq(const Operand *OpQd, const Operand *OpQm) {
3243   // VMVN (integer) - ARM section A8.8.354, encoding A1:
3244   //   vmvn <Qd>, <Qm>
3245   //
3246   // 111100111D110000dddd01011QM0mmmm where Dddd=Qd, Mmmm=Qm, and 1=Q.
3247   // TODO(jpp) xxx: unify
3248   constexpr const char *Vmvn = "vmvn";
3249   constexpr IValueT VmvnOpcode = B24 | B23 | B21 | B20 | B10 | B8 | B7;
3250   const IValueT Qd = encodeQRegister(OpQd, "Qd", Vmvn);
3251   constexpr IValueT Qn = 0;
3252   const IValueT Qm = encodeQRegister(OpQm, "Qm", Vmvn);
3253   constexpr bool UseQRegs = true;
3254   constexpr bool IsFloat = false;
3255   emitSIMDBase(VmvnOpcode, mapQRegToDReg(Qd), mapQRegToDReg(Qn),
3256                mapQRegToDReg(Qm), UseQRegs, IsFloat);
3257 }
3258 
vnegqs(Type ElmtTy,const Operand * OpQd,const Operand * OpQm)3259 void AssemblerARM32::vnegqs(Type ElmtTy, const Operand *OpQd,
3260                             const Operand *OpQm) {
3261   // VNEG - ARM section A8.8.355, encoding A1:
3262   //   vneg.<dt> <Qd>, <Qm>
3263   //
3264   // 111111111D11ss01dddd0F111QM0mmmm where Dddd=Qd, and Mmmm=Qm, and:
3265   //     * dt=s8  -> 00=ss, 0=F
3266   //     * dt=s16 -> 01=ss, 0=F
3267   //     * dt=s32 -> 10=ss, 0=F
3268   //     * dt=s32 -> 10=ss, 1=F
3269   constexpr const char *Vneg = "vneg";
3270   constexpr IValueT VnegOpcode = B24 | B23 | B21 | B20 | B16 | B9 | B8 | B7;
3271   const IValueT Qd = encodeQRegister(OpQd, "Qd", Vneg);
3272   constexpr IValueT Qn = 0;
3273   const IValueT Qm = encodeQRegister(OpQm, "Qm", Vneg);
3274   constexpr bool UseQRegs = true;
3275   constexpr IValueT ElmtShift = 18;
3276   const IValueT ElmtSize = encodeElmtType(ElmtTy);
3277   assert(Utils::IsUint(2, ElmtSize));
3278   emitSIMDBase(VnegOpcode | (ElmtSize << ElmtShift), mapQRegToDReg(Qd),
3279                mapQRegToDReg(Qn), mapQRegToDReg(Qm), UseQRegs,
3280                isFloatingType(ElmtTy));
3281 }
3282 
vorrq(const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)3283 void AssemblerARM32::vorrq(const Operand *OpQd, const Operand *OpQm,
3284                            const Operand *OpQn) {
3285   // VORR (register) - ARM section A8.8.360, encoding A1:
3286   //   vorr <Qd>, <Qn>, <Qm>
3287   //
3288   // 111100100D10nnn0ddd00001N1M1mmm0 where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm.
3289   constexpr const char *Vorrq = "vorrq";
3290   constexpr IValueT VorrqOpcode = B21 | B8 | B4;
3291   constexpr Type ElmtTy = IceType_i8;
3292   emitSIMDqqq(VorrqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vorrq);
3293 }
3294 
vstrd(const Operand * OpDd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)3295 void AssemblerARM32::vstrd(const Operand *OpDd, const Operand *OpAddress,
3296                            CondARM32::Cond Cond, const TargetInfo &TInfo) {
3297   // VSTR - ARM section A8.8.413, encoding A1:
3298   //   vstr<c> <Dd>, [<Rn>{, #+/-<Imm>}]
3299   //
3300   // cccc1101UD00nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd,
3301   // iiiiiiii=abs(Imm >> 2), and U=1 if Imm>=0.
3302   constexpr const char *Vstrd = "vstrd";
3303   IValueT Dd = encodeDRegister(OpDd, "Dd", Vstrd);
3304   assert(CondARM32::isDefined(Cond));
3305   IValueT Address;
3306   IValueT AddressEncoding =
3307       encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address);
3308   (void)AddressEncoding;
3309   assert(AddressEncoding == EncodedAsImmRegOffset);
3310   IValueT Encoding = B27 | B26 | B24 | B11 | B9 | B8 |
3311                      (encodeCondition(Cond) << kConditionShift) |
3312                      (getYInRegYXXXX(Dd) << 22) |
3313                      (getXXXXInRegYXXXX(Dd) << 12) | Address;
3314   emitInst(Encoding);
3315 }
3316 
vstrs(const Operand * OpSd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)3317 void AssemblerARM32::vstrs(const Operand *OpSd, const Operand *OpAddress,
3318                            CondARM32::Cond Cond, const TargetInfo &TInfo) {
3319   // VSTR - ARM section A8.8.413, encoding A2:
3320   //   vstr<c> <Sd>, [<Rn>{, #+/-<imm>]]
3321   //
3322   // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd,
3323   // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0;
3324   constexpr const char *Vstrs = "vstrs";
3325   IValueT Sd = encodeSRegister(OpSd, "Sd", Vstrs);
3326   assert(CondARM32::isDefined(Cond));
3327   IValueT Address;
3328   IValueT AddressEncoding =
3329       encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address);
3330   (void)AddressEncoding;
3331   assert(AddressEncoding == EncodedAsImmRegOffset);
3332   IValueT Encoding =
3333       B27 | B26 | B24 | B11 | B9 | (encodeCondition(Cond) << kConditionShift) |
3334       (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) | Address;
3335   emitInst(Encoding);
3336 }
3337 
vst1qr(size_t ElmtSize,const Operand * OpQd,const Operand * OpAddress,const TargetInfo & TInfo)3338 void AssemblerARM32::vst1qr(size_t ElmtSize, const Operand *OpQd,
3339                             const Operand *OpAddress, const TargetInfo &TInfo) {
3340   // VST1 (multiple single elements) - ARM section A8.8.404, encoding A1:
3341   //   vst1.<size> <Qd>, [<Rn>]
3342   //
3343   // 111101000D00nnnnddd0ttttssaammmm where tttt=DRegListSize2, Dddd=Qd,
3344   // nnnn=Rn, aa=0 (use default alignment), size=ElmtSize, and ss is the
3345   // encoding of ElmtSize.
3346   constexpr const char *Vst1qr = "vst1qr";
3347   const IValueT Qd = encodeQRegister(OpQd, "Qd", Vst1qr);
3348   const IValueT Dd = mapQRegToDReg(Qd);
3349   IValueT Address;
3350   if (encodeAddress(OpAddress, Address, TInfo, NoImmOffsetAddress) !=
3351       EncodedAsImmRegOffset)
3352     llvm::report_fatal_error(std::string(Vst1qr) + ": malform memory address");
3353   const IValueT Rn = mask(Address, kRnShift, 4);
3354   constexpr IValueT Rm = RegARM32::Reg_pc;
3355   constexpr IValueT Opcode = B26;
3356   constexpr IValueT Align = 0; // use default alignment.
3357   emitVMem1Op(Opcode, Dd, Rn, Rm, DRegListSize2, ElmtSize, Align, Vst1qr);
3358 }
3359 
vsubs(const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,CondARM32::Cond Cond)3360 void AssemblerARM32::vsubs(const Operand *OpSd, const Operand *OpSn,
3361                            const Operand *OpSm, CondARM32::Cond Cond) {
3362   // VSUB (floating-point) - ARM section A8.8.415, encoding A2:
3363   //   vsub<c>.f32 <Sd>, <Sn>, <Sm>
3364   //
3365   // cccc11100D11nnnndddd101sN1M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn,
3366   // and mmmmM=Rm.
3367   constexpr const char *Vsubs = "vsubs";
3368   constexpr IValueT VsubsOpcode = B21 | B20 | B6;
3369   emitVFPsss(Cond, VsubsOpcode, OpSd, OpSn, OpSm, Vsubs);
3370 }
3371 
vsubd(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,CondARM32::Cond Cond)3372 void AssemblerARM32::vsubd(const Operand *OpDd, const Operand *OpDn,
3373                            const Operand *OpDm, CondARM32::Cond Cond) {
3374   // VSUB (floating-point) - ARM section A8.8.415, encoding A2:
3375   //   vsub<c>.f64 <Dd>, <Dn>, <Dm>
3376   //
3377   // cccc11100D11nnnndddd101sN1M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn,
3378   // and Mmmmm=Rm.
3379   constexpr const char *Vsubd = "vsubd";
3380   constexpr IValueT VsubdOpcode = B21 | B20 | B6;
3381   emitVFPddd(Cond, VsubdOpcode, OpDd, OpDn, OpDm, Vsubd);
3382 }
3383 
vsubqi(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)3384 void AssemblerARM32::vsubqi(Type ElmtTy, const Operand *OpQd,
3385                             const Operand *OpQm, const Operand *OpQn) {
3386   // VSUB (integer) - ARM section A8.8.414, encoding A1:
3387   //   vsub.<dt> <Qd>, <Qn>, <Qm>
3388   //
3389   // 111100110Dssnnn0ddd01000N1M0mmm0 where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm,
3390   // and dt in [i8, i16, i32, i64] where ss is the index.
3391   assert(isScalarIntegerType(ElmtTy) &&
3392          "vsubqi expects vector with integer element type");
3393   constexpr const char *Vsubqi = "vsubqi";
3394   constexpr IValueT VsubqiOpcode = B24 | B11;
3395   emitSIMDqqq(VsubqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vsubqi);
3396 }
3397 
vsubqf(const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)3398 void AssemblerARM32::vsubqf(const Operand *OpQd, const Operand *OpQn,
3399                             const Operand *OpQm) {
3400   // VSUB (floating-point) - ARM section A8.8.415, Encoding A1:
3401   //   vsub.f32 <Qd>, <Qn>, <Qm>
3402   //
3403   // 111100100D10nnn0ddd01101N1M0mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm.
3404   assert(OpQd->getType() == IceType_v4f32 && "vsubqf expects type <4 x float>");
3405   constexpr const char *Vsubqf = "vsubqf";
3406   constexpr IValueT VsubqfOpcode = B21 | B11 | B8;
3407   emitSIMDqqq(VsubqfOpcode, IceType_f32, OpQd, OpQn, OpQm, Vsubqf);
3408 }
3409 
emitVStackOp(CondARM32::Cond Cond,IValueT Opcode,const Variable * OpBaseReg,SizeT NumConsecRegs)3410 void AssemblerARM32::emitVStackOp(CondARM32::Cond Cond, IValueT Opcode,
3411                                   const Variable *OpBaseReg,
3412                                   SizeT NumConsecRegs) {
3413   const IValueT BaseReg = getEncodedSRegNum(OpBaseReg);
3414   const IValueT DLastBit = mask(BaseReg, 0, 1); // Last bit of base register.
3415   const IValueT Rd = mask(BaseReg, 1, 4);       // Top 4 bits of base register.
3416   assert(0 < NumConsecRegs);
3417   (void)VpushVpopMaxConsecRegs;
3418   assert(NumConsecRegs <= VpushVpopMaxConsecRegs);
3419   assert((BaseReg + NumConsecRegs) <= RegARM32::getNumSRegs());
3420   assert(CondARM32::isDefined(Cond));
3421   const IValueT Encoding = Opcode | (Cond << kConditionShift) | DLastBit |
3422                            (Rd << kRdShift) | NumConsecRegs;
3423   emitInst(Encoding);
3424 }
3425 
vpop(const Variable * OpBaseReg,SizeT NumConsecRegs,CondARM32::Cond Cond)3426 void AssemblerARM32::vpop(const Variable *OpBaseReg, SizeT NumConsecRegs,
3427                           CondARM32::Cond Cond) {
3428   // Note: Current implementation assumes that OpBaseReg is defined using S
3429   // registers. It doesn't implement the D register form.
3430   //
3431   // VPOP - ARM section A8.8.367, encoding A2:
3432   //  vpop<c> <RegList>
3433   //
3434   // cccc11001D111101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and
3435   // iiiiiiii=NumConsecRegs.
3436   constexpr IValueT VpopOpcode =
3437       B27 | B26 | B23 | B21 | B20 | B19 | B18 | B16 | B11 | B9;
3438   emitVStackOp(Cond, VpopOpcode, OpBaseReg, NumConsecRegs);
3439 }
3440 
vpush(const Variable * OpBaseReg,SizeT NumConsecRegs,CondARM32::Cond Cond)3441 void AssemblerARM32::vpush(const Variable *OpBaseReg, SizeT NumConsecRegs,
3442                            CondARM32::Cond Cond) {
3443   // Note: Current implementation assumes that OpBaseReg is defined using S
3444   // registers. It doesn't implement the D register form.
3445   //
3446   // VPUSH - ARM section A8.8.368, encoding A2:
3447   //   vpush<c> <RegList>
3448   //
3449   // cccc11010D101101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and
3450   // iiiiiiii=NumConsecRegs.
3451   constexpr IValueT VpushOpcode =
3452       B27 | B26 | B24 | B21 | B19 | B18 | B16 | B11 | B9;
3453   emitVStackOp(Cond, VpushOpcode, OpBaseReg, NumConsecRegs);
3454 }
3455 
vshlqi(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)3456 void AssemblerARM32::vshlqi(Type ElmtTy, const Operand *OpQd,
3457                             const Operand *OpQm, const Operand *OpQn) {
3458   // VSHL - ARM section A8.8.396, encoding A1:
3459   //   vshl Qd, Qm, Qn
3460   //
3461   // 1111001U0Dssnnnndddd0100NQM0mmmm where Ddddd=Qd, Mmmmm=Qm, Nnnnn=Qn, 0=U,
3462   // 1=Q
3463   assert(isScalarIntegerType(ElmtTy) &&
3464          "vshl expects vector with integer element type");
3465   constexpr const char *Vshl = "vshl";
3466   constexpr IValueT VshlOpcode = B10 | B6;
3467   emitSIMDqqq(VshlOpcode, ElmtTy, OpQd, OpQn, OpQm, Vshl);
3468 }
3469 
3470 namespace {
3471 enum SIMDShiftType { ST_Vshl, ST_Vshr };
encodeSIMDShiftImm6(SIMDShiftType Shift,Type ElmtTy,const ConstantInteger32 * Imm6)3472 IValueT encodeSIMDShiftImm6(SIMDShiftType Shift, Type ElmtTy,
3473                             const ConstantInteger32 *Imm6) {
3474   const IValueT Imm = Imm6->getValue();
3475   assert(Imm > 0);
3476   const SizeT MaxShift = getScalarIntBitWidth(ElmtTy);
3477   assert(Imm < MaxShift);
3478   assert(ElmtTy == IceType_i8 || ElmtTy == IceType_i16 ||
3479          ElmtTy == IceType_i32);
3480   const IValueT VshlImm = Imm - MaxShift;
3481   const IValueT VshrImm = 2 * MaxShift - Imm;
3482   return ((Shift == ST_Vshl) ? VshlImm : VshrImm) & (2 * MaxShift - 1);
3483 }
3484 } // end of anonymous namespace
3485 
vshlqc(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const ConstantInteger32 * Imm6)3486 void AssemblerARM32::vshlqc(Type ElmtTy, const Operand *OpQd,
3487                             const Operand *OpQm,
3488                             const ConstantInteger32 *Imm6) {
3489   // VSHL - ARM section A8.8.395, encoding A1:
3490   //   vshl Qd, Qm, #Imm
3491   //
3492   // 1111001U1Diiiiiidddd0101LQM1mmmm where Ddddd=Qd, Mmmmm=Qm, iiiiii=Imm6,
3493   // 0=U, 1=Q, 0=L.
3494   assert(isScalarIntegerType(ElmtTy) &&
3495          "vshl expects vector with integer element type");
3496   constexpr const char *Vshl = "vshl";
3497   constexpr IValueT VshlOpcode = B23 | B10 | B8 | B4;
3498   emitSIMDShiftqqc(VshlOpcode, OpQd, OpQm,
3499                    encodeSIMDShiftImm6(ST_Vshl, ElmtTy, Imm6), Vshl);
3500 }
3501 
vshrqic(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const ConstantInteger32 * Imm6)3502 void AssemblerARM32::vshrqic(Type ElmtTy, const Operand *OpQd,
3503                              const Operand *OpQm,
3504                              const ConstantInteger32 *Imm6) {
3505   // VSHR - ARM section A8.8.398, encoding A1:
3506   //   vshr Qd, Qm, #Imm
3507   //
3508   // 1111001U1Diiiiiidddd0101LQM1mmmm where Ddddd=Qd, Mmmmm=Qm, iiiiii=Imm6,
3509   // 0=U, 1=Q, 0=L.
3510   assert(isScalarIntegerType(ElmtTy) &&
3511          "vshr expects vector with integer element type");
3512   constexpr const char *Vshr = "vshr";
3513   constexpr IValueT VshrOpcode = B23 | B4;
3514   emitSIMDShiftqqc(VshrOpcode, OpQd, OpQm,
3515                    encodeSIMDShiftImm6(ST_Vshr, ElmtTy, Imm6), Vshr);
3516 }
3517 
vshrquc(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const ConstantInteger32 * Imm6)3518 void AssemblerARM32::vshrquc(Type ElmtTy, const Operand *OpQd,
3519                              const Operand *OpQm,
3520                              const ConstantInteger32 *Imm6) {
3521   // VSHR - ARM section A8.8.398, encoding A1:
3522   //   vshr Qd, Qm, #Imm
3523   //
3524   // 1111001U1Diiiiiidddd0101LQM1mmmm where Ddddd=Qd, Mmmmm=Qm, iiiiii=Imm6,
3525   // 0=U, 1=Q, 0=L.
3526   assert(isScalarIntegerType(ElmtTy) &&
3527          "vshr expects vector with integer element type");
3528   constexpr const char *Vshr = "vshr";
3529   constexpr IValueT VshrOpcode = B23 | B4;
3530   emitSIMDShiftqqc(VshrOpcode, OpQd, OpQm,
3531                    encodeSIMDShiftImm6(ST_Vshr, ElmtTy, Imm6), Vshr);
3532 }
3533 
vshlqu(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)3534 void AssemblerARM32::vshlqu(Type ElmtTy, const Operand *OpQd,
3535                             const Operand *OpQm, const Operand *OpQn) {
3536   // VSHL - ARM section A8.8.396, encoding A1:
3537   //   vshl Qd, Qm, Qn
3538   //
3539   // 1111001U0Dssnnnndddd0100NQM0mmmm where Ddddd=Qd, Mmmmm=Qm, Nnnnn=Qn, 1=U,
3540   // 1=Q
3541   assert(isScalarIntegerType(ElmtTy) &&
3542          "vshl expects vector with integer element type");
3543   constexpr const char *Vshl = "vshl";
3544   constexpr IValueT VshlOpcode = B24 | B10 | B6;
3545   emitSIMDqqq(VshlOpcode, ElmtTy, OpQd, OpQn, OpQm, Vshl);
3546 }
3547 
vsqrtd(const Operand * OpDd,const Operand * OpDm,CondARM32::Cond Cond)3548 void AssemblerARM32::vsqrtd(const Operand *OpDd, const Operand *OpDm,
3549                             CondARM32::Cond Cond) {
3550   // VSQRT - ARM section A8.8.401, encoding A1:
3551   //   vsqrt<c>.f64 <Dd>, <Dm>
3552   //
3553   // cccc11101D110001dddd101111M0mmmm where cccc=Cond, Ddddd=Sd, and Mmmmm=Sm.
3554   constexpr const char *Vsqrtd = "vsqrtd";
3555   IValueT Dd = encodeDRegister(OpDd, "Dd", Vsqrtd);
3556   IValueT Dm = encodeDRegister(OpDm, "Dm", Vsqrtd);
3557   constexpr IValueT VsqrtdOpcode = B23 | B21 | B20 | B16 | B7 | B6;
3558   constexpr IValueT D0 = 0;
3559   emitVFPddd(Cond, VsqrtdOpcode, Dd, D0, Dm);
3560 }
3561 
vsqrts(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)3562 void AssemblerARM32::vsqrts(const Operand *OpSd, const Operand *OpSm,
3563                             CondARM32::Cond Cond) {
3564   // VSQRT - ARM section A8.8.401, encoding A1:
3565   //   vsqrt<c>.f32 <Sd>, <Sm>
3566   //
3567   // cccc11101D110001dddd101011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
3568   constexpr const char *Vsqrts = "vsqrts";
3569   IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts);
3570   IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts);
3571   constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6;
3572   constexpr IValueT S0 = 0;
3573   emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm);
3574 }
3575 
3576 } // end of namespace ARM32
3577 } // end of namespace Ice
3578