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