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