blob: add4df02ab00f7390af048b1778f5c9bee54faf5 [file] [log] [blame]
Jan Voungb2d50842015-05-12 09:53:50 -07001//===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
11/// This file implements the InstARM32 and OperandARM32 classes,
12/// primarily the constructors and the dump()/emit() methods.
13///
Jan Voungb2d50842015-05-12 09:53:50 -070014//===----------------------------------------------------------------------===//
15
John Porto67f8de92015-06-25 10:14:17 -070016#include "IceInstARM32.h"
17
John Portoaff4ccf2015-06-10 16:35:06 -070018#include "IceAssemblerARM32.h"
Jan Voungb2d50842015-05-12 09:53:50 -070019#include "IceCfg.h"
20#include "IceCfgNode.h"
21#include "IceInst.h"
Jan Voungb2d50842015-05-12 09:53:50 -070022#include "IceOperand.h"
23#include "IceRegistersARM32.h"
24#include "IceTargetLoweringARM32.h"
25
26namespace Ice {
27
28namespace {
29
30const struct TypeARM32Attributes_ {
Jan Voung86ebec12015-08-09 07:58:35 -070031 const char *WidthString; // b, h, <blank>, or d
32 const char *VecWidthString; // i8, i16, i32, f32, f64
Jan Voungb2d50842015-05-12 09:53:50 -070033 int8_t SExtAddrOffsetBits;
34 int8_t ZExtAddrOffsetBits;
35} TypeARM32Attributes[] = {
Jan Voung86ebec12015-08-09 07:58:35 -070036#define X(tag, elementty, int_width, vec_width, sbits, ubits) \
37 { int_width, vec_width, sbits, ubits } \
Jan Voungb2d50842015-05-12 09:53:50 -070038 ,
39 ICETYPEARM32_TABLE
40#undef X
41};
42
Jan Voungb3401d22015-05-18 09:38:21 -070043const struct InstARM32ShiftAttributes_ {
44 const char *EmitString;
45} InstARM32ShiftAttributes[] = {
46#define X(tag, emit) \
47 { emit } \
48 ,
49 ICEINSTARM32SHIFT_TABLE
50#undef X
51};
52
Jan Voung3bfd99a2015-05-22 16:35:25 -070053const struct InstARM32CondAttributes_ {
54 CondARM32::Cond Opposite;
55 const char *EmitString;
56} InstARM32CondAttributes[] = {
57#define X(tag, encode, opp, emit) \
58 { CondARM32::opp, emit } \
59 ,
60 ICEINSTARM32COND_TABLE
61#undef X
62};
63
Jan Voungb2d50842015-05-12 09:53:50 -070064} // end of anonymous namespace
65
66const char *InstARM32::getWidthString(Type Ty) {
67 return TypeARM32Attributes[Ty].WidthString;
68}
69
Jan Voung86ebec12015-08-09 07:58:35 -070070const char *InstARM32::getVecWidthString(Type Ty) {
71 return TypeARM32Attributes[Ty].VecWidthString;
72}
73
Jan Voung3bfd99a2015-05-22 16:35:25 -070074const char *InstARM32Pred::predString(CondARM32::Cond Pred) {
75 return InstARM32CondAttributes[Pred].EmitString;
76}
77
78void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode,
79 Type Ty) const {
80 Str << Opcode << getPredicate() << "." << Ty;
81}
82
83CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) {
84 return InstARM32CondAttributes[Cond].Opposite;
85}
86
Jan Voung66c3d5e2015-06-04 17:02:31 -070087void InstARM32Pred::emitUnaryopGPR(const char *Opcode,
Jan Voungf645d852015-07-09 10:35:09 -070088 const InstARM32Pred *Inst, const Cfg *Func,
89 bool NeedsWidthSuffix) {
Jan Voung66c3d5e2015-06-04 17:02:31 -070090 Ostream &Str = Func->getContext()->getStrEmit();
91 assert(Inst->getSrcSize() == 1);
92 Type SrcTy = Inst->getSrc(0)->getType();
Jan Voung66c3d5e2015-06-04 17:02:31 -070093 Str << "\t" << Opcode;
Jan Voungf645d852015-07-09 10:35:09 -070094 if (NeedsWidthSuffix)
Jan Voung66c3d5e2015-06-04 17:02:31 -070095 Str << getWidthString(SrcTy);
Jan Voungf645d852015-07-09 10:35:09 -070096 Str << Inst->getPredicate() << "\t";
Jan Voung66c3d5e2015-06-04 17:02:31 -070097 Inst->getDest()->emit(Func);
98 Str << ", ";
99 Inst->getSrc(0)->emit(Func);
100}
101
Jan Voung86ebec12015-08-09 07:58:35 -0700102void InstARM32Pred::emitUnaryopFP(const char *Opcode, const InstARM32Pred *Inst,
103 const Cfg *Func) {
104 Ostream &Str = Func->getContext()->getStrEmit();
105 assert(Inst->getSrcSize() == 1);
106 Type SrcTy = Inst->getSrc(0)->getType();
107 Str << "\t" << Opcode << Inst->getPredicate() << getVecWidthString(SrcTy)
108 << "\t";
109 Inst->getDest()->emit(Func);
110 Str << ", ";
111 Inst->getSrc(0)->emit(Func);
112}
113
Jan Voung3bfd99a2015-05-22 16:35:25 -0700114void InstARM32Pred::emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst,
115 const Cfg *Func) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700116 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700117 return;
118 Ostream &Str = Func->getContext()->getStrEmit();
119 assert(Inst->getSrcSize() == 2);
120 Variable *Dest = Inst->getDest();
121 assert(Dest == Inst->getSrc(0));
Jan Voung3bfd99a2015-05-22 16:35:25 -0700122 Str << "\t" << Opcode << Inst->getPredicate() << "\t";
Jan Voungb3401d22015-05-18 09:38:21 -0700123 Dest->emit(Func);
124 Str << ", ";
Jan Voung29719972015-05-19 11:24:51 -0700125 Inst->getSrc(1)->emit(Func);
126}
127
Jan Voung3bfd99a2015-05-22 16:35:25 -0700128void InstARM32Pred::emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst,
129 const Cfg *Func, bool SetFlags) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700130 if (!BuildDefs::dump())
Jan Voung29719972015-05-19 11:24:51 -0700131 return;
132 Ostream &Str = Func->getContext()->getStrEmit();
133 assert(Inst->getSrcSize() == 2);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700134 Str << "\t" << Opcode << (SetFlags ? "s" : "") << Inst->getPredicate()
135 << "\t";
Jan Voung29719972015-05-19 11:24:51 -0700136 Inst->getDest()->emit(Func);
137 Str << ", ";
138 Inst->getSrc(0)->emit(Func);
139 Str << ", ";
140 Inst->getSrc(1)->emit(Func);
Jan Voungb3401d22015-05-18 09:38:21 -0700141}
142
Jan Voung86ebec12015-08-09 07:58:35 -0700143void InstARM32::emitThreeAddrFP(const char *Opcode, const InstARM32 *Inst,
144 const Cfg *Func) {
145 if (!BuildDefs::dump())
146 return;
147 Ostream &Str = Func->getContext()->getStrEmit();
148 assert(Inst->getSrcSize() == 2);
149 Str << "\t" << Opcode << getVecWidthString(Inst->getDest()->getType())
150 << "\t";
151 Inst->getDest()->emit(Func);
152 Str << ", ";
153 Inst->getSrc(0)->emit(Func);
154 Str << ", ";
155 Inst->getSrc(1)->emit(Func);
156}
157
Jan Voung6ec369e2015-06-30 11:03:15 -0700158void InstARM32Pred::emitFourAddr(const char *Opcode, const InstARM32Pred *Inst,
159 const Cfg *Func) {
160 if (!BuildDefs::dump())
161 return;
162 Ostream &Str = Func->getContext()->getStrEmit();
163 assert(Inst->getSrcSize() == 3);
164 Str << "\t" << Opcode << Inst->getPredicate() << "\t";
165 Inst->getDest()->emit(Func);
166 Str << ", ";
167 Inst->getSrc(0)->emit(Func);
168 Str << ", ";
169 Inst->getSrc(1)->emit(Func);
170 Str << ", ";
171 Inst->getSrc(2)->emit(Func);
172}
173
174void InstARM32Pred::emitCmpLike(const char *Opcode, const InstARM32Pred *Inst,
175 const Cfg *Func) {
176 if (!BuildDefs::dump())
177 return;
178 Ostream &Str = Func->getContext()->getStrEmit();
179 assert(Inst->getSrcSize() == 2);
180 Str << "\t" << Opcode << Inst->getPredicate() << "\t";
181 Inst->getSrc(0)->emit(Func);
182 Str << ", ";
183 Inst->getSrc(1)->emit(Func);
184}
185
Jan Voungb3401d22015-05-18 09:38:21 -0700186OperandARM32Mem::OperandARM32Mem(Cfg * /* Func */, Type Ty, Variable *Base,
187 ConstantInteger32 *ImmOffset, AddrMode Mode)
188 : OperandARM32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Index(nullptr),
189 ShiftOp(kNoShift), ShiftAmt(0), Mode(Mode) {
190 // The Neg modes are only needed for Reg +/- Reg.
191 assert(!isNegAddrMode());
192 NumVars = 1;
193 Vars = &this->Base;
194}
195
196OperandARM32Mem::OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
197 Variable *Index, ShiftKind ShiftOp,
198 uint16_t ShiftAmt, AddrMode Mode)
199 : OperandARM32(kMem, Ty), Base(Base), ImmOffset(0), Index(Index),
200 ShiftOp(ShiftOp), ShiftAmt(ShiftAmt), Mode(Mode) {
201 NumVars = 2;
202 Vars = Func->allocateArrayOf<Variable *>(2);
203 Vars[0] = Base;
204 Vars[1] = Index;
205}
206
Jan Voungb2d50842015-05-12 09:53:50 -0700207bool OperandARM32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) {
208 int32_t Bits = SignExt ? TypeARM32Attributes[Ty].SExtAddrOffsetBits
209 : TypeARM32Attributes[Ty].ZExtAddrOffsetBits;
210 if (Bits == 0)
211 return Offset == 0;
212 // Note that encodings for offsets are sign-magnitude for ARM, so we check
213 // with IsAbsoluteUint().
214 if (isScalarFloatingType(Ty))
215 return Utils::IsAligned(Offset, 4) && Utils::IsAbsoluteUint(Bits, Offset);
216 return Utils::IsAbsoluteUint(Bits, Offset);
217}
218
Jan Voungb3401d22015-05-18 09:38:21 -0700219OperandARM32FlexImm::OperandARM32FlexImm(Cfg * /* Func */, Type Ty,
220 uint32_t Imm, uint32_t RotateAmt)
221 : OperandARM32Flex(kFlexImm, Ty), Imm(Imm), RotateAmt(RotateAmt) {
222 NumVars = 0;
223 Vars = nullptr;
224}
225
226bool OperandARM32FlexImm::canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
227 uint32_t *Immed_8) {
228 // Avoid the more expensive test for frequent small immediate values.
229 if (Immediate <= 0xFF) {
230 *RotateAmt = 0;
231 *Immed_8 = Immediate;
232 return true;
233 }
234 // Note that immediate must be unsigned for the test to work correctly.
235 for (int Rot = 1; Rot < 16; Rot++) {
236 uint32_t Imm8 = Utils::rotateLeft32(Immediate, 2 * Rot);
237 if (Imm8 <= 0xFF) {
238 *RotateAmt = Rot;
239 *Immed_8 = Imm8;
240 return true;
241 }
242 }
243 return false;
244}
245
246OperandARM32FlexReg::OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg,
247 ShiftKind ShiftOp, Operand *ShiftAmt)
248 : OperandARM32Flex(kFlexReg, Ty), Reg(Reg), ShiftOp(ShiftOp),
249 ShiftAmt(ShiftAmt) {
250 NumVars = 1;
251 Variable *ShiftVar = llvm::dyn_cast_or_null<Variable>(ShiftAmt);
252 if (ShiftVar)
253 ++NumVars;
254 Vars = Func->allocateArrayOf<Variable *>(NumVars);
255 Vars[0] = Reg;
256 if (ShiftVar)
257 Vars[1] = ShiftVar;
258}
259
Jan Voungb0a8c242015-06-18 15:00:14 -0700260InstARM32AdjustStack::InstARM32AdjustStack(Cfg *Func, Variable *SP,
261 SizeT Amount, Operand *SrcAmount)
262 : InstARM32(Func, InstARM32::Adjuststack, 2, SP), Amount(Amount) {
263 addSource(SP);
264 addSource(SrcAmount);
265}
266
Jan Voung3bfd99a2015-05-22 16:35:25 -0700267InstARM32Br::InstARM32Br(Cfg *Func, const CfgNode *TargetTrue,
Jan Voung6ec369e2015-06-30 11:03:15 -0700268 const CfgNode *TargetFalse,
269 const InstARM32Label *Label, CondARM32::Cond Pred)
Jan Voung3bfd99a2015-05-22 16:35:25 -0700270 : InstARM32Pred(Func, InstARM32::Br, 0, nullptr, Pred),
Jan Voung6ec369e2015-06-30 11:03:15 -0700271 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {}
Jan Voung3bfd99a2015-05-22 16:35:25 -0700272
273bool InstARM32Br::optimizeBranch(const CfgNode *NextNode) {
274 // If there is no next block, then there can be no fallthrough to
275 // optimize.
276 if (NextNode == nullptr)
277 return false;
Jan Voung6ec369e2015-06-30 11:03:15 -0700278 // Intra-block conditional branches can't be optimized.
279 if (Label)
280 return false;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700281 // If there is no fallthrough node, such as a non-default case label
282 // for a switch instruction, then there is no opportunity to
283 // optimize.
284 if (getTargetFalse() == nullptr)
285 return false;
286
287 // Unconditional branch to the next node can be removed.
288 if (isUnconditionalBranch() && getTargetFalse() == NextNode) {
289 assert(getTargetTrue() == nullptr);
290 setDeleted();
291 return true;
292 }
293 // If the fallthrough is to the next node, set fallthrough to nullptr
294 // to indicate.
295 if (getTargetFalse() == NextNode) {
296 TargetFalse = nullptr;
297 return true;
298 }
299 // If TargetTrue is the next node, and TargetFalse is not nullptr
300 // (which was already tested above), then invert the branch
301 // condition, swap the targets, and set new fallthrough to nullptr.
302 if (getTargetTrue() == NextNode) {
303 assert(Predicate != CondARM32::AL);
304 setPredicate(getOppositeCondition(getPredicate()));
305 TargetTrue = getTargetFalse();
306 TargetFalse = nullptr;
307 return true;
308 }
309 return false;
310}
311
Andrew Scull87f80c12015-07-20 10:19:16 -0700312bool InstARM32Br::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
313 bool Found = false;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700314 if (TargetFalse == OldNode) {
315 TargetFalse = NewNode;
Andrew Scull87f80c12015-07-20 10:19:16 -0700316 Found = true;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700317 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700318 if (TargetTrue == OldNode) {
319 TargetTrue = NewNode;
320 Found = true;
321 }
322 return Found;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700323}
324
325InstARM32Call::InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
326 : InstARM32(Func, InstARM32::Call, 1, Dest) {
327 HasSideEffects = true;
328 addSource(CallTarget);
329}
330
Jan Voung6ec369e2015-06-30 11:03:15 -0700331InstARM32Label::InstARM32Label(Cfg *Func, TargetARM32 *Target)
332 : InstARM32(Func, InstARM32::Label, 0, nullptr),
333 Number(Target->makeNextLabelNumber()) {}
334
335IceString InstARM32Label::getName(const Cfg *Func) const {
336 return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700337}
338
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700339InstARM32Pop::InstARM32Pop(Cfg *Func, const VarList &Dests)
340 : InstARM32(Func, InstARM32::Pop, 0, nullptr), Dests(Dests) {
341 // Track modifications to Dests separately via FakeDefs.
342 // Also, a pop instruction affects the stack pointer and so it should not
343 // be allowed to be automatically dead-code eliminated. This is automatic
344 // since we leave the Dest as nullptr.
345}
346
347InstARM32Push::InstARM32Push(Cfg *Func, const VarList &Srcs)
348 : InstARM32(Func, InstARM32::Push, Srcs.size(), nullptr) {
349 for (Variable *Source : Srcs)
350 addSource(Source);
351}
352
Jan Voungb2d50842015-05-12 09:53:50 -0700353InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source)
354 : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) {
355 addSource(LR);
356 if (Source)
357 addSource(Source);
358}
359
Jan Voungbefd03a2015-06-02 11:03:03 -0700360InstARM32Str::InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
361 CondARM32::Cond Predicate)
362 : InstARM32Pred(Func, InstARM32::Str, 2, nullptr, Predicate) {
363 addSource(Value);
364 addSource(Mem);
365}
366
Jan Voung6ec369e2015-06-30 11:03:15 -0700367InstARM32Trap::InstARM32Trap(Cfg *Func)
368 : InstARM32(Func, InstARM32::Trap, 0, nullptr) {}
369
Jan Voung29719972015-05-19 11:24:51 -0700370InstARM32Umull::InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700371 Variable *Src0, Variable *Src1,
372 CondARM32::Cond Predicate)
373 : InstARM32Pred(Func, InstARM32::Umull, 2, DestLo, Predicate),
Jan Voung29719972015-05-19 11:24:51 -0700374 // DestHi is expected to have a FakeDef inserted by the lowering code.
375 DestHi(DestHi) {
376 addSource(Src0);
377 addSource(Src1);
378}
379
Jan Voungb2d50842015-05-12 09:53:50 -0700380// ======================== Dump routines ======================== //
381
Jan Voungb3401d22015-05-18 09:38:21 -0700382// Two-addr ops
383template <> const char *InstARM32Movt::Opcode = "movt";
384// Unary ops
385template <> const char *InstARM32Movw::Opcode = "movw";
Jan Voungf645d852015-07-09 10:35:09 -0700386template <> const char *InstARM32Clz::Opcode = "clz";
Jan Voungb3401d22015-05-18 09:38:21 -0700387template <> const char *InstARM32Mvn::Opcode = "mvn";
Jan Voungf645d852015-07-09 10:35:09 -0700388template <> const char *InstARM32Rbit::Opcode = "rbit";
389template <> const char *InstARM32Rev::Opcode = "rev";
Jan Voung66c3d5e2015-06-04 17:02:31 -0700390template <> const char *InstARM32Sxt::Opcode = "sxt"; // still requires b/h
391template <> const char *InstARM32Uxt::Opcode = "uxt"; // still requires b/h
Jan Voung86ebec12015-08-09 07:58:35 -0700392// FP
393template <> const char *InstARM32Vsqrt::Opcode = "vsqrt";
Jan Voungb3401d22015-05-18 09:38:21 -0700394// Mov-like ops
Jan Voung86ebec12015-08-09 07:58:35 -0700395template <> const char *InstARM32Ldr::Opcode = "ldr";
Jan Voungb3401d22015-05-18 09:38:21 -0700396template <> const char *InstARM32Mov::Opcode = "mov";
Jan Voung86ebec12015-08-09 07:58:35 -0700397// FP
398template <> const char *InstARM32Vldr::Opcode = "vldr";
399template <> const char *InstARM32Vmov::Opcode = "vmov";
Jan Voung29719972015-05-19 11:24:51 -0700400// Three-addr ops
401template <> const char *InstARM32Adc::Opcode = "adc";
402template <> const char *InstARM32Add::Opcode = "add";
403template <> const char *InstARM32And::Opcode = "and";
Jan Voung66c3d5e2015-06-04 17:02:31 -0700404template <> const char *InstARM32Asr::Opcode = "asr";
Jan Voung55500db2015-05-26 14:25:40 -0700405template <> const char *InstARM32Bic::Opcode = "bic";
Jan Voung29719972015-05-19 11:24:51 -0700406template <> const char *InstARM32Eor::Opcode = "eor";
Jan Voung3bfd99a2015-05-22 16:35:25 -0700407template <> const char *InstARM32Lsl::Opcode = "lsl";
Jan Voung66c3d5e2015-06-04 17:02:31 -0700408template <> const char *InstARM32Lsr::Opcode = "lsr";
Jan Voung29719972015-05-19 11:24:51 -0700409template <> const char *InstARM32Mul::Opcode = "mul";
410template <> const char *InstARM32Orr::Opcode = "orr";
Jan Voung66c3d5e2015-06-04 17:02:31 -0700411template <> const char *InstARM32Rsb::Opcode = "rsb";
Jan Voung29719972015-05-19 11:24:51 -0700412template <> const char *InstARM32Sbc::Opcode = "sbc";
Jan Voung6ec369e2015-06-30 11:03:15 -0700413template <> const char *InstARM32Sdiv::Opcode = "sdiv";
Jan Voung29719972015-05-19 11:24:51 -0700414template <> const char *InstARM32Sub::Opcode = "sub";
Jan Voung6ec369e2015-06-30 11:03:15 -0700415template <> const char *InstARM32Udiv::Opcode = "udiv";
Jan Voung86ebec12015-08-09 07:58:35 -0700416// FP
417template <> const char *InstARM32Vadd::Opcode = "vadd";
418template <> const char *InstARM32Vdiv::Opcode = "vdiv";
419template <> const char *InstARM32Vmul::Opcode = "vmul";
420template <> const char *InstARM32Vsub::Opcode = "vsub";
Jan Voung6ec369e2015-06-30 11:03:15 -0700421// Four-addr ops
422template <> const char *InstARM32Mla::Opcode = "mla";
423template <> const char *InstARM32Mls::Opcode = "mls";
424// Cmp-like ops
425template <> const char *InstARM32Cmp::Opcode = "cmp";
426template <> const char *InstARM32Tst::Opcode = "tst";
Jan Voungb3401d22015-05-18 09:38:21 -0700427
Jan Voungb2d50842015-05-12 09:53:50 -0700428void InstARM32::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700429 if (!BuildDefs::dump())
Jan Voungb2d50842015-05-12 09:53:50 -0700430 return;
431 Ostream &Str = Func->getContext()->getStrDump();
432 Str << "[ARM32] ";
433 Inst::dump(Func);
434}
435
Jan Voungb3401d22015-05-18 09:38:21 -0700436template <> void InstARM32Mov::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700437 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700438 return;
439 Ostream &Str = Func->getContext()->getStrEmit();
440 assert(getSrcSize() == 1);
441 Variable *Dest = getDest();
442 if (Dest->hasReg()) {
Jan Voung86ebec12015-08-09 07:58:35 -0700443 IceString ActualOpcode = Opcode;
Jan Voungc207d512015-05-27 14:34:34 -0700444 Operand *Src0 = getSrc(0);
445 if (const auto *Src0V = llvm::dyn_cast<Variable>(Src0)) {
446 if (!Src0V->hasReg()) {
Jan Voung28068ad2015-07-31 12:58:46 -0700447 // Always use the whole stack slot. A 32-bit load has a larger range
448 // of offsets than 16-bit, etc.
Jan Voung86ebec12015-08-09 07:58:35 -0700449 ActualOpcode = IceString("ldr");
Jan Voungc207d512015-05-27 14:34:34 -0700450 }
451 } else {
Jan Voungbefd03a2015-06-02 11:03:03 -0700452 if (llvm::isa<OperandARM32Mem>(Src0))
Jan Voung86ebec12015-08-09 07:58:35 -0700453 ActualOpcode = IceString("ldr") + getWidthString(Dest->getType());
Jan Voungc207d512015-05-27 14:34:34 -0700454 }
Jan Voung86ebec12015-08-09 07:58:35 -0700455 Str << "\t" << ActualOpcode << getPredicate() << "\t";
Jan Voungb3401d22015-05-18 09:38:21 -0700456 getDest()->emit(Func);
457 Str << ", ";
458 getSrc(0)->emit(Func);
459 } else {
460 Variable *Src0 = llvm::cast<Variable>(getSrc(0));
461 assert(Src0->hasReg());
462 Str << "\t"
Jan Voung3bfd99a2015-05-22 16:35:25 -0700463 << "str" << getPredicate() << "\t";
Jan Voungb3401d22015-05-18 09:38:21 -0700464 Src0->emit(Func);
465 Str << ", ";
466 Dest->emit(Func);
467 }
468}
469
470template <> void InstARM32Mov::emitIAS(const Cfg *Func) const {
471 assert(getSrcSize() == 1);
472 (void)Func;
473 llvm_unreachable("Not yet implemented");
474}
475
Jan Voung86ebec12015-08-09 07:58:35 -0700476template <> void InstARM32Vldr::emit(const Cfg *Func) const {
477 if (!BuildDefs::dump())
478 return;
479 Ostream &Str = Func->getContext()->getStrEmit();
480 assert(getSrcSize() == 1);
481 assert(getDest()->hasReg());
Jim Stichnoth992f91d2015-08-10 11:18:38 -0700482 Str << "\t" << Opcode << getPredicate() << "\t";
Jan Voung86ebec12015-08-09 07:58:35 -0700483 getDest()->emit(Func);
484 Str << ", ";
485 getSrc(0)->emit(Func);
486}
487
488template <> void InstARM32Vldr::emitIAS(const Cfg *Func) const {
489 assert(getSrcSize() == 1);
490 (void)Func;
491 llvm_unreachable("Not yet implemented");
492}
493
494template <> void InstARM32Vmov::emit(const Cfg *Func) const {
495 if (!BuildDefs::dump())
496 return;
497 assert(CondARM32::AL == getPredicate());
498 Ostream &Str = Func->getContext()->getStrEmit();
499 assert(getSrcSize() == 1);
500 Variable *Dest = getDest();
501 if (Dest->hasReg()) {
502 IceString ActualOpcode = Opcode;
503 Operand *Src0 = getSrc(0);
504 if (const auto *Src0V = llvm::dyn_cast<Variable>(Src0)) {
505 if (!Src0V->hasReg()) {
506 ActualOpcode = IceString("vldr");
507 }
508 } else {
509 if (llvm::isa<OperandARM32Mem>(Src0))
510 ActualOpcode = IceString("vldr");
511 }
512 Str << "\t" << ActualOpcode << "\t";
513 getDest()->emit(Func);
514 Str << ", ";
515 getSrc(0)->emit(Func);
516 } else {
517 Variable *Src0 = llvm::cast<Variable>(getSrc(0));
518 assert(Src0->hasReg());
519 Str << "\t"
520 "vstr"
521 "\t";
522 Src0->emit(Func);
523 Str << ", ";
524 Dest->emit(Func);
525 }
526}
527
528template <> void InstARM32Vmov::emitIAS(const Cfg *Func) const {
529 assert(getSrcSize() == 1);
530 (void)Func;
531 llvm_unreachable("Not yet implemented");
532}
533
Jan Voung3bfd99a2015-05-22 16:35:25 -0700534void InstARM32Br::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700535 if (!BuildDefs::dump())
Jan Voung3bfd99a2015-05-22 16:35:25 -0700536 return;
537 Ostream &Str = Func->getContext()->getStrEmit();
538 Str << "\t"
539 << "b" << getPredicate() << "\t";
Jan Voung6ec369e2015-06-30 11:03:15 -0700540 if (Label) {
541 Str << Label->getName(Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700542 } else {
Jan Voung6ec369e2015-06-30 11:03:15 -0700543 if (isUnconditionalBranch()) {
544 Str << getTargetFalse()->getAsmName();
545 } else {
546 Str << getTargetTrue()->getAsmName();
547 if (getTargetFalse()) {
548 Str << "\n\t"
549 << "b"
550 << "\t" << getTargetFalse()->getAsmName();
551 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700552 }
553 }
554}
555
556void InstARM32Br::emitIAS(const Cfg *Func) const {
557 (void)Func;
558 llvm_unreachable("Not yet implemented");
559}
560
561void InstARM32Br::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700562 if (!BuildDefs::dump())
Jan Voung3bfd99a2015-05-22 16:35:25 -0700563 return;
564 Ostream &Str = Func->getContext()->getStrDump();
565 Str << "br ";
566
567 if (getPredicate() == CondARM32::AL) {
Jan Voung6ec369e2015-06-30 11:03:15 -0700568 Str << "label %"
569 << (Label ? Label->getName(Func) : getTargetFalse()->getName());
Jan Voung3bfd99a2015-05-22 16:35:25 -0700570 return;
571 }
572
Jan Voung6ec369e2015-06-30 11:03:15 -0700573 if (Label) {
574 Str << "label %" << Label->getName(Func);
575 } else {
576 Str << getPredicate() << ", label %" << getTargetTrue()->getName();
577 if (getTargetFalse()) {
578 Str << ", label %" << getTargetFalse()->getName();
579 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700580 }
581}
582
583void InstARM32Call::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700584 if (!BuildDefs::dump())
Jan Voung3bfd99a2015-05-22 16:35:25 -0700585 return;
586 Ostream &Str = Func->getContext()->getStrEmit();
587 assert(getSrcSize() == 1);
588 if (llvm::isa<ConstantInteger32>(getCallTarget())) {
589 // This shouldn't happen (typically have to copy the full 32-bits
590 // to a register and do an indirect jump).
591 llvm::report_fatal_error("ARM32Call to ConstantInteger32");
592 } else if (const auto CallTarget =
593 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
594 // Calls only have 24-bits, but the linker should insert veneers to
595 // extend the range if needed.
596 Str << "\t"
597 << "bl"
598 << "\t";
599 CallTarget->emitWithoutPrefix(Func->getTarget());
600 } else {
601 Str << "\t"
602 << "blx"
603 << "\t";
604 getCallTarget()->emit(Func);
605 }
606 Func->getTarget()->resetStackAdjustment();
607}
608
609void InstARM32Call::emitIAS(const Cfg *Func) const {
610 (void)Func;
611 llvm_unreachable("Not yet implemented");
612}
613
614void InstARM32Call::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700615 if (!BuildDefs::dump())
Jan Voung3bfd99a2015-05-22 16:35:25 -0700616 return;
617 Ostream &Str = Func->getContext()->getStrDump();
618 if (getDest()) {
619 dumpDest(Func);
620 Str << " = ";
621 }
622 Str << "call ";
623 getCallTarget()->dump(Func);
624}
625
Jan Voung6ec369e2015-06-30 11:03:15 -0700626void InstARM32Label::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700627 if (!BuildDefs::dump())
Jan Voung3bfd99a2015-05-22 16:35:25 -0700628 return;
629 Ostream &Str = Func->getContext()->getStrEmit();
Jan Voung6ec369e2015-06-30 11:03:15 -0700630 Str << getName(Func) << ":";
Jan Voung3bfd99a2015-05-22 16:35:25 -0700631}
632
Jan Voung6ec369e2015-06-30 11:03:15 -0700633void InstARM32Label::emitIAS(const Cfg *Func) const {
Jan Voung3bfd99a2015-05-22 16:35:25 -0700634 (void)Func;
635 llvm_unreachable("Not yet implemented");
636}
637
Jan Voung6ec369e2015-06-30 11:03:15 -0700638void InstARM32Label::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700639 if (!BuildDefs::dump())
Jan Voung3bfd99a2015-05-22 16:35:25 -0700640 return;
641 Ostream &Str = Func->getContext()->getStrDump();
Jan Voung6ec369e2015-06-30 11:03:15 -0700642 Str << getName(Func) << ":";
Jan Voung3bfd99a2015-05-22 16:35:25 -0700643}
644
Jan Voung86ebec12015-08-09 07:58:35 -0700645template <> void InstARM32Ldr::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700646 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700647 return;
648 Ostream &Str = Func->getContext()->getStrEmit();
649 assert(getSrcSize() == 1);
650 assert(getDest()->hasReg());
651 Type Ty = getSrc(0)->getType();
Jim Stichnoth992f91d2015-08-10 11:18:38 -0700652 Str << "\t" << Opcode << getWidthString(Ty) << getPredicate() << "\t";
Jan Voungb3401d22015-05-18 09:38:21 -0700653 getDest()->emit(Func);
654 Str << ", ";
655 getSrc(0)->emit(Func);
656}
657
Jan Voung86ebec12015-08-09 07:58:35 -0700658template <> void InstARM32Ldr::emitIAS(const Cfg *Func) const {
Jan Voung29719972015-05-19 11:24:51 -0700659 assert(getSrcSize() == 1);
Jan Voungb3401d22015-05-18 09:38:21 -0700660 (void)Func;
661 llvm_unreachable("Not yet implemented");
662}
663
Jan Voungb3401d22015-05-18 09:38:21 -0700664template <> void InstARM32Movw::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700665 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700666 return;
667 Ostream &Str = Func->getContext()->getStrEmit();
668 assert(getSrcSize() == 1);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700669 Str << "\t" << Opcode << getPredicate() << "\t";
Jan Voungb3401d22015-05-18 09:38:21 -0700670 getDest()->emit(Func);
671 Str << ", ";
672 Constant *Src0 = llvm::cast<Constant>(getSrc(0));
673 if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
674 Str << "#:lower16:";
675 CR->emitWithoutPrefix(Func->getTarget());
676 } else {
677 Src0->emit(Func);
678 }
679}
680
681template <> void InstARM32Movt::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700682 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700683 return;
684 Ostream &Str = Func->getContext()->getStrEmit();
685 assert(getSrcSize() == 2);
686 Variable *Dest = getDest();
687 Constant *Src1 = llvm::cast<Constant>(getSrc(1));
Jan Voung3bfd99a2015-05-22 16:35:25 -0700688 Str << "\t" << Opcode << getPredicate() << "\t";
Jan Voungb3401d22015-05-18 09:38:21 -0700689 Dest->emit(Func);
690 Str << ", ";
691 if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src1)) {
692 Str << "#:upper16:";
693 CR->emitWithoutPrefix(Func->getTarget());
694 } else {
695 Src1->emit(Func);
696 }
697}
698
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700699void InstARM32Pop::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700700 if (!BuildDefs::dump())
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700701 return;
702 assert(Dests.size() > 0);
703 Ostream &Str = Func->getContext()->getStrEmit();
704 Str << "\t"
705 << "pop"
706 << "\t{";
707 for (SizeT I = 0; I < Dests.size(); ++I) {
708 if (I > 0)
709 Str << ", ";
710 Dests[I]->emit(Func);
711 }
712 Str << "}";
713}
714
715void InstARM32Pop::emitIAS(const Cfg *Func) const {
716 (void)Func;
717 llvm_unreachable("Not yet implemented");
718}
719
720void InstARM32Pop::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700721 if (!BuildDefs::dump())
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700722 return;
723 Ostream &Str = Func->getContext()->getStrDump();
724 Str << "pop"
725 << " ";
726 for (SizeT I = 0; I < Dests.size(); ++I) {
727 if (I > 0)
728 Str << ", ";
729 Dests[I]->dump(Func);
730 }
731}
732
Jan Voungb0a8c242015-06-18 15:00:14 -0700733void InstARM32AdjustStack::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700734 if (!BuildDefs::dump())
Jan Voungb0a8c242015-06-18 15:00:14 -0700735 return;
736 Ostream &Str = Func->getContext()->getStrEmit();
737 assert(getSrcSize() == 2);
738 Str << "\t"
739 << "sub"
740 << "\t";
741 getDest()->emit(Func);
742 Str << ", ";
743 getSrc(0)->emit(Func);
744 Str << ", ";
745 getSrc(1)->emit(Func);
746 Func->getTarget()->updateStackAdjustment(Amount);
747}
748
749void InstARM32AdjustStack::emitIAS(const Cfg *Func) const {
750 (void)Func;
751 llvm_unreachable("Not yet implemented");
752 Func->getTarget()->updateStackAdjustment(Amount);
753}
754
755void InstARM32AdjustStack::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700756 if (!BuildDefs::dump())
Jan Voungb0a8c242015-06-18 15:00:14 -0700757 return;
758 Ostream &Str = Func->getContext()->getStrDump();
759 getDest()->dump(Func);
760 Str << " = sub.i32 ";
761 getSrc(0)->dump(Func);
762 Str << ", " << Amount << " ; ";
763 getSrc(1)->dump(Func);
764}
765
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700766void InstARM32Push::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700767 if (!BuildDefs::dump())
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700768 return;
769 assert(getSrcSize() > 0);
770 Ostream &Str = Func->getContext()->getStrEmit();
771 Str << "\t"
772 << "push"
773 << "\t{";
774 emitSources(Func);
775 Str << "}";
776}
777
778void InstARM32Push::emitIAS(const Cfg *Func) const {
779 (void)Func;
780 llvm_unreachable("Not yet implemented");
781}
782
783void InstARM32Push::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700784 if (!BuildDefs::dump())
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700785 return;
786 Ostream &Str = Func->getContext()->getStrDump();
787 Str << "push"
788 << " ";
789 dumpSources(Func);
790}
791
Jan Voungb2d50842015-05-12 09:53:50 -0700792void InstARM32Ret::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700793 if (!BuildDefs::dump())
Jan Voungb2d50842015-05-12 09:53:50 -0700794 return;
795 assert(getSrcSize() > 0);
796 Variable *LR = llvm::cast<Variable>(getSrc(0));
797 assert(LR->hasReg());
798 assert(LR->getRegNum() == RegARM32::Reg_lr);
799 Ostream &Str = Func->getContext()->getStrEmit();
Jan Voung29719972015-05-19 11:24:51 -0700800 Str << "\t"
801 << "bx"
802 << "\t";
Jan Voungb2d50842015-05-12 09:53:50 -0700803 LR->emit(Func);
804}
805
806void InstARM32Ret::emitIAS(const Cfg *Func) const {
807 (void)Func;
808 llvm_unreachable("Not yet implemented");
809}
810
811void InstARM32Ret::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700812 if (!BuildDefs::dump())
Jan Voungb2d50842015-05-12 09:53:50 -0700813 return;
814 Ostream &Str = Func->getContext()->getStrDump();
815 Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType());
816 Str << "ret." << Ty << " ";
817 dumpSources(Func);
818}
819
Jan Voungbefd03a2015-06-02 11:03:03 -0700820void InstARM32Str::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700821 if (!BuildDefs::dump())
Jan Voungbefd03a2015-06-02 11:03:03 -0700822 return;
823 Ostream &Str = Func->getContext()->getStrEmit();
824 assert(getSrcSize() == 2);
825 Type Ty = getSrc(0)->getType();
826 Str << "\t"
827 << "str" << getWidthString(Ty) << getPredicate() << "\t";
828 getSrc(0)->emit(Func);
829 Str << ", ";
830 getSrc(1)->emit(Func);
831}
832
833void InstARM32Str::emitIAS(const Cfg *Func) const {
834 assert(getSrcSize() == 2);
835 (void)Func;
836 llvm_unreachable("Not yet implemented");
837}
838
839void InstARM32Str::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700840 if (!BuildDefs::dump())
Jan Voungbefd03a2015-06-02 11:03:03 -0700841 return;
842 Ostream &Str = Func->getContext()->getStrDump();
Jan Voung66c3d5e2015-06-04 17:02:31 -0700843 Type Ty = getSrc(0)->getType();
844 dumpOpcodePred(Str, "str", Ty);
Jan Voungbefd03a2015-06-02 11:03:03 -0700845 Str << " ";
846 getSrc(1)->dump(Func);
847 Str << ", ";
848 getSrc(0)->dump(Func);
849}
850
Jan Voung6ec369e2015-06-30 11:03:15 -0700851void InstARM32Trap::emit(const Cfg *Func) const {
852 if (!BuildDefs::dump())
853 return;
854 Ostream &Str = Func->getContext()->getStrEmit();
855 assert(getSrcSize() == 0);
856 // There isn't a mnemonic for the special NaCl Trap encoding, so dump
857 // the raw bytes.
858 Str << "\t.long 0x";
859 ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
860 for (uint8_t I : Asm->getNonExecBundlePadding()) {
861 Str.write_hex(I);
862 }
863}
864
865void InstARM32Trap::emitIAS(const Cfg *Func) const {
866 assert(getSrcSize() == 0);
867 (void)Func;
868 llvm_unreachable("Not yet implemented");
869}
870
871void InstARM32Trap::dump(const Cfg *Func) const {
872 if (!BuildDefs::dump())
873 return;
874 Ostream &Str = Func->getContext()->getStrDump();
875 Str << "trap";
876}
877
Jan Voung29719972015-05-19 11:24:51 -0700878void InstARM32Umull::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700879 if (!BuildDefs::dump())
Jan Voung29719972015-05-19 11:24:51 -0700880 return;
881 Ostream &Str = Func->getContext()->getStrEmit();
882 assert(getSrcSize() == 2);
883 assert(getDest()->hasReg());
884 Str << "\t"
Jan Voung3bfd99a2015-05-22 16:35:25 -0700885 << "umull" << getPredicate() << "\t";
Jan Voung29719972015-05-19 11:24:51 -0700886 getDest()->emit(Func);
887 Str << ", ";
888 DestHi->emit(Func);
889 Str << ", ";
890 getSrc(0)->emit(Func);
891 Str << ", ";
892 getSrc(1)->emit(Func);
893}
894
895void InstARM32Umull::emitIAS(const Cfg *Func) const {
896 assert(getSrcSize() == 2);
897 (void)Func;
898 llvm_unreachable("Not yet implemented");
899}
900
901void InstARM32Umull::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700902 if (!BuildDefs::dump())
Jan Voung29719972015-05-19 11:24:51 -0700903 return;
904 Ostream &Str = Func->getContext()->getStrDump();
905 dumpDest(Func);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700906 Str << " = ";
907 dumpOpcodePred(Str, "umull", getDest()->getType());
908 Str << " ";
Jan Voung29719972015-05-19 11:24:51 -0700909 dumpSources(Func);
910}
911
Jan Voungb3401d22015-05-18 09:38:21 -0700912void OperandARM32Mem::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700913 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700914 return;
915 Ostream &Str = Func->getContext()->getStrEmit();
916 Str << "[";
917 getBase()->emit(Func);
918 switch (getAddrMode()) {
919 case PostIndex:
920 case NegPostIndex:
921 Str << "], ";
922 break;
923 default:
924 Str << ", ";
925 break;
926 }
927 if (isRegReg()) {
928 if (isNegAddrMode()) {
929 Str << "-";
930 }
931 getIndex()->emit(Func);
932 if (getShiftOp() != kNoShift) {
933 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
934 << getShiftAmt();
935 }
936 } else {
937 getOffset()->emit(Func);
938 }
939 switch (getAddrMode()) {
940 case Offset:
941 case NegOffset:
942 Str << "]";
943 break;
944 case PreIndex:
945 case NegPreIndex:
946 Str << "]!";
947 break;
948 case PostIndex:
949 case NegPostIndex:
950 // Brace is already closed off.
951 break;
952 }
953}
954
955void OperandARM32Mem::dump(const Cfg *Func, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700956 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700957 return;
958 Str << "[";
959 if (Func)
960 getBase()->dump(Func);
961 else
962 getBase()->dump(Str);
963 Str << ", ";
964 if (isRegReg()) {
965 if (isNegAddrMode()) {
966 Str << "-";
967 }
968 if (Func)
969 getIndex()->dump(Func);
970 else
971 getIndex()->dump(Str);
972 if (getShiftOp() != kNoShift) {
973 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
974 << getShiftAmt();
975 }
976 } else {
977 getOffset()->dump(Func, Str);
978 }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700979 Str << "] AddrMode==" << getAddrMode();
Jan Voungb3401d22015-05-18 09:38:21 -0700980}
981
982void OperandARM32FlexImm::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700983 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700984 return;
985 Ostream &Str = Func->getContext()->getStrEmit();
986 uint32_t Imm = getImm();
987 uint32_t RotateAmt = getRotateAmt();
988 Str << "#" << Utils::rotateRight32(Imm, 2 * RotateAmt);
989}
990
991void OperandARM32FlexImm::dump(const Cfg * /* Func */, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700992 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -0700993 return;
994 uint32_t Imm = getImm();
995 uint32_t RotateAmt = getRotateAmt();
996 Str << "#(" << Imm << " ror 2*" << RotateAmt << ")";
997}
998
999void OperandARM32FlexReg::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001000 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -07001001 return;
1002 Ostream &Str = Func->getContext()->getStrEmit();
1003 getReg()->emit(Func);
1004 if (getShiftOp() != kNoShift) {
1005 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
1006 getShiftAmt()->emit(Func);
1007 }
1008}
1009
1010void OperandARM32FlexReg::dump(const Cfg *Func, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001011 if (!BuildDefs::dump())
Jan Voungb3401d22015-05-18 09:38:21 -07001012 return;
1013 Variable *Reg = getReg();
1014 if (Func)
1015 Reg->dump(Func);
1016 else
1017 Reg->dump(Str);
1018 if (getShiftOp() != kNoShift) {
1019 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
1020 if (Func)
1021 getShiftAmt()->dump(Func);
1022 else
1023 getShiftAmt()->dump(Str);
1024 }
1025}
1026
Jan Voungb2d50842015-05-12 09:53:50 -07001027} // end of namespace Ice