• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===//
2 //
3 //                        The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Implements the InstARM32 and OperandARM32 classes, primarily the
12 /// constructors and the dump()/emit() methods.
13 ///
14 //===----------------------------------------------------------------------===//
15 
16 #include "IceInstARM32.h"
17 
18 #include "IceAssemblerARM32.h"
19 #include "IceCfg.h"
20 #include "IceCfgNode.h"
21 #include "IceInst.h"
22 #include "IceOperand.h"
23 #include "IceTargetLoweringARM32.h"
24 
25 namespace Ice {
26 namespace ARM32 {
27 
28 namespace {
29 
30 using Register = RegARM32::AllRegisters;
31 
32 // maximum number of registers allowed in vpush/vpop.
33 static constexpr SizeT VpushVpopMaxConsecRegs = 16;
34 
35 const struct TypeARM32Attributes_ {
36   const char *WidthString;     // b, h, <blank>, or d
37   const char *FpWidthString;   // i8, i16, i32, f32, f64
38   const char *SVecWidthString; // s8, s16, s32, f32
39   const char *UVecWidthString; // u8, u16, u32, f32
40   int8_t SExtAddrOffsetBits;
41   int8_t ZExtAddrOffsetBits;
42 } TypeARM32Attributes[] = {
43 #define X(tag, elementty, int_width, fp_width, uvec_width, svec_width, sbits,  \
44           ubits, rraddr, shaddr)                                               \
45   { int_width, fp_width, svec_width, uvec_width, sbits, ubits }                \
46   ,
47     ICETYPEARM32_TABLE
48 #undef X
49 };
50 
51 const struct InstARM32ShiftAttributes_ {
52   const char *EmitString;
53 } InstARM32ShiftAttributes[] = {
54 #define X(tag, emit)                                                           \
55   { emit }                                                                     \
56   ,
57     ICEINSTARM32SHIFT_TABLE
58 #undef X
59 };
60 
61 const struct InstARM32CondAttributes_ {
62   CondARM32::Cond Opposite;
63   const char *EmitString;
64 } InstARM32CondAttributes[] = {
65 #define X(tag, encode, opp, emit)                                              \
66   { CondARM32::opp, emit }                                                     \
67   ,
68     ICEINSTARM32COND_TABLE
69 #undef X
70 };
71 
getVecElmtBitsize(Type Ty)72 size_t getVecElmtBitsize(Type Ty) {
73   return typeWidthInBytes(typeElementType(Ty)) * CHAR_BIT;
74 }
75 
getWidthString(Type Ty)76 const char *getWidthString(Type Ty) {
77   return TypeARM32Attributes[Ty].WidthString;
78 }
79 
getFpWidthString(Type Ty)80 const char *getFpWidthString(Type Ty) {
81   return TypeARM32Attributes[Ty].FpWidthString;
82 }
83 
getSVecWidthString(Type Ty)84 const char *getSVecWidthString(Type Ty) {
85   return TypeARM32Attributes[Ty].SVecWidthString;
86 }
87 
getUVecWidthString(Type Ty)88 const char *getUVecWidthString(Type Ty) {
89   return TypeARM32Attributes[Ty].UVecWidthString;
90 }
91 
getVWidthString(Type Ty,InstARM32::FPSign SignType)92 const char *getVWidthString(Type Ty, InstARM32::FPSign SignType) {
93   switch (SignType) {
94   case InstARM32::FS_None:
95     return getFpWidthString(Ty);
96   case InstARM32::FS_Signed:
97     return getSVecWidthString(Ty);
98   case InstARM32::FS_Unsigned:
99     return getUVecWidthString(Ty);
100   }
101   llvm_unreachable("Invalid Sign Type.");
102   return getFpWidthString(Ty);
103 }
104 
105 } // end of anonymous namespace
106 
predString(CondARM32::Cond Pred)107 const char *InstARM32Pred::predString(CondARM32::Cond Pred) {
108   return InstARM32CondAttributes[Pred].EmitString;
109 }
110 
dumpOpcodePred(Ostream & Str,const char * Opcode,Type Ty) const111 void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode,
112                                    Type Ty) const {
113   Str << Opcode << getPredicate() << "." << Ty;
114 }
115 
getOppositeCondition(CondARM32::Cond Cond)116 CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) {
117   return InstARM32CondAttributes[Cond].Opposite;
118 }
119 
startNextInst(const Cfg * Func) const120 void InstARM32::startNextInst(const Cfg *Func) const {
121   if (auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>())
122     Asm->incEmitTextSize(InstSize);
123 }
124 
emitUsingTextFixup(const Cfg * Func) const125 void InstARM32::emitUsingTextFixup(const Cfg *Func) const {
126   if (!BuildDefs::dump())
127     return;
128   GlobalContext *Ctx = Func->getContext();
129   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
130   if (getFlags().getDisableHybridAssembly() &&
131       getFlags().getSkipUnimplemented()) {
132     Asm->trap();
133     Asm->resetNeedsTextFixup();
134     return;
135   }
136   std::string Buffer;
137   llvm::raw_string_ostream StrBuf(Buffer);
138   OstreamLocker L(Ctx);
139   Ostream &OldStr = Ctx->getStrEmit();
140   Ctx->setStrEmit(StrBuf);
141   // Start counting instructions here, so that emit() methods don't
142   // need to call this for the first instruction.
143   Asm->resetEmitTextSize();
144   Asm->incEmitTextSize(InstSize);
145   emit(Func);
146   Ctx->setStrEmit(OldStr);
147   if (getFlags().getDisableHybridAssembly()) {
148     if (getFlags().getSkipUnimplemented()) {
149       Asm->trap();
150     } else {
151       llvm::errs() << "Can't assemble: " << StrBuf.str() << "\n";
152       UnimplementedError(getFlags());
153     }
154     Asm->resetNeedsTextFixup();
155     return;
156   }
157   Asm->emitTextInst(StrBuf.str(), Asm->getEmitTextSize());
158 }
159 
emitIAS(const Cfg * Func) const160 void InstARM32::emitIAS(const Cfg *Func) const { emitUsingTextFixup(Func); }
161 
emitUnaryopGPR(const char * Opcode,const InstARM32Pred * Instr,const Cfg * Func,bool NeedsWidthSuffix)162 void InstARM32Pred::emitUnaryopGPR(const char *Opcode,
163                                    const InstARM32Pred *Instr, const Cfg *Func,
164                                    bool NeedsWidthSuffix) {
165   Ostream &Str = Func->getContext()->getStrEmit();
166   assert(Instr->getSrcSize() == 1);
167   Type SrcTy = Instr->getSrc(0)->getType();
168   Str << "\t" << Opcode;
169   if (NeedsWidthSuffix)
170     Str << getWidthString(SrcTy);
171   Str << Instr->getPredicate() << "\t";
172   Instr->getDest()->emit(Func);
173   Str << ", ";
174   Instr->getSrc(0)->emit(Func);
175 }
176 
emitUnaryopFP(const char * Opcode,FPSign Sign,const InstARM32Pred * Instr,const Cfg * Func)177 void InstARM32Pred::emitUnaryopFP(const char *Opcode, FPSign Sign,
178                                   const InstARM32Pred *Instr, const Cfg *Func) {
179   Ostream &Str = Func->getContext()->getStrEmit();
180   assert(Instr->getSrcSize() == 1);
181   Type SrcTy = Instr->getSrc(0)->getType();
182   Str << "\t" << Opcode << Instr->getPredicate();
183   switch (Sign) {
184   case FS_None:
185     Str << getFpWidthString(SrcTy);
186     break;
187   case FS_Signed:
188     Str << getSVecWidthString(SrcTy);
189     break;
190   case FS_Unsigned:
191     Str << getUVecWidthString(SrcTy);
192     break;
193   }
194   Str << "\t";
195   Instr->getDest()->emit(Func);
196   Str << ", ";
197   Instr->getSrc(0)->emit(Func);
198 }
199 
emitTwoAddr(const char * Opcode,const InstARM32Pred * Instr,const Cfg * Func)200 void InstARM32Pred::emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr,
201                                 const Cfg *Func) {
202   if (!BuildDefs::dump())
203     return;
204   Ostream &Str = Func->getContext()->getStrEmit();
205   assert(Instr->getSrcSize() == 2);
206   Variable *Dest = Instr->getDest();
207   assert(Dest == Instr->getSrc(0));
208   Str << "\t" << Opcode << Instr->getPredicate() << "\t";
209   Dest->emit(Func);
210   Str << ", ";
211   Instr->getSrc(1)->emit(Func);
212 }
213 
emitThreeAddr(const char * Opcode,const InstARM32Pred * Instr,const Cfg * Func,bool SetFlags)214 void InstARM32Pred::emitThreeAddr(const char *Opcode,
215                                   const InstARM32Pred *Instr, const Cfg *Func,
216                                   bool SetFlags) {
217   if (!BuildDefs::dump())
218     return;
219   Ostream &Str = Func->getContext()->getStrEmit();
220   assert(Instr->getSrcSize() == 2);
221   Str << "\t" << Opcode << (SetFlags ? "s" : "") << Instr->getPredicate()
222       << "\t";
223   Instr->getDest()->emit(Func);
224   Str << ", ";
225   Instr->getSrc(0)->emit(Func);
226   Str << ", ";
227   Instr->getSrc(1)->emit(Func);
228 }
229 
emitThreeAddrFP(const char * Opcode,FPSign SignType,const InstARM32 * Instr,const Cfg * Func,Type OpType)230 void InstARM32::emitThreeAddrFP(const char *Opcode, FPSign SignType,
231                                 const InstARM32 *Instr, const Cfg *Func,
232                                 Type OpType) {
233   if (!BuildDefs::dump())
234     return;
235   Ostream &Str = Func->getContext()->getStrEmit();
236   assert(Instr->getSrcSize() == 2);
237   Str << "\t" << Opcode << getVWidthString(OpType, SignType) << "\t";
238   Instr->getDest()->emit(Func);
239   Str << ", ";
240   Instr->getSrc(0)->emit(Func);
241   Str << ", ";
242   Instr->getSrc(1)->emit(Func);
243 }
244 
emitFourAddrFP(const char * Opcode,FPSign SignType,const InstARM32 * Instr,const Cfg * Func)245 void InstARM32::emitFourAddrFP(const char *Opcode, FPSign SignType,
246                                const InstARM32 *Instr, const Cfg *Func) {
247   if (!BuildDefs::dump())
248     return;
249   Ostream &Str = Func->getContext()->getStrEmit();
250   assert(Instr->getSrcSize() == 3);
251   assert(Instr->getSrc(0) == Instr->getDest());
252   Str << "\t" << Opcode
253       << getVWidthString(Instr->getDest()->getType(), SignType) << "\t";
254   Instr->getDest()->emit(Func);
255   Str << ", ";
256   Instr->getSrc(1)->emit(Func);
257   Str << ", ";
258   Instr->getSrc(2)->emit(Func);
259 }
260 
emitFourAddr(const char * Opcode,const InstARM32Pred * Instr,const Cfg * Func)261 void InstARM32Pred::emitFourAddr(const char *Opcode, const InstARM32Pred *Instr,
262                                  const Cfg *Func) {
263   if (!BuildDefs::dump())
264     return;
265   Ostream &Str = Func->getContext()->getStrEmit();
266   assert(Instr->getSrcSize() == 3);
267   Str << "\t" << Opcode << Instr->getPredicate() << "\t";
268   Instr->getDest()->emit(Func);
269   Str << ", ";
270   Instr->getSrc(0)->emit(Func);
271   Str << ", ";
272   Instr->getSrc(1)->emit(Func);
273   Str << ", ";
274   Instr->getSrc(2)->emit(Func);
275 }
276 
277 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const278 void InstARM32FourAddrGPR<K>::emitIAS(const Cfg *Func) const {
279   emitUsingTextFixup(Func);
280 }
281 
282 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const283 void InstARM32FourAddrFP<K>::emitIAS(const Cfg *Func) const {
284   emitUsingTextFixup(Func);
285 }
286 
287 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const288 void InstARM32ThreeAddrFP<K>::emitIAS(const Cfg *Func) const {
289   emitUsingTextFixup(Func);
290 }
291 
292 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const293 void InstARM32ThreeAddrSignAwareFP<K>::emitIAS(const Cfg *Func) const {
294   InstARM32::emitUsingTextFixup(Func);
295 }
296 
emitIAS(const Cfg * Func) const297 template <> void InstARM32Mla::emitIAS(const Cfg *Func) const {
298   assert(getSrcSize() == 3);
299   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
300   Asm->mla(getDest(), getSrc(0), getSrc(1), getSrc(2), getPredicate());
301   if (Asm->needsTextFixup())
302     emitUsingTextFixup(Func);
303 }
304 
emitIAS(const Cfg * Func) const305 template <> void InstARM32Mls::emitIAS(const Cfg *Func) const {
306   assert(getSrcSize() == 3);
307   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
308   Asm->mls(getDest(), getSrc(0), getSrc(1), getSrc(2), getPredicate());
309   if (Asm->needsTextFixup())
310     emitUsingTextFixup(Func);
311 }
312 
emitCmpLike(const char * Opcode,const InstARM32Pred * Instr,const Cfg * Func)313 void InstARM32Pred::emitCmpLike(const char *Opcode, const InstARM32Pred *Instr,
314                                 const Cfg *Func) {
315   if (!BuildDefs::dump())
316     return;
317   Ostream &Str = Func->getContext()->getStrEmit();
318   assert(Instr->getSrcSize() == 2);
319   Str << "\t" << Opcode << Instr->getPredicate() << "\t";
320   Instr->getSrc(0)->emit(Func);
321   Str << ", ";
322   Instr->getSrc(1)->emit(Func);
323 }
324 
OperandARM32Mem(Cfg *,Type Ty,Variable * Base,ConstantInteger32 * ImmOffset,AddrMode Mode)325 OperandARM32Mem::OperandARM32Mem(Cfg * /* Func */, Type Ty, Variable *Base,
326                                  ConstantInteger32 *ImmOffset, AddrMode Mode)
327     : OperandARM32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Index(nullptr),
328       ShiftOp(kNoShift), ShiftAmt(0), Mode(Mode) {
329   // The Neg modes are only needed for Reg +/- Reg.
330   assert(!isNegAddrMode());
331   NumVars = 1;
332   Vars = &this->Base;
333 }
334 
OperandARM32Mem(Cfg * Func,Type Ty,Variable * Base,Variable * Index,ShiftKind ShiftOp,uint16_t ShiftAmt,AddrMode Mode)335 OperandARM32Mem::OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
336                                  Variable *Index, ShiftKind ShiftOp,
337                                  uint16_t ShiftAmt, AddrMode Mode)
338     : OperandARM32(kMem, Ty), Base(Base), ImmOffset(0), Index(Index),
339       ShiftOp(ShiftOp), ShiftAmt(ShiftAmt), Mode(Mode) {
340   if (Index->isRematerializable()) {
341     llvm::report_fatal_error("Rematerializable Index Register is not allowed.");
342   }
343   NumVars = 2;
344   Vars = Func->allocateArrayOf<Variable *>(2);
345   Vars[0] = Base;
346   Vars[1] = Index;
347 }
348 
OperandARM32ShAmtImm(ConstantInteger32 * SA)349 OperandARM32ShAmtImm::OperandARM32ShAmtImm(ConstantInteger32 *SA)
350     : OperandARM32(kShAmtImm, IceType_i8), ShAmt(SA) {}
351 
canHoldOffset(Type Ty,bool SignExt,int32_t Offset)352 bool OperandARM32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) {
353   int32_t Bits = SignExt ? TypeARM32Attributes[Ty].SExtAddrOffsetBits
354                          : TypeARM32Attributes[Ty].ZExtAddrOffsetBits;
355   if (Bits == 0)
356     return Offset == 0;
357   // Note that encodings for offsets are sign-magnitude for ARM, so we check
358   // with IsAbsoluteUint().
359   // Scalar fp, and vector types require an offset that is aligned to a multiple
360   // of 4.
361   if (isScalarFloatingType(Ty) || isVectorType(Ty))
362     return Utils::IsAligned(Offset, 4) && Utils::IsAbsoluteUint(Bits, Offset);
363   return Utils::IsAbsoluteUint(Bits, Offset);
364 }
365 
OperandARM32FlexImm(Cfg *,Type Ty,uint32_t Imm,uint32_t RotateAmt)366 OperandARM32FlexImm::OperandARM32FlexImm(Cfg * /* Func */, Type Ty,
367                                          uint32_t Imm, uint32_t RotateAmt)
368     : OperandARM32Flex(kFlexImm, Ty), Imm(Imm), RotateAmt(RotateAmt) {
369   NumVars = 0;
370   Vars = nullptr;
371 }
372 
canHoldImm(uint32_t Immediate,uint32_t * RotateAmt,uint32_t * Immed_8)373 bool OperandARM32FlexImm::canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
374                                      uint32_t *Immed_8) {
375   // Avoid the more expensive test for frequent small immediate values.
376   if (Immediate <= 0xFF) {
377     *RotateAmt = 0;
378     *Immed_8 = Immediate;
379     return true;
380   }
381   // Note that immediate must be unsigned for the test to work correctly.
382   for (int Rot = 1; Rot < 16; Rot++) {
383     uint32_t Imm8 = Utils::rotateLeft32(Immediate, 2 * Rot);
384     if (Imm8 <= 0xFF) {
385       *RotateAmt = Rot;
386       *Immed_8 = Imm8;
387       return true;
388     }
389   }
390   return false;
391 }
392 
OperandARM32FlexFpImm(Cfg *,Type Ty,uint32_t ModifiedImm)393 OperandARM32FlexFpImm::OperandARM32FlexFpImm(Cfg * /*Func*/, Type Ty,
394                                              uint32_t ModifiedImm)
395     : OperandARM32Flex(kFlexFpImm, Ty), ModifiedImm(ModifiedImm) {}
396 
canHoldImm(const Operand * C,uint32_t * ModifiedImm)397 bool OperandARM32FlexFpImm::canHoldImm(const Operand *C,
398                                        uint32_t *ModifiedImm) {
399   switch (C->getType()) {
400   default:
401     llvm::report_fatal_error("Unhandled fp constant type.");
402   case IceType_f32: {
403     // We violate llvm naming conventions a bit here so that the constants are
404     // named after the bit fields they represent. See "A7.5.1 Operation of
405     // modified immediate constants, Floating-point" in the ARM ARM.
406     static constexpr uint32_t a = 0x80000000u;
407     static constexpr uint32_t B = 0x40000000;
408     static constexpr uint32_t bbbbb = 0x3E000000;
409     static constexpr uint32_t cdefgh = 0x01F80000;
410     static constexpr uint32_t AllowedBits = a | B | bbbbb | cdefgh;
411     static_assert(AllowedBits == 0xFFF80000u,
412                   "Invalid mask for f32 modified immediates.");
413     const float F32 = llvm::cast<const ConstantFloat>(C)->getValue();
414     const uint32_t I32 = Utils::bitCopy<uint32_t>(F32);
415     if (I32 & ~AllowedBits) {
416       // constant has disallowed bits.
417       return false;
418     }
419 
420     if ((I32 & bbbbb) != bbbbb && (I32 & bbbbb)) {
421       // not all bbbbb bits are 0 or 1.
422       return false;
423     }
424 
425     if (((I32 & B) != 0) == ((I32 & bbbbb) != 0)) {
426       // B ^ b = 0;
427       return false;
428     }
429 
430     *ModifiedImm = ((I32 & a) ? 0x80 : 0x00) | ((I32 & bbbbb) ? 0x40 : 0x00) |
431                    ((I32 & cdefgh) >> 19);
432     return true;
433   }
434   case IceType_f64: {
435     static constexpr uint32_t a = 0x80000000u;
436     static constexpr uint32_t B = 0x40000000;
437     static constexpr uint32_t bbbbbbbb = 0x3FC00000;
438     static constexpr uint32_t cdefgh = 0x003F0000;
439     static constexpr uint32_t AllowedBits = a | B | bbbbbbbb | cdefgh;
440     static_assert(AllowedBits == 0xFFFF0000u,
441                   "Invalid mask for f64 modified immediates.");
442     const double F64 = llvm::cast<const ConstantDouble>(C)->getValue();
443     const uint64_t I64 = Utils::bitCopy<uint64_t>(F64);
444     if (I64 & 0xFFFFFFFFu) {
445       // constant has disallowed bits.
446       return false;
447     }
448     const uint32_t I32 = I64 >> 32;
449 
450     if (I32 & ~AllowedBits) {
451       // constant has disallowed bits.
452       return false;
453     }
454 
455     if ((I32 & bbbbbbbb) != bbbbbbbb && (I32 & bbbbbbbb)) {
456       // not all bbbbb bits are 0 or 1.
457       return false;
458     }
459 
460     if (((I32 & B) != 0) == ((I32 & bbbbbbbb) != 0)) {
461       // B ^ b = 0;
462       return false;
463     }
464 
465     *ModifiedImm = ((I32 & a) ? 0x80 : 0x00) |
466                    ((I32 & bbbbbbbb) ? 0x40 : 0x00) | ((I32 & cdefgh) >> 16);
467     return true;
468   }
469   }
470 }
471 
OperandARM32FlexFpZero(Cfg *,Type Ty)472 OperandARM32FlexFpZero::OperandARM32FlexFpZero(Cfg * /*Func*/, Type Ty)
473     : OperandARM32Flex(kFlexFpZero, Ty) {}
474 
OperandARM32FlexReg(Cfg * Func,Type Ty,Variable * Reg,ShiftKind ShiftOp,Operand * ShiftAmt)475 OperandARM32FlexReg::OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg,
476                                          ShiftKind ShiftOp, Operand *ShiftAmt)
477     : OperandARM32Flex(kFlexReg, Ty), Reg(Reg), ShiftOp(ShiftOp),
478       ShiftAmt(ShiftAmt) {
479   NumVars = 1;
480   auto *ShiftVar = llvm::dyn_cast_or_null<Variable>(ShiftAmt);
481   if (ShiftVar)
482     ++NumVars;
483   Vars = Func->allocateArrayOf<Variable *>(NumVars);
484   Vars[0] = Reg;
485   if (ShiftVar)
486     Vars[1] = ShiftVar;
487 }
488 
InstARM32Br(Cfg * Func,const CfgNode * TargetTrue,const CfgNode * TargetFalse,const InstARM32Label * Label,CondARM32::Cond Pred)489 InstARM32Br::InstARM32Br(Cfg *Func, const CfgNode *TargetTrue,
490                          const CfgNode *TargetFalse,
491                          const InstARM32Label *Label, CondARM32::Cond Pred)
492     : InstARM32Pred(Func, InstARM32::Br, 0, nullptr, Pred),
493       TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {}
494 
optimizeBranch(const CfgNode * NextNode)495 bool InstARM32Br::optimizeBranch(const CfgNode *NextNode) {
496   // If there is no next block, then there can be no fallthrough to optimize.
497   if (NextNode == nullptr)
498     return false;
499   // Intra-block conditional branches can't be optimized.
500   if (Label)
501     return false;
502   // If there is no fallthrough node, such as a non-default case label for a
503   // switch instruction, then there is no opportunity to optimize.
504   if (getTargetFalse() == nullptr)
505     return false;
506 
507   // Unconditional branch to the next node can be removed.
508   if (isUnconditionalBranch() && getTargetFalse() == NextNode) {
509     assert(getTargetTrue() == nullptr);
510     setDeleted();
511     return true;
512   }
513   // If the fallthrough is to the next node, set fallthrough to nullptr to
514   // indicate.
515   if (getTargetFalse() == NextNode) {
516     TargetFalse = nullptr;
517     return true;
518   }
519   // If TargetTrue is the next node, and TargetFalse is not nullptr (which was
520   // already tested above), then invert the branch condition, swap the targets,
521   // and set new fallthrough to nullptr.
522   if (getTargetTrue() == NextNode) {
523     assert(Predicate != CondARM32::AL);
524     setPredicate(getOppositeCondition(getPredicate()));
525     TargetTrue = getTargetFalse();
526     TargetFalse = nullptr;
527     return true;
528   }
529   return false;
530 }
531 
repointEdges(CfgNode * OldNode,CfgNode * NewNode)532 bool InstARM32Br::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
533   bool Found = false;
534   if (TargetFalse == OldNode) {
535     TargetFalse = NewNode;
536     Found = true;
537   }
538   if (TargetTrue == OldNode) {
539     TargetTrue = NewNode;
540     Found = true;
541   }
542   return Found;
543 }
544 
545 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const546 void InstARM32ThreeAddrGPR<K>::emitIAS(const Cfg *Func) const {
547   emitUsingTextFixup(Func);
548 }
549 
emitIAS(const Cfg * Func) const550 template <> void InstARM32Adc::emitIAS(const Cfg *Func) const {
551   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
552   Asm->adc(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
553   if (Asm->needsTextFixup())
554     emitUsingTextFixup(Func);
555 }
556 
emitIAS(const Cfg * Func) const557 template <> void InstARM32Add::emitIAS(const Cfg *Func) const {
558   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
559   Asm->add(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
560   assert(!Asm->needsTextFixup());
561 }
562 
emitIAS(const Cfg * Func) const563 template <> void InstARM32And::emitIAS(const Cfg *Func) const {
564   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
565   Asm->and_(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
566   if (Asm->needsTextFixup())
567     emitUsingTextFixup(Func);
568 }
569 
emitIAS(const Cfg * Func) const570 template <> void InstARM32Bic::emitIAS(const Cfg *Func) const {
571   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
572   Asm->bic(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
573   if (Asm->needsTextFixup())
574     emitUsingTextFixup(Func);
575 }
576 
emitIAS(const Cfg * Func) const577 template <> void InstARM32Eor::emitIAS(const Cfg *Func) const {
578   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
579   Asm->eor(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
580   if (Asm->needsTextFixup())
581     emitUsingTextFixup(Func);
582 }
583 
emitIAS(const Cfg * Func) const584 template <> void InstARM32Asr::emitIAS(const Cfg *Func) const {
585   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
586   Asm->asr(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
587   if (Asm->needsTextFixup())
588     emitUsingTextFixup(Func);
589 }
590 
emitIAS(const Cfg * Func) const591 template <> void InstARM32Lsl::emitIAS(const Cfg *Func) const {
592   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
593   Asm->lsl(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
594   if (Asm->needsTextFixup())
595     emitUsingTextFixup(Func);
596 }
597 
emitIAS(const Cfg * Func) const598 template <> void InstARM32Lsr::emitIAS(const Cfg *Func) const {
599   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
600   Asm->lsr(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
601   if (Asm->needsTextFixup())
602     emitUsingTextFixup(Func);
603 }
604 
emitIAS(const Cfg * Func) const605 template <> void InstARM32Orr::emitIAS(const Cfg *Func) const {
606   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
607   Asm->orr(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
608   if (Asm->needsTextFixup())
609     emitUsingTextFixup(Func);
610 }
611 
emitIAS(const Cfg * Func) const612 template <> void InstARM32Mul::emitIAS(const Cfg *Func) const {
613   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
614   Asm->mul(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
615   if (Asm->needsTextFixup())
616     emitUsingTextFixup(Func);
617 }
618 
emitIAS(const Cfg * Func) const619 template <> void InstARM32Rsb::emitIAS(const Cfg *Func) const {
620   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
621   Asm->rsb(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
622   if (Asm->needsTextFixup())
623     emitUsingTextFixup(Func);
624 }
625 
emitIAS(const Cfg * Func) const626 template <> void InstARM32Rsc::emitIAS(const Cfg *Func) const {
627   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
628   Asm->rsc(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
629   if (Asm->needsTextFixup())
630     emitUsingTextFixup(Func);
631 }
632 
emitIAS(const Cfg * Func) const633 template <> void InstARM32Sbc::emitIAS(const Cfg *Func) const {
634   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
635   Asm->sbc(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
636   if (Asm->needsTextFixup())
637     emitUsingTextFixup(Func);
638 }
639 
emitIAS(const Cfg * Func) const640 template <> void InstARM32Sdiv::emitIAS(const Cfg *Func) const {
641   assert(!SetFlags);
642   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
643   Asm->sdiv(getDest(), getSrc(0), getSrc(1), getPredicate());
644   if (Asm->needsTextFixup())
645     emitUsingTextFixup(Func);
646 }
647 
emitIAS(const Cfg * Func) const648 template <> void InstARM32Sub::emitIAS(const Cfg *Func) const {
649   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
650   Asm->sub(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
651   if (Asm->needsTextFixup())
652     emitUsingTextFixup(Func);
653 }
654 
emitIAS(const Cfg * Func) const655 template <> void InstARM32Udiv::emitIAS(const Cfg *Func) const {
656   assert(!SetFlags);
657   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
658   Asm->udiv(getDest(), getSrc(0), getSrc(1), getPredicate());
659   if (Asm->needsTextFixup())
660     emitUsingTextFixup(Func);
661 }
662 
emitIAS(const Cfg * Func) const663 template <> void InstARM32Vadd::emitIAS(const Cfg *Func) const {
664   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
665   const Variable *Dest = getDest();
666   Type DestTy = Dest->getType();
667   switch (DestTy) {
668   default:
669     llvm::report_fatal_error("Vadd not defined on type " +
670                              typeStdString(DestTy));
671   case IceType_v16i8:
672   case IceType_v8i16:
673   case IceType_v4i32:
674     Asm->vaddqi(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
675     break;
676   case IceType_v4f32:
677     Asm->vaddqf(Dest, getSrc(0), getSrc(1));
678     break;
679   case IceType_f32:
680     Asm->vadds(Dest, getSrc(0), getSrc(1), CondARM32::AL);
681     break;
682   case IceType_f64:
683     Asm->vaddd(Dest, getSrc(0), getSrc(1), CondARM32::AL);
684     break;
685   }
686   assert(!Asm->needsTextFixup());
687 }
688 
emitIAS(const Cfg * Func) const689 template <> void InstARM32Vand::emitIAS(const Cfg *Func) const {
690   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
691   const Variable *Dest = getDest();
692   switch (Dest->getType()) {
693   default:
694     llvm::report_fatal_error("Vand not defined on type " +
695                              typeStdString(Dest->getType()));
696   case IceType_v4i1:
697   case IceType_v8i1:
698   case IceType_v16i1:
699   case IceType_v16i8:
700   case IceType_v8i16:
701   case IceType_v4i32:
702     Asm->vandq(Dest, getSrc(0), getSrc(1));
703   }
704   assert(!Asm->needsTextFixup());
705 }
706 
emitIAS(const Cfg * Func) const707 template <> void InstARM32Vceq::emitIAS(const Cfg *Func) const {
708   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
709   const Variable *Dest = getDest();
710   const Type SrcTy = getSrc(0)->getType();
711   switch (SrcTy) {
712   default:
713     llvm::report_fatal_error("Vceq not defined on type " +
714                              typeStdString(SrcTy));
715   case IceType_v4i1:
716   case IceType_v8i1:
717   case IceType_v16i1:
718   case IceType_v16i8:
719   case IceType_v8i16:
720   case IceType_v4i32:
721     Asm->vceqqi(typeElementType(SrcTy), Dest, getSrc(0), getSrc(1));
722     break;
723   case IceType_v4f32:
724     Asm->vceqqs(Dest, getSrc(0), getSrc(1));
725     break;
726   }
727   assert(!Asm->needsTextFixup());
728 }
729 
emitIAS(const Cfg * Func) const730 template <> void InstARM32Vcge::emitIAS(const Cfg *Func) const {
731   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
732   const Variable *Dest = getDest();
733   const Type SrcTy = getSrc(0)->getType();
734   switch (SrcTy) {
735   default:
736     llvm::report_fatal_error("Vcge not defined on type " +
737                              typeStdString(Dest->getType()));
738   case IceType_v4i1:
739   case IceType_v8i1:
740   case IceType_v16i1:
741   case IceType_v16i8:
742   case IceType_v8i16:
743   case IceType_v4i32: {
744     const Type ElmtTy = typeElementType(SrcTy);
745     assert(Sign != InstARM32::FS_None);
746     switch (Sign) {
747     case InstARM32::FS_None: // defaults to unsigned.
748       llvm_unreachable("Sign should not be FS_None.");
749     case InstARM32::FS_Unsigned:
750       Asm->vcugeqi(ElmtTy, Dest, getSrc(0), getSrc(1));
751       break;
752     case InstARM32::FS_Signed:
753       Asm->vcgeqi(ElmtTy, Dest, getSrc(0), getSrc(1));
754       break;
755     }
756   } break;
757   case IceType_v4f32:
758     Asm->vcgeqs(Dest, getSrc(0), getSrc(1));
759     break;
760   }
761 }
762 
emitIAS(const Cfg * Func) const763 template <> void InstARM32Vcgt::emitIAS(const Cfg *Func) const {
764   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
765   const Variable *Dest = getDest();
766   const Type SrcTy = getSrc(0)->getType();
767   switch (SrcTy) {
768   default:
769     llvm::report_fatal_error("Vcgt not defined on type " +
770                              typeStdString(Dest->getType()));
771   case IceType_v4i1:
772   case IceType_v8i1:
773   case IceType_v16i1:
774   case IceType_v16i8:
775   case IceType_v8i16:
776   case IceType_v4i32: {
777     const Type ElmtTy = typeElementType(SrcTy);
778     assert(Sign != InstARM32::FS_None);
779     switch (Sign) {
780     case InstARM32::FS_None: // defaults to unsigned.
781       llvm_unreachable("Sign should not be FS_None.");
782     case InstARM32::FS_Unsigned:
783       Asm->vcugtqi(ElmtTy, Dest, getSrc(0), getSrc(1));
784       break;
785     case InstARM32::FS_Signed:
786       Asm->vcgtqi(ElmtTy, Dest, getSrc(0), getSrc(1));
787       break;
788     }
789   } break;
790   case IceType_v4f32:
791     Asm->vcgtqs(Dest, getSrc(0), getSrc(1));
792     break;
793   }
794 }
795 
emitIAS(const Cfg * Func) const796 template <> void InstARM32Vbsl::emitIAS(const Cfg *Func) const {
797   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
798   const Variable *Dest = getDest();
799   switch (Dest->getType()) {
800   default:
801     llvm::report_fatal_error("Vbsl not defined on type " +
802                              typeStdString(Dest->getType()));
803   case IceType_v4i1:
804   case IceType_v8i1:
805   case IceType_v16i1:
806   case IceType_v16i8:
807   case IceType_v8i16:
808   case IceType_v4i32:
809     Asm->vbslq(Dest, getSrc(0), getSrc(1));
810   }
811   assert(!Asm->needsTextFixup());
812 }
813 
emitIAS(const Cfg * Func) const814 template <> void InstARM32Vdiv::emitIAS(const Cfg *Func) const {
815   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
816   const Variable *Dest = getDest();
817   switch (Dest->getType()) {
818   default:
819     // TODO(kschimpf) Figure if more cases are needed.
820     Asm->setNeedsTextFixup();
821     break;
822   case IceType_f32:
823     Asm->vdivs(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
824     break;
825   case IceType_f64:
826     Asm->vdivd(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
827     break;
828   }
829   assert(!Asm->needsTextFixup());
830 }
831 
emitIAS(const Cfg * Func) const832 template <> void InstARM32Veor::emitIAS(const Cfg *Func) const {
833   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
834   const Variable *Dest = getDest();
835   if (isVectorType(Dest->getType())) {
836     Asm->veorq(Dest, getSrc(0), getSrc(1));
837     assert(!Asm->needsTextFixup());
838     return;
839   }
840   assert(Dest->getType() == IceType_f64);
841   Asm->veord(Dest, getSrc(0), getSrc(1));
842   assert(!Asm->needsTextFixup());
843 }
844 
emitIAS(const Cfg * Func) const845 template <> void InstARM32Vmla::emitIAS(const Cfg *Func) const {
846   // Note: Dest == getSrc(0) for four address FP instructions.
847   assert(getSrcSize() == 3);
848   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
849   const Variable *Dest = getDest();
850   switch (Dest->getType()) {
851   default:
852     // TODO(kschimpf) Figure out how vector operations apply.
853     emitUsingTextFixup(Func);
854     return;
855   case IceType_f32:
856     Asm->vmlas(getDest(), getSrc(1), getSrc(2), CondARM32::AL);
857     assert(!Asm->needsTextFixup());
858     return;
859   case IceType_f64:
860     Asm->vmlad(getDest(), getSrc(1), getSrc(2), CondARM32::AL);
861     assert(!Asm->needsTextFixup());
862     return;
863   }
864 }
865 
emitIAS(const Cfg * Func) const866 template <> void InstARM32Vmls::emitIAS(const Cfg *Func) const {
867   // Note: Dest == getSrc(0) for four address FP instructions.
868   assert(getSrcSize() == 3);
869   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
870   const Variable *Dest = getDest();
871   switch (Dest->getType()) {
872   default:
873     // TODO(kschimpf) Figure out how vector operations apply.
874     emitUsingTextFixup(Func);
875     return;
876   case IceType_f32:
877     Asm->vmlss(getDest(), getSrc(1), getSrc(2), CondARM32::AL);
878     assert(!Asm->needsTextFixup());
879     return;
880   case IceType_f64:
881     Asm->vmlsd(getDest(), getSrc(1), getSrc(2), CondARM32::AL);
882     assert(!Asm->needsTextFixup());
883     return;
884   }
885 }
886 
emitIAS(const Cfg * Func) const887 template <> void InstARM32Vmvn::emitIAS(const Cfg *Func) const {
888   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
889   const Variable *Dest = getDest();
890   switch (Dest->getType()) {
891   default:
892     llvm::report_fatal_error("Vmvn not defined on type " +
893                              typeStdString(Dest->getType()));
894   case IceType_v4i1:
895   case IceType_v8i1:
896   case IceType_v16i1:
897   case IceType_v16i8:
898   case IceType_v8i16:
899   case IceType_v4i32:
900   case IceType_v4f32: {
901     Asm->vmvnq(Dest, getSrc(0));
902   } break;
903   }
904 }
905 
emitIAS(const Cfg * Func) const906 template <> void InstARM32Vmovl::emitIAS(const Cfg *Func) const {
907   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
908   const Variable *Dest = getDest();
909   switch (Dest->getType()) {
910   default:
911     llvm::report_fatal_error("Vmovlq not defined on type " +
912                              typeStdString(Dest->getType()));
913   case IceType_v4i1:
914   case IceType_v8i1:
915   case IceType_v16i1:
916   case IceType_v16i8:
917   case IceType_v8i16:
918   case IceType_v4i32:
919   case IceType_v4f32: {
920     Asm->vmovlq(Dest, getSrc(0), getSrc(1));
921   } break;
922   }
923 }
924 
emitIAS(const Cfg * Func) const925 template <> void InstARM32Vmovh::emitIAS(const Cfg *Func) const {
926   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
927   const Variable *Dest = getDest();
928   switch (Dest->getType()) {
929   default:
930     llvm::report_fatal_error("Vmovhq not defined on type " +
931                              typeStdString(Dest->getType()));
932   case IceType_v4i1:
933   case IceType_v8i1:
934   case IceType_v16i1:
935   case IceType_v16i8:
936   case IceType_v8i16:
937   case IceType_v4i32:
938   case IceType_v4f32: {
939     Asm->vmovhq(Dest, getSrc(0), getSrc(1));
940   } break;
941   }
942 }
943 
emitIAS(const Cfg * Func) const944 template <> void InstARM32Vmovhl::emitIAS(const Cfg *Func) const {
945   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
946   const Variable *Dest = getDest();
947   switch (Dest->getType()) {
948   default:
949     llvm::report_fatal_error("Vmovhlq not defined on type " +
950                              typeStdString(Dest->getType()));
951   case IceType_v4i1:
952   case IceType_v8i1:
953   case IceType_v16i1:
954   case IceType_v16i8:
955   case IceType_v8i16:
956   case IceType_v4i32:
957   case IceType_v4f32: {
958     Asm->vmovhlq(Dest, getSrc(0), getSrc(1));
959   } break;
960   }
961 }
962 
emitIAS(const Cfg * Func) const963 template <> void InstARM32Vmovlh::emitIAS(const Cfg *Func) const {
964   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
965   const Variable *Dest = getDest();
966   switch (Dest->getType()) {
967   default:
968     llvm::report_fatal_error("Vmovlhq not defined on type " +
969                              typeStdString(Dest->getType()));
970   case IceType_v4i1:
971   case IceType_v8i1:
972   case IceType_v16i1:
973   case IceType_v16i8:
974   case IceType_v8i16:
975   case IceType_v4i32:
976   case IceType_v4f32: {
977     Asm->vmovlhq(Dest, getSrc(0), getSrc(1));
978   } break;
979   }
980 }
981 
emitIAS(const Cfg * Func) const982 template <> void InstARM32Vneg::emitIAS(const Cfg *Func) const {
983   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
984   const Variable *Dest = getDest();
985   const Type DestTy = Dest->getType();
986   switch (Dest->getType()) {
987   default:
988     llvm::report_fatal_error("Vneg not defined on type " +
989                              typeStdString(Dest->getType()));
990   case IceType_v4i1:
991   case IceType_v8i1:
992   case IceType_v16i1:
993   case IceType_v16i8:
994   case IceType_v8i16:
995   case IceType_v4i32:
996   case IceType_v4f32: {
997     const Type ElmtTy = typeElementType(DestTy);
998     Asm->vnegqs(ElmtTy, Dest, getSrc(0));
999   } break;
1000   }
1001 }
1002 
emitIAS(const Cfg * Func) const1003 template <> void InstARM32Vorr::emitIAS(const Cfg *Func) const {
1004   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1005   const Variable *Dest = getDest();
1006   switch (Dest->getType()) {
1007   default:
1008     llvm::report_fatal_error("Vorr not defined on type " +
1009                              typeStdString(Dest->getType()));
1010   case IceType_v4i1:
1011   case IceType_v8i1:
1012   case IceType_v16i1:
1013   case IceType_v16i8:
1014   case IceType_v8i16:
1015   case IceType_v4i32:
1016     Asm->vorrq(Dest, getSrc(0), getSrc(1));
1017   }
1018   assert(!Asm->needsTextFixup());
1019 }
1020 
emitIAS(const Cfg * Func) const1021 template <> void InstARM32Vshl::emitIAS(const Cfg *Func) const {
1022   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1023   const Variable *Dest = getDest();
1024   const Type DestTy = Dest->getType();
1025   switch (DestTy) {
1026   default:
1027     llvm::report_fatal_error("Vshl not defined on type " +
1028                              typeStdString(Dest->getType()));
1029   // TODO(jpp): handle i1 vectors in terms of element count instead of element
1030   // type.
1031   case IceType_v4i1:
1032   case IceType_v8i1:
1033   case IceType_v16i1:
1034   case IceType_v16i8:
1035   case IceType_v8i16:
1036   case IceType_v4i32: {
1037     const Type ElmtTy = typeElementType(DestTy);
1038     assert(Sign != InstARM32::FS_None);
1039     switch (Sign) {
1040     case InstARM32::FS_None: // defaults to unsigned.
1041     case InstARM32::FS_Unsigned:
1042       if (const auto *Imm6 = llvm::dyn_cast<ConstantInteger32>(getSrc(1))) {
1043         Asm->vshlqc(ElmtTy, Dest, getSrc(0), Imm6);
1044       } else {
1045         Asm->vshlqu(ElmtTy, Dest, getSrc(0), getSrc(1));
1046       }
1047       break;
1048     case InstARM32::FS_Signed:
1049       if (const auto *Imm6 = llvm::dyn_cast<ConstantInteger32>(getSrc(1))) {
1050         Asm->vshlqc(ElmtTy, Dest, getSrc(0), Imm6);
1051       } else {
1052         Asm->vshlqi(ElmtTy, Dest, getSrc(0), getSrc(1));
1053       }
1054       break;
1055     }
1056   } break;
1057   }
1058 }
1059 
emitIAS(const Cfg * Func) const1060 template <> void InstARM32Vshr::emitIAS(const Cfg *Func) const {
1061   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1062   const Variable *Dest = getDest();
1063   const Type DestTy = Dest->getType();
1064   switch (DestTy) {
1065   default:
1066     llvm::report_fatal_error("Vshr not defined on type " +
1067                              typeStdString(Dest->getType()));
1068   // TODO(jpp): handle i1 vectors in terms of element count instead of element
1069   // type.
1070   case IceType_v4i1:
1071   case IceType_v8i1:
1072   case IceType_v16i1:
1073   case IceType_v16i8:
1074   case IceType_v8i16:
1075   case IceType_v4i32: {
1076     const Type ElmtTy = typeElementType(DestTy);
1077     const auto *Imm6 = llvm::cast<ConstantInteger32>(getSrc(1));
1078     switch (Sign) {
1079     case InstARM32::FS_Signed:
1080     case InstARM32::FS_Unsigned:
1081       Asm->vshrqc(ElmtTy, Dest, getSrc(0), Imm6, Sign);
1082       break;
1083     default:
1084       assert(false && "Vshr requires signedness specification.");
1085     }
1086   } break;
1087   }
1088 }
1089 
emitIAS(const Cfg * Func) const1090 template <> void InstARM32Vsub::emitIAS(const Cfg *Func) const {
1091   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1092   const Variable *Dest = getDest();
1093   Type DestTy = Dest->getType();
1094   switch (DestTy) {
1095   default:
1096     llvm::report_fatal_error("Vsub not defined on type " +
1097                              typeStdString(DestTy));
1098   case IceType_v16i8:
1099   case IceType_v8i16:
1100   case IceType_v4i32:
1101     Asm->vsubqi(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
1102     break;
1103   case IceType_v4f32:
1104     Asm->vsubqf(Dest, getSrc(0), getSrc(1));
1105     break;
1106   case IceType_f32:
1107     Asm->vsubs(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
1108     break;
1109   case IceType_f64:
1110     Asm->vsubd(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
1111     break;
1112   }
1113   assert(!Asm->needsTextFixup());
1114 }
1115 
emitIAS(const Cfg * Func) const1116 template <> void InstARM32Vqadd::emitIAS(const Cfg *Func) const {
1117   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1118   const Variable *Dest = getDest();
1119   Type DestTy = Dest->getType();
1120   switch (DestTy) {
1121   default:
1122     llvm::report_fatal_error("Vqadd not defined on type " +
1123                              typeStdString(DestTy));
1124   case IceType_v16i8:
1125   case IceType_v8i16:
1126   case IceType_v4i32:
1127     switch (Sign) {
1128     case InstARM32::FS_None: // defaults to unsigned.
1129     case InstARM32::FS_Unsigned:
1130       Asm->vqaddqu(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
1131       break;
1132     case InstARM32::FS_Signed:
1133       Asm->vqaddqi(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
1134       break;
1135     }
1136     break;
1137   }
1138   assert(!Asm->needsTextFixup());
1139 }
1140 
emitIAS(const Cfg * Func) const1141 template <> void InstARM32Vqsub::emitIAS(const Cfg *Func) const {
1142   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1143   const Variable *Dest = getDest();
1144   Type DestTy = Dest->getType();
1145   switch (DestTy) {
1146   default:
1147     llvm::report_fatal_error("Vqsub not defined on type " +
1148                              typeStdString(DestTy));
1149   case IceType_v16i8:
1150   case IceType_v8i16:
1151   case IceType_v4i32:
1152     switch (Sign) {
1153     case InstARM32::FS_None: // defaults to unsigned.
1154     case InstARM32::FS_Unsigned:
1155       Asm->vqsubqu(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
1156       break;
1157     case InstARM32::FS_Signed:
1158       Asm->vqsubqi(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
1159       break;
1160     }
1161     break;
1162   }
1163   assert(!Asm->needsTextFixup());
1164 }
1165 
emitIAS(const Cfg * Func) const1166 template <> void InstARM32Vqmovn2::emitIAS(const Cfg *Func) const {
1167   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1168   const Operand *Src0 = getSrc(0);
1169   const Operand *Src1 = getSrc(1);
1170   Type SrcTy = Src0->getType();
1171   Type DestTy = Dest->getType();
1172   bool Unsigned = true;
1173   bool Saturating = true;
1174   switch (SrcTy) {
1175   default:
1176     llvm::report_fatal_error("Vqmovn2 not defined on type " +
1177                              typeStdString(SrcTy));
1178   case IceType_v8i16:
1179   case IceType_v4i32:
1180     switch (Sign) {
1181     case InstARM32::FS_None:
1182       Unsigned = true;
1183       Saturating = false;
1184       Asm->vqmovn2(typeElementType(DestTy), Dest, Src0, Src1, Unsigned,
1185                    Saturating);
1186       break;
1187     case InstARM32::FS_Unsigned:
1188       Unsigned = true;
1189       Saturating = true;
1190       Asm->vqmovn2(typeElementType(DestTy), Dest, Src0, Src1, Unsigned,
1191                    Saturating);
1192       break;
1193     case InstARM32::FS_Signed:
1194       Unsigned = false;
1195       Saturating = true;
1196       Asm->vqmovn2(typeElementType(DestTy), Dest, Src0, Src1, Unsigned,
1197                    Saturating);
1198       break;
1199     }
1200     break;
1201   }
1202   assert(!Asm->needsTextFixup());
1203 }
1204 
emitIAS(const Cfg * Func) const1205 template <> void InstARM32Vmulh::emitIAS(const Cfg *Func) const {
1206   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1207   const Operand *Src0 = getSrc(0);
1208   Type SrcTy = Src0->getType();
1209   bool Unsigned = true;
1210   switch (SrcTy) {
1211   default:
1212     llvm::report_fatal_error("Vmulh not defined on type " +
1213                              typeStdString(SrcTy));
1214   case IceType_v8i16:
1215     switch (Sign) {
1216     case InstARM32::FS_None: // defaults to unsigned.
1217     case InstARM32::FS_Unsigned:
1218       Unsigned = true;
1219       Asm->vmulh(typeElementType(SrcTy), Dest, getSrc(0), getSrc(1), Unsigned);
1220       break;
1221     case InstARM32::FS_Signed:
1222       Unsigned = false;
1223       Asm->vmulh(typeElementType(SrcTy), Dest, getSrc(0), getSrc(1), Unsigned);
1224       break;
1225     }
1226     break;
1227   }
1228   assert(!Asm->needsTextFixup());
1229 }
1230 
emitIAS(const Cfg * Func) const1231 template <> void InstARM32Vmlap::emitIAS(const Cfg *Func) const {
1232   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1233   const Operand *Src0 = getSrc(0);
1234   const Operand *Src1 = getSrc(1);
1235   Type SrcTy = Src0->getType();
1236   switch (SrcTy) {
1237   default:
1238     llvm::report_fatal_error("Vmlap not defined on type " +
1239                              typeStdString(SrcTy));
1240   case IceType_v8i16:
1241     Asm->vmlap(typeElementType(SrcTy), Dest, Src0, Src1);
1242     break;
1243   }
1244   assert(!Asm->needsTextFixup());
1245 }
1246 
emitIAS(const Cfg * Func) const1247 template <> void InstARM32Vzip::emitIAS(const Cfg *Func) const {
1248   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1249   const Operand *Src0 = getSrc(0);
1250   const Operand *Src1 = getSrc(1);
1251   Type DestTy = Dest->getType();
1252   Asm->vzip(typeElementType(DestTy), Dest, Src0, Src1);
1253   assert(!Asm->needsTextFixup());
1254 }
1255 
emitIAS(const Cfg * Func) const1256 template <> void InstARM32Vmul::emitIAS(const Cfg *Func) const {
1257   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1258   const Variable *Dest = getDest();
1259   const Type DestTy = Dest->getType();
1260   switch (DestTy) {
1261   default:
1262     llvm::report_fatal_error("Vmul not defined on type " +
1263                              typeStdString(DestTy));
1264 
1265   case IceType_v16i8:
1266   case IceType_v8i16:
1267   case IceType_v4i32:
1268     Asm->vmulqi(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
1269     break;
1270   case IceType_v4f32:
1271     Asm->vmulqf(Dest, getSrc(0), getSrc(1));
1272     break;
1273   case IceType_f32:
1274     Asm->vmuls(Dest, getSrc(0), getSrc(1), CondARM32::AL);
1275     break;
1276   case IceType_f64:
1277     Asm->vmuld(Dest, getSrc(0), getSrc(1), CondARM32::AL);
1278     break;
1279   }
1280 }
1281 
InstARM32Call(Cfg * Func,Variable * Dest,Operand * CallTarget)1282 InstARM32Call::InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
1283     : InstARM32(Func, InstARM32::Call, 1, Dest) {
1284   HasSideEffects = true;
1285   addSource(CallTarget);
1286 }
1287 
InstARM32Label(Cfg * Func,TargetARM32 * Target)1288 InstARM32Label::InstARM32Label(Cfg *Func, TargetARM32 *Target)
1289     : InstARM32(Func, InstARM32::Label, 0, nullptr),
1290       Number(Target->makeNextLabelNumber()) {
1291   if (BuildDefs::dump()) {
1292     Name = GlobalString::createWithString(
1293         Func->getContext(),
1294         ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number));
1295   } else {
1296     Name = GlobalString::createWithoutString(Func->getContext());
1297   }
1298 }
1299 
1300 namespace {
1301 // Requirements for Push/Pop:
1302 //  1) All the Variables have the same type;
1303 //  2) All the variables have registers assigned to them.
validatePushOrPopRegisterListOrDie(const VarList & RegList)1304 void validatePushOrPopRegisterListOrDie(const VarList &RegList) {
1305   Type PreviousTy = IceType_void;
1306   for (Variable *Reg : RegList) {
1307     if (PreviousTy != IceType_void && Reg->getType() != PreviousTy) {
1308       llvm::report_fatal_error("Type mismatch when popping/pushing "
1309                                "registers.");
1310     }
1311 
1312     if (!Reg->hasReg()) {
1313       llvm::report_fatal_error("Push/pop operand does not have a register "
1314                                "assigned to it.");
1315     }
1316 
1317     PreviousTy = Reg->getType();
1318   }
1319 }
1320 } // end of anonymous namespace
1321 
emit(const Cfg * Func) const1322 void InstARM32RegisterStackOp::emit(const Cfg *Func) const {
1323   if (!BuildDefs::dump())
1324     return;
1325   emitUsingForm(Func, Emit_Text);
1326 }
1327 
emitIAS(const Cfg * Func) const1328 void InstARM32RegisterStackOp::emitIAS(const Cfg *Func) const {
1329   emitUsingForm(Func, Emit_Binary);
1330   assert(!Func->getAssembler<ARM32::AssemblerARM32>()->needsTextFixup());
1331 }
1332 
dump(const Cfg * Func) const1333 void InstARM32RegisterStackOp::dump(const Cfg *Func) const {
1334   if (!BuildDefs::dump())
1335     return;
1336   Ostream &Str = Func->getContext()->getStrDump();
1337   Str << getDumpOpcode() << " ";
1338   SizeT NumRegs = getNumStackRegs();
1339   for (SizeT I = 0; I < NumRegs; ++I) {
1340     if (I > 0)
1341       Str << ", ";
1342     getStackReg(I)->dump(Func);
1343   }
1344 }
1345 
emitGPRsAsText(const Cfg * Func) const1346 void InstARM32RegisterStackOp::emitGPRsAsText(const Cfg *Func) const {
1347   if (!BuildDefs::dump())
1348     return;
1349   Ostream &Str = Func->getContext()->getStrEmit();
1350   Str << "\t" << getGPROpcode() << "\t{";
1351   getStackReg(0)->emit(Func);
1352   const SizeT NumRegs = getNumStackRegs();
1353   for (SizeT i = 1; i < NumRegs; ++i) {
1354     Str << ", ";
1355     getStackReg(i)->emit(Func);
1356   }
1357   Str << "}";
1358 }
1359 
emitSRegsAsText(const Cfg * Func,const Variable * BaseReg,SizeT RegCount) const1360 void InstARM32RegisterStackOp::emitSRegsAsText(const Cfg *Func,
1361                                                const Variable *BaseReg,
1362                                                SizeT RegCount) const {
1363   if (!BuildDefs::dump())
1364     return;
1365   Ostream &Str = Func->getContext()->getStrEmit();
1366   Str << "\t" << getSRegOpcode() << "\t{";
1367   bool IsFirst = true;
1368   const auto Base = BaseReg->getRegNum();
1369   for (SizeT i = 0; i < RegCount; ++i) {
1370     if (IsFirst)
1371       IsFirst = false;
1372     else
1373       Str << ", ";
1374     Str << RegARM32::getRegName(RegNumT::fixme(Base + i));
1375   }
1376   Str << "}";
1377 }
1378 
emitSRegsOp(const Cfg * Func,EmitForm Form,const Variable * BaseReg,SizeT RegCount,SizeT InstIndex) const1379 void InstARM32RegisterStackOp::emitSRegsOp(const Cfg *Func, EmitForm Form,
1380                                            const Variable *BaseReg,
1381                                            SizeT RegCount,
1382                                            SizeT InstIndex) const {
1383   if (Form == Emit_Text && BuildDefs::dump() && InstIndex > 0) {
1384     startNextInst(Func);
1385     Func->getContext()->getStrEmit() << "\n";
1386   }
1387   emitSRegs(Func, Form, BaseReg, RegCount);
1388 }
1389 
1390 namespace {
1391 
isAssignedConsecutiveRegisters(const Variable * Before,const Variable * After)1392 bool isAssignedConsecutiveRegisters(const Variable *Before,
1393                                     const Variable *After) {
1394   assert(Before->hasReg());
1395   assert(After->hasReg());
1396   return RegNumT::fixme(Before->getRegNum() + 1) == After->getRegNum();
1397 }
1398 
1399 } // end of anonymous namespace
1400 
emitUsingForm(const Cfg * Func,const EmitForm Form) const1401 void InstARM32RegisterStackOp::emitUsingForm(const Cfg *Func,
1402                                              const EmitForm Form) const {
1403   SizeT NumRegs = getNumStackRegs();
1404   assert(NumRegs);
1405 
1406   const auto *Reg = llvm::cast<Variable>(getStackReg(0));
1407   if (isScalarIntegerType(Reg->getType())) {
1408     // Push/pop GPR registers.
1409     SizeT IntegerCount = 0;
1410     ARM32::IValueT GPRegisters = 0;
1411     const Variable *LastDest = nullptr;
1412     for (SizeT i = 0; i < NumRegs; ++i) {
1413       const Variable *Var = getStackReg(i);
1414       assert(Var->hasReg() && "stack op only applies to registers");
1415       const RegARM32::GPRRegister Reg =
1416           RegARM32::getEncodedGPR(Var->getRegNum());
1417       LastDest = Var;
1418       GPRegisters |= (1 << Reg);
1419       ++IntegerCount;
1420     }
1421     if (IntegerCount == 1) {
1422       emitSingleGPR(Func, Form, LastDest);
1423     } else {
1424       emitMultipleGPRs(Func, Form, GPRegisters);
1425     }
1426     return;
1427   }
1428 
1429   // Push/pop floating point registers. Divide into a list of instructions,
1430   // defined on consecutive register ranges. Then generate the corresponding
1431   // instructions.
1432 
1433   // Typical max number of registers ranges pushed/popd is no more than 5.
1434   llvm::SmallVector<std::pair<const Variable *, SizeT>, 5> InstData;
1435   const Variable *BaseReg = nullptr;
1436   SizeT RegCount = 0;
1437   for (SizeT i = 0; i < NumRegs; ++i) {
1438     const Variable *NextReg = getStackReg(i);
1439     assert(NextReg->hasReg());
1440     if (BaseReg == nullptr) {
1441       BaseReg = NextReg;
1442       RegCount = 1;
1443     } else if (RegCount < VpushVpopMaxConsecRegs &&
1444                isAssignedConsecutiveRegisters(Reg, NextReg)) {
1445       ++RegCount;
1446     } else {
1447       InstData.emplace_back(BaseReg, RegCount);
1448       BaseReg = NextReg;
1449       RegCount = 1;
1450     }
1451     Reg = NextReg;
1452   }
1453   if (RegCount) {
1454     InstData.emplace_back(BaseReg, RegCount);
1455   }
1456   SizeT InstCount = 0;
1457   if (llvm::isa<InstARM32Push>(*this)) {
1458     for (const auto &Pair : InstData)
1459       emitSRegsOp(Func, Form, Pair.first, Pair.second, InstCount++);
1460     return;
1461   }
1462   assert(llvm::isa<InstARM32Pop>(*this));
1463   for (const auto &Pair : reverse_range(InstData))
1464     emitSRegsOp(Func, Form, Pair.first, Pair.second, InstCount++);
1465 }
1466 
InstARM32Pop(Cfg * Func,const VarList & Dests)1467 InstARM32Pop::InstARM32Pop(Cfg *Func, const VarList &Dests)
1468     : InstARM32RegisterStackOp(Func, InstARM32::Pop, 0, nullptr), Dests(Dests) {
1469   // Track modifications to Dests separately via FakeDefs. Also, a pop
1470   // instruction affects the stack pointer and so it should not be allowed to
1471   // be automatically dead-code eliminated. This is automatic since we leave
1472   // the Dest as nullptr.
1473   validatePushOrPopRegisterListOrDie(Dests);
1474 }
1475 
InstARM32Push(Cfg * Func,const VarList & Srcs)1476 InstARM32Push::InstARM32Push(Cfg *Func, const VarList &Srcs)
1477     : InstARM32RegisterStackOp(Func, InstARM32::Push, Srcs.size(), nullptr) {
1478   validatePushOrPopRegisterListOrDie(Srcs);
1479   for (Variable *Source : Srcs) {
1480     addSource(Source);
1481   }
1482 }
1483 
InstARM32Ret(Cfg * Func,Variable * LR,Variable * Source)1484 InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source)
1485     : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) {
1486   addSource(LR);
1487   if (Source)
1488     addSource(Source);
1489 }
1490 
InstARM32Str(Cfg * Func,Variable * Value,OperandARM32Mem * Mem,CondARM32::Cond Predicate)1491 InstARM32Str::InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1492                            CondARM32::Cond Predicate)
1493     : InstARM32Pred(Func, InstARM32::Str, 2, nullptr, Predicate) {
1494   addSource(Value);
1495   addSource(Mem);
1496 }
1497 
InstARM32Strex(Cfg * Func,Variable * Dest,Variable * Value,OperandARM32Mem * Mem,CondARM32::Cond Predicate)1498 InstARM32Strex::InstARM32Strex(Cfg *Func, Variable *Dest, Variable *Value,
1499                                OperandARM32Mem *Mem, CondARM32::Cond Predicate)
1500     : InstARM32Pred(Func, InstARM32::Strex, 2, Dest, Predicate) {
1501   addSource(Value);
1502   addSource(Mem);
1503 }
1504 
InstARM32Vstr1(Cfg * Func,Variable * Value,OperandARM32Mem * Mem,CondARM32::Cond Predicate,SizeT Size)1505 InstARM32Vstr1::InstARM32Vstr1(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1506                                CondARM32::Cond Predicate, SizeT Size)
1507     : InstARM32Pred(Func, InstARM32::Vstr1, 2, nullptr, Predicate) {
1508   addSource(Value);
1509   addSource(Mem);
1510   this->Size = Size;
1511 }
1512 
InstARM32Vdup(Cfg * Func,Variable * Dest,Variable * Src,IValueT Idx)1513 InstARM32Vdup::InstARM32Vdup(Cfg *Func, Variable *Dest, Variable *Src,
1514                              IValueT Idx)
1515     : InstARM32Pred(Func, InstARM32::Vdup, 1, Dest, CondARM32::AL), Idx(Idx) {
1516   addSource(Src);
1517 }
1518 
InstARM32Trap(Cfg * Func)1519 InstARM32Trap::InstARM32Trap(Cfg *Func)
1520     : InstARM32(Func, InstARM32::Trap, 0, nullptr) {}
1521 
InstARM32Umull(Cfg * Func,Variable * DestLo,Variable * DestHi,Variable * Src0,Variable * Src1,CondARM32::Cond Predicate)1522 InstARM32Umull::InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi,
1523                                Variable *Src0, Variable *Src1,
1524                                CondARM32::Cond Predicate)
1525     : InstARM32Pred(Func, InstARM32::Umull, 2, DestLo, Predicate),
1526       // DestHi is expected to have a FakeDef inserted by the lowering code.
1527       DestHi(DestHi) {
1528   addSource(Src0);
1529   addSource(Src1);
1530 }
1531 
InstARM32Vcvt(Cfg * Func,Variable * Dest,Variable * Src,VcvtVariant Variant,CondARM32::Cond Predicate)1532 InstARM32Vcvt::InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src,
1533                              VcvtVariant Variant, CondARM32::Cond Predicate)
1534     : InstARM32Pred(Func, InstARM32::Vcvt, 1, Dest, Predicate),
1535       Variant(Variant) {
1536   addSource(Src);
1537 }
1538 
InstARM32Mov(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)1539 InstARM32Mov::InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
1540                            CondARM32::Cond Predicate)
1541     : InstARM32Pred(Func, InstARM32::Mov, 2, Dest, Predicate) {
1542   auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest);
1543   auto *Src64 = llvm::dyn_cast<Variable64On32>(Src);
1544 
1545   assert(Dest64 == nullptr || Src64 == nullptr);
1546 
1547   if (Dest64 != nullptr) {
1548     // this-> is needed below because there is a parameter named Dest.
1549     this->Dest = Dest64->getLo();
1550     DestHi = Dest64->getHi();
1551   }
1552 
1553   if (Src64 == nullptr) {
1554     addSource(Src);
1555   } else {
1556     addSource(Src64->getLo());
1557     addSource(Src64->getHi());
1558   }
1559 }
1560 
1561 namespace {
1562 
1563 // These next two functions find the D register that maps to the half of the Q
1564 // register that this instruction is accessing.
getDRegister(const Variable * Src,uint32_t Index)1565 Register getDRegister(const Variable *Src, uint32_t Index) {
1566   assert(Src->hasReg());
1567   const auto SrcReg = Src->getRegNum();
1568 
1569   const RegARM32::RegTableType &SrcEntry = RegARM32::RegTable[SrcReg];
1570   assert(SrcEntry.IsVec128);
1571 
1572   const uint32_t NumElements = typeNumElements(Src->getType());
1573 
1574   // This code assumes the Aliases list goes Q_n, S_2n, S_2n+1. The asserts in
1575   // the next two branches help to check that this is still true.
1576   if (Index < NumElements / 2) {
1577     // We have a Q register that's made up of two D registers. This assert is
1578     // to help ensure that we picked the right D register.
1579     //
1580     // TODO(jpp): find a way to do this that doesn't rely on ordering of the
1581     // alias list.
1582     assert(RegARM32::RegTable[SrcEntry.Aliases[1]].Encoding + 1 ==
1583            RegARM32::RegTable[SrcEntry.Aliases[2]].Encoding);
1584     return static_cast<Register>(SrcEntry.Aliases[1]);
1585   } else {
1586     // We have a Q register that's made up of two D registers. This assert is
1587     // to help ensure that we picked the right D register.
1588     //
1589     // TODO(jpp): find a way to do this that doesn't rely on ordering of the
1590     // alias list.
1591     assert(RegARM32::RegTable[SrcEntry.Aliases[2]].Encoding - 1 ==
1592            RegARM32::RegTable[SrcEntry.Aliases[1]].Encoding);
1593     return static_cast<Register>(SrcEntry.Aliases[2]);
1594   }
1595 }
1596 
adjustDIndex(Type Ty,uint32_t DIndex)1597 uint32_t adjustDIndex(Type Ty, uint32_t DIndex) {
1598   // If Ty is a vector of i1, we may need to adjust DIndex. This is needed
1599   // because, e.g., the second i1 in a v4i1 is accessed with a
1600   //
1601   // vmov.s8 Qd[4], Rn
1602   switch (Ty) {
1603   case IceType_v4i1:
1604     return DIndex * 4;
1605   case IceType_v8i1:
1606     return DIndex * 2;
1607   case IceType_v16i1:
1608     return DIndex;
1609   default:
1610     return DIndex;
1611   }
1612 }
1613 
getDIndex(Type Ty,uint32_t NumElements,uint32_t Index)1614 uint32_t getDIndex(Type Ty, uint32_t NumElements, uint32_t Index) {
1615   const uint32_t DIndex =
1616       (Index < NumElements / 2) ? Index : Index - (NumElements / 2);
1617   return adjustDIndex(Ty, DIndex);
1618 }
1619 
1620 // For floating point values, we can insertelement or extractelement by moving
1621 // directly from an S register. This function finds the right one.
getSRegister(const Variable * Src,uint32_t Index)1622 Register getSRegister(const Variable *Src, uint32_t Index) {
1623   assert(Src->hasReg());
1624   const auto SrcReg = Src->getRegNum();
1625 
1626   // For floating point values, we need to be allocated to Q0 - Q7, so we can
1627   // directly access the value we want as one of the S registers.
1628   assert(Src->getType() == IceType_v4f32);
1629   assert(SrcReg < RegARM32::Reg_q8);
1630 
1631   // This part assumes the register alias list goes q0, d0, d1, s0, s1, s2, s3.
1632   assert(Index < 4);
1633 
1634   // TODO(jpp): find a way to do this that doesn't rely on ordering of the alias
1635   // list.
1636   return static_cast<Register>(RegARM32::RegTable[SrcReg].Aliases[Index + 3]);
1637 }
1638 
1639 } // end of anonymous namespace
1640 
emit(const Cfg * Func) const1641 void InstARM32Extract::emit(const Cfg *Func) const {
1642   Ostream &Str = Func->getContext()->getStrEmit();
1643   const Type DestTy = getDest()->getType();
1644 
1645   const auto *Src = llvm::cast<Variable>(getSrc(0));
1646 
1647   if (isIntegerType(DestTy)) {
1648     Str << "\t"
1649         << "vmov" << getPredicate();
1650     const uint32_t BitSize = typeWidthInBytes(DestTy) * CHAR_BIT;
1651     if (BitSize < 32) {
1652       Str << ".s" << BitSize;
1653     } else {
1654       Str << "." << BitSize;
1655     }
1656     Str << "\t";
1657     getDest()->emit(Func);
1658     Str << ", ";
1659 
1660     const Type SrcTy = Src->getType();
1661     const size_t VectorSize = typeNumElements(SrcTy);
1662 
1663     const Register SrcReg = getDRegister(Src, Index);
1664 
1665     Str << RegARM32::RegTable[SrcReg].Name;
1666     Str << "[" << getDIndex(SrcTy, VectorSize, Index) << "]";
1667   } else if (isFloatingType(DestTy)) {
1668     const Register SrcReg = getSRegister(Src, Index);
1669 
1670     Str << "\t"
1671         << "vmov" << getPredicate() << ".f32"
1672         << "\t";
1673     getDest()->emit(Func);
1674     Str << ", " << RegARM32::RegTable[SrcReg].Name;
1675   } else {
1676     assert(false && "Invalid extract type");
1677   }
1678 }
1679 
emitIAS(const Cfg * Func) const1680 void InstARM32Extract::emitIAS(const Cfg *Func) const {
1681   const Operand *Dest = getDest();
1682   const Type DestTy = Dest->getType();
1683   const Operand *Src = getSrc(0);
1684   const Type SrcTy = Src->getType();
1685   assert(isVectorType(Src->getType()));
1686   assert(DestTy == typeElementType(Src->getType()));
1687   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1688   if (isIntegerType(DestTy)) {
1689     Asm->vmovrqi(Dest, Src, adjustDIndex(SrcTy, Index), getPredicate());
1690     assert(!Asm->needsTextFixup());
1691     return;
1692   }
1693   assert(isFloatingType(DestTy));
1694   Asm->vmovsqi(Dest, Src, Index, getPredicate());
1695   assert(!Asm->needsTextFixup());
1696 }
1697 
1698 namespace {
insertionType(Type Ty)1699 Type insertionType(Type Ty) {
1700   assert(isVectorType(Ty));
1701   switch (Ty) {
1702   case IceType_v4i1:
1703     return IceType_v4i32;
1704   case IceType_v8i1:
1705     return IceType_v8i16;
1706   case IceType_v16i1:
1707     return IceType_v16i8;
1708   default:
1709     return Ty;
1710   }
1711 }
1712 } // end of anonymous namespace
1713 
emit(const Cfg * Func) const1714 void InstARM32Insert::emit(const Cfg *Func) const {
1715   Ostream &Str = Func->getContext()->getStrEmit();
1716   const Variable *Dest = getDest();
1717   const auto *Src = llvm::cast<Variable>(getSrc(0));
1718   const Type DestTy = insertionType(getDest()->getType());
1719   assert(isVectorType(DestTy));
1720 
1721   if (isIntegerType(DestTy)) {
1722     Str << "\t"
1723         << "vmov" << getPredicate();
1724     const size_t BitSize = typeWidthInBytes(typeElementType(DestTy)) * CHAR_BIT;
1725     Str << "." << BitSize << "\t";
1726 
1727     const size_t VectorSize = typeNumElements(DestTy);
1728     const Register DestReg = getDRegister(Dest, Index);
1729     const uint32_t Index =
1730         getDIndex(insertionType(DestTy), VectorSize, this->Index);
1731     Str << RegARM32::RegTable[DestReg].Name;
1732     Str << "[" << Index << "], ";
1733     Src->emit(Func);
1734   } else if (isFloatingType(DestTy)) {
1735     Str << "\t"
1736         << "vmov" << getPredicate() << ".f32"
1737         << "\t";
1738     const Register DestReg = getSRegister(Dest, Index);
1739     Str << RegARM32::RegTable[DestReg].Name << ", ";
1740     Src->emit(Func);
1741   } else {
1742     assert(false && "Invalid insert type");
1743   }
1744 }
1745 
emitIAS(const Cfg * Func) const1746 void InstARM32Insert::emitIAS(const Cfg *Func) const {
1747   const Variable *Dest = getDest();
1748   const auto *Src = llvm::cast<Variable>(getSrc(0));
1749   const Type DestTy = insertionType(Dest->getType());
1750   const Type SrcTy = typeElementType(DestTy);
1751   assert(SrcTy == Src->getType() || Src->getType() == IceType_i1);
1752   assert(isVectorType(DestTy));
1753   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1754   if (isIntegerType(SrcTy)) {
1755     Asm->vmovqir(Dest->asType(Func, DestTy, Dest->getRegNum()),
1756                  adjustDIndex(DestTy, Index),
1757                  Src->asType(Func, SrcTy, Src->getRegNum()), getPredicate());
1758     assert(!Asm->needsTextFixup());
1759     return;
1760   }
1761   assert(isFloatingType(SrcTy));
1762   Asm->vmovqis(Dest, Index, Src, getPredicate());
1763   assert(!Asm->needsTextFixup());
1764 }
1765 
1766 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const1767 void InstARM32CmpLike<K>::emitIAS(const Cfg *Func) const {
1768   emitUsingTextFixup(Func);
1769 }
1770 
emitIAS(const Cfg * Func) const1771 template <> void InstARM32Cmn::emitIAS(const Cfg *Func) const {
1772   assert(getSrcSize() == 2);
1773   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1774   Asm->cmn(getSrc(0), getSrc(1), getPredicate());
1775   if (Asm->needsTextFixup())
1776     emitUsingTextFixup(Func);
1777 }
1778 
emitIAS(const Cfg * Func) const1779 template <> void InstARM32Cmp::emitIAS(const Cfg *Func) const {
1780   assert(getSrcSize() == 2);
1781   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1782   Asm->cmp(getSrc(0), getSrc(1), getPredicate());
1783   if (Asm->needsTextFixup())
1784     emitUsingTextFixup(Func);
1785 }
1786 
emitIAS(const Cfg * Func) const1787 template <> void InstARM32Tst::emitIAS(const Cfg *Func) const {
1788   assert(getSrcSize() == 2);
1789   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1790   Asm->tst(getSrc(0), getSrc(1), getPredicate());
1791   if (Asm->needsTextFixup())
1792     emitUsingTextFixup(Func);
1793 }
1794 
InstARM32Dmb(Cfg * Func)1795 InstARM32Dmb::InstARM32Dmb(Cfg *Func)
1796     : InstARM32Pred(Func, InstARM32::Dmb, 0, nullptr, CondARM32::AL) {}
1797 
InstARM32Nop(Cfg * Func)1798 InstARM32Nop::InstARM32Nop(Cfg *Func)
1799     : InstARM32Pred(Func, InstARM32::Nop, 0, nullptr, CondARM32::AL) {}
1800 
InstARM32Vcmp(Cfg * Func,Variable * Src0,Operand * Src1,CondARM32::Cond Predicate)1801 InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1,
1802                              CondARM32::Cond Predicate)
1803     : InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) {
1804   HasSideEffects = true;
1805   addSource(Src0);
1806   addSource(Src1);
1807 }
1808 
InstARM32Vmrs(Cfg * Func,CondARM32::Cond Predicate)1809 InstARM32Vmrs::InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate)
1810     : InstARM32Pred(Func, InstARM32::Vmrs, 0, nullptr, Predicate) {
1811   HasSideEffects = true;
1812 }
1813 
InstARM32Vabs(Cfg * Func,Variable * Dest,Variable * Src,CondARM32::Cond Predicate)1814 InstARM32Vabs::InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src,
1815                              CondARM32::Cond Predicate)
1816     : InstARM32Pred(Func, InstARM32::Vabs, 1, Dest, Predicate) {
1817   addSource(Src);
1818 }
1819 
1820 // ======================== Dump routines ======================== //
1821 
1822 // Two-addr ops
1823 template <> const char *InstARM32Movt::Opcode = "movt";
1824 // Unary ops
1825 template <> const char *InstARM32Movw::Opcode = "movw";
1826 template <> const char *InstARM32Clz::Opcode = "clz";
1827 template <> const char *InstARM32Mvn::Opcode = "mvn";
1828 template <> const char *InstARM32Rbit::Opcode = "rbit";
1829 template <> const char *InstARM32Rev::Opcode = "rev";
1830 template <> const char *InstARM32Sxt::Opcode = "sxt"; // still requires b/h
1831 template <> const char *InstARM32Uxt::Opcode = "uxt"; // still requires b/h
1832 // FP
1833 template <> const char *InstARM32Vsqrt::Opcode = "vsqrt";
1834 // Mov-like ops
1835 template <> const char *InstARM32Ldr::Opcode = "ldr";
1836 template <> const char *InstARM32Ldrex::Opcode = "ldrex";
1837 template <> const char *InstARM32Vldr1d::Opcode = "vldr1d";
1838 template <> const char *InstARM32Vldr1q::Opcode = "vldr1q";
1839 // Three-addr ops
1840 template <> const char *InstARM32Adc::Opcode = "adc";
1841 template <> const char *InstARM32Add::Opcode = "add";
1842 template <> const char *InstARM32And::Opcode = "and";
1843 template <> const char *InstARM32Asr::Opcode = "asr";
1844 template <> const char *InstARM32Bic::Opcode = "bic";
1845 template <> const char *InstARM32Eor::Opcode = "eor";
1846 template <> const char *InstARM32Lsl::Opcode = "lsl";
1847 template <> const char *InstARM32Lsr::Opcode = "lsr";
1848 template <> const char *InstARM32Mul::Opcode = "mul";
1849 template <> const char *InstARM32Orr::Opcode = "orr";
1850 template <> const char *InstARM32Rsb::Opcode = "rsb";
1851 template <> const char *InstARM32Rsc::Opcode = "rsc";
1852 template <> const char *InstARM32Sbc::Opcode = "sbc";
1853 template <> const char *InstARM32Sdiv::Opcode = "sdiv";
1854 template <> const char *InstARM32Sub::Opcode = "sub";
1855 template <> const char *InstARM32Udiv::Opcode = "udiv";
1856 // FP
1857 template <> const char *InstARM32Vadd::Opcode = "vadd";
1858 template <> const char *InstARM32Vand::Opcode = "vand";
1859 template <> const char *InstARM32Vbsl::Opcode = "vbsl";
1860 template <> const char *InstARM32Vceq::Opcode = "vceq";
1861 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vcge>::Opcode = "vcge";
1862 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vcgt>::Opcode = "vcgt";
1863 template <> const char *InstARM32Vdiv::Opcode = "vdiv";
1864 template <> const char *InstARM32Veor::Opcode = "veor";
1865 template <> const char *InstARM32Vmla::Opcode = "vmla";
1866 template <> const char *InstARM32Vmls::Opcode = "vmls";
1867 template <> const char *InstARM32Vmul::Opcode = "vmul";
1868 template <> const char *InstARM32Vmvn::Opcode = "vmvn";
1869 template <> const char *InstARM32Vmovl::Opcode = "vmovl";
1870 template <> const char *InstARM32Vmovh::Opcode = "vmovh";
1871 template <> const char *InstARM32Vmovhl::Opcode = "vmovhl";
1872 template <> const char *InstARM32Vmovlh::Opcode = "vmovlh";
1873 template <> const char *InstARM32Vorr::Opcode = "vorr";
1874 template <> const char *InstARM32UnaryopFP<InstARM32::Vneg>::Opcode = "vneg";
1875 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vshl>::Opcode = "vshl";
1876 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vshr>::Opcode = "vshr";
1877 template <> const char *InstARM32Vsub::Opcode = "vsub";
1878 template <>
1879 const char *InstARM32ThreeAddrFP<InstARM32::Vqadd>::Opcode = "vqadd";
1880 template <>
1881 const char *InstARM32ThreeAddrFP<InstARM32::Vqsub>::Opcode = "vqsub";
1882 template <>
1883 const char *InstARM32ThreeAddrFP<InstARM32::Vqmovn2>::Opcode = "vqmovn2";
1884 template <>
1885 const char *InstARM32ThreeAddrFP<InstARM32::Vmulh>::Opcode = "vmulh";
1886 template <>
1887 const char *InstARM32ThreeAddrFP<InstARM32::Vmlap>::Opcode = "vmlap";
1888 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vzip>::Opcode = "vzip";
1889 // Four-addr ops
1890 template <> const char *InstARM32Mla::Opcode = "mla";
1891 template <> const char *InstARM32Mls::Opcode = "mls";
1892 // Cmp-like ops
1893 template <> const char *InstARM32Cmn::Opcode = "cmn";
1894 template <> const char *InstARM32Cmp::Opcode = "cmp";
1895 template <> const char *InstARM32Tst::Opcode = "tst";
1896 
dump(const Cfg * Func) const1897 void InstARM32::dump(const Cfg *Func) const {
1898   if (!BuildDefs::dump())
1899     return;
1900   Ostream &Str = Func->getContext()->getStrDump();
1901   Str << "[ARM32] ";
1902   Inst::dump(Func);
1903 }
1904 
emitMultiDestSingleSource(const Cfg * Func) const1905 void InstARM32Mov::emitMultiDestSingleSource(const Cfg *Func) const {
1906   if (!BuildDefs::dump())
1907     return;
1908   Ostream &Str = Func->getContext()->getStrEmit();
1909   Variable *DestLo = getDest();
1910   Variable *DestHi = getDestHi();
1911   auto *Src = llvm::cast<Variable>(getSrc(0));
1912 
1913   assert(DestHi->hasReg());
1914   assert(DestLo->hasReg());
1915   assert(Src->hasReg());
1916 
1917   Str << "\t"
1918          "vmov" << getPredicate() << "\t";
1919   DestLo->emit(Func);
1920   Str << ", ";
1921   DestHi->emit(Func);
1922   Str << ", ";
1923   Src->emit(Func);
1924 }
1925 
emitSingleDestMultiSource(const Cfg * Func) const1926 void InstARM32Mov::emitSingleDestMultiSource(const Cfg *Func) const {
1927   if (!BuildDefs::dump())
1928     return;
1929   Ostream &Str = Func->getContext()->getStrEmit();
1930   Variable *Dest = getDest();
1931   auto *SrcLo = llvm::cast<Variable>(getSrc(0));
1932   auto *SrcHi = llvm::cast<Variable>(getSrc(1));
1933 
1934   assert(SrcHi->hasReg());
1935   assert(SrcLo->hasReg());
1936   assert(Dest->hasReg());
1937   assert(getSrcSize() == 2);
1938 
1939   Str << "\t"
1940          "vmov" << getPredicate() << "\t";
1941   Dest->emit(Func);
1942   Str << ", ";
1943   SrcLo->emit(Func);
1944   Str << ", ";
1945   SrcHi->emit(Func);
1946 }
1947 
1948 namespace {
1949 
isVariableWithoutRegister(const Operand * Op)1950 bool isVariableWithoutRegister(const Operand *Op) {
1951   if (const auto *OpV = llvm::dyn_cast<Variable>(Op)) {
1952     return !OpV->hasReg();
1953   }
1954   return false;
1955 }
isMemoryAccess(Operand * Op)1956 bool isMemoryAccess(Operand *Op) {
1957   return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op);
1958 }
1959 
isMoveBetweenCoreAndVFPRegisters(Variable * Dest,Operand * Src)1960 bool isMoveBetweenCoreAndVFPRegisters(Variable *Dest, Operand *Src) {
1961   const Type DestTy = Dest->getType();
1962   const Type SrcTy = Src->getType();
1963   return !isVectorType(DestTy) && !isVectorType(SrcTy) &&
1964          (isScalarIntegerType(DestTy) == isScalarFloatingType(SrcTy));
1965 }
1966 
1967 } // end of anonymous namespace
1968 
emitSingleDestSingleSource(const Cfg * Func) const1969 void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
1970   if (!BuildDefs::dump())
1971     return;
1972   Ostream &Str = Func->getContext()->getStrEmit();
1973   Variable *Dest = getDest();
1974 
1975   if (!Dest->hasReg()) {
1976     llvm::report_fatal_error("mov can't store.");
1977   }
1978 
1979   Operand *Src0 = getSrc(0);
1980   if (isMemoryAccess(Src0)) {
1981     llvm::report_fatal_error("mov can't load.");
1982   }
1983 
1984   Type Ty = Dest->getType();
1985   const bool IsVector = isVectorType(Ty);
1986   const bool IsScalarFP = isScalarFloatingType(Ty);
1987   const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
1988   const bool IsVMove = (IsVector || IsScalarFP || CoreVFPMove);
1989   const char *Opcode = IsVMove ? "vmov" : "mov";
1990   // when vmov{c}'ing, we need to emit a width string. Otherwise, the
1991   // assembler might be tempted to assume we want a vector vmov{c}, and that
1992   // is disallowed because ARM.
1993   const char *WidthString = !CoreVFPMove ? getFpWidthString(Ty) : "";
1994   CondARM32::Cond Cond = getPredicate();
1995   if (IsVector)
1996     assert(CondARM32::isUnconditional(Cond) &&
1997            "Moves on vectors must be unconditional!");
1998   Str << "\t" << Opcode;
1999   if (IsVMove) {
2000     Str << Cond << WidthString;
2001   } else {
2002     Str << WidthString << Cond;
2003   }
2004   Str << "\t";
2005   Dest->emit(Func);
2006   Str << ", ";
2007   Src0->emit(Func);
2008 }
2009 
emit(const Cfg * Func) const2010 void InstARM32Mov::emit(const Cfg *Func) const {
2011   if (!BuildDefs::dump())
2012     return;
2013   assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
2014   if (isMultiDest()) {
2015     emitMultiDestSingleSource(Func);
2016     return;
2017   }
2018 
2019   if (isMultiSource()) {
2020     emitSingleDestMultiSource(Func);
2021     return;
2022   }
2023 
2024   emitSingleDestSingleSource(Func);
2025 }
2026 
emitIAS(const Cfg * Func) const2027 void InstARM32Mov::emitIAS(const Cfg *Func) const {
2028   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2029   const Variable *Dest = getDest();
2030   Operand *Src0 = getSrc(0);
2031   const CondARM32::Cond Cond = getPredicate();
2032   if (!Dest->hasReg()) {
2033     llvm::report_fatal_error("mov can't store.");
2034   }
2035   if (isMemoryAccess(Src0)) {
2036     llvm::report_fatal_error("mov can't load.");
2037   }
2038 
2039   assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
2040   if (isMultiDest()) {
2041     Asm->vmovrrd(Dest, getDestHi(), Src0, Cond);
2042     return;
2043   }
2044   if (isMultiSource()) {
2045     Asm->vmovdrr(Dest, Src0, getSrc(1), Cond);
2046     return;
2047   }
2048 
2049   const Type DestTy = Dest->getType();
2050   const Type SrcTy = Src0->getType();
2051   switch (DestTy) {
2052   default:
2053     break; // Error
2054   case IceType_i1:
2055   case IceType_i8:
2056   case IceType_i16:
2057   case IceType_i32:
2058     switch (SrcTy) {
2059     default:
2060       break; // Error
2061     case IceType_i1:
2062     case IceType_i8:
2063     case IceType_i16:
2064     case IceType_i32:
2065     case IceType_i64:
2066       Asm->mov(Dest, Src0, Cond);
2067       return;
2068     case IceType_f32:
2069       Asm->vmovrs(Dest, Src0, Cond);
2070       return;
2071     }
2072     break; // Error
2073   case IceType_i64:
2074     if (isScalarIntegerType(SrcTy)) {
2075       Asm->mov(Dest, Src0, Cond);
2076       return;
2077     }
2078     if (SrcTy == IceType_f64) {
2079       if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
2080         Asm->vmovdd(Dest, Var, Cond);
2081         return;
2082       }
2083       if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
2084         Asm->vmovd(Dest, FpImm, Cond);
2085         return;
2086       }
2087     }
2088     break; // Error
2089   case IceType_f32:
2090     switch (SrcTy) {
2091     default:
2092       break; // Error
2093     case IceType_i1:
2094     case IceType_i8:
2095     case IceType_i16:
2096     case IceType_i32:
2097       return Asm->vmovsr(Dest, Src0, Cond);
2098     case IceType_f32:
2099       if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
2100         Asm->vmovss(Dest, Var, Cond);
2101         return;
2102       }
2103       if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
2104         Asm->vmovs(Dest, FpImm, Cond);
2105         return;
2106       }
2107       break; // Error
2108     }
2109     break; // Error
2110   case IceType_f64:
2111     if (SrcTy == IceType_f64) {
2112       if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
2113         Asm->vmovdd(Dest, Var, Cond);
2114         return;
2115       }
2116       if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
2117         Asm->vmovd(Dest, FpImm, Cond);
2118         return;
2119       }
2120     }
2121     break; // Error
2122   // TODO(jpp): Remove vectors of i1.
2123   case IceType_v4i1:
2124   case IceType_v8i1:
2125   case IceType_v16i1:
2126   case IceType_v16i8:
2127   case IceType_v8i16:
2128   case IceType_v4i32:
2129   case IceType_v4f32:
2130     assert(CondARM32::isUnconditional(Cond) &&
2131            "Moves on vector must be unconditional!");
2132     if (isVectorType(SrcTy)) {
2133       // Mov between different Src and Dest types is used for bitcasting
2134       // vectors.  We still want to make sure SrcTy is a vector type.
2135       Asm->vorrq(Dest, Src0, Src0);
2136       return;
2137     } else if (const auto *C = llvm::dyn_cast<ConstantInteger32>(Src0)) {
2138       // Mov with constant argument, allowing the initializing all elements of
2139       // the vector.
2140       if (Asm->vmovqc(Dest, C))
2141         return;
2142     }
2143   }
2144   llvm::report_fatal_error("Mov: don't know how to move " +
2145                            typeStdString(SrcTy) + " to " +
2146                            typeStdString(DestTy));
2147 }
2148 
dump(const Cfg * Func) const2149 void InstARM32Mov::dump(const Cfg *Func) const {
2150   if (!BuildDefs::dump())
2151     return;
2152   assert(getSrcSize() == 1 || getSrcSize() == 2);
2153   Ostream &Str = Func->getContext()->getStrDump();
2154   Variable *Dest = getDest();
2155   Variable *DestHi = getDestHi();
2156   Dest->dump(Func);
2157   if (DestHi) {
2158     Str << ", ";
2159     DestHi->dump(Func);
2160   }
2161 
2162   dumpOpcodePred(Str, " = mov", getDest()->getType());
2163   Str << " ";
2164 
2165   dumpSources(Func);
2166 }
2167 
emit(const Cfg * Func) const2168 void InstARM32Br::emit(const Cfg *Func) const {
2169   if (!BuildDefs::dump())
2170     return;
2171   Ostream &Str = Func->getContext()->getStrEmit();
2172   Str << "\t"
2173          "b" << getPredicate() << "\t";
2174   if (Label) {
2175     Str << Label->getLabelName();
2176   } else {
2177     if (isUnconditionalBranch()) {
2178       Str << getTargetFalse()->getAsmName();
2179     } else {
2180       Str << getTargetTrue()->getAsmName();
2181       if (getTargetFalse()) {
2182         startNextInst(Func);
2183         Str << "\n\t"
2184             << "b"
2185             << "\t" << getTargetFalse()->getAsmName();
2186       }
2187     }
2188   }
2189 }
2190 
emitIAS(const Cfg * Func) const2191 void InstARM32Br::emitIAS(const Cfg *Func) const {
2192   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2193   if (Label) {
2194     Asm->b(Asm->getOrCreateLocalLabel(Label->getNumber()), getPredicate());
2195   } else if (isUnconditionalBranch()) {
2196     Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()),
2197            getPredicate());
2198   } else {
2199     Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex()),
2200            getPredicate());
2201     if (const CfgNode *False = getTargetFalse())
2202       Asm->b(Asm->getOrCreateCfgNodeLabel(False->getIndex()), CondARM32::AL);
2203   }
2204   if (Asm->needsTextFixup())
2205     emitUsingTextFixup(Func);
2206 }
2207 
dump(const Cfg * Func) const2208 void InstARM32Br::dump(const Cfg *Func) const {
2209   if (!BuildDefs::dump())
2210     return;
2211   Ostream &Str = Func->getContext()->getStrDump();
2212   Str << "br ";
2213 
2214   if (getPredicate() == CondARM32::AL) {
2215     if (Label) {
2216       Str << "label %" << Label->getLabelName();
2217     } else {
2218       Str << "label %" << getTargetFalse()->getName();
2219     }
2220     return;
2221   }
2222 
2223   if (Label) {
2224     Str << getPredicate() << ", label %" << Label->getLabelName();
2225   } else {
2226     Str << getPredicate() << ", label %" << getTargetTrue()->getName();
2227     if (getTargetFalse()) {
2228       Str << ", label %" << getTargetFalse()->getName();
2229     }
2230   }
2231 }
2232 
emit(const Cfg * Func) const2233 void InstARM32Call::emit(const Cfg *Func) const {
2234   if (!BuildDefs::dump())
2235     return;
2236   Ostream &Str = Func->getContext()->getStrEmit();
2237   assert(getSrcSize() == 1);
2238   if (llvm::isa<ConstantInteger32>(getCallTarget())) {
2239     // This shouldn't happen (typically have to copy the full 32-bits to a
2240     // register and do an indirect jump).
2241     llvm::report_fatal_error("ARM32Call to ConstantInteger32");
2242   } else if (const auto *CallTarget =
2243                  llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
2244     // Calls only have 24-bits, but the linker should insert veneers to extend
2245     // the range if needed.
2246     Str << "\t"
2247            "bl"
2248            "\t";
2249     CallTarget->emitWithoutPrefix(Func->getTarget());
2250   } else {
2251     Str << "\t"
2252            "blx"
2253            "\t";
2254     getCallTarget()->emit(Func);
2255   }
2256 }
2257 
emitIAS(const Cfg * Func) const2258 void InstARM32Call::emitIAS(const Cfg *Func) const {
2259   assert(getSrcSize() == 1);
2260   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2261   if (llvm::isa<ConstantInteger32>(getCallTarget())) {
2262     // This shouldn't happen (typically have to copy the full 32-bits to a
2263     // register and do an indirect jump).
2264     llvm::report_fatal_error("ARM32Call to ConstantInteger32");
2265   } else if (const auto *CallTarget =
2266                  llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
2267     // Calls only have 24-bits, but the linker should insert veneers to extend
2268     // the range if needed.
2269     Asm->bl(CallTarget);
2270   } else {
2271     Asm->blx(getCallTarget());
2272   }
2273   if (Asm->needsTextFixup())
2274     return emitUsingTextFixup(Func);
2275 }
2276 
dump(const Cfg * Func) const2277 void InstARM32Call::dump(const Cfg *Func) const {
2278   if (!BuildDefs::dump())
2279     return;
2280   Ostream &Str = Func->getContext()->getStrDump();
2281   if (getDest()) {
2282     dumpDest(Func);
2283     Str << " = ";
2284   }
2285   Str << "call ";
2286   getCallTarget()->dump(Func);
2287 }
2288 
emit(const Cfg * Func) const2289 void InstARM32Label::emit(const Cfg *Func) const {
2290   if (!BuildDefs::dump())
2291     return;
2292   // A label is not really an instruction. Hence, we need to fix the
2293   // emitted text size.
2294   if (auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>())
2295     Asm->decEmitTextSize(InstSize);
2296   Ostream &Str = Func->getContext()->getStrEmit();
2297   Str << getLabelName() << ":";
2298 }
2299 
emitIAS(const Cfg * Func) const2300 void InstARM32Label::emitIAS(const Cfg *Func) const {
2301   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2302   Asm->bindLocalLabel(this, Number);
2303   if (OffsetReloc != nullptr) {
2304     Asm->bindRelocOffset(OffsetReloc);
2305   }
2306   if (Asm->needsTextFixup())
2307     emitUsingTextFixup(Func);
2308 }
2309 
dump(const Cfg * Func) const2310 void InstARM32Label::dump(const Cfg *Func) const {
2311   if (!BuildDefs::dump())
2312     return;
2313   Ostream &Str = Func->getContext()->getStrDump();
2314   Str << getLabelName() << ":";
2315 }
2316 
2317 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const2318 void InstARM32LoadBase<K>::emitIAS(const Cfg *Func) const {
2319   emitUsingTextFixup(Func);
2320 }
2321 
emit(const Cfg * Func) const2322 template <> void InstARM32Ldr::emit(const Cfg *Func) const {
2323   if (!BuildDefs::dump())
2324     return;
2325   Ostream &Str = Func->getContext()->getStrEmit();
2326   assert(getSrcSize() == 1);
2327   assert(getDest()->hasReg());
2328   Variable *Dest = getDest();
2329   Type Ty = Dest->getType();
2330   const bool IsVector = isVectorType(Ty);
2331   const bool IsScalarFloat = isScalarFloatingType(Ty);
2332   const char *ActualOpcode =
2333       IsVector ? "vld1" : (IsScalarFloat ? "vldr" : "ldr");
2334   const char *WidthString = IsVector ? "" : getWidthString(Ty);
2335   Str << "\t" << ActualOpcode;
2336   const bool IsVInst = IsVector || IsScalarFloat;
2337   if (IsVInst) {
2338     Str << getPredicate() << WidthString;
2339   } else {
2340     Str << WidthString << getPredicate();
2341   }
2342   if (IsVector)
2343     Str << "." << getVecElmtBitsize(Ty);
2344   Str << "\t";
2345   getDest()->emit(Func);
2346   Str << ", ";
2347   getSrc(0)->emit(Func);
2348 }
2349 
emit(const Cfg * Func) const2350 template <> void InstARM32Vldr1d::emit(const Cfg *Func) const {
2351   if (!BuildDefs::dump())
2352     return;
2353   Ostream &Str = Func->getContext()->getStrEmit();
2354   assert(getSrcSize() == 1);
2355   assert(getDest()->hasReg());
2356   Variable *Dest = getDest();
2357   Type Ty = Dest->getType();
2358   const bool IsVector = isVectorType(Ty);
2359   const bool IsScalarFloat = isScalarFloatingType(Ty);
2360   const char *ActualOpcode =
2361       IsVector ? "vld1" : (IsScalarFloat ? "vldr" : "ldr");
2362   const char *WidthString = IsVector ? "" : getWidthString(Ty);
2363   Str << "\t" << ActualOpcode;
2364   const bool IsVInst = IsVector || IsScalarFloat;
2365   if (IsVInst) {
2366     Str << getPredicate() << WidthString;
2367   } else {
2368     Str << WidthString << getPredicate();
2369   }
2370   if (IsVector)
2371     Str << "." << getVecElmtBitsize(Ty);
2372   Str << "\t";
2373   getDest()->emit(Func);
2374   Str << ", ";
2375   getSrc(0)->emit(Func);
2376 }
2377 
emit(const Cfg * Func) const2378 template <> void InstARM32Vldr1q::emit(const Cfg *Func) const {
2379   if (!BuildDefs::dump())
2380     return;
2381   Ostream &Str = Func->getContext()->getStrEmit();
2382   assert(getSrcSize() == 1);
2383   assert(getDest()->hasReg());
2384   Variable *Dest = getDest();
2385   Type Ty = Dest->getType();
2386   const bool IsVector = isVectorType(Ty);
2387   const bool IsScalarFloat = isScalarFloatingType(Ty);
2388   const char *ActualOpcode =
2389       IsVector ? "vld1" : (IsScalarFloat ? "vldr" : "ldr");
2390   const char *WidthString = IsVector ? "" : getWidthString(Ty);
2391   Str << "\t" << ActualOpcode;
2392   const bool IsVInst = IsVector || IsScalarFloat;
2393   if (IsVInst) {
2394     Str << getPredicate() << WidthString;
2395   } else {
2396     Str << WidthString << getPredicate();
2397   }
2398   if (IsVector)
2399     Str << "." << getVecElmtBitsize(Ty);
2400   Str << "\t";
2401   getDest()->emit(Func);
2402   Str << ", ";
2403   getSrc(0)->emit(Func);
2404 }
2405 
emitIAS(const Cfg * Func) const2406 template <> void InstARM32Ldr::emitIAS(const Cfg *Func) const {
2407   assert(getSrcSize() == 1);
2408   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2409   Variable *Dest = getDest();
2410   const Type DestTy = Dest->getType();
2411   switch (DestTy) {
2412   default:
2413     llvm::report_fatal_error("Ldr on unknown type: " + typeStdString(DestTy));
2414   case IceType_i1:
2415   case IceType_i8:
2416   case IceType_i16:
2417   case IceType_i32:
2418   case IceType_i64:
2419     Asm->ldr(Dest, getSrc(0), getPredicate(), Func->getTarget());
2420     break;
2421   case IceType_f32:
2422     Asm->vldrs(Dest, getSrc(0), getPredicate(), Func->getTarget());
2423     break;
2424   case IceType_f64:
2425     Asm->vldrd(Dest, getSrc(0), getPredicate(), Func->getTarget());
2426     break;
2427   case IceType_v16i8:
2428   case IceType_v8i16:
2429   case IceType_v4i32:
2430   case IceType_v4f32:
2431   case IceType_v16i1:
2432   case IceType_v8i1:
2433   case IceType_v4i1:
2434     Asm->vld1qr(getVecElmtBitsize(DestTy), Dest, getSrc(0), Func->getTarget());
2435     break;
2436   }
2437 }
2438 
emitIAS(const Cfg * Func) const2439 template <> void InstARM32Vldr1d::emitIAS(const Cfg *Func) const {
2440   assert(getSrcSize() == 1);
2441   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2442   Variable *Dest = getDest();
2443   Asm->vld1(32, Dest, getSrc(0), Func->getTarget());
2444 }
2445 
emitIAS(const Cfg * Func) const2446 template <> void InstARM32Vldr1q::emitIAS(const Cfg *Func) const {
2447   assert(getSrcSize() == 1);
2448   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2449   Variable *Dest = getDest();
2450   Asm->vld1(64, Dest, getSrc(0), Func->getTarget());
2451 }
2452 
emit(const Cfg * Func) const2453 template <> void InstARM32Ldrex::emit(const Cfg *Func) const {
2454   if (!BuildDefs::dump())
2455     return;
2456   Ostream &Str = Func->getContext()->getStrEmit();
2457   assert(getSrcSize() == 1);
2458   assert(getDest()->hasReg());
2459   Variable *Dest = getDest();
2460   Type DestTy = Dest->getType();
2461   assert(isScalarIntegerType(DestTy));
2462   const char *WidthString = getWidthString(DestTy);
2463   Str << "\t" << Opcode << WidthString << getPredicate() << "\t";
2464   getDest()->emit(Func);
2465   Str << ", ";
2466   getSrc(0)->emit(Func);
2467 }
2468 
emitIAS(const Cfg * Func) const2469 template <> void InstARM32Ldrex::emitIAS(const Cfg *Func) const {
2470   assert(getSrcSize() == 1);
2471   assert(getDest()->hasReg());
2472   Variable *Dest = getDest();
2473   assert(isScalarIntegerType(Dest->getType()));
2474   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2475   Asm->ldrex(Dest, getSrc(0), getPredicate(), Func->getTarget());
2476   if (Asm->needsTextFixup())
2477     emitUsingTextFixup(Func);
2478 }
2479 
2480 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const2481 void InstARM32TwoAddrGPR<K>::emitIAS(const Cfg *Func) const {
2482   emitUsingTextFixup(Func);
2483 }
2484 
2485 template <InstARM32::InstKindARM32 K, bool Nws>
emitIAS(const Cfg * Func) const2486 void InstARM32UnaryopGPR<K, Nws>::emitIAS(const Cfg *Func) const {
2487   emitUsingTextFixup(Func);
2488 }
2489 
emitIAS(const Cfg * Func) const2490 template <> void InstARM32Rbit::emitIAS(const Cfg *Func) const {
2491   assert(getSrcSize() == 1);
2492   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2493   Asm->rbit(getDest(), getSrc(0), getPredicate());
2494   if (Asm->needsTextFixup())
2495     emitUsingTextFixup(Func);
2496 }
2497 
emitIAS(const Cfg * Func) const2498 template <> void InstARM32Rev::emitIAS(const Cfg *Func) const {
2499   assert(getSrcSize() == 1);
2500   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2501   Asm->rev(getDest(), getSrc(0), getPredicate());
2502   if (Asm->needsTextFixup())
2503     emitUsingTextFixup(Func);
2504 }
2505 
emit(const Cfg * Func) const2506 template <> void InstARM32Movw::emit(const Cfg *Func) const {
2507   if (!BuildDefs::dump())
2508     return;
2509   Ostream &Str = Func->getContext()->getStrEmit();
2510   assert(getSrcSize() == 1);
2511   Str << "\t" << Opcode << getPredicate() << "\t";
2512   getDest()->emit(Func);
2513   Str << ", ";
2514   auto *Src0 = llvm::cast<Constant>(getSrc(0));
2515   if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
2516     Str << "#:lower16:";
2517     CR->emitWithoutPrefix(Func->getTarget());
2518     if (getFlags().getUseNonsfi()) {
2519       Str << " - .";
2520     }
2521   } else {
2522     Src0->emit(Func);
2523   }
2524 }
2525 
emitIAS(const Cfg * Func) const2526 template <> void InstARM32Movw::emitIAS(const Cfg *Func) const {
2527   assert(getSrcSize() == 1);
2528   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2529   Asm->movw(getDest(), getSrc(0), getPredicate());
2530   if (Asm->needsTextFixup())
2531     emitUsingTextFixup(Func);
2532 }
2533 
emit(const Cfg * Func) const2534 template <> void InstARM32Movt::emit(const Cfg *Func) const {
2535   if (!BuildDefs::dump())
2536     return;
2537   Ostream &Str = Func->getContext()->getStrEmit();
2538   assert(getSrcSize() == 2);
2539   Variable *Dest = getDest();
2540   auto *Src1 = llvm::cast<Constant>(getSrc(1));
2541   Str << "\t" << Opcode << getPredicate() << "\t";
2542   Dest->emit(Func);
2543   Str << ", ";
2544   if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src1)) {
2545     Str << "#:upper16:";
2546     CR->emitWithoutPrefix(Func->getTarget());
2547     if (getFlags().getUseNonsfi()) {
2548       Str << " - .";
2549     }
2550   } else {
2551     Src1->emit(Func);
2552   }
2553 }
2554 
emitIAS(const Cfg * Func) const2555 template <> void InstARM32Movt::emitIAS(const Cfg *Func) const {
2556   assert(getSrcSize() == 2);
2557   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2558   Asm->movt(getDest(), getSrc(1), getPredicate());
2559   if (Asm->needsTextFixup())
2560     emitUsingTextFixup(Func);
2561 }
2562 
emitIAS(const Cfg * Func) const2563 template <> void InstARM32Clz::emitIAS(const Cfg *Func) const {
2564   assert(getSrcSize() == 1);
2565   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2566   Asm->clz(getDest(), getSrc(0), getPredicate());
2567   if (Asm->needsTextFixup())
2568     emitUsingTextFixup(Func);
2569 }
2570 
emitIAS(const Cfg * Func) const2571 template <> void InstARM32Mvn::emitIAS(const Cfg *Func) const {
2572   assert(getSrcSize() == 1);
2573   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2574   Asm->mvn(getDest(), getSrc(0), getPredicate());
2575   if (Asm->needsTextFixup())
2576     emitUsingTextFixup(Func);
2577 }
2578 
emitIAS(const Cfg * Func) const2579 template <> void InstARM32Sxt::emitIAS(const Cfg *Func) const {
2580   assert(getSrcSize() == 1);
2581   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2582   Asm->sxt(getDest(), getSrc(0), getPredicate());
2583   if (Asm->needsTextFixup())
2584     emitUsingTextFixup(Func);
2585 }
2586 
emitIAS(const Cfg * Func) const2587 template <> void InstARM32Uxt::emitIAS(const Cfg *Func) const {
2588   assert(getSrcSize() == 1);
2589   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2590   Asm->uxt(getDest(), getSrc(0), getPredicate());
2591   if (Asm->needsTextFixup())
2592     emitUsingTextFixup(Func);
2593 }
2594 
2595 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const2596 void InstARM32UnaryopFP<K>::emitIAS(const Cfg *Func) const {
2597   emitUsingTextFixup(Func);
2598 }
2599 
2600 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const2601 void InstARM32UnaryopSignAwareFP<K>::emitIAS(const Cfg *Func) const {
2602   InstARM32::emitUsingTextFixup(Func);
2603 }
2604 
emitIAS(const Cfg * Func) const2605 template <> void InstARM32Vsqrt::emitIAS(const Cfg *Func) const {
2606   assert(getSrcSize() == 1);
2607   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2608   const Operand *Dest = getDest();
2609   switch (Dest->getType()) {
2610   case IceType_f32:
2611     Asm->vsqrts(Dest, getSrc(0), getPredicate());
2612     break;
2613   case IceType_f64:
2614     Asm->vsqrtd(Dest, getSrc(0), getPredicate());
2615     break;
2616   default:
2617     llvm::report_fatal_error("Vsqrt of non-floating type");
2618   }
2619   if (Asm->needsTextFixup())
2620     emitUsingTextFixup(Func);
2621 }
2622 
getGPROpcode() const2623 const char *InstARM32Pop::getGPROpcode() const { return "pop"; }
2624 
getSRegOpcode() const2625 const char *InstARM32Pop::getSRegOpcode() const { return "vpop"; }
2626 
getStackReg(SizeT Index) const2627 Variable *InstARM32Pop::getStackReg(SizeT Index) const { return Dests[Index]; }
2628 
getNumStackRegs() const2629 SizeT InstARM32Pop::getNumStackRegs() const { return Dests.size(); }
2630 
emitSingleGPR(const Cfg * Func,const EmitForm Form,const Variable * Reg) const2631 void InstARM32Pop::emitSingleGPR(const Cfg *Func, const EmitForm Form,
2632                                  const Variable *Reg) const {
2633   switch (Form) {
2634   case Emit_Text:
2635     emitGPRsAsText(Func);
2636     return;
2637   case Emit_Binary:
2638     Func->getAssembler<ARM32::AssemblerARM32>()->pop(Reg, CondARM32::AL);
2639     return;
2640   }
2641 }
2642 
emitMultipleGPRs(const Cfg * Func,const EmitForm Form,IValueT Registers) const2643 void InstARM32Pop::emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
2644                                     IValueT Registers) const {
2645   switch (Form) {
2646   case Emit_Text:
2647     emitGPRsAsText(Func);
2648     return;
2649   case Emit_Binary:
2650     Func->getAssembler<ARM32::AssemblerARM32>()->popList(Registers,
2651                                                          CondARM32::AL);
2652     return;
2653   }
2654 }
2655 
emitSRegs(const Cfg * Func,const EmitForm Form,const Variable * BaseReg,SizeT RegCount) const2656 void InstARM32Pop::emitSRegs(const Cfg *Func, const EmitForm Form,
2657                              const Variable *BaseReg, SizeT RegCount) const {
2658   switch (Form) {
2659   case Emit_Text:
2660     emitSRegsAsText(Func, BaseReg, RegCount);
2661     return;
2662   case Emit_Binary:
2663     Func->getAssembler<ARM32::AssemblerARM32>()->vpop(BaseReg, RegCount,
2664                                                       CondARM32::AL);
2665     return;
2666   }
2667 }
2668 
getGPROpcode() const2669 const char *InstARM32Push::getGPROpcode() const { return "push"; }
2670 
getSRegOpcode() const2671 const char *InstARM32Push::getSRegOpcode() const { return "vpush"; }
2672 
getStackReg(SizeT Index) const2673 Variable *InstARM32Push::getStackReg(SizeT Index) const {
2674   return llvm::cast<Variable>(getSrc(Index));
2675 }
2676 
getNumStackRegs() const2677 SizeT InstARM32Push::getNumStackRegs() const { return getSrcSize(); }
2678 
emitSingleGPR(const Cfg * Func,const EmitForm Form,const Variable * Reg) const2679 void InstARM32Push::emitSingleGPR(const Cfg *Func, const EmitForm Form,
2680                                   const Variable *Reg) const {
2681   switch (Form) {
2682   case Emit_Text:
2683     emitGPRsAsText(Func);
2684     return;
2685   case Emit_Binary:
2686     Func->getAssembler<ARM32::AssemblerARM32>()->push(Reg, CondARM32::AL);
2687     return;
2688   }
2689 }
2690 
emitMultipleGPRs(const Cfg * Func,const EmitForm Form,IValueT Registers) const2691 void InstARM32Push::emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
2692                                      IValueT Registers) const {
2693   switch (Form) {
2694   case Emit_Text:
2695     emitGPRsAsText(Func);
2696     return;
2697   case Emit_Binary:
2698     Func->getAssembler<ARM32::AssemblerARM32>()->pushList(Registers,
2699                                                           CondARM32::AL);
2700     return;
2701   }
2702 }
2703 
emitSRegs(const Cfg * Func,const EmitForm Form,const Variable * BaseReg,SizeT RegCount) const2704 void InstARM32Push::emitSRegs(const Cfg *Func, const EmitForm Form,
2705                               const Variable *BaseReg, SizeT RegCount) const {
2706   switch (Form) {
2707   case Emit_Text:
2708     emitSRegsAsText(Func, BaseReg, RegCount);
2709     return;
2710   case Emit_Binary:
2711     Func->getAssembler<ARM32::AssemblerARM32>()->vpush(BaseReg, RegCount,
2712                                                        CondARM32::AL);
2713     return;
2714   }
2715 }
2716 
emit(const Cfg * Func) const2717 void InstARM32Ret::emit(const Cfg *Func) const {
2718   if (!BuildDefs::dump())
2719     return;
2720   assert(getSrcSize() > 0);
2721   auto *LR = llvm::cast<Variable>(getSrc(0));
2722   assert(LR->hasReg());
2723   assert(LR->getRegNum() == RegARM32::Reg_lr);
2724   Ostream &Str = Func->getContext()->getStrEmit();
2725   Str << "\t"
2726          "bx"
2727          "\t";
2728   LR->emit(Func);
2729 }
2730 
emitIAS(const Cfg * Func) const2731 void InstARM32Ret::emitIAS(const Cfg *Func) const {
2732   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2733   Asm->bx(RegARM32::Encoded_Reg_lr);
2734   if (Asm->needsTextFixup())
2735     emitUsingTextFixup(Func);
2736 }
2737 
dump(const Cfg * Func) const2738 void InstARM32Ret::dump(const Cfg *Func) const {
2739   if (!BuildDefs::dump())
2740     return;
2741   Ostream &Str = Func->getContext()->getStrDump();
2742   Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType());
2743   Str << "ret." << Ty << " ";
2744   dumpSources(Func);
2745 }
2746 
emit(const Cfg * Func) const2747 void InstARM32Str::emit(const Cfg *Func) const {
2748   if (!BuildDefs::dump())
2749     return;
2750   Ostream &Str = Func->getContext()->getStrEmit();
2751   assert(getSrcSize() == 2);
2752   Type Ty = getSrc(0)->getType();
2753   const bool IsVectorStore = isVectorType(Ty);
2754   const bool IsScalarFloat = isScalarFloatingType(Ty);
2755   const char *Opcode =
2756       IsVectorStore ? "vst1" : (IsScalarFloat ? "vstr" : "str");
2757   Str << "\t" << Opcode;
2758   const bool IsVInst = IsVectorStore || IsScalarFloat;
2759   if (IsVInst) {
2760     Str << getPredicate() << getWidthString(Ty);
2761   } else {
2762     Str << getWidthString(Ty) << getPredicate();
2763   }
2764   if (IsVectorStore)
2765     Str << "." << getVecElmtBitsize(Ty);
2766   Str << "\t";
2767   getSrc(0)->emit(Func);
2768   Str << ", ";
2769   getSrc(1)->emit(Func);
2770 }
2771 
emitIAS(const Cfg * Func) const2772 void InstARM32Str::emitIAS(const Cfg *Func) const {
2773   assert(getSrcSize() == 2);
2774   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2775   const Operand *Src0 = getSrc(0);
2776   const Operand *Src1 = getSrc(1);
2777   Type Ty = Src0->getType();
2778   switch (Ty) {
2779   default:
2780     llvm::report_fatal_error("Str on unknown type: " + typeStdString(Ty));
2781   case IceType_i1:
2782   case IceType_i8:
2783   case IceType_i16:
2784   case IceType_i32:
2785   case IceType_i64:
2786     Asm->str(Src0, Src1, getPredicate(), Func->getTarget());
2787     break;
2788   case IceType_f32:
2789     Asm->vstrs(Src0, Src1, getPredicate(), Func->getTarget());
2790     break;
2791   case IceType_f64:
2792     Asm->vstrd(Src0, Src1, getPredicate(), Func->getTarget());
2793     break;
2794   case IceType_v16i8:
2795   case IceType_v8i16:
2796   case IceType_v4i32:
2797   case IceType_v4f32:
2798   case IceType_v16i1:
2799   case IceType_v8i1:
2800   case IceType_v4i1:
2801     Asm->vst1qr(getVecElmtBitsize(Ty), Src0, Src1, Func->getTarget());
2802     break;
2803   }
2804 }
2805 
dump(const Cfg * Func) const2806 void InstARM32Str::dump(const Cfg *Func) const {
2807   if (!BuildDefs::dump())
2808     return;
2809   Ostream &Str = Func->getContext()->getStrDump();
2810   Type Ty = getSrc(0)->getType();
2811   dumpOpcodePred(Str, "str", Ty);
2812   Str << " ";
2813   getSrc(1)->dump(Func);
2814   Str << ", ";
2815   getSrc(0)->dump(Func);
2816 }
2817 
emit(const Cfg * Func) const2818 void InstARM32Strex::emit(const Cfg *Func) const {
2819   if (!BuildDefs::dump())
2820     return;
2821   assert(getSrcSize() == 2);
2822   Type Ty = getSrc(0)->getType();
2823   assert(isScalarIntegerType(Ty));
2824   Variable *Dest = getDest();
2825   Ostream &Str = Func->getContext()->getStrEmit();
2826   static constexpr char Opcode[] = "strex";
2827   const char *WidthString = getWidthString(Ty);
2828   Str << "\t" << Opcode << WidthString << getPredicate() << "\t";
2829   Dest->emit(Func);
2830   Str << ", ";
2831   emitSources(Func);
2832 }
2833 
emitIAS(const Cfg * Func) const2834 void InstARM32Strex::emitIAS(const Cfg *Func) const {
2835   assert(getSrcSize() == 2);
2836   const Operand *Src0 = getSrc(0);
2837   assert(isScalarIntegerType(Src0->getType()));
2838   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2839   Asm->strex(Dest, Src0, getSrc(1), getPredicate(), Func->getTarget());
2840   if (Asm->needsTextFixup())
2841     emitUsingTextFixup(Func);
2842 }
2843 
dump(const Cfg * Func) const2844 void InstARM32Strex::dump(const Cfg *Func) const {
2845   if (!BuildDefs::dump())
2846     return;
2847   Ostream &Str = Func->getContext()->getStrDump();
2848   Variable *Dest = getDest();
2849   Dest->dump(Func);
2850   Str << " = ";
2851   Type Ty = getSrc(0)->getType();
2852   dumpOpcodePred(Str, "strex", Ty);
2853   Str << " ";
2854   getSrc(1)->dump(Func);
2855   Str << ", ";
2856   getSrc(0)->dump(Func);
2857 }
2858 
emit(const Cfg * Func) const2859 void InstARM32Vstr1::emit(const Cfg *Func) const {
2860   if (!BuildDefs::dump())
2861     return;
2862   Ostream &Str = Func->getContext()->getStrEmit();
2863   assert(getSrcSize() == 2);
2864   Type Ty = getSrc(0)->getType();
2865   const bool IsVectorStore = isVectorType(Ty);
2866   const bool IsScalarFloat = isScalarFloatingType(Ty);
2867   const char *Opcode =
2868       IsVectorStore ? "vst1" : (IsScalarFloat ? "vstr" : "str");
2869   Str << "\t" << Opcode;
2870   const bool IsVInst = IsVectorStore || IsScalarFloat;
2871   if (IsVInst) {
2872     Str << getPredicate() << getWidthString(Ty);
2873   } else {
2874     Str << getWidthString(Ty) << getPredicate();
2875   }
2876   if (IsVectorStore)
2877     Str << "." << getVecElmtBitsize(Ty);
2878   Str << "\t";
2879   getSrc(0)->emit(Func);
2880   Str << ", ";
2881   getSrc(1)->emit(Func);
2882 }
2883 
emitIAS(const Cfg * Func) const2884 void InstARM32Vstr1::emitIAS(const Cfg *Func) const {
2885   assert(getSrcSize() == 2);
2886   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2887   const Operand *Src0 = getSrc(0);
2888   const Operand *Src1 = getSrc(1);
2889   Asm->vst1(Size, Src0, Src1, Func->getTarget());
2890 }
2891 
dump(const Cfg * Func) const2892 void InstARM32Vstr1::dump(const Cfg *Func) const {
2893   if (!BuildDefs::dump())
2894     return;
2895   Ostream &Str = Func->getContext()->getStrDump();
2896   Type Ty = getSrc(0)->getType();
2897   dumpOpcodePred(Str, "str", Ty);
2898   Str << " ";
2899   getSrc(1)->dump(Func);
2900   Str << ", ";
2901   getSrc(0)->dump(Func);
2902 }
2903 
emit(const Cfg * Func) const2904 void InstARM32Vdup::emit(const Cfg *Func) const {
2905   if (!BuildDefs::dump())
2906     return;
2907   Ostream &Str = Func->getContext()->getStrEmit();
2908   assert(getSrcSize() == 2);
2909   Type Ty = getSrc(0)->getType();
2910   const char *Opcode = "vdup";
2911   Str << "\t" << Opcode;
2912   Str << getPredicate() << "." << getWidthString(Ty) << getVecElmtBitsize(Ty);
2913   Str << "\t";
2914   getSrc(0)->emit(Func);
2915   Str << ", ";
2916   getSrc(1)->emit(Func);
2917   Str << ", " << Idx;
2918 }
2919 
emitIAS(const Cfg * Func) const2920 void InstARM32Vdup::emitIAS(const Cfg *Func) const {
2921   assert(getSrcSize() == 1);
2922   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2923   const Operand *Dest = getDest();
2924   const Operand *Src = getSrc(0);
2925   Type DestTy = Dest->getType();
2926   Asm->vdup(typeElementType(DestTy), Dest, Src, Idx);
2927 }
2928 
dump(const Cfg * Func) const2929 void InstARM32Vdup::dump(const Cfg *Func) const {
2930   if (!BuildDefs::dump())
2931     return;
2932   Ostream &Str = Func->getContext()->getStrDump();
2933   dumpDest(Func);
2934   Str << " = ";
2935   dumpOpcodePred(Str, "vdup", getDest()->getType());
2936   Str << " ";
2937   dumpSources(Func);
2938   Str << ", " << Idx;
2939 }
2940 
emit(const Cfg * Func) const2941 void InstARM32Trap::emit(const Cfg *Func) const {
2942   if (!BuildDefs::dump())
2943     return;
2944   Ostream &Str = Func->getContext()->getStrEmit();
2945   assert(getSrcSize() == 0);
2946   // There isn't a mnemonic for the special NaCl Trap encoding, so dump
2947   // the raw bytes.
2948   Str << "\t.long 0x";
2949   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2950   for (uint8_t I : Asm->getNonExecBundlePadding()) {
2951     Str.write_hex(I);
2952   }
2953 }
2954 
emitIAS(const Cfg * Func) const2955 void InstARM32Trap::emitIAS(const Cfg *Func) const {
2956   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2957   Asm->trap();
2958   assert(!Asm->needsTextFixup());
2959 }
2960 
dump(const Cfg * Func) const2961 void InstARM32Trap::dump(const Cfg *Func) const {
2962   if (!BuildDefs::dump())
2963     return;
2964   Ostream &Str = Func->getContext()->getStrDump();
2965   Str << "trap";
2966 }
2967 
emit(const Cfg * Func) const2968 void InstARM32Umull::emit(const Cfg *Func) const {
2969   if (!BuildDefs::dump())
2970     return;
2971   Ostream &Str = Func->getContext()->getStrEmit();
2972   assert(getSrcSize() == 2);
2973   assert(getDest()->hasReg());
2974   Str << "\t"
2975          "umull" << getPredicate() << "\t";
2976   getDest()->emit(Func);
2977   Str << ", ";
2978   DestHi->emit(Func);
2979   Str << ", ";
2980   getSrc(0)->emit(Func);
2981   Str << ", ";
2982   getSrc(1)->emit(Func);
2983 }
2984 
emitIAS(const Cfg * Func) const2985 void InstARM32Umull::emitIAS(const Cfg *Func) const {
2986   assert(getSrcSize() == 2);
2987   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2988   Asm->umull(getDest(), DestHi, getSrc(0), getSrc(1), getPredicate());
2989   if (Asm->needsTextFixup())
2990     emitUsingTextFixup(Func);
2991 }
2992 
dump(const Cfg * Func) const2993 void InstARM32Umull::dump(const Cfg *Func) const {
2994   if (!BuildDefs::dump())
2995     return;
2996   Ostream &Str = Func->getContext()->getStrDump();
2997   dumpDest(Func);
2998   Str << " = ";
2999   dumpOpcodePred(Str, "umull", getDest()->getType());
3000   Str << " ";
3001   dumpSources(Func);
3002 }
3003 
3004 namespace {
vcvtVariantSuffix(const InstARM32Vcvt::VcvtVariant Variant)3005 const char *vcvtVariantSuffix(const InstARM32Vcvt::VcvtVariant Variant) {
3006   switch (Variant) {
3007   case InstARM32Vcvt::S2si:
3008     return ".s32.f32";
3009   case InstARM32Vcvt::S2ui:
3010     return ".u32.f32";
3011   case InstARM32Vcvt::Si2s:
3012     return ".f32.s32";
3013   case InstARM32Vcvt::Ui2s:
3014     return ".f32.u32";
3015   case InstARM32Vcvt::D2si:
3016     return ".s32.f64";
3017   case InstARM32Vcvt::D2ui:
3018     return ".u32.f64";
3019   case InstARM32Vcvt::Si2d:
3020     return ".f64.s32";
3021   case InstARM32Vcvt::Ui2d:
3022     return ".f64.u32";
3023   case InstARM32Vcvt::S2d:
3024     return ".f64.f32";
3025   case InstARM32Vcvt::D2s:
3026     return ".f32.f64";
3027   case InstARM32Vcvt::Vs2si:
3028     return ".s32.f32";
3029   case InstARM32Vcvt::Vs2ui:
3030     return ".u32.f32";
3031   case InstARM32Vcvt::Vsi2s:
3032     return ".f32.s32";
3033   case InstARM32Vcvt::Vui2s:
3034     return ".f32.u32";
3035   }
3036   llvm::report_fatal_error("Invalid VcvtVariant enum.");
3037 }
3038 } // end of anonymous namespace
3039 
emit(const Cfg * Func) const3040 void InstARM32Vcvt::emit(const Cfg *Func) const {
3041   if (!BuildDefs::dump())
3042     return;
3043   Ostream &Str = Func->getContext()->getStrEmit();
3044   assert(getSrcSize() == 1);
3045   assert(getDest()->hasReg());
3046   Str << "\t"
3047          "vcvt" << getPredicate() << vcvtVariantSuffix(Variant) << "\t";
3048   getDest()->emit(Func);
3049   Str << ", ";
3050   getSrc(0)->emit(Func);
3051 }
3052 
emitIAS(const Cfg * Func) const3053 void InstARM32Vcvt::emitIAS(const Cfg *Func) const {
3054   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3055   switch (Variant) {
3056   case S2si:
3057     Asm->vcvtis(getDest(), getSrc(0), getPredicate());
3058     break;
3059   case S2ui:
3060     Asm->vcvtus(getDest(), getSrc(0), getPredicate());
3061     break;
3062   case Si2s:
3063     Asm->vcvtsi(getDest(), getSrc(0), getPredicate());
3064     break;
3065   case Ui2s:
3066     Asm->vcvtsu(getDest(), getSrc(0), getPredicate());
3067     break;
3068   case D2si:
3069     Asm->vcvtid(getDest(), getSrc(0), getPredicate());
3070     break;
3071   case D2ui:
3072     Asm->vcvtud(getDest(), getSrc(0), getPredicate());
3073     break;
3074   case Si2d:
3075     Asm->vcvtdi(getDest(), getSrc(0), getPredicate());
3076     break;
3077   case Ui2d:
3078     Asm->vcvtdu(getDest(), getSrc(0), getPredicate());
3079     break;
3080   case S2d:
3081     Asm->vcvtds(getDest(), getSrc(0), getPredicate());
3082     break;
3083   case D2s:
3084     Asm->vcvtsd(getDest(), getSrc(0), getPredicate());
3085     break;
3086   case Vs2si:
3087     Asm->vcvtqsi(getDest(), getSrc(0));
3088     break;
3089   case Vs2ui:
3090     Asm->vcvtqsu(getDest(), getSrc(0));
3091     break;
3092   case Vsi2s:
3093     Asm->vcvtqis(getDest(), getSrc(0));
3094     break;
3095   case Vui2s:
3096     Asm->vcvtqus(getDest(), getSrc(0));
3097     break;
3098   }
3099   assert(!Asm->needsTextFixup());
3100 }
3101 
dump(const Cfg * Func) const3102 void InstARM32Vcvt::dump(const Cfg *Func) const {
3103   if (!BuildDefs::dump())
3104     return;
3105   Ostream &Str = Func->getContext()->getStrDump();
3106   dumpDest(Func);
3107   Str << " = "
3108       << "vcvt" << getPredicate() << vcvtVariantSuffix(Variant) << " ";
3109   dumpSources(Func);
3110 }
3111 
emit(const Cfg * Func) const3112 void InstARM32Vcmp::emit(const Cfg *Func) const {
3113   if (!BuildDefs::dump())
3114     return;
3115   Ostream &Str = Func->getContext()->getStrEmit();
3116   assert(getSrcSize() == 2);
3117   Str << "\t"
3118          "vcmp" << getPredicate() << getFpWidthString(getSrc(0)->getType())
3119       << "\t";
3120   getSrc(0)->emit(Func);
3121   Str << ", ";
3122   getSrc(1)->emit(Func);
3123 }
3124 
emitIAS(const Cfg * Func) const3125 void InstARM32Vcmp::emitIAS(const Cfg *Func) const {
3126   assert(getSrcSize() == 2);
3127   const Operand *Src0 = getSrc(0);
3128   const Type Ty = Src0->getType();
3129   const Operand *Src1 = getSrc(1);
3130   const CondARM32::Cond Cond = getPredicate();
3131   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3132   if (llvm::isa<OperandARM32FlexFpZero>(Src1)) {
3133     switch (Ty) {
3134     case IceType_f32:
3135       Asm->vcmpsz(Src0, Cond);
3136       break;
3137     case IceType_f64:
3138       Asm->vcmpdz(Src0, Cond);
3139       break;
3140     default:
3141       llvm::report_fatal_error("Vcvt on non floating value");
3142     }
3143   } else {
3144     switch (Ty) {
3145     case IceType_f32:
3146       Asm->vcmps(Src0, Src1, Cond);
3147       break;
3148     case IceType_f64:
3149       Asm->vcmpd(Src0, Src1, Cond);
3150       break;
3151     default:
3152       llvm::report_fatal_error("Vcvt on non floating value");
3153     }
3154   }
3155   assert(!Asm->needsTextFixup());
3156 }
3157 
dump(const Cfg * Func) const3158 void InstARM32Vcmp::dump(const Cfg *Func) const {
3159   if (!BuildDefs::dump())
3160     return;
3161   Ostream &Str = Func->getContext()->getStrDump();
3162   Str << "vcmp" << getPredicate() << getFpWidthString(getSrc(0)->getType());
3163   dumpSources(Func);
3164 }
3165 
emit(const Cfg * Func) const3166 void InstARM32Vmrs::emit(const Cfg *Func) const {
3167   if (!BuildDefs::dump())
3168     return;
3169   Ostream &Str = Func->getContext()->getStrEmit();
3170   assert(getSrcSize() == 0);
3171   Str << "\t"
3172          "vmrs" << getPredicate() << "\t"
3173                                      "APSR_nzcv"
3174                                      ", "
3175                                      "FPSCR";
3176 }
3177 
emitIAS(const Cfg * Func) const3178 void InstARM32Vmrs::emitIAS(const Cfg *Func) const {
3179   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3180   Asm->vmrsAPSR_nzcv(getPredicate());
3181   assert(!Asm->needsTextFixup());
3182 }
3183 
dump(const Cfg * Func) const3184 void InstARM32Vmrs::dump(const Cfg *Func) const {
3185   if (!BuildDefs::dump())
3186     return;
3187   Ostream &Str = Func->getContext()->getStrDump();
3188   Str << "APSR{n,z,v,c} = vmrs" << getPredicate() << "\t"
3189                                                      "FPSCR{n,z,c,v}";
3190 }
3191 
emit(const Cfg * Func) const3192 void InstARM32Vabs::emit(const Cfg *Func) const {
3193   if (!BuildDefs::dump())
3194     return;
3195   Ostream &Str = Func->getContext()->getStrEmit();
3196   assert(getSrcSize() == 1);
3197   Str << "\t"
3198          "vabs" << getPredicate() << getFpWidthString(getSrc(0)->getType())
3199       << "\t";
3200   getDest()->emit(Func);
3201   Str << ", ";
3202   getSrc(0)->emit(Func);
3203 }
3204 
emitIAS(const Cfg * Func) const3205 void InstARM32Vabs::emitIAS(const Cfg *Func) const {
3206   assert(getSrcSize() == 1);
3207   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3208   const Variable *Dest = getDest();
3209   switch (Dest->getType()) {
3210   default:
3211     llvm::report_fatal_error("fabs not defined on type " +
3212                              typeStdString(Dest->getType()));
3213   case IceType_f32:
3214     Asm->vabss(Dest, getSrc(0), getPredicate());
3215     break;
3216   case IceType_f64:
3217     Asm->vabsd(Dest, getSrc(0), getPredicate());
3218     break;
3219   case IceType_v4f32:
3220     assert(CondARM32::isUnconditional(getPredicate()) &&
3221            "fabs must be unconditional");
3222     Asm->vabsq(Dest, getSrc(0));
3223   }
3224   assert(!Asm->needsTextFixup());
3225 }
3226 
dump(const Cfg * Func) const3227 void InstARM32Vabs::dump(const Cfg *Func) const {
3228   if (!BuildDefs::dump())
3229     return;
3230   Ostream &Str = Func->getContext()->getStrDump();
3231   dumpDest(Func);
3232   Str << " = vabs" << getPredicate() << getFpWidthString(getSrc(0)->getType());
3233 }
3234 
emit(const Cfg * Func) const3235 void InstARM32Dmb::emit(const Cfg *Func) const {
3236   if (!BuildDefs::dump())
3237     return;
3238   Ostream &Str = Func->getContext()->getStrEmit();
3239   assert(getSrcSize() == 0);
3240   Str << "\t"
3241          "dmb"
3242          "\t"
3243          "sy";
3244 }
3245 
emitIAS(const Cfg * Func) const3246 void InstARM32Dmb::emitIAS(const Cfg *Func) const {
3247   assert(getSrcSize() == 0);
3248   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3249   constexpr ARM32::IValueT SyOption = 0xF; // i.e. 1111
3250   Asm->dmb(SyOption);
3251   if (Asm->needsTextFixup())
3252     emitUsingTextFixup(Func);
3253 }
3254 
dump(const Cfg * Func) const3255 void InstARM32Dmb::dump(const Cfg *Func) const {
3256   if (!BuildDefs::dump())
3257     return;
3258   Func->getContext()->getStrDump() << "dmb\t"
3259                                       "sy";
3260 }
3261 
emit(const Cfg * Func) const3262 void InstARM32Nop::emit(const Cfg *Func) const {
3263   if (!BuildDefs::dump())
3264     return;
3265   assert(getSrcSize() == 0);
3266   Func->getContext()->getStrEmit() << "\t"
3267                                    << "nop";
3268 }
3269 
emitIAS(const Cfg * Func) const3270 void InstARM32Nop::emitIAS(const Cfg *Func) const {
3271   assert(getSrcSize() == 0);
3272   Func->getAssembler<ARM32::AssemblerARM32>()->nop();
3273 }
3274 
dump(const Cfg * Func) const3275 void InstARM32Nop::dump(const Cfg *Func) const {
3276   if (!BuildDefs::dump())
3277     return;
3278   assert(getSrcSize() == 0);
3279   Func->getContext()->getStrDump() << "nop";
3280 }
3281 
emit(const Cfg * Func) const3282 void OperandARM32Mem::emit(const Cfg *Func) const {
3283   if (!BuildDefs::dump())
3284     return;
3285   Ostream &Str = Func->getContext()->getStrEmit();
3286   Str << "[";
3287   getBase()->emit(Func);
3288   switch (getAddrMode()) {
3289   case PostIndex:
3290   case NegPostIndex:
3291     Str << "]";
3292     break;
3293   default:
3294     break;
3295   }
3296   if (isRegReg()) {
3297     Str << ", ";
3298     if (isNegAddrMode()) {
3299       Str << "-";
3300     }
3301     getIndex()->emit(Func);
3302     if (getShiftOp() != kNoShift) {
3303       Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
3304           << getShiftAmt();
3305     }
3306   } else {
3307     ConstantInteger32 *Offset = getOffset();
3308     if (Offset && Offset->getValue() != 0) {
3309       Str << ", ";
3310       Offset->emit(Func);
3311     }
3312   }
3313   switch (getAddrMode()) {
3314   case Offset:
3315   case NegOffset:
3316     Str << "]";
3317     break;
3318   case PreIndex:
3319   case NegPreIndex:
3320     Str << "]!";
3321     break;
3322   case PostIndex:
3323   case NegPostIndex:
3324     // Brace is already closed off.
3325     break;
3326   }
3327 }
3328 
dump(const Cfg * Func,Ostream & Str) const3329 void OperandARM32Mem::dump(const Cfg *Func, Ostream &Str) const {
3330   if (!BuildDefs::dump())
3331     return;
3332   Str << "[";
3333   if (Func)
3334     getBase()->dump(Func);
3335   else
3336     getBase()->dump(Str);
3337   Str << ", ";
3338   if (isRegReg()) {
3339     if (isNegAddrMode()) {
3340       Str << "-";
3341     }
3342     if (Func)
3343       getIndex()->dump(Func);
3344     else
3345       getIndex()->dump(Str);
3346     if (getShiftOp() != kNoShift) {
3347       Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
3348           << getShiftAmt();
3349     }
3350   } else {
3351     getOffset()->dump(Func, Str);
3352   }
3353   Str << "] AddrMode==" << getAddrMode();
3354 }
3355 
emit(const Cfg * Func) const3356 void OperandARM32ShAmtImm::emit(const Cfg *Func) const { ShAmt->emit(Func); }
3357 
dump(const Cfg *,Ostream & Str) const3358 void OperandARM32ShAmtImm::dump(const Cfg *, Ostream &Str) const {
3359   ShAmt->dump(Str);
3360 }
3361 
create(Cfg * Func,Type Ty,uint32_t Imm,uint32_t RotateAmt)3362 OperandARM32FlexImm *OperandARM32FlexImm::create(Cfg *Func, Type Ty,
3363                                                  uint32_t Imm,
3364                                                  uint32_t RotateAmt) {
3365   // The assembler wants the smallest rotation. Rotate if needed. Note: Imm is
3366   // an 8-bit value.
3367   assert(Utils::IsUint(8, Imm) &&
3368          "Flex immediates can only be defined on 8-bit immediates");
3369   while ((Imm & 0x03) == 0 && RotateAmt > 0) {
3370     --RotateAmt;
3371     Imm = Imm >> 2;
3372   }
3373   return new (Func->allocate<OperandARM32FlexImm>())
3374       OperandARM32FlexImm(Func, Ty, Imm, RotateAmt);
3375 }
3376 
emit(const Cfg * Func) const3377 void OperandARM32FlexImm::emit(const Cfg *Func) const {
3378   if (!BuildDefs::dump())
3379     return;
3380   Ostream &Str = Func->getContext()->getStrEmit();
3381   uint32_t Imm = getImm();
3382   uint32_t RotateAmt = getRotateAmt();
3383   Str << "#" << Utils::rotateRight32(Imm, 2 * RotateAmt);
3384 }
3385 
dump(const Cfg *,Ostream & Str) const3386 void OperandARM32FlexImm::dump(const Cfg * /* Func */, Ostream &Str) const {
3387   if (!BuildDefs::dump())
3388     return;
3389   uint32_t Imm = getImm();
3390   uint32_t RotateAmt = getRotateAmt();
3391   Str << "#(" << Imm << " ror 2*" << RotateAmt << ")";
3392 }
3393 
3394 namespace {
3395 static constexpr uint32_t a = 0x80;
3396 static constexpr uint32_t b = 0x40;
3397 static constexpr uint32_t cdefgh = 0x3F;
3398 static constexpr uint32_t AllowedBits = a | b | cdefgh;
3399 static_assert(AllowedBits == 0xFF,
3400               "Invalid mask for f32/f64 constant rematerialization.");
3401 
3402 // There's no loss in always returning the modified immediate as float.
3403 // TODO(jpp): returning a double causes problems when outputting the constants
3404 // for filetype=asm. Why?
materializeFloatImmediate(uint32_t ModifiedImm)3405 float materializeFloatImmediate(uint32_t ModifiedImm) {
3406   const uint32_t Ret = ((ModifiedImm & a) ? 0x80000000 : 0) |
3407                        ((ModifiedImm & b) ? 0x3E000000 : 0x40000000) |
3408                        ((ModifiedImm & cdefgh) << 19);
3409   return Utils::bitCopy<float>(Ret);
3410 }
3411 
3412 } // end of anonymous namespace
3413 
emit(const Cfg * Func) const3414 void OperandARM32FlexFpImm::emit(const Cfg *Func) const {
3415   if (!BuildDefs::dump())
3416     return;
3417   Ostream &Str = Func->getContext()->getStrEmit();
3418   switch (Ty) {
3419   default:
3420     llvm::report_fatal_error("Invalid flex fp imm type.");
3421   case IceType_f64:
3422   case IceType_f32:
3423     Str << "#" << materializeFloatImmediate(ModifiedImm)
3424         << " @ Modified: " << ModifiedImm;
3425     break;
3426   }
3427 }
3428 
dump(const Cfg *,Ostream & Str) const3429 void OperandARM32FlexFpImm::dump(const Cfg * /*Func*/, Ostream &Str) const {
3430   if (!BuildDefs::dump())
3431     return;
3432   Str << "#" << materializeFloatImmediate(ModifiedImm) << getFpWidthString(Ty);
3433 }
3434 
emit(const Cfg * Func) const3435 void OperandARM32FlexFpZero::emit(const Cfg *Func) const {
3436   if (!BuildDefs::dump())
3437     return;
3438   Ostream &Str = Func->getContext()->getStrEmit();
3439   switch (Ty) {
3440   default:
3441     llvm::report_fatal_error("Invalid flex fp imm type.");
3442   case IceType_f64:
3443   case IceType_f32:
3444     Str << "#0.0";
3445   }
3446 }
3447 
dump(const Cfg *,Ostream & Str) const3448 void OperandARM32FlexFpZero::dump(const Cfg * /*Func*/, Ostream &Str) const {
3449   if (!BuildDefs::dump())
3450     return;
3451   Str << "#0.0" << getFpWidthString(Ty);
3452 }
3453 
emit(const Cfg * Func) const3454 void OperandARM32FlexReg::emit(const Cfg *Func) const {
3455   if (!BuildDefs::dump())
3456     return;
3457   Ostream &Str = Func->getContext()->getStrEmit();
3458   getReg()->emit(Func);
3459   if (getShiftOp() != kNoShift) {
3460     Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
3461     getShiftAmt()->emit(Func);
3462   }
3463 }
3464 
dump(const Cfg * Func,Ostream & Str) const3465 void OperandARM32FlexReg::dump(const Cfg *Func, Ostream &Str) const {
3466   if (!BuildDefs::dump())
3467     return;
3468   Variable *Reg = getReg();
3469   if (Func)
3470     Reg->dump(Func);
3471   else
3472     Reg->dump(Str);
3473   if (getShiftOp() != kNoShift) {
3474     Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
3475     if (Func)
3476       getShiftAmt()->dump(Func);
3477     else
3478       getShiftAmt()->dump(Str);
3479   }
3480 }
3481 
3482 // Force instantition of template classes
3483 template class InstARM32ThreeAddrGPR<InstARM32::Adc>;
3484 template class InstARM32ThreeAddrGPR<InstARM32::Add>;
3485 template class InstARM32ThreeAddrGPR<InstARM32::And>;
3486 template class InstARM32ThreeAddrGPR<InstARM32::Asr>;
3487 template class InstARM32ThreeAddrGPR<InstARM32::Bic>;
3488 template class InstARM32ThreeAddrGPR<InstARM32::Eor>;
3489 template class InstARM32ThreeAddrGPR<InstARM32::Lsl>;
3490 template class InstARM32ThreeAddrGPR<InstARM32::Lsr>;
3491 template class InstARM32ThreeAddrGPR<InstARM32::Mul>;
3492 template class InstARM32ThreeAddrGPR<InstARM32::Orr>;
3493 template class InstARM32ThreeAddrGPR<InstARM32::Rsb>;
3494 template class InstARM32ThreeAddrGPR<InstARM32::Rsc>;
3495 template class InstARM32ThreeAddrGPR<InstARM32::Sbc>;
3496 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
3497 template class InstARM32ThreeAddrGPR<InstARM32::Sub>;
3498 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>;
3499 
3500 template class InstARM32ThreeAddrFP<InstARM32::Vadd>;
3501 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vcge>;
3502 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vcgt>;
3503 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>;
3504 template class InstARM32ThreeAddrFP<InstARM32::Veor>;
3505 template class InstARM32FourAddrFP<InstARM32::Vmla>;
3506 template class InstARM32FourAddrFP<InstARM32::Vmls>;
3507 template class InstARM32ThreeAddrFP<InstARM32::Vmul>;
3508 template class InstARM32UnaryopSignAwareFP<InstARM32::Vneg>;
3509 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>;
3510 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vshr>;
3511 template class InstARM32ThreeAddrFP<InstARM32::Vsub>;
3512 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vqadd>;
3513 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vqsub>;
3514 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vqmovn2>;
3515 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vmulh>;
3516 template class InstARM32ThreeAddrFP<InstARM32::Vmlap>;
3517 
3518 template class InstARM32LoadBase<InstARM32::Ldr>;
3519 template class InstARM32LoadBase<InstARM32::Ldrex>;
3520 template class InstARM32LoadBase<InstARM32::Vldr1d>;
3521 template class InstARM32LoadBase<InstARM32::Vldr1q>;
3522 template class InstARM32ThreeAddrFP<InstARM32::Vzip>;
3523 template class InstARM32TwoAddrGPR<InstARM32::Movt>;
3524 
3525 template class InstARM32UnaryopGPR<InstARM32::Movw, false>;
3526 template class InstARM32UnaryopGPR<InstARM32::Clz, false>;
3527 template class InstARM32UnaryopGPR<InstARM32::Mvn, false>;
3528 template class InstARM32UnaryopGPR<InstARM32::Rbit, false>;
3529 template class InstARM32UnaryopGPR<InstARM32::Rev, false>;
3530 template class InstARM32UnaryopGPR<InstARM32::Sxt, true>;
3531 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>;
3532 template class InstARM32UnaryopFP<InstARM32::Vsqrt>;
3533 
3534 template class InstARM32FourAddrGPR<InstARM32::Mla>;
3535 template class InstARM32FourAddrGPR<InstARM32::Mls>;
3536 
3537 template class InstARM32CmpLike<InstARM32::Cmn>;
3538 template class InstARM32CmpLike<InstARM32::Cmp>;
3539 template class InstARM32CmpLike<InstARM32::Tst>;
3540 
3541 } // end of namespace ARM32
3542 } // end of namespace Ice
3543