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 
1817 // Two-addr ops
1818 template <> const char *InstARM32Movt::Opcode = "movt";
1819 // Unary ops
1820 template <> const char *InstARM32Movw::Opcode = "movw";
1821 template <> const char *InstARM32Clz::Opcode = "clz";
1822 template <> const char *InstARM32Mvn::Opcode = "mvn";
1823 template <> const char *InstARM32Rbit::Opcode = "rbit";
1824 template <> const char *InstARM32Rev::Opcode = "rev";
1825 template <> const char *InstARM32Sxt::Opcode = "sxt"; // still requires b/h
1826 template <> const char *InstARM32Uxt::Opcode = "uxt"; // still requires b/h
1827 // FP
1828 template <> const char *InstARM32Vsqrt::Opcode = "vsqrt";
1829 // Mov-like ops
1830 template <> const char *InstARM32Ldr::Opcode = "ldr";
1831 template <> const char *InstARM32Ldrex::Opcode = "ldrex";
1832 template <> const char *InstARM32Vldr1d::Opcode = "vldr1d";
1833 template <> const char *InstARM32Vldr1q::Opcode = "vldr1q";
1834 // Three-addr ops
1835 template <> const char *InstARM32Adc::Opcode = "adc";
1836 template <> const char *InstARM32Add::Opcode = "add";
1837 template <> const char *InstARM32And::Opcode = "and";
1838 template <> const char *InstARM32Asr::Opcode = "asr";
1839 template <> const char *InstARM32Bic::Opcode = "bic";
1840 template <> const char *InstARM32Eor::Opcode = "eor";
1841 template <> const char *InstARM32Lsl::Opcode = "lsl";
1842 template <> const char *InstARM32Lsr::Opcode = "lsr";
1843 template <> const char *InstARM32Mul::Opcode = "mul";
1844 template <> const char *InstARM32Orr::Opcode = "orr";
1845 template <> const char *InstARM32Rsb::Opcode = "rsb";
1846 template <> const char *InstARM32Rsc::Opcode = "rsc";
1847 template <> const char *InstARM32Sbc::Opcode = "sbc";
1848 template <> const char *InstARM32Sdiv::Opcode = "sdiv";
1849 template <> const char *InstARM32Sub::Opcode = "sub";
1850 template <> const char *InstARM32Udiv::Opcode = "udiv";
1851 // FP
1852 template <> const char *InstARM32Vadd::Opcode = "vadd";
1853 template <> const char *InstARM32Vand::Opcode = "vand";
1854 template <> const char *InstARM32Vbsl::Opcode = "vbsl";
1855 template <> const char *InstARM32Vceq::Opcode = "vceq";
1856 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vcge>::Opcode = "vcge";
1857 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vcgt>::Opcode = "vcgt";
1858 template <> const char *InstARM32Vdiv::Opcode = "vdiv";
1859 template <> const char *InstARM32Veor::Opcode = "veor";
1860 template <> const char *InstARM32Vmla::Opcode = "vmla";
1861 template <> const char *InstARM32Vmls::Opcode = "vmls";
1862 template <> const char *InstARM32Vmul::Opcode = "vmul";
1863 template <> const char *InstARM32Vmvn::Opcode = "vmvn";
1864 template <> const char *InstARM32Vmovl::Opcode = "vmovl";
1865 template <> const char *InstARM32Vmovh::Opcode = "vmovh";
1866 template <> const char *InstARM32Vmovhl::Opcode = "vmovhl";
1867 template <> const char *InstARM32Vmovlh::Opcode = "vmovlh";
1868 template <> const char *InstARM32Vorr::Opcode = "vorr";
1869 template <> const char *InstARM32UnaryopFP<InstARM32::Vneg>::Opcode = "vneg";
1870 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vshl>::Opcode = "vshl";
1871 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vshr>::Opcode = "vshr";
1872 template <> const char *InstARM32Vsub::Opcode = "vsub";
1873 template <>
1874 const char *InstARM32ThreeAddrFP<InstARM32::Vqadd>::Opcode = "vqadd";
1875 template <>
1876 const char *InstARM32ThreeAddrFP<InstARM32::Vqsub>::Opcode = "vqsub";
1877 template <>
1878 const char *InstARM32ThreeAddrFP<InstARM32::Vqmovn2>::Opcode = "vqmovn2";
1879 template <>
1880 const char *InstARM32ThreeAddrFP<InstARM32::Vmulh>::Opcode = "vmulh";
1881 template <>
1882 const char *InstARM32ThreeAddrFP<InstARM32::Vmlap>::Opcode = "vmlap";
1883 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vzip>::Opcode = "vzip";
1884 // Four-addr ops
1885 template <> const char *InstARM32Mla::Opcode = "mla";
1886 template <> const char *InstARM32Mls::Opcode = "mls";
1887 // Cmp-like ops
1888 template <> const char *InstARM32Cmn::Opcode = "cmn";
1889 template <> const char *InstARM32Cmp::Opcode = "cmp";
1890 template <> const char *InstARM32Tst::Opcode = "tst";
1891 
dump(const Cfg * Func) const1892 void InstARM32::dump(const Cfg *Func) const {
1893   if (!BuildDefs::dump())
1894     return;
1895   Ostream &Str = Func->getContext()->getStrDump();
1896   Str << "[ARM32] ";
1897   Inst::dump(Func);
1898 }
1899 
emitMultiDestSingleSource(const Cfg * Func) const1900 void InstARM32Mov::emitMultiDestSingleSource(const Cfg *Func) const {
1901   if (!BuildDefs::dump())
1902     return;
1903   Ostream &Str = Func->getContext()->getStrEmit();
1904   Variable *DestLo = getDest();
1905   Variable *DestHi = getDestHi();
1906   auto *Src = llvm::cast<Variable>(getSrc(0));
1907 
1908   assert(DestHi->hasReg());
1909   assert(DestLo->hasReg());
1910   assert(Src->hasReg());
1911 
1912   Str << "\t"
1913          "vmov"
1914       << getPredicate() << "\t";
1915   DestLo->emit(Func);
1916   Str << ", ";
1917   DestHi->emit(Func);
1918   Str << ", ";
1919   Src->emit(Func);
1920 }
1921 
emitSingleDestMultiSource(const Cfg * Func) const1922 void InstARM32Mov::emitSingleDestMultiSource(const Cfg *Func) const {
1923   if (!BuildDefs::dump())
1924     return;
1925   Ostream &Str = Func->getContext()->getStrEmit();
1926   Variable *Dest = getDest();
1927   auto *SrcLo = llvm::cast<Variable>(getSrc(0));
1928   auto *SrcHi = llvm::cast<Variable>(getSrc(1));
1929 
1930   assert(SrcHi->hasReg());
1931   assert(SrcLo->hasReg());
1932   assert(Dest->hasReg());
1933   assert(getSrcSize() == 2);
1934 
1935   Str << "\t"
1936          "vmov"
1937       << getPredicate() << "\t";
1938   Dest->emit(Func);
1939   Str << ", ";
1940   SrcLo->emit(Func);
1941   Str << ", ";
1942   SrcHi->emit(Func);
1943 }
1944 
1945 namespace {
1946 
isVariableWithoutRegister(const Operand * Op)1947 bool isVariableWithoutRegister(const Operand *Op) {
1948   if (const auto *OpV = llvm::dyn_cast<Variable>(Op)) {
1949     return !OpV->hasReg();
1950   }
1951   return false;
1952 }
isMemoryAccess(Operand * Op)1953 bool isMemoryAccess(Operand *Op) {
1954   return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op);
1955 }
1956 
isMoveBetweenCoreAndVFPRegisters(Variable * Dest,Operand * Src)1957 bool isMoveBetweenCoreAndVFPRegisters(Variable *Dest, Operand *Src) {
1958   const Type DestTy = Dest->getType();
1959   const Type SrcTy = Src->getType();
1960   return !isVectorType(DestTy) && !isVectorType(SrcTy) &&
1961          (isScalarIntegerType(DestTy) == isScalarFloatingType(SrcTy));
1962 }
1963 
1964 } // end of anonymous namespace
1965 
emitSingleDestSingleSource(const Cfg * Func) const1966 void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
1967   if (!BuildDefs::dump())
1968     return;
1969   Ostream &Str = Func->getContext()->getStrEmit();
1970   Variable *Dest = getDest();
1971 
1972   if (!Dest->hasReg()) {
1973     llvm::report_fatal_error("mov can't store.");
1974   }
1975 
1976   Operand *Src0 = getSrc(0);
1977   if (isMemoryAccess(Src0)) {
1978     llvm::report_fatal_error("mov can't load.");
1979   }
1980 
1981   Type Ty = Dest->getType();
1982   const bool IsVector = isVectorType(Ty);
1983   const bool IsScalarFP = isScalarFloatingType(Ty);
1984   const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
1985   const bool IsVMove = (IsVector || IsScalarFP || CoreVFPMove);
1986   const char *Opcode = IsVMove ? "vmov" : "mov";
1987   // when vmov{c}'ing, we need to emit a width string. Otherwise, the
1988   // assembler might be tempted to assume we want a vector vmov{c}, and that
1989   // is disallowed because ARM.
1990   const char *WidthString = !CoreVFPMove ? getFpWidthString(Ty) : "";
1991   CondARM32::Cond Cond = getPredicate();
1992   if (IsVector)
1993     assert(CondARM32::isUnconditional(Cond) &&
1994            "Moves on vectors must be unconditional!");
1995   Str << "\t" << Opcode;
1996   if (IsVMove) {
1997     Str << Cond << WidthString;
1998   } else {
1999     Str << WidthString << Cond;
2000   }
2001   Str << "\t";
2002   Dest->emit(Func);
2003   Str << ", ";
2004   Src0->emit(Func);
2005 }
2006 
emit(const Cfg * Func) const2007 void InstARM32Mov::emit(const Cfg *Func) const {
2008   if (!BuildDefs::dump())
2009     return;
2010   assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
2011   if (isMultiDest()) {
2012     emitMultiDestSingleSource(Func);
2013     return;
2014   }
2015 
2016   if (isMultiSource()) {
2017     emitSingleDestMultiSource(Func);
2018     return;
2019   }
2020 
2021   emitSingleDestSingleSource(Func);
2022 }
2023 
emitIAS(const Cfg * Func) const2024 void InstARM32Mov::emitIAS(const Cfg *Func) const {
2025   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2026   const Variable *Dest = getDest();
2027   Operand *Src0 = getSrc(0);
2028   const CondARM32::Cond Cond = getPredicate();
2029   if (!Dest->hasReg()) {
2030     llvm::report_fatal_error("mov can't store.");
2031   }
2032   if (isMemoryAccess(Src0)) {
2033     llvm::report_fatal_error("mov can't load.");
2034   }
2035 
2036   assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
2037   if (isMultiDest()) {
2038     Asm->vmovrrd(Dest, getDestHi(), Src0, Cond);
2039     return;
2040   }
2041   if (isMultiSource()) {
2042     Asm->vmovdrr(Dest, Src0, getSrc(1), Cond);
2043     return;
2044   }
2045 
2046   const Type DestTy = Dest->getType();
2047   const Type SrcTy = Src0->getType();
2048   switch (DestTy) {
2049   default:
2050     break; // Error
2051   case IceType_i1:
2052   case IceType_i8:
2053   case IceType_i16:
2054   case IceType_i32:
2055     switch (SrcTy) {
2056     default:
2057       break; // Error
2058     case IceType_i1:
2059     case IceType_i8:
2060     case IceType_i16:
2061     case IceType_i32:
2062     case IceType_i64:
2063       Asm->mov(Dest, Src0, Cond);
2064       return;
2065     case IceType_f32:
2066       Asm->vmovrs(Dest, Src0, Cond);
2067       return;
2068     }
2069     break; // Error
2070   case IceType_i64:
2071     if (isScalarIntegerType(SrcTy)) {
2072       Asm->mov(Dest, Src0, Cond);
2073       return;
2074     }
2075     if (SrcTy == IceType_f64) {
2076       if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
2077         Asm->vmovdd(Dest, Var, Cond);
2078         return;
2079       }
2080       if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
2081         Asm->vmovd(Dest, FpImm, Cond);
2082         return;
2083       }
2084     }
2085     break; // Error
2086   case IceType_f32:
2087     switch (SrcTy) {
2088     default:
2089       break; // Error
2090     case IceType_i1:
2091     case IceType_i8:
2092     case IceType_i16:
2093     case IceType_i32:
2094       return Asm->vmovsr(Dest, Src0, Cond);
2095     case IceType_f32:
2096       if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
2097         Asm->vmovss(Dest, Var, Cond);
2098         return;
2099       }
2100       if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
2101         Asm->vmovs(Dest, FpImm, Cond);
2102         return;
2103       }
2104       break; // Error
2105     }
2106     break; // Error
2107   case IceType_f64:
2108     if (SrcTy == IceType_f64) {
2109       if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
2110         Asm->vmovdd(Dest, Var, Cond);
2111         return;
2112       }
2113       if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
2114         Asm->vmovd(Dest, FpImm, Cond);
2115         return;
2116       }
2117     }
2118     break; // Error
2119   // TODO(jpp): Remove vectors of i1.
2120   case IceType_v4i1:
2121   case IceType_v8i1:
2122   case IceType_v16i1:
2123   case IceType_v16i8:
2124   case IceType_v8i16:
2125   case IceType_v4i32:
2126   case IceType_v4f32:
2127     assert(CondARM32::isUnconditional(Cond) &&
2128            "Moves on vector must be unconditional!");
2129     if (isVectorType(SrcTy)) {
2130       // Mov between different Src and Dest types is used for bitcasting
2131       // vectors.  We still want to make sure SrcTy is a vector type.
2132       Asm->vorrq(Dest, Src0, Src0);
2133       return;
2134     } else if (const auto *C = llvm::dyn_cast<ConstantInteger32>(Src0)) {
2135       // Mov with constant argument, allowing the initializing all elements of
2136       // the vector.
2137       if (Asm->vmovqc(Dest, C))
2138         return;
2139     }
2140   }
2141   llvm::report_fatal_error("Mov: don't know how to move " +
2142                            typeStdString(SrcTy) + " to " +
2143                            typeStdString(DestTy));
2144 }
2145 
dump(const Cfg * Func) const2146 void InstARM32Mov::dump(const Cfg *Func) const {
2147   if (!BuildDefs::dump())
2148     return;
2149   assert(getSrcSize() == 1 || getSrcSize() == 2);
2150   Ostream &Str = Func->getContext()->getStrDump();
2151   Variable *Dest = getDest();
2152   Variable *DestHi = getDestHi();
2153   Dest->dump(Func);
2154   if (DestHi) {
2155     Str << ", ";
2156     DestHi->dump(Func);
2157   }
2158 
2159   dumpOpcodePred(Str, " = mov", getDest()->getType());
2160   Str << " ";
2161 
2162   dumpSources(Func);
2163 }
2164 
emit(const Cfg * Func) const2165 void InstARM32Br::emit(const Cfg *Func) const {
2166   if (!BuildDefs::dump())
2167     return;
2168   Ostream &Str = Func->getContext()->getStrEmit();
2169   Str << "\t"
2170          "b"
2171       << getPredicate() << "\t";
2172   if (Label) {
2173     Str << Label->getLabelName();
2174   } else {
2175     if (isUnconditionalBranch()) {
2176       Str << getTargetFalse()->getAsmName();
2177     } else {
2178       Str << getTargetTrue()->getAsmName();
2179       if (getTargetFalse()) {
2180         startNextInst(Func);
2181         Str << "\n\t"
2182             << "b"
2183             << "\t" << getTargetFalse()->getAsmName();
2184       }
2185     }
2186   }
2187 }
2188 
emitIAS(const Cfg * Func) const2189 void InstARM32Br::emitIAS(const Cfg *Func) const {
2190   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2191   if (Label) {
2192     Asm->b(Asm->getOrCreateLocalLabel(Label->getNumber()), getPredicate());
2193   } else if (isUnconditionalBranch()) {
2194     Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()),
2195            getPredicate());
2196   } else {
2197     Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex()),
2198            getPredicate());
2199     if (const CfgNode *False = getTargetFalse())
2200       Asm->b(Asm->getOrCreateCfgNodeLabel(False->getIndex()), CondARM32::AL);
2201   }
2202   if (Asm->needsTextFixup())
2203     emitUsingTextFixup(Func);
2204 }
2205 
dump(const Cfg * Func) const2206 void InstARM32Br::dump(const Cfg *Func) const {
2207   if (!BuildDefs::dump())
2208     return;
2209   Ostream &Str = Func->getContext()->getStrDump();
2210   Str << "br ";
2211 
2212   if (getPredicate() == CondARM32::AL) {
2213     if (Label) {
2214       Str << "label %" << Label->getLabelName();
2215     } else {
2216       Str << "label %" << getTargetFalse()->getName();
2217     }
2218     return;
2219   }
2220 
2221   if (Label) {
2222     Str << getPredicate() << ", label %" << Label->getLabelName();
2223   } else {
2224     Str << getPredicate() << ", label %" << getTargetTrue()->getName();
2225     if (getTargetFalse()) {
2226       Str << ", label %" << getTargetFalse()->getName();
2227     }
2228   }
2229 }
2230 
emit(const Cfg * Func) const2231 void InstARM32Call::emit(const Cfg *Func) const {
2232   if (!BuildDefs::dump())
2233     return;
2234   Ostream &Str = Func->getContext()->getStrEmit();
2235   assert(getSrcSize() == 1);
2236   if (llvm::isa<ConstantInteger32>(getCallTarget())) {
2237     // This shouldn't happen (typically have to copy the full 32-bits to a
2238     // register and do an indirect jump).
2239     llvm::report_fatal_error("ARM32Call to ConstantInteger32");
2240   } else if (const auto *CallTarget =
2241                  llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
2242     // Calls only have 24-bits, but the linker should insert veneers to extend
2243     // the range if needed.
2244     Str << "\t"
2245            "bl"
2246            "\t";
2247     CallTarget->emitWithoutPrefix(Func->getTarget());
2248   } else {
2249     Str << "\t"
2250            "blx"
2251            "\t";
2252     getCallTarget()->emit(Func);
2253   }
2254 }
2255 
emitIAS(const Cfg * Func) const2256 void InstARM32Call::emitIAS(const Cfg *Func) const {
2257   assert(getSrcSize() == 1);
2258   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2259   if (llvm::isa<ConstantInteger32>(getCallTarget())) {
2260     // This shouldn't happen (typically have to copy the full 32-bits to a
2261     // register and do an indirect jump).
2262     llvm::report_fatal_error("ARM32Call to ConstantInteger32");
2263   } else if (const auto *CallTarget =
2264                  llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
2265     // Calls only have 24-bits, but the linker should insert veneers to extend
2266     // the range if needed.
2267     Asm->bl(CallTarget);
2268   } else {
2269     Asm->blx(getCallTarget());
2270   }
2271   if (Asm->needsTextFixup())
2272     return emitUsingTextFixup(Func);
2273 }
2274 
dump(const Cfg * Func) const2275 void InstARM32Call::dump(const Cfg *Func) const {
2276   if (!BuildDefs::dump())
2277     return;
2278   Ostream &Str = Func->getContext()->getStrDump();
2279   if (getDest()) {
2280     dumpDest(Func);
2281     Str << " = ";
2282   }
2283   Str << "call ";
2284   getCallTarget()->dump(Func);
2285 }
2286 
emit(const Cfg * Func) const2287 void InstARM32Label::emit(const Cfg *Func) const {
2288   if (!BuildDefs::dump())
2289     return;
2290   // A label is not really an instruction. Hence, we need to fix the
2291   // emitted text size.
2292   if (auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>())
2293     Asm->decEmitTextSize(InstSize);
2294   Ostream &Str = Func->getContext()->getStrEmit();
2295   Str << getLabelName() << ":";
2296 }
2297 
emitIAS(const Cfg * Func) const2298 void InstARM32Label::emitIAS(const Cfg *Func) const {
2299   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2300   Asm->bindLocalLabel(this, Number);
2301   if (OffsetReloc != nullptr) {
2302     Asm->bindRelocOffset(OffsetReloc);
2303   }
2304   if (Asm->needsTextFixup())
2305     emitUsingTextFixup(Func);
2306 }
2307 
dump(const Cfg * Func) const2308 void InstARM32Label::dump(const Cfg *Func) const {
2309   if (!BuildDefs::dump())
2310     return;
2311   Ostream &Str = Func->getContext()->getStrDump();
2312   Str << getLabelName() << ":";
2313 }
2314 
2315 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const2316 void InstARM32LoadBase<K>::emitIAS(const Cfg *Func) const {
2317   emitUsingTextFixup(Func);
2318 }
2319 
emit(const Cfg * Func) const2320 template <> void InstARM32Ldr::emit(const Cfg *Func) const {
2321   if (!BuildDefs::dump())
2322     return;
2323   Ostream &Str = Func->getContext()->getStrEmit();
2324   assert(getSrcSize() == 1);
2325   assert(getDest()->hasReg());
2326   Variable *Dest = getDest();
2327   Type Ty = Dest->getType();
2328   const bool IsVector = isVectorType(Ty);
2329   const bool IsScalarFloat = isScalarFloatingType(Ty);
2330   const char *ActualOpcode =
2331       IsVector ? "vld1" : (IsScalarFloat ? "vldr" : "ldr");
2332   const char *WidthString = IsVector ? "" : getWidthString(Ty);
2333   Str << "\t" << ActualOpcode;
2334   const bool IsVInst = IsVector || IsScalarFloat;
2335   if (IsVInst) {
2336     Str << getPredicate() << WidthString;
2337   } else {
2338     Str << WidthString << getPredicate();
2339   }
2340   if (IsVector)
2341     Str << "." << getVecElmtBitsize(Ty);
2342   Str << "\t";
2343   getDest()->emit(Func);
2344   Str << ", ";
2345   getSrc(0)->emit(Func);
2346 }
2347 
emit(const Cfg * Func) const2348 template <> void InstARM32Vldr1d::emit(const Cfg *Func) const {
2349   if (!BuildDefs::dump())
2350     return;
2351   Ostream &Str = Func->getContext()->getStrEmit();
2352   assert(getSrcSize() == 1);
2353   assert(getDest()->hasReg());
2354   Variable *Dest = getDest();
2355   Type Ty = Dest->getType();
2356   const bool IsVector = isVectorType(Ty);
2357   const bool IsScalarFloat = isScalarFloatingType(Ty);
2358   const char *ActualOpcode =
2359       IsVector ? "vld1" : (IsScalarFloat ? "vldr" : "ldr");
2360   const char *WidthString = IsVector ? "" : getWidthString(Ty);
2361   Str << "\t" << ActualOpcode;
2362   const bool IsVInst = IsVector || IsScalarFloat;
2363   if (IsVInst) {
2364     Str << getPredicate() << WidthString;
2365   } else {
2366     Str << WidthString << getPredicate();
2367   }
2368   if (IsVector)
2369     Str << "." << getVecElmtBitsize(Ty);
2370   Str << "\t";
2371   getDest()->emit(Func);
2372   Str << ", ";
2373   getSrc(0)->emit(Func);
2374 }
2375 
emit(const Cfg * Func) const2376 template <> void InstARM32Vldr1q::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 Ty = Dest->getType();
2384   const bool IsVector = isVectorType(Ty);
2385   const bool IsScalarFloat = isScalarFloatingType(Ty);
2386   const char *ActualOpcode =
2387       IsVector ? "vld1" : (IsScalarFloat ? "vldr" : "ldr");
2388   const char *WidthString = IsVector ? "" : getWidthString(Ty);
2389   Str << "\t" << ActualOpcode;
2390   const bool IsVInst = IsVector || IsScalarFloat;
2391   if (IsVInst) {
2392     Str << getPredicate() << WidthString;
2393   } else {
2394     Str << WidthString << getPredicate();
2395   }
2396   if (IsVector)
2397     Str << "." << getVecElmtBitsize(Ty);
2398   Str << "\t";
2399   getDest()->emit(Func);
2400   Str << ", ";
2401   getSrc(0)->emit(Func);
2402 }
2403 
emitIAS(const Cfg * Func) const2404 template <> void InstARM32Ldr::emitIAS(const Cfg *Func) const {
2405   assert(getSrcSize() == 1);
2406   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2407   Variable *Dest = getDest();
2408   const Type DestTy = Dest->getType();
2409   switch (DestTy) {
2410   default:
2411     llvm::report_fatal_error("Ldr on unknown type: " + typeStdString(DestTy));
2412   case IceType_i1:
2413   case IceType_i8:
2414   case IceType_i16:
2415   case IceType_i32:
2416   case IceType_i64:
2417     Asm->ldr(Dest, getSrc(0), getPredicate(), Func->getTarget());
2418     break;
2419   case IceType_f32:
2420     Asm->vldrs(Dest, getSrc(0), getPredicate(), Func->getTarget());
2421     break;
2422   case IceType_f64:
2423     Asm->vldrd(Dest, getSrc(0), getPredicate(), Func->getTarget());
2424     break;
2425   case IceType_v16i8:
2426   case IceType_v8i16:
2427   case IceType_v4i32:
2428   case IceType_v4f32:
2429   case IceType_v16i1:
2430   case IceType_v8i1:
2431   case IceType_v4i1:
2432     Asm->vld1qr(getVecElmtBitsize(DestTy), Dest, getSrc(0), Func->getTarget());
2433     break;
2434   }
2435 }
2436 
emitIAS(const Cfg * Func) const2437 template <> void InstARM32Vldr1d::emitIAS(const Cfg *Func) const {
2438   assert(getSrcSize() == 1);
2439   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2440   Variable *Dest = getDest();
2441   Asm->vld1(32, Dest, getSrc(0), Func->getTarget());
2442 }
2443 
emitIAS(const Cfg * Func) const2444 template <> void InstARM32Vldr1q::emitIAS(const Cfg *Func) const {
2445   assert(getSrcSize() == 1);
2446   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2447   Variable *Dest = getDest();
2448   Asm->vld1(64, Dest, getSrc(0), Func->getTarget());
2449 }
2450 
emit(const Cfg * Func) const2451 template <> void InstARM32Ldrex::emit(const Cfg *Func) const {
2452   if (!BuildDefs::dump())
2453     return;
2454   Ostream &Str = Func->getContext()->getStrEmit();
2455   assert(getSrcSize() == 1);
2456   assert(getDest()->hasReg());
2457   Variable *Dest = getDest();
2458   Type DestTy = Dest->getType();
2459   assert(isScalarIntegerType(DestTy));
2460   const char *WidthString = getWidthString(DestTy);
2461   Str << "\t" << Opcode << WidthString << getPredicate() << "\t";
2462   getDest()->emit(Func);
2463   Str << ", ";
2464   getSrc(0)->emit(Func);
2465 }
2466 
emitIAS(const Cfg * Func) const2467 template <> void InstARM32Ldrex::emitIAS(const Cfg *Func) const {
2468   assert(getSrcSize() == 1);
2469   assert(getDest()->hasReg());
2470   Variable *Dest = getDest();
2471   assert(isScalarIntegerType(Dest->getType()));
2472   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2473   Asm->ldrex(Dest, getSrc(0), getPredicate(), Func->getTarget());
2474   if (Asm->needsTextFixup())
2475     emitUsingTextFixup(Func);
2476 }
2477 
2478 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const2479 void InstARM32TwoAddrGPR<K>::emitIAS(const Cfg *Func) const {
2480   emitUsingTextFixup(Func);
2481 }
2482 
2483 template <InstARM32::InstKindARM32 K, bool Nws>
emitIAS(const Cfg * Func) const2484 void InstARM32UnaryopGPR<K, Nws>::emitIAS(const Cfg *Func) const {
2485   emitUsingTextFixup(Func);
2486 }
2487 
emitIAS(const Cfg * Func) const2488 template <> void InstARM32Rbit::emitIAS(const Cfg *Func) const {
2489   assert(getSrcSize() == 1);
2490   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2491   Asm->rbit(getDest(), getSrc(0), getPredicate());
2492   if (Asm->needsTextFixup())
2493     emitUsingTextFixup(Func);
2494 }
2495 
emitIAS(const Cfg * Func) const2496 template <> void InstARM32Rev::emitIAS(const Cfg *Func) const {
2497   assert(getSrcSize() == 1);
2498   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2499   Asm->rev(getDest(), getSrc(0), getPredicate());
2500   if (Asm->needsTextFixup())
2501     emitUsingTextFixup(Func);
2502 }
2503 
emit(const Cfg * Func) const2504 template <> void InstARM32Movw::emit(const Cfg *Func) const {
2505   if (!BuildDefs::dump())
2506     return;
2507   Ostream &Str = Func->getContext()->getStrEmit();
2508   assert(getSrcSize() == 1);
2509   Str << "\t" << Opcode << getPredicate() << "\t";
2510   getDest()->emit(Func);
2511   Str << ", ";
2512   auto *Src0 = llvm::cast<Constant>(getSrc(0));
2513   if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
2514     Str << "#:lower16:";
2515     CR->emitWithoutPrefix(Func->getTarget());
2516     if (getFlags().getUseNonsfi()) {
2517       Str << " - .";
2518     }
2519   } else {
2520     Src0->emit(Func);
2521   }
2522 }
2523 
emitIAS(const Cfg * Func) const2524 template <> void InstARM32Movw::emitIAS(const Cfg *Func) const {
2525   assert(getSrcSize() == 1);
2526   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2527   Asm->movw(getDest(), getSrc(0), getPredicate());
2528   if (Asm->needsTextFixup())
2529     emitUsingTextFixup(Func);
2530 }
2531 
emit(const Cfg * Func) const2532 template <> void InstARM32Movt::emit(const Cfg *Func) const {
2533   if (!BuildDefs::dump())
2534     return;
2535   Ostream &Str = Func->getContext()->getStrEmit();
2536   assert(getSrcSize() == 2);
2537   Variable *Dest = getDest();
2538   auto *Src1 = llvm::cast<Constant>(getSrc(1));
2539   Str << "\t" << Opcode << getPredicate() << "\t";
2540   Dest->emit(Func);
2541   Str << ", ";
2542   if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src1)) {
2543     Str << "#:upper16:";
2544     CR->emitWithoutPrefix(Func->getTarget());
2545     if (getFlags().getUseNonsfi()) {
2546       Str << " - .";
2547     }
2548   } else {
2549     Src1->emit(Func);
2550   }
2551 }
2552 
emitIAS(const Cfg * Func) const2553 template <> void InstARM32Movt::emitIAS(const Cfg *Func) const {
2554   assert(getSrcSize() == 2);
2555   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2556   Asm->movt(getDest(), getSrc(1), getPredicate());
2557   if (Asm->needsTextFixup())
2558     emitUsingTextFixup(Func);
2559 }
2560 
emitIAS(const Cfg * Func) const2561 template <> void InstARM32Clz::emitIAS(const Cfg *Func) const {
2562   assert(getSrcSize() == 1);
2563   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2564   Asm->clz(getDest(), getSrc(0), getPredicate());
2565   if (Asm->needsTextFixup())
2566     emitUsingTextFixup(Func);
2567 }
2568 
emitIAS(const Cfg * Func) const2569 template <> void InstARM32Mvn::emitIAS(const Cfg *Func) const {
2570   assert(getSrcSize() == 1);
2571   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2572   Asm->mvn(getDest(), getSrc(0), getPredicate());
2573   if (Asm->needsTextFixup())
2574     emitUsingTextFixup(Func);
2575 }
2576 
emitIAS(const Cfg * Func) const2577 template <> void InstARM32Sxt::emitIAS(const Cfg *Func) const {
2578   assert(getSrcSize() == 1);
2579   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2580   Asm->sxt(getDest(), getSrc(0), getPredicate());
2581   if (Asm->needsTextFixup())
2582     emitUsingTextFixup(Func);
2583 }
2584 
emitIAS(const Cfg * Func) const2585 template <> void InstARM32Uxt::emitIAS(const Cfg *Func) const {
2586   assert(getSrcSize() == 1);
2587   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2588   Asm->uxt(getDest(), getSrc(0), getPredicate());
2589   if (Asm->needsTextFixup())
2590     emitUsingTextFixup(Func);
2591 }
2592 
2593 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const2594 void InstARM32UnaryopFP<K>::emitIAS(const Cfg *Func) const {
2595   emitUsingTextFixup(Func);
2596 }
2597 
2598 template <InstARM32::InstKindARM32 K>
emitIAS(const Cfg * Func) const2599 void InstARM32UnaryopSignAwareFP<K>::emitIAS(const Cfg *Func) const {
2600   InstARM32::emitUsingTextFixup(Func);
2601 }
2602 
emitIAS(const Cfg * Func) const2603 template <> void InstARM32Vsqrt::emitIAS(const Cfg *Func) const {
2604   assert(getSrcSize() == 1);
2605   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2606   const Operand *Dest = getDest();
2607   switch (Dest->getType()) {
2608   case IceType_f32:
2609     Asm->vsqrts(Dest, getSrc(0), getPredicate());
2610     break;
2611   case IceType_f64:
2612     Asm->vsqrtd(Dest, getSrc(0), getPredicate());
2613     break;
2614   default:
2615     llvm::report_fatal_error("Vsqrt of non-floating type");
2616   }
2617   if (Asm->needsTextFixup())
2618     emitUsingTextFixup(Func);
2619 }
2620 
getGPROpcode() const2621 const char *InstARM32Pop::getGPROpcode() const { return "pop"; }
2622 
getSRegOpcode() const2623 const char *InstARM32Pop::getSRegOpcode() const { return "vpop"; }
2624 
getStackReg(SizeT Index) const2625 Variable *InstARM32Pop::getStackReg(SizeT Index) const { return Dests[Index]; }
2626 
getNumStackRegs() const2627 SizeT InstARM32Pop::getNumStackRegs() const { return Dests.size(); }
2628 
emitSingleGPR(const Cfg * Func,const EmitForm Form,const Variable * Reg) const2629 void InstARM32Pop::emitSingleGPR(const Cfg *Func, const EmitForm Form,
2630                                  const Variable *Reg) const {
2631   switch (Form) {
2632   case Emit_Text:
2633     emitGPRsAsText(Func);
2634     return;
2635   case Emit_Binary:
2636     Func->getAssembler<ARM32::AssemblerARM32>()->pop(Reg, CondARM32::AL);
2637     return;
2638   }
2639 }
2640 
emitMultipleGPRs(const Cfg * Func,const EmitForm Form,IValueT Registers) const2641 void InstARM32Pop::emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
2642                                     IValueT Registers) const {
2643   switch (Form) {
2644   case Emit_Text:
2645     emitGPRsAsText(Func);
2646     return;
2647   case Emit_Binary:
2648     Func->getAssembler<ARM32::AssemblerARM32>()->popList(Registers,
2649                                                          CondARM32::AL);
2650     return;
2651   }
2652 }
2653 
emitSRegs(const Cfg * Func,const EmitForm Form,const Variable * BaseReg,SizeT RegCount) const2654 void InstARM32Pop::emitSRegs(const Cfg *Func, const EmitForm Form,
2655                              const Variable *BaseReg, SizeT RegCount) const {
2656   switch (Form) {
2657   case Emit_Text:
2658     emitSRegsAsText(Func, BaseReg, RegCount);
2659     return;
2660   case Emit_Binary:
2661     Func->getAssembler<ARM32::AssemblerARM32>()->vpop(BaseReg, RegCount,
2662                                                       CondARM32::AL);
2663     return;
2664   }
2665 }
2666 
getGPROpcode() const2667 const char *InstARM32Push::getGPROpcode() const { return "push"; }
2668 
getSRegOpcode() const2669 const char *InstARM32Push::getSRegOpcode() const { return "vpush"; }
2670 
getStackReg(SizeT Index) const2671 Variable *InstARM32Push::getStackReg(SizeT Index) const {
2672   return llvm::cast<Variable>(getSrc(Index));
2673 }
2674 
getNumStackRegs() const2675 SizeT InstARM32Push::getNumStackRegs() const { return getSrcSize(); }
2676 
emitSingleGPR(const Cfg * Func,const EmitForm Form,const Variable * Reg) const2677 void InstARM32Push::emitSingleGPR(const Cfg *Func, const EmitForm Form,
2678                                   const Variable *Reg) const {
2679   switch (Form) {
2680   case Emit_Text:
2681     emitGPRsAsText(Func);
2682     return;
2683   case Emit_Binary:
2684     Func->getAssembler<ARM32::AssemblerARM32>()->push(Reg, CondARM32::AL);
2685     return;
2686   }
2687 }
2688 
emitMultipleGPRs(const Cfg * Func,const EmitForm Form,IValueT Registers) const2689 void InstARM32Push::emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
2690                                      IValueT Registers) const {
2691   switch (Form) {
2692   case Emit_Text:
2693     emitGPRsAsText(Func);
2694     return;
2695   case Emit_Binary:
2696     Func->getAssembler<ARM32::AssemblerARM32>()->pushList(Registers,
2697                                                           CondARM32::AL);
2698     return;
2699   }
2700 }
2701 
emitSRegs(const Cfg * Func,const EmitForm Form,const Variable * BaseReg,SizeT RegCount) const2702 void InstARM32Push::emitSRegs(const Cfg *Func, const EmitForm Form,
2703                               const Variable *BaseReg, SizeT RegCount) const {
2704   switch (Form) {
2705   case Emit_Text:
2706     emitSRegsAsText(Func, BaseReg, RegCount);
2707     return;
2708   case Emit_Binary:
2709     Func->getAssembler<ARM32::AssemblerARM32>()->vpush(BaseReg, RegCount,
2710                                                        CondARM32::AL);
2711     return;
2712   }
2713 }
2714 
emit(const Cfg * Func) const2715 void InstARM32Ret::emit(const Cfg *Func) const {
2716   if (!BuildDefs::dump())
2717     return;
2718   assert(getSrcSize() > 0);
2719   auto *LR = llvm::cast<Variable>(getSrc(0));
2720   assert(LR->hasReg());
2721   assert(LR->getRegNum() == RegARM32::Reg_lr);
2722   Ostream &Str = Func->getContext()->getStrEmit();
2723   Str << "\t"
2724          "bx"
2725          "\t";
2726   LR->emit(Func);
2727 }
2728 
emitIAS(const Cfg * Func) const2729 void InstARM32Ret::emitIAS(const Cfg *Func) const {
2730   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2731   Asm->bx(RegARM32::Encoded_Reg_lr);
2732   if (Asm->needsTextFixup())
2733     emitUsingTextFixup(Func);
2734 }
2735 
dump(const Cfg * Func) const2736 void InstARM32Ret::dump(const Cfg *Func) const {
2737   if (!BuildDefs::dump())
2738     return;
2739   Ostream &Str = Func->getContext()->getStrDump();
2740   Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType());
2741   Str << "ret." << Ty << " ";
2742   dumpSources(Func);
2743 }
2744 
emit(const Cfg * Func) const2745 void InstARM32Str::emit(const Cfg *Func) const {
2746   if (!BuildDefs::dump())
2747     return;
2748   Ostream &Str = Func->getContext()->getStrEmit();
2749   assert(getSrcSize() == 2);
2750   Type Ty = getSrc(0)->getType();
2751   const bool IsVectorStore = isVectorType(Ty);
2752   const bool IsScalarFloat = isScalarFloatingType(Ty);
2753   const char *Opcode =
2754       IsVectorStore ? "vst1" : (IsScalarFloat ? "vstr" : "str");
2755   Str << "\t" << Opcode;
2756   const bool IsVInst = IsVectorStore || IsScalarFloat;
2757   if (IsVInst) {
2758     Str << getPredicate() << getWidthString(Ty);
2759   } else {
2760     Str << getWidthString(Ty) << getPredicate();
2761   }
2762   if (IsVectorStore)
2763     Str << "." << getVecElmtBitsize(Ty);
2764   Str << "\t";
2765   getSrc(0)->emit(Func);
2766   Str << ", ";
2767   getSrc(1)->emit(Func);
2768 }
2769 
emitIAS(const Cfg * Func) const2770 void InstARM32Str::emitIAS(const Cfg *Func) const {
2771   assert(getSrcSize() == 2);
2772   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2773   const Operand *Src0 = getSrc(0);
2774   const Operand *Src1 = getSrc(1);
2775   Type Ty = Src0->getType();
2776   switch (Ty) {
2777   default:
2778     llvm::report_fatal_error("Str on unknown type: " + typeStdString(Ty));
2779   case IceType_i1:
2780   case IceType_i8:
2781   case IceType_i16:
2782   case IceType_i32:
2783   case IceType_i64:
2784     Asm->str(Src0, Src1, getPredicate(), Func->getTarget());
2785     break;
2786   case IceType_f32:
2787     Asm->vstrs(Src0, Src1, getPredicate(), Func->getTarget());
2788     break;
2789   case IceType_f64:
2790     Asm->vstrd(Src0, Src1, getPredicate(), Func->getTarget());
2791     break;
2792   case IceType_v16i8:
2793   case IceType_v8i16:
2794   case IceType_v4i32:
2795   case IceType_v4f32:
2796   case IceType_v16i1:
2797   case IceType_v8i1:
2798   case IceType_v4i1:
2799     Asm->vst1qr(getVecElmtBitsize(Ty), Src0, Src1, Func->getTarget());
2800     break;
2801   }
2802 }
2803 
dump(const Cfg * Func) const2804 void InstARM32Str::dump(const Cfg *Func) const {
2805   if (!BuildDefs::dump())
2806     return;
2807   Ostream &Str = Func->getContext()->getStrDump();
2808   Type Ty = getSrc(0)->getType();
2809   dumpOpcodePred(Str, "str", Ty);
2810   Str << " ";
2811   getSrc(1)->dump(Func);
2812   Str << ", ";
2813   getSrc(0)->dump(Func);
2814 }
2815 
emit(const Cfg * Func) const2816 void InstARM32Strex::emit(const Cfg *Func) const {
2817   if (!BuildDefs::dump())
2818     return;
2819   assert(getSrcSize() == 2);
2820   Type Ty = getSrc(0)->getType();
2821   assert(isScalarIntegerType(Ty));
2822   Variable *Dest = getDest();
2823   Ostream &Str = Func->getContext()->getStrEmit();
2824   static constexpr char Opcode[] = "strex";
2825   const char *WidthString = getWidthString(Ty);
2826   Str << "\t" << Opcode << WidthString << getPredicate() << "\t";
2827   Dest->emit(Func);
2828   Str << ", ";
2829   emitSources(Func);
2830 }
2831 
emitIAS(const Cfg * Func) const2832 void InstARM32Strex::emitIAS(const Cfg *Func) const {
2833   assert(getSrcSize() == 2);
2834   const Operand *Src0 = getSrc(0);
2835   assert(isScalarIntegerType(Src0->getType()));
2836   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2837   Asm->strex(Dest, Src0, getSrc(1), getPredicate(), Func->getTarget());
2838   if (Asm->needsTextFixup())
2839     emitUsingTextFixup(Func);
2840 }
2841 
dump(const Cfg * Func) const2842 void InstARM32Strex::dump(const Cfg *Func) const {
2843   if (!BuildDefs::dump())
2844     return;
2845   Ostream &Str = Func->getContext()->getStrDump();
2846   Variable *Dest = getDest();
2847   Dest->dump(Func);
2848   Str << " = ";
2849   Type Ty = getSrc(0)->getType();
2850   dumpOpcodePred(Str, "strex", Ty);
2851   Str << " ";
2852   getSrc(1)->dump(Func);
2853   Str << ", ";
2854   getSrc(0)->dump(Func);
2855 }
2856 
emit(const Cfg * Func) const2857 void InstARM32Vstr1::emit(const Cfg *Func) const {
2858   if (!BuildDefs::dump())
2859     return;
2860   Ostream &Str = Func->getContext()->getStrEmit();
2861   assert(getSrcSize() == 2);
2862   Type Ty = getSrc(0)->getType();
2863   const bool IsVectorStore = isVectorType(Ty);
2864   const bool IsScalarFloat = isScalarFloatingType(Ty);
2865   const char *Opcode =
2866       IsVectorStore ? "vst1" : (IsScalarFloat ? "vstr" : "str");
2867   Str << "\t" << Opcode;
2868   const bool IsVInst = IsVectorStore || IsScalarFloat;
2869   if (IsVInst) {
2870     Str << getPredicate() << getWidthString(Ty);
2871   } else {
2872     Str << getWidthString(Ty) << getPredicate();
2873   }
2874   if (IsVectorStore)
2875     Str << "." << getVecElmtBitsize(Ty);
2876   Str << "\t";
2877   getSrc(0)->emit(Func);
2878   Str << ", ";
2879   getSrc(1)->emit(Func);
2880 }
2881 
emitIAS(const Cfg * Func) const2882 void InstARM32Vstr1::emitIAS(const Cfg *Func) const {
2883   assert(getSrcSize() == 2);
2884   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2885   const Operand *Src0 = getSrc(0);
2886   const Operand *Src1 = getSrc(1);
2887   Asm->vst1(Size, Src0, Src1, Func->getTarget());
2888 }
2889 
dump(const Cfg * Func) const2890 void InstARM32Vstr1::dump(const Cfg *Func) const {
2891   if (!BuildDefs::dump())
2892     return;
2893   Ostream &Str = Func->getContext()->getStrDump();
2894   Type Ty = getSrc(0)->getType();
2895   dumpOpcodePred(Str, "str", Ty);
2896   Str << " ";
2897   getSrc(1)->dump(Func);
2898   Str << ", ";
2899   getSrc(0)->dump(Func);
2900 }
2901 
emit(const Cfg * Func) const2902 void InstARM32Vdup::emit(const Cfg *Func) const {
2903   if (!BuildDefs::dump())
2904     return;
2905   Ostream &Str = Func->getContext()->getStrEmit();
2906   assert(getSrcSize() == 2);
2907   Type Ty = getSrc(0)->getType();
2908   const char *Opcode = "vdup";
2909   Str << "\t" << Opcode;
2910   Str << getPredicate() << "." << getWidthString(Ty) << getVecElmtBitsize(Ty);
2911   Str << "\t";
2912   getSrc(0)->emit(Func);
2913   Str << ", ";
2914   getSrc(1)->emit(Func);
2915   Str << ", " << Idx;
2916 }
2917 
emitIAS(const Cfg * Func) const2918 void InstARM32Vdup::emitIAS(const Cfg *Func) const {
2919   assert(getSrcSize() == 1);
2920   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2921   const Operand *Dest = getDest();
2922   const Operand *Src = getSrc(0);
2923   Type DestTy = Dest->getType();
2924   Asm->vdup(typeElementType(DestTy), Dest, Src, Idx);
2925 }
2926 
dump(const Cfg * Func) const2927 void InstARM32Vdup::dump(const Cfg *Func) const {
2928   if (!BuildDefs::dump())
2929     return;
2930   Ostream &Str = Func->getContext()->getStrDump();
2931   dumpDest(Func);
2932   Str << " = ";
2933   dumpOpcodePred(Str, "vdup", getDest()->getType());
2934   Str << " ";
2935   dumpSources(Func);
2936   Str << ", " << Idx;
2937 }
2938 
emit(const Cfg * Func) const2939 void InstARM32Trap::emit(const Cfg *Func) const {
2940   if (!BuildDefs::dump())
2941     return;
2942   Ostream &Str = Func->getContext()->getStrEmit();
2943   assert(getSrcSize() == 0);
2944   // There isn't a mnemonic for the special NaCl Trap encoding, so dump
2945   // the raw bytes.
2946   Str << "\t.long 0x";
2947   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2948   for (uint8_t I : Asm->getNonExecBundlePadding()) {
2949     Str.write_hex(I);
2950   }
2951 }
2952 
emitIAS(const Cfg * Func) const2953 void InstARM32Trap::emitIAS(const Cfg *Func) const {
2954   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2955   Asm->trap();
2956   assert(!Asm->needsTextFixup());
2957 }
2958 
dump(const Cfg * Func) const2959 void InstARM32Trap::dump(const Cfg *Func) const {
2960   if (!BuildDefs::dump())
2961     return;
2962   Ostream &Str = Func->getContext()->getStrDump();
2963   Str << "trap";
2964 }
2965 
emit(const Cfg * Func) const2966 void InstARM32Umull::emit(const Cfg *Func) const {
2967   if (!BuildDefs::dump())
2968     return;
2969   Ostream &Str = Func->getContext()->getStrEmit();
2970   assert(getSrcSize() == 2);
2971   assert(getDest()->hasReg());
2972   Str << "\t"
2973          "umull"
2974       << getPredicate() << "\t";
2975   getDest()->emit(Func);
2976   Str << ", ";
2977   DestHi->emit(Func);
2978   Str << ", ";
2979   getSrc(0)->emit(Func);
2980   Str << ", ";
2981   getSrc(1)->emit(Func);
2982 }
2983 
emitIAS(const Cfg * Func) const2984 void InstARM32Umull::emitIAS(const Cfg *Func) const {
2985   assert(getSrcSize() == 2);
2986   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2987   Asm->umull(getDest(), DestHi, getSrc(0), getSrc(1), getPredicate());
2988   if (Asm->needsTextFixup())
2989     emitUsingTextFixup(Func);
2990 }
2991 
dump(const Cfg * Func) const2992 void InstARM32Umull::dump(const Cfg *Func) const {
2993   if (!BuildDefs::dump())
2994     return;
2995   Ostream &Str = Func->getContext()->getStrDump();
2996   dumpDest(Func);
2997   Str << " = ";
2998   dumpOpcodePred(Str, "umull", getDest()->getType());
2999   Str << " ";
3000   dumpSources(Func);
3001 }
3002 
3003 namespace {
vcvtVariantSuffix(const InstARM32Vcvt::VcvtVariant Variant)3004 const char *vcvtVariantSuffix(const InstARM32Vcvt::VcvtVariant Variant) {
3005   switch (Variant) {
3006   case InstARM32Vcvt::S2si:
3007     return ".s32.f32";
3008   case InstARM32Vcvt::S2ui:
3009     return ".u32.f32";
3010   case InstARM32Vcvt::Si2s:
3011     return ".f32.s32";
3012   case InstARM32Vcvt::Ui2s:
3013     return ".f32.u32";
3014   case InstARM32Vcvt::D2si:
3015     return ".s32.f64";
3016   case InstARM32Vcvt::D2ui:
3017     return ".u32.f64";
3018   case InstARM32Vcvt::Si2d:
3019     return ".f64.s32";
3020   case InstARM32Vcvt::Ui2d:
3021     return ".f64.u32";
3022   case InstARM32Vcvt::S2d:
3023     return ".f64.f32";
3024   case InstARM32Vcvt::D2s:
3025     return ".f32.f64";
3026   case InstARM32Vcvt::Vs2si:
3027     return ".s32.f32";
3028   case InstARM32Vcvt::Vs2ui:
3029     return ".u32.f32";
3030   case InstARM32Vcvt::Vsi2s:
3031     return ".f32.s32";
3032   case InstARM32Vcvt::Vui2s:
3033     return ".f32.u32";
3034   }
3035   llvm::report_fatal_error("Invalid VcvtVariant enum.");
3036 }
3037 } // end of anonymous namespace
3038 
emit(const Cfg * Func) const3039 void InstARM32Vcvt::emit(const Cfg *Func) const {
3040   if (!BuildDefs::dump())
3041     return;
3042   Ostream &Str = Func->getContext()->getStrEmit();
3043   assert(getSrcSize() == 1);
3044   assert(getDest()->hasReg());
3045   Str << "\t"
3046          "vcvt"
3047       << getPredicate() << vcvtVariantSuffix(Variant) << "\t";
3048   getDest()->emit(Func);
3049   Str << ", ";
3050   getSrc(0)->emit(Func);
3051 }
3052 
emitIAS(const Cfg * Func) const3053 void InstARM32Vcvt::emitIAS(const Cfg *Func) const {
3054   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3055   switch (Variant) {
3056   case S2si:
3057     Asm->vcvtis(getDest(), getSrc(0), getPredicate());
3058     break;
3059   case S2ui:
3060     Asm->vcvtus(getDest(), getSrc(0), getPredicate());
3061     break;
3062   case Si2s:
3063     Asm->vcvtsi(getDest(), getSrc(0), getPredicate());
3064     break;
3065   case Ui2s:
3066     Asm->vcvtsu(getDest(), getSrc(0), getPredicate());
3067     break;
3068   case D2si:
3069     Asm->vcvtid(getDest(), getSrc(0), getPredicate());
3070     break;
3071   case D2ui:
3072     Asm->vcvtud(getDest(), getSrc(0), getPredicate());
3073     break;
3074   case Si2d:
3075     Asm->vcvtdi(getDest(), getSrc(0), getPredicate());
3076     break;
3077   case Ui2d:
3078     Asm->vcvtdu(getDest(), getSrc(0), getPredicate());
3079     break;
3080   case S2d:
3081     Asm->vcvtds(getDest(), getSrc(0), getPredicate());
3082     break;
3083   case D2s:
3084     Asm->vcvtsd(getDest(), getSrc(0), getPredicate());
3085     break;
3086   case Vs2si:
3087     Asm->vcvtqsi(getDest(), getSrc(0));
3088     break;
3089   case Vs2ui:
3090     Asm->vcvtqsu(getDest(), getSrc(0));
3091     break;
3092   case Vsi2s:
3093     Asm->vcvtqis(getDest(), getSrc(0));
3094     break;
3095   case Vui2s:
3096     Asm->vcvtqus(getDest(), getSrc(0));
3097     break;
3098   }
3099   assert(!Asm->needsTextFixup());
3100 }
3101 
dump(const Cfg * Func) const3102 void InstARM32Vcvt::dump(const Cfg *Func) const {
3103   if (!BuildDefs::dump())
3104     return;
3105   Ostream &Str = Func->getContext()->getStrDump();
3106   dumpDest(Func);
3107   Str << " = "
3108       << "vcvt" << getPredicate() << vcvtVariantSuffix(Variant) << " ";
3109   dumpSources(Func);
3110 }
3111 
emit(const Cfg * Func) const3112 void InstARM32Vcmp::emit(const Cfg *Func) const {
3113   if (!BuildDefs::dump())
3114     return;
3115   Ostream &Str = Func->getContext()->getStrEmit();
3116   assert(getSrcSize() == 2);
3117   Str << "\t"
3118          "vcmp"
3119       << getPredicate() << getFpWidthString(getSrc(0)->getType()) << "\t";
3120   getSrc(0)->emit(Func);
3121   Str << ", ";
3122   getSrc(1)->emit(Func);
3123 }
3124 
emitIAS(const Cfg * Func) const3125 void InstARM32Vcmp::emitIAS(const Cfg *Func) const {
3126   assert(getSrcSize() == 2);
3127   const Operand *Src0 = getSrc(0);
3128   const Type Ty = Src0->getType();
3129   const Operand *Src1 = getSrc(1);
3130   const CondARM32::Cond Cond = getPredicate();
3131   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3132   if (llvm::isa<OperandARM32FlexFpZero>(Src1)) {
3133     switch (Ty) {
3134     case IceType_f32:
3135       Asm->vcmpsz(Src0, Cond);
3136       break;
3137     case IceType_f64:
3138       Asm->vcmpdz(Src0, Cond);
3139       break;
3140     default:
3141       llvm::report_fatal_error("Vcvt on non floating value");
3142     }
3143   } else {
3144     switch (Ty) {
3145     case IceType_f32:
3146       Asm->vcmps(Src0, Src1, Cond);
3147       break;
3148     case IceType_f64:
3149       Asm->vcmpd(Src0, Src1, Cond);
3150       break;
3151     default:
3152       llvm::report_fatal_error("Vcvt on non floating value");
3153     }
3154   }
3155   assert(!Asm->needsTextFixup());
3156 }
3157 
dump(const Cfg * Func) const3158 void InstARM32Vcmp::dump(const Cfg *Func) const {
3159   if (!BuildDefs::dump())
3160     return;
3161   Ostream &Str = Func->getContext()->getStrDump();
3162   Str << "vcmp" << getPredicate() << getFpWidthString(getSrc(0)->getType());
3163   dumpSources(Func);
3164 }
3165 
emit(const Cfg * Func) const3166 void InstARM32Vmrs::emit(const Cfg *Func) const {
3167   if (!BuildDefs::dump())
3168     return;
3169   Ostream &Str = Func->getContext()->getStrEmit();
3170   assert(getSrcSize() == 0);
3171   Str << "\t"
3172          "vmrs"
3173       << getPredicate()
3174       << "\t"
3175          "APSR_nzcv"
3176          ", "
3177          "FPSCR";
3178 }
3179 
emitIAS(const Cfg * Func) const3180 void InstARM32Vmrs::emitIAS(const Cfg *Func) const {
3181   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3182   Asm->vmrsAPSR_nzcv(getPredicate());
3183   assert(!Asm->needsTextFixup());
3184 }
3185 
dump(const Cfg * Func) const3186 void InstARM32Vmrs::dump(const Cfg *Func) const {
3187   if (!BuildDefs::dump())
3188     return;
3189   Ostream &Str = Func->getContext()->getStrDump();
3190   Str << "APSR{n,z,v,c} = vmrs" << getPredicate()
3191       << "\t"
3192          "FPSCR{n,z,c,v}";
3193 }
3194 
emit(const Cfg * Func) const3195 void InstARM32Vabs::emit(const Cfg *Func) const {
3196   if (!BuildDefs::dump())
3197     return;
3198   Ostream &Str = Func->getContext()->getStrEmit();
3199   assert(getSrcSize() == 1);
3200   Str << "\t"
3201          "vabs"
3202       << getPredicate() << getFpWidthString(getSrc(0)->getType()) << "\t";
3203   getDest()->emit(Func);
3204   Str << ", ";
3205   getSrc(0)->emit(Func);
3206 }
3207 
emitIAS(const Cfg * Func) const3208 void InstARM32Vabs::emitIAS(const Cfg *Func) const {
3209   assert(getSrcSize() == 1);
3210   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3211   const Variable *Dest = getDest();
3212   switch (Dest->getType()) {
3213   default:
3214     llvm::report_fatal_error("fabs not defined on type " +
3215                              typeStdString(Dest->getType()));
3216   case IceType_f32:
3217     Asm->vabss(Dest, getSrc(0), getPredicate());
3218     break;
3219   case IceType_f64:
3220     Asm->vabsd(Dest, getSrc(0), getPredicate());
3221     break;
3222   case IceType_v4f32:
3223     assert(CondARM32::isUnconditional(getPredicate()) &&
3224            "fabs must be unconditional");
3225     Asm->vabsq(Dest, getSrc(0));
3226   }
3227   assert(!Asm->needsTextFixup());
3228 }
3229 
dump(const Cfg * Func) const3230 void InstARM32Vabs::dump(const Cfg *Func) const {
3231   if (!BuildDefs::dump())
3232     return;
3233   Ostream &Str = Func->getContext()->getStrDump();
3234   dumpDest(Func);
3235   Str << " = vabs" << getPredicate() << getFpWidthString(getSrc(0)->getType());
3236 }
3237 
emit(const Cfg * Func) const3238 void InstARM32Dmb::emit(const Cfg *Func) const {
3239   if (!BuildDefs::dump())
3240     return;
3241   Ostream &Str = Func->getContext()->getStrEmit();
3242   assert(getSrcSize() == 0);
3243   Str << "\t"
3244          "dmb"
3245          "\t"
3246          "sy";
3247 }
3248 
emitIAS(const Cfg * Func) const3249 void InstARM32Dmb::emitIAS(const Cfg *Func) const {
3250   assert(getSrcSize() == 0);
3251   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3252   constexpr ARM32::IValueT SyOption = 0xF; // i.e. 1111
3253   Asm->dmb(SyOption);
3254   if (Asm->needsTextFixup())
3255     emitUsingTextFixup(Func);
3256 }
3257 
dump(const Cfg * Func) const3258 void InstARM32Dmb::dump(const Cfg *Func) const {
3259   if (!BuildDefs::dump())
3260     return;
3261   Func->getContext()->getStrDump() << "dmb\t"
3262                                       "sy";
3263 }
3264 
emit(const Cfg * Func) const3265 void InstARM32Nop::emit(const Cfg *Func) const {
3266   if (!BuildDefs::dump())
3267     return;
3268   assert(getSrcSize() == 0);
3269   Func->getContext()->getStrEmit() << "\t"
3270                                    << "nop";
3271 }
3272 
emitIAS(const Cfg * Func) const3273 void InstARM32Nop::emitIAS(const Cfg *Func) const {
3274   assert(getSrcSize() == 0);
3275   Func->getAssembler<ARM32::AssemblerARM32>()->nop();
3276 }
3277 
dump(const Cfg * Func) const3278 void InstARM32Nop::dump(const Cfg *Func) const {
3279   if (!BuildDefs::dump())
3280     return;
3281   assert(getSrcSize() == 0);
3282   Func->getContext()->getStrDump() << "nop";
3283 }
3284 
emit(const Cfg * Func) const3285 void OperandARM32Mem::emit(const Cfg *Func) const {
3286   if (!BuildDefs::dump())
3287     return;
3288   Ostream &Str = Func->getContext()->getStrEmit();
3289   Str << "[";
3290   getBase()->emit(Func);
3291   switch (getAddrMode()) {
3292   case PostIndex:
3293   case NegPostIndex:
3294     Str << "]";
3295     break;
3296   default:
3297     break;
3298   }
3299   if (isRegReg()) {
3300     Str << ", ";
3301     if (isNegAddrMode()) {
3302       Str << "-";
3303     }
3304     getIndex()->emit(Func);
3305     if (getShiftOp() != kNoShift) {
3306       Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
3307           << getShiftAmt();
3308     }
3309   } else {
3310     ConstantInteger32 *Offset = getOffset();
3311     if (Offset && Offset->getValue() != 0) {
3312       Str << ", ";
3313       Offset->emit(Func);
3314     }
3315   }
3316   switch (getAddrMode()) {
3317   case Offset:
3318   case NegOffset:
3319     Str << "]";
3320     break;
3321   case PreIndex:
3322   case NegPreIndex:
3323     Str << "]!";
3324     break;
3325   case PostIndex:
3326   case NegPostIndex:
3327     // Brace is already closed off.
3328     break;
3329   }
3330 }
3331 
dump(const Cfg * Func,Ostream & Str) const3332 void OperandARM32Mem::dump(const Cfg *Func, Ostream &Str) const {
3333   if (!BuildDefs::dump())
3334     return;
3335   Str << "[";
3336   if (Func)
3337     getBase()->dump(Func);
3338   else
3339     getBase()->dump(Str);
3340   Str << ", ";
3341   if (isRegReg()) {
3342     if (isNegAddrMode()) {
3343       Str << "-";
3344     }
3345     if (Func)
3346       getIndex()->dump(Func);
3347     else
3348       getIndex()->dump(Str);
3349     if (getShiftOp() != kNoShift) {
3350       Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
3351           << getShiftAmt();
3352     }
3353   } else {
3354     getOffset()->dump(Func, Str);
3355   }
3356   Str << "] AddrMode==" << getAddrMode();
3357 }
3358 
emit(const Cfg * Func) const3359 void OperandARM32ShAmtImm::emit(const Cfg *Func) const { ShAmt->emit(Func); }
3360 
dump(const Cfg *,Ostream & Str) const3361 void OperandARM32ShAmtImm::dump(const Cfg *, Ostream &Str) const {
3362   ShAmt->dump(Str);
3363 }
3364 
create(Cfg * Func,Type Ty,uint32_t Imm,uint32_t RotateAmt)3365 OperandARM32FlexImm *OperandARM32FlexImm::create(Cfg *Func, Type Ty,
3366                                                  uint32_t Imm,
3367                                                  uint32_t RotateAmt) {
3368   // The assembler wants the smallest rotation. Rotate if needed. Note: Imm is
3369   // an 8-bit value.
3370   assert(Utils::IsUint(8, Imm) &&
3371          "Flex immediates can only be defined on 8-bit immediates");
3372   while ((Imm & 0x03) == 0 && RotateAmt > 0) {
3373     --RotateAmt;
3374     Imm = Imm >> 2;
3375   }
3376   return new (Func->allocate<OperandARM32FlexImm>())
3377       OperandARM32FlexImm(Func, Ty, Imm, RotateAmt);
3378 }
3379 
emit(const Cfg * Func) const3380 void OperandARM32FlexImm::emit(const Cfg *Func) const {
3381   if (!BuildDefs::dump())
3382     return;
3383   Ostream &Str = Func->getContext()->getStrEmit();
3384   uint32_t Imm = getImm();
3385   uint32_t RotateAmt = getRotateAmt();
3386   Str << "#" << Utils::rotateRight32(Imm, 2 * RotateAmt);
3387 }
3388 
dump(const Cfg *,Ostream & Str) const3389 void OperandARM32FlexImm::dump(const Cfg * /* Func */, Ostream &Str) const {
3390   if (!BuildDefs::dump())
3391     return;
3392   uint32_t Imm = getImm();
3393   uint32_t RotateAmt = getRotateAmt();
3394   Str << "#(" << Imm << " ror 2*" << RotateAmt << ")";
3395 }
3396 
3397 namespace {
3398 static constexpr uint32_t a = 0x80;
3399 static constexpr uint32_t b = 0x40;
3400 static constexpr uint32_t cdefgh = 0x3F;
3401 static constexpr uint32_t AllowedBits = a | b | cdefgh;
3402 static_assert(AllowedBits == 0xFF,
3403               "Invalid mask for f32/f64 constant rematerialization.");
3404 
3405 // There's no loss in always returning the modified immediate as float.
3406 // TODO(jpp): returning a double causes problems when outputting the constants
3407 // for filetype=asm. Why?
materializeFloatImmediate(uint32_t ModifiedImm)3408 float materializeFloatImmediate(uint32_t ModifiedImm) {
3409   const uint32_t Ret = ((ModifiedImm & a) ? 0x80000000 : 0) |
3410                        ((ModifiedImm & b) ? 0x3E000000 : 0x40000000) |
3411                        ((ModifiedImm & cdefgh) << 19);
3412   return Utils::bitCopy<float>(Ret);
3413 }
3414 
3415 } // end of anonymous namespace
3416 
emit(const Cfg * Func) const3417 void OperandARM32FlexFpImm::emit(const Cfg *Func) const {
3418   if (!BuildDefs::dump())
3419     return;
3420   Ostream &Str = Func->getContext()->getStrEmit();
3421   switch (Ty) {
3422   default:
3423     llvm::report_fatal_error("Invalid flex fp imm type.");
3424   case IceType_f64:
3425   case IceType_f32:
3426     Str << "#" << materializeFloatImmediate(ModifiedImm)
3427         << " @ Modified: " << ModifiedImm;
3428     break;
3429   }
3430 }
3431 
dump(const Cfg *,Ostream & Str) const3432 void OperandARM32FlexFpImm::dump(const Cfg * /*Func*/, Ostream &Str) const {
3433   if (!BuildDefs::dump())
3434     return;
3435   Str << "#" << materializeFloatImmediate(ModifiedImm) << getFpWidthString(Ty);
3436 }
3437 
emit(const Cfg * Func) const3438 void OperandARM32FlexFpZero::emit(const Cfg *Func) const {
3439   if (!BuildDefs::dump())
3440     return;
3441   Ostream &Str = Func->getContext()->getStrEmit();
3442   switch (Ty) {
3443   default:
3444     llvm::report_fatal_error("Invalid flex fp imm type.");
3445   case IceType_f64:
3446   case IceType_f32:
3447     Str << "#0.0";
3448   }
3449 }
3450 
dump(const Cfg *,Ostream & Str) const3451 void OperandARM32FlexFpZero::dump(const Cfg * /*Func*/, Ostream &Str) const {
3452   if (!BuildDefs::dump())
3453     return;
3454   Str << "#0.0" << getFpWidthString(Ty);
3455 }
3456 
emit(const Cfg * Func) const3457 void OperandARM32FlexReg::emit(const Cfg *Func) const {
3458   if (!BuildDefs::dump())
3459     return;
3460   Ostream &Str = Func->getContext()->getStrEmit();
3461   getReg()->emit(Func);
3462   if (getShiftOp() != kNoShift) {
3463     Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
3464     getShiftAmt()->emit(Func);
3465   }
3466 }
3467 
dump(const Cfg * Func,Ostream & Str) const3468 void OperandARM32FlexReg::dump(const Cfg *Func, Ostream &Str) const {
3469   if (!BuildDefs::dump())
3470     return;
3471   Variable *Reg = getReg();
3472   if (Func)
3473     Reg->dump(Func);
3474   else
3475     Reg->dump(Str);
3476   if (getShiftOp() != kNoShift) {
3477     Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
3478     if (Func)
3479       getShiftAmt()->dump(Func);
3480     else
3481       getShiftAmt()->dump(Str);
3482   }
3483 }
3484 
3485 // Force instantition of template classes
3486 template class InstARM32ThreeAddrGPR<InstARM32::Adc>;
3487 template class InstARM32ThreeAddrGPR<InstARM32::Add>;
3488 template class InstARM32ThreeAddrGPR<InstARM32::And>;
3489 template class InstARM32ThreeAddrGPR<InstARM32::Asr>;
3490 template class InstARM32ThreeAddrGPR<InstARM32::Bic>;
3491 template class InstARM32ThreeAddrGPR<InstARM32::Eor>;
3492 template class InstARM32ThreeAddrGPR<InstARM32::Lsl>;
3493 template class InstARM32ThreeAddrGPR<InstARM32::Lsr>;
3494 template class InstARM32ThreeAddrGPR<InstARM32::Mul>;
3495 template class InstARM32ThreeAddrGPR<InstARM32::Orr>;
3496 template class InstARM32ThreeAddrGPR<InstARM32::Rsb>;
3497 template class InstARM32ThreeAddrGPR<InstARM32::Rsc>;
3498 template class InstARM32ThreeAddrGPR<InstARM32::Sbc>;
3499 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
3500 template class InstARM32ThreeAddrGPR<InstARM32::Sub>;
3501 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>;
3502 
3503 template class InstARM32ThreeAddrFP<InstARM32::Vadd>;
3504 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vcge>;
3505 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vcgt>;
3506 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>;
3507 template class InstARM32ThreeAddrFP<InstARM32::Veor>;
3508 template class InstARM32FourAddrFP<InstARM32::Vmla>;
3509 template class InstARM32FourAddrFP<InstARM32::Vmls>;
3510 template class InstARM32ThreeAddrFP<InstARM32::Vmul>;
3511 template class InstARM32UnaryopSignAwareFP<InstARM32::Vneg>;
3512 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>;
3513 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vshr>;
3514 template class InstARM32ThreeAddrFP<InstARM32::Vsub>;
3515 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vqadd>;
3516 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vqsub>;
3517 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vqmovn2>;
3518 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vmulh>;
3519 template class InstARM32ThreeAddrFP<InstARM32::Vmlap>;
3520 
3521 template class InstARM32LoadBase<InstARM32::Ldr>;
3522 template class InstARM32LoadBase<InstARM32::Ldrex>;
3523 template class InstARM32LoadBase<InstARM32::Vldr1d>;
3524 template class InstARM32LoadBase<InstARM32::Vldr1q>;
3525 template class InstARM32ThreeAddrFP<InstARM32::Vzip>;
3526 template class InstARM32TwoAddrGPR<InstARM32::Movt>;
3527 
3528 template class InstARM32UnaryopGPR<InstARM32::Movw, false>;
3529 template class InstARM32UnaryopGPR<InstARM32::Clz, false>;
3530 template class InstARM32UnaryopGPR<InstARM32::Mvn, false>;
3531 template class InstARM32UnaryopGPR<InstARM32::Rbit, false>;
3532 template class InstARM32UnaryopGPR<InstARM32::Rev, false>;
3533 template class InstARM32UnaryopGPR<InstARM32::Sxt, true>;
3534 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>;
3535 template class InstARM32UnaryopFP<InstARM32::Vsqrt>;
3536 
3537 template class InstARM32FourAddrGPR<InstARM32::Mla>;
3538 template class InstARM32FourAddrGPR<InstARM32::Mls>;
3539 
3540 template class InstARM32CmpLike<InstARM32::Cmn>;
3541 template class InstARM32CmpLike<InstARM32::Cmp>;
3542 template class InstARM32CmpLike<InstARM32::Tst>;
3543 
3544 } // end of namespace ARM32
3545 } // end of namespace Ice
3546