ARMInstPrinter.cpp revision 638d1ca07a09c765bd088465d991df39cfdf818f
1//===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This class prints an ARM MCInst to a .s file.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "asm-printer"
15#include "ARMBaseInfo.h"
16#include "ARMInstPrinter.h"
17#include "ARMAddressingModes.h"
18#include "llvm/MC/MCInst.h"
19#include "llvm/MC/MCAsmInfo.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/ADT/StringExtras.h"
22#include "llvm/Support/raw_ostream.h"
23using namespace llvm;
24
25#include "ARMGenAsmWriter.inc"
26
27void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
28  // Check for MOVs and print canonical forms, instead.
29  if (MI->getOpcode() == ARM::MOVs) {
30    // FIXME: Thumb variants?
31    const MCOperand &Dst = MI->getOperand(0);
32    const MCOperand &MO1 = MI->getOperand(1);
33    const MCOperand &MO2 = MI->getOperand(2);
34    const MCOperand &MO3 = MI->getOperand(3);
35
36    O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
37    printSBitModifierOperand(MI, 6, O);
38    printPredicateOperand(MI, 4, O);
39
40    O << '\t' << getRegisterName(Dst.getReg())
41      << ", " << getRegisterName(MO1.getReg());
42
43    if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
44      return;
45
46    O << ", ";
47
48    if (MO2.getReg()) {
49      O << getRegisterName(MO2.getReg());
50      assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
51    } else {
52      O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
53    }
54    return;
55  }
56
57  // A8.6.123 PUSH
58  if ((MI->getOpcode() == ARM::STM_UPD || MI->getOpcode() == ARM::t2STM_UPD) &&
59      MI->getOperand(0).getReg() == ARM::SP) {
60    const MCOperand &MO1 = MI->getOperand(2);
61    if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
62      O << '\t' << "push";
63      printPredicateOperand(MI, 3, O);
64      O << '\t';
65      printRegisterList(MI, 5, O);
66      return;
67    }
68  }
69
70  // A8.6.122 POP
71  if ((MI->getOpcode() == ARM::LDM_UPD || MI->getOpcode() == ARM::t2LDM_UPD) &&
72      MI->getOperand(0).getReg() == ARM::SP) {
73    const MCOperand &MO1 = MI->getOperand(2);
74    if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
75      O << '\t' << "pop";
76      printPredicateOperand(MI, 3, O);
77      O << '\t';
78      printRegisterList(MI, 5, O);
79      return;
80    }
81  }
82
83  // A8.6.355 VPUSH
84  if ((MI->getOpcode() == ARM::VSTMS_UPD || MI->getOpcode() ==ARM::VSTMD_UPD) &&
85      MI->getOperand(0).getReg() == ARM::SP) {
86    const MCOperand &MO1 = MI->getOperand(2);
87    if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
88      O << '\t' << "vpush";
89      printPredicateOperand(MI, 3, O);
90      O << '\t';
91      printRegisterList(MI, 5, O);
92      return;
93    }
94  }
95
96  // A8.6.354 VPOP
97  if ((MI->getOpcode() == ARM::VLDMS_UPD || MI->getOpcode() ==ARM::VLDMD_UPD) &&
98      MI->getOperand(0).getReg() == ARM::SP) {
99    const MCOperand &MO1 = MI->getOperand(2);
100    if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
101      O << '\t' << "vpop";
102      printPredicateOperand(MI, 3, O);
103      O << '\t';
104      printRegisterList(MI, 5, O);
105      return;
106    }
107  }
108
109  printInstruction(MI, O);
110 }
111
112void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
113                                  raw_ostream &O, const char *Modifier) {
114  const MCOperand &Op = MI->getOperand(OpNo);
115  if (Op.isReg()) {
116    unsigned Reg = Op.getReg();
117    O << getRegisterName(Reg);
118  } else if (Op.isImm()) {
119    assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
120    O << '#' << Op.getImm();
121  } else {
122    assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
123    assert(Op.isExpr() && "unknown operand kind in printOperand");
124    O << *Op.getExpr();
125  }
126}
127
128static void printSOImm(raw_ostream &O, int64_t V, raw_ostream *CommentStream,
129                       const MCAsmInfo *MAI) {
130  // Break it up into two parts that make up a shifter immediate.
131  V = ARM_AM::getSOImmVal(V);
132  assert(V != -1 && "Not a valid so_imm value!");
133
134  unsigned Imm = ARM_AM::getSOImmValImm(V);
135  unsigned Rot = ARM_AM::getSOImmValRot(V);
136
137  // Print low-level immediate formation info, per
138  // A5.1.3: "Data-processing operands - Immediate".
139  if (Rot) {
140    O << "#" << Imm << ", " << Rot;
141    // Pretty printed version.
142    if (CommentStream)
143      *CommentStream << (int)ARM_AM::rotr32(Imm, Rot) << "\n";
144  } else {
145    O << "#" << Imm;
146  }
147}
148
149
150/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
151/// immediate in bits 0-7.
152void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum,
153                                       raw_ostream &O) {
154  const MCOperand &MO = MI->getOperand(OpNum);
155  assert(MO.isImm() && "Not a valid so_imm value!");
156  printSOImm(O, MO.getImm(), CommentStream, &MAI);
157}
158
159/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
160/// followed by an 'orr' to materialize.
161void ARMInstPrinter::printSOImm2PartOperand(const MCInst *MI, unsigned OpNum,
162                                            raw_ostream &O) {
163  // FIXME: REMOVE this method.
164  abort();
165}
166
167// so_reg is a 4-operand unit corresponding to register forms of the A5.1
168// "Addressing Mode 1 - Data-processing operands" forms.  This includes:
169//    REG 0   0           - e.g. R5
170//    REG REG 0,SH_OPC    - e.g. R5, ROR R3
171//    REG 0   IMM,SH_OPC  - e.g. R5, LSL #3
172void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
173                                       raw_ostream &O) {
174  const MCOperand &MO1 = MI->getOperand(OpNum);
175  const MCOperand &MO2 = MI->getOperand(OpNum+1);
176  const MCOperand &MO3 = MI->getOperand(OpNum+2);
177
178  O << getRegisterName(MO1.getReg());
179
180  // Print the shift opc.
181  ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
182  O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
183  if (MO2.getReg()) {
184    O << ' ' << getRegisterName(MO2.getReg());
185    assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
186  } else if (ShOpc != ARM_AM::rrx) {
187    O << " #" << ARM_AM::getSORegOffset(MO3.getImm());
188  }
189}
190
191
192void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
193                                           raw_ostream &O) {
194  const MCOperand &MO1 = MI->getOperand(Op);
195  const MCOperand &MO2 = MI->getOperand(Op+1);
196  const MCOperand &MO3 = MI->getOperand(Op+2);
197
198  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
199    printOperand(MI, Op, O);
200    return;
201  }
202
203  O << "[" << getRegisterName(MO1.getReg());
204
205  if (!MO2.getReg()) {
206    if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
207      O << ", #"
208        << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
209        << ARM_AM::getAM2Offset(MO3.getImm());
210    O << "]";
211    return;
212  }
213
214  O << ", "
215    << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
216    << getRegisterName(MO2.getReg());
217
218  if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
219    O << ", "
220    << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
221    << " #" << ShImm;
222  O << "]";
223}
224
225void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
226                                                 unsigned OpNum,
227                                                 raw_ostream &O) {
228  const MCOperand &MO1 = MI->getOperand(OpNum);
229  const MCOperand &MO2 = MI->getOperand(OpNum+1);
230
231  if (!MO1.getReg()) {
232    unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
233    O << '#'
234      << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
235      << ImmOffs;
236    return;
237  }
238
239  O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
240    << getRegisterName(MO1.getReg());
241
242  if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
243    O << ", "
244    << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
245    << " #" << ShImm;
246}
247
248void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum,
249                                           raw_ostream &O) {
250  const MCOperand &MO1 = MI->getOperand(OpNum);
251  const MCOperand &MO2 = MI->getOperand(OpNum+1);
252  const MCOperand &MO3 = MI->getOperand(OpNum+2);
253
254  O << '[' << getRegisterName(MO1.getReg());
255
256  if (MO2.getReg()) {
257    O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
258      << getRegisterName(MO2.getReg()) << ']';
259    return;
260  }
261
262  if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
263    O << ", #"
264      << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
265      << ImmOffs;
266  O << ']';
267}
268
269void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
270                                                 unsigned OpNum,
271                                                 raw_ostream &O) {
272  const MCOperand &MO1 = MI->getOperand(OpNum);
273  const MCOperand &MO2 = MI->getOperand(OpNum+1);
274
275  if (MO1.getReg()) {
276    O << (char)ARM_AM::getAM3Op(MO2.getImm())
277    << getRegisterName(MO1.getReg());
278    return;
279  }
280
281  unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
282  O << '#'
283    << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
284    << ImmOffs;
285}
286
287
288void ARMInstPrinter::printAddrMode4Operand(const MCInst *MI, unsigned OpNum,
289                                           raw_ostream &O,
290                                           const char *Modifier) {
291  const MCOperand &MO2 = MI->getOperand(OpNum+1);
292  ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
293  if (Modifier && strcmp(Modifier, "submode") == 0) {
294    O << ARM_AM::getAMSubModeStr(Mode);
295  } else if (Modifier && strcmp(Modifier, "wide") == 0) {
296    ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
297    if (Mode == ARM_AM::ia)
298      O << ".w";
299  } else {
300    printOperand(MI, OpNum, O);
301  }
302}
303
304void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
305                                           raw_ostream &O,
306                                           const char *Modifier) {
307  const MCOperand &MO1 = MI->getOperand(OpNum);
308  const MCOperand &MO2 = MI->getOperand(OpNum+1);
309
310  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
311    printOperand(MI, OpNum, O);
312    return;
313  }
314
315  O << "[" << getRegisterName(MO1.getReg());
316
317  if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
318    O << ", #"
319      << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
320      << ImmOffs*4;
321  }
322  O << "]";
323}
324
325void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
326                                           raw_ostream &O) {
327  const MCOperand &MO1 = MI->getOperand(OpNum);
328  const MCOperand &MO2 = MI->getOperand(OpNum+1);
329
330  O << "[" << getRegisterName(MO1.getReg());
331  if (MO2.getImm()) {
332    // FIXME: Both darwin as and GNU as violate ARM docs here.
333    O << ", :" << (MO2.getImm() << 3);
334  }
335  O << "]";
336}
337
338void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
339                                                 unsigned OpNum,
340                                                 raw_ostream &O) {
341  const MCOperand &MO = MI->getOperand(OpNum);
342  if (MO.getReg() == 0)
343    O << "!";
344  else
345    O << ", " << getRegisterName(MO.getReg());
346}
347
348void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum,
349                                            raw_ostream &O,
350                                            const char *Modifier) {
351  // All instructions using addrmodepc are pseudos and should have been
352  // handled explicitly in printInstructionThroughMCStreamer(). If one got
353  // here, it wasn't, so something's wrong.
354  llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
355}
356
357void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
358                                                    unsigned OpNum,
359                                                    raw_ostream &O) {
360  const MCOperand &MO = MI->getOperand(OpNum);
361  uint32_t v = ~MO.getImm();
362  int32_t lsb = CountTrailingZeros_32(v);
363  int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
364  assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
365  O << '#' << lsb << ", #" << width;
366}
367
368void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
369                                     raw_ostream &O) {
370  unsigned val = MI->getOperand(OpNum).getImm();
371  O << ARM_MB::MemBOptToString(val);
372}
373
374void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
375                                          raw_ostream &O) {
376  unsigned ShiftOp = MI->getOperand(OpNum).getImm();
377  ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
378  switch (Opc) {
379  case ARM_AM::no_shift:
380    return;
381  case ARM_AM::lsl:
382    O << ", lsl #";
383    break;
384  case ARM_AM::asr:
385    O << ", asr #";
386    break;
387  default:
388    assert(0 && "unexpected shift opcode for shift immediate operand");
389  }
390  O << ARM_AM::getSORegOffset(ShiftOp);
391}
392
393void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
394                                       raw_ostream &O) {
395  O << "{";
396  for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
397    if (i != OpNum) O << ", ";
398    O << getRegisterName(MI->getOperand(i).getReg());
399  }
400  O << "}";
401}
402
403void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
404                                        raw_ostream &O) {
405  const MCOperand &Op = MI->getOperand(OpNum);
406  if (Op.getImm())
407    O << "be";
408  else
409    O << "le";
410}
411
412void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum,
413                                           raw_ostream &O) {
414  const MCOperand &Op = MI->getOperand(OpNum);
415  unsigned option = Op.getImm();
416  unsigned mode = option & 31;
417  bool changemode = option >> 5 & 1;
418  unsigned AIF = option >> 6 & 7;
419  unsigned imod = option >> 9 & 3;
420  if (imod == 2)
421    O << "ie";
422  else if (imod == 3)
423    O << "id";
424  O << '\t';
425  if (imod > 1) {
426    if (AIF & 4) O << 'a';
427    if (AIF & 2) O << 'i';
428    if (AIF & 1) O << 'f';
429    if (AIF > 0 && changemode) O << ", ";
430  }
431  if (changemode)
432    O << '#' << mode;
433}
434
435void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
436                                         raw_ostream &O) {
437  const MCOperand &Op = MI->getOperand(OpNum);
438  unsigned Mask = Op.getImm();
439  if (Mask) {
440    O << '_';
441    if (Mask & 8) O << 'f';
442    if (Mask & 4) O << 's';
443    if (Mask & 2) O << 'x';
444    if (Mask & 1) O << 'c';
445  }
446}
447
448void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum,
449                                         raw_ostream &O) {
450  const MCOperand &Op = MI->getOperand(OpNum);
451  O << '#';
452  if (Op.getImm() < 0)
453    O << '-' << (-Op.getImm() - 1);
454  else
455    O << Op.getImm();
456}
457
458void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
459                                           raw_ostream &O) {
460  ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
461  if (CC != ARMCC::AL)
462    O << ARMCondCodeToString(CC);
463}
464
465void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
466                                                    unsigned OpNum,
467                                                    raw_ostream &O) {
468  ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
469  O << ARMCondCodeToString(CC);
470}
471
472void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
473                                              raw_ostream &O) {
474  if (MI->getOperand(OpNum).getReg()) {
475    assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
476           "Expect ARM CPSR register!");
477    O << 's';
478  }
479}
480
481
482
483void ARMInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNum,
484                                        raw_ostream &O,
485                                        const char *Modifier) {
486  // FIXME: remove this.
487  abort();
488}
489
490void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
491                                          raw_ostream &O) {
492  O << MI->getOperand(OpNum).getImm();
493}
494
495
496void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
497                                  raw_ostream &O) {
498  llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
499}
500
501void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
502                                            raw_ostream &O) {
503  O << "#" <<  MI->getOperand(OpNum).getImm() * 4;
504}
505
506void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
507                                      raw_ostream &O) {
508  // (3 - the number of trailing zeros) is the number of then / else.
509  unsigned Mask = MI->getOperand(OpNum).getImm();
510  unsigned CondBit0 = Mask >> 4 & 1;
511  unsigned NumTZ = CountTrailingZeros_32(Mask);
512  assert(NumTZ <= 3 && "Invalid IT mask!");
513  for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
514    bool T = ((Mask >> Pos) & 1) == CondBit0;
515    if (T)
516      O << 't';
517    else
518      O << 'e';
519  }
520}
521
522void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
523                                                 raw_ostream &O) {
524  const MCOperand &MO1 = MI->getOperand(Op);
525  const MCOperand &MO2 = MI->getOperand(Op+1);
526  O << "[" << getRegisterName(MO1.getReg());
527  O << ", " << getRegisterName(MO2.getReg()) << "]";
528}
529
530void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op,
531                                                  raw_ostream &O,
532                                                  unsigned Scale) {
533  const MCOperand &MO1 = MI->getOperand(Op);
534  const MCOperand &MO2 = MI->getOperand(Op+1);
535  const MCOperand &MO3 = MI->getOperand(Op+2);
536
537  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
538    printOperand(MI, Op, O);
539    return;
540  }
541
542  O << "[" << getRegisterName(MO1.getReg());
543  if (MO3.getReg())
544    O << ", " << getRegisterName(MO3.getReg());
545  else if (unsigned ImmOffs = MO2.getImm())
546    O << ", #" << ImmOffs * Scale;
547  O << "]";
548}
549
550void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op,
551                                                 raw_ostream &O) {
552  printThumbAddrModeRI5Operand(MI, Op, O, 1);
553}
554
555void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op,
556                                                 raw_ostream &O) {
557  printThumbAddrModeRI5Operand(MI, Op, O, 2);
558}
559
560void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op,
561                                                 raw_ostream &O) {
562  printThumbAddrModeRI5Operand(MI, Op, O, 4);
563}
564
565void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
566                                                 raw_ostream &O) {
567  const MCOperand &MO1 = MI->getOperand(Op);
568  const MCOperand &MO2 = MI->getOperand(Op+1);
569  O << "[" << getRegisterName(MO1.getReg());
570  if (unsigned ImmOffs = MO2.getImm())
571    O << ", #" << ImmOffs*4;
572  O << "]";
573}
574
575void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum,
576                                     raw_ostream &O) {
577  O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
578  if (MI->getOpcode() == ARM::t2TBH)
579    O << ", lsl #1";
580  O << ']';
581}
582
583// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
584// register with shift forms.
585// REG 0   0           - e.g. R5
586// REG IMM, SH_OPC     - e.g. R5, LSL #3
587void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
588                                      raw_ostream &O) {
589  const MCOperand &MO1 = MI->getOperand(OpNum);
590  const MCOperand &MO2 = MI->getOperand(OpNum+1);
591
592  unsigned Reg = MO1.getReg();
593  O << getRegisterName(Reg);
594
595  // Print the shift opc.
596  assert(MO2.isImm() && "Not a valid t2_so_reg value!");
597  ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
598  O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
599  if (ShOpc != ARM_AM::rrx)
600    O << " #" << ARM_AM::getSORegOffset(MO2.getImm());
601}
602
603void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
604                                               raw_ostream &O) {
605  const MCOperand &MO1 = MI->getOperand(OpNum);
606  const MCOperand &MO2 = MI->getOperand(OpNum+1);
607
608  O << "[" << getRegisterName(MO1.getReg());
609
610  unsigned OffImm = MO2.getImm();
611  if (OffImm)  // Don't print +0.
612    O << ", #" << OffImm;
613  O << "]";
614}
615
616void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
617                                                unsigned OpNum,
618                                                raw_ostream &O) {
619  const MCOperand &MO1 = MI->getOperand(OpNum);
620  const MCOperand &MO2 = MI->getOperand(OpNum+1);
621
622  O << "[" << getRegisterName(MO1.getReg());
623
624  int32_t OffImm = (int32_t)MO2.getImm();
625  // Don't print +0.
626  if (OffImm < 0)
627    O << ", #-" << -OffImm;
628  else if (OffImm > 0)
629    O << ", #" << OffImm;
630  O << "]";
631}
632
633void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
634                                                  unsigned OpNum,
635                                                  raw_ostream &O) {
636  const MCOperand &MO1 = MI->getOperand(OpNum);
637  const MCOperand &MO2 = MI->getOperand(OpNum+1);
638
639  O << "[" << getRegisterName(MO1.getReg());
640
641  int32_t OffImm = (int32_t)MO2.getImm() / 4;
642  // Don't print +0.
643  if (OffImm < 0)
644    O << ", #-" << -OffImm * 4;
645  else if (OffImm > 0)
646    O << ", #" << OffImm * 4;
647  O << "]";
648}
649
650void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
651                                                      unsigned OpNum,
652                                                      raw_ostream &O) {
653  const MCOperand &MO1 = MI->getOperand(OpNum);
654  int32_t OffImm = (int32_t)MO1.getImm();
655  // Don't print +0.
656  if (OffImm < 0)
657    O << "#-" << -OffImm;
658  else if (OffImm > 0)
659    O << "#" << OffImm;
660}
661
662void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
663                                                        unsigned OpNum,
664                                                        raw_ostream &O) {
665  const MCOperand &MO1 = MI->getOperand(OpNum);
666  int32_t OffImm = (int32_t)MO1.getImm() / 4;
667  // Don't print +0.
668  if (OffImm < 0)
669    O << "#-" << -OffImm * 4;
670  else if (OffImm > 0)
671    O << "#" << OffImm * 4;
672}
673
674void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
675                                                 unsigned OpNum,
676                                                 raw_ostream &O) {
677  const MCOperand &MO1 = MI->getOperand(OpNum);
678  const MCOperand &MO2 = MI->getOperand(OpNum+1);
679  const MCOperand &MO3 = MI->getOperand(OpNum+2);
680
681  O << "[" << getRegisterName(MO1.getReg());
682
683  assert(MO2.getReg() && "Invalid so_reg load / store address!");
684  O << ", " << getRegisterName(MO2.getReg());
685
686  unsigned ShAmt = MO3.getImm();
687  if (ShAmt) {
688    assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
689    O << ", lsl #" << ShAmt;
690  }
691  O << "]";
692}
693
694void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
695                                           raw_ostream &O) {
696  O << '#' << (float)MI->getOperand(OpNum).getFPImm();
697}
698
699void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
700                                           raw_ostream &O) {
701  O << '#' << MI->getOperand(OpNum).getFPImm();
702}
703
704void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
705                                            raw_ostream &O) {
706  unsigned EncodedImm = MI->getOperand(OpNum).getImm();
707  unsigned EltBits;
708  uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
709  O << "#0x" << utohexstr(Val);
710}
711