~louis/ubuntu/trusty/clamav/lp799623_fix_logrotate

« back to all changes in this revision

Viewing changes to libclamav/c++/llvm/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-03-12 11:30:04 UTC
  • mfrom: (0.41.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100312113004-b0fop4bkycszdd0z
Tags: 0.96~rc1+dfsg-0ubuntu1
* New upstream RC - FFE (LP: #537636):
  - Add OfficialDatabaseOnly option to clamav-base.postinst.in
  - Add LocalSocketGroup option to clamav-base.postinst.in
  - Add LocalSocketMode option to clamav-base.postinst.in
  - Add CrossFilesystems option to clamav-base.postinst.in
  - Add ClamukoScannerCount option to clamav-base.postinst.in
  - Add BytecodeSecurity opiton to clamav-base.postinst.in
  - Add DetectionStatsHostID option to clamav-freshclam.postinst.in
  - Add Bytecode option to clamav-freshclam.postinst.in
  - Add MilterSocketGroup option to clamav-milter.postinst.in
  - Add MilterSocketMode option to clamav-milter.postinst.in
  - Add ReportHostname option to clamav-milter.postinst.in
  - Bump libclamav SO version to 6.1.0 in libclamav6.install
  - Drop clamdmon from clamav.examples (no longer shipped by upstream)
  - Drop libclamav.a from libclamav-dev.install (not built by upstream)
  - Update SO version for lintian override for libclamav6
  - Add new Bytecode Testing Tool, usr/bin/clambc, to clamav.install
  - Add build-depends on python and python-setuptools for new test suite
  - Update debian/copyright for the embedded copy of llvm (using the system
    llvm is not currently feasible)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===//
 
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 file contains a printer that converts from our internal representation
 
11
// of machine-dependent LLVM code to GAS-format ARM assembly language.
 
12
//
 
13
//===----------------------------------------------------------------------===//
 
14
 
 
15
#define DEBUG_TYPE "asm-printer"
 
16
#include "ARM.h"
 
17
#include "ARMBuildAttrs.h"
 
18
#include "ARMAddressingModes.h"
 
19
#include "ARMConstantPoolValue.h"
 
20
#include "ARMInstPrinter.h"
 
21
#include "ARMMachineFunctionInfo.h"
 
22
#include "ARMMCInstLower.h"
 
23
#include "ARMTargetMachine.h"
 
24
#include "llvm/Constants.h"
 
25
#include "llvm/Module.h"
 
26
#include "llvm/Type.h"
 
27
#include "llvm/Assembly/Writer.h"
 
28
#include "llvm/CodeGen/AsmPrinter.h"
 
29
#include "llvm/CodeGen/DwarfWriter.h"
 
30
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
 
31
#include "llvm/CodeGen/MachineFunctionPass.h"
 
32
#include "llvm/CodeGen/MachineJumpTableInfo.h"
 
33
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
 
34
#include "llvm/MC/MCAsmInfo.h"
 
35
#include "llvm/MC/MCContext.h"
 
36
#include "llvm/MC/MCInst.h"
 
37
#include "llvm/MC/MCSectionMachO.h"
 
38
#include "llvm/MC/MCStreamer.h"
 
39
#include "llvm/MC/MCSymbol.h"
 
40
#include "llvm/Target/TargetData.h"
 
41
#include "llvm/Target/TargetMachine.h"
 
42
#include "llvm/Target/TargetOptions.h"
 
43
#include "llvm/Target/TargetRegistry.h"
 
44
#include "llvm/ADT/SmallPtrSet.h"
 
45
#include "llvm/ADT/SmallString.h"
 
46
#include "llvm/ADT/StringExtras.h"
 
47
#include "llvm/ADT/StringSet.h"
 
48
#include "llvm/Support/CommandLine.h"
 
49
#include "llvm/Support/ErrorHandling.h"
 
50
#include "llvm/Support/FormattedStream.h"
 
51
#include "llvm/Support/MathExtras.h"
 
52
#include <cctype>
 
53
using namespace llvm;
 
54
 
 
55
static cl::opt<bool>
 
56
EnableMCInst("enable-arm-mcinst-printer", cl::Hidden,
 
57
            cl::desc("enable experimental asmprinter gunk in the arm backend"));
 
58
 
 
59
namespace {
 
60
  class ARMAsmPrinter : public AsmPrinter {
 
61
 
 
62
    /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
 
63
    /// make the right decision when printing asm code for different targets.
 
64
    const ARMSubtarget *Subtarget;
 
65
 
 
66
    /// AFI - Keep a pointer to ARMFunctionInfo for the current
 
67
    /// MachineFunction.
 
68
    ARMFunctionInfo *AFI;
 
69
 
 
70
    /// MCP - Keep a pointer to constantpool entries of the current
 
71
    /// MachineFunction.
 
72
    const MachineConstantPool *MCP;
 
73
 
 
74
  public:
 
75
    explicit ARMAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
 
76
                           MCContext &Ctx, MCStreamer &Streamer,
 
77
                           const MCAsmInfo *T)
 
78
      : AsmPrinter(O, TM, Ctx, Streamer, T), AFI(NULL), MCP(NULL) {
 
79
      Subtarget = &TM.getSubtarget<ARMSubtarget>();
 
80
    }
 
81
 
 
82
    virtual const char *getPassName() const {
 
83
      return "ARM Assembly Printer";
 
84
    }
 
85
    
 
86
    void printInstructionThroughMCStreamer(const MachineInstr *MI);
 
87
    
 
88
 
 
89
    void printOperand(const MachineInstr *MI, int OpNum,
 
90
                      const char *Modifier = 0);
 
91
    void printSOImmOperand(const MachineInstr *MI, int OpNum);
 
92
    void printSOImm2PartOperand(const MachineInstr *MI, int OpNum);
 
93
    void printSORegOperand(const MachineInstr *MI, int OpNum);
 
94
    void printAddrMode2Operand(const MachineInstr *MI, int OpNum);
 
95
    void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNum);
 
96
    void printAddrMode3Operand(const MachineInstr *MI, int OpNum);
 
97
    void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNum);
 
98
    void printAddrMode4Operand(const MachineInstr *MI, int OpNum,
 
99
                               const char *Modifier = 0);
 
100
    void printAddrMode5Operand(const MachineInstr *MI, int OpNum,
 
101
                               const char *Modifier = 0);
 
102
    void printAddrMode6Operand(const MachineInstr *MI, int OpNum);
 
103
    void printAddrModePCOperand(const MachineInstr *MI, int OpNum,
 
104
                                const char *Modifier = 0);
 
105
    void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNum);
 
106
 
 
107
    void printThumbS4ImmOperand(const MachineInstr *MI, int OpNum);
 
108
    void printThumbITMask(const MachineInstr *MI, int OpNum);
 
109
    void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNum);
 
110
    void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNum,
 
111
                                      unsigned Scale);
 
112
    void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNum);
 
113
    void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNum);
 
114
    void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNum);
 
115
    void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNum);
 
116
 
 
117
    void printT2SOOperand(const MachineInstr *MI, int OpNum);
 
118
    void printT2AddrModeImm12Operand(const MachineInstr *MI, int OpNum);
 
119
    void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum);
 
120
    void printT2AddrModeImm8s4Operand(const MachineInstr *MI, int OpNum);
 
121
    void printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum);
 
122
    void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum);
 
123
 
 
124
    void printPredicateOperand(const MachineInstr *MI, int OpNum);
 
125
    void printMandatoryPredicateOperand(const MachineInstr *MI, int OpNum);
 
126
    void printSBitModifierOperand(const MachineInstr *MI, int OpNum);
 
127
    void printPCLabel(const MachineInstr *MI, int OpNum);
 
128
    void printRegisterList(const MachineInstr *MI, int OpNum);
 
129
    void printCPInstOperand(const MachineInstr *MI, int OpNum,
 
130
                            const char *Modifier);
 
131
    void printJTBlockOperand(const MachineInstr *MI, int OpNum);
 
132
    void printJT2BlockOperand(const MachineInstr *MI, int OpNum);
 
133
    void printTBAddrMode(const MachineInstr *MI, int OpNum);
 
134
    void printNoHashImmediate(const MachineInstr *MI, int OpNum);
 
135
    void printVFPf32ImmOperand(const MachineInstr *MI, int OpNum);
 
136
    void printVFPf64ImmOperand(const MachineInstr *MI, int OpNum);
 
137
 
 
138
    void printHex8ImmOperand(const MachineInstr *MI, int OpNum) {
 
139
      O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm() & 0xff);
 
140
    }
 
141
    void printHex16ImmOperand(const MachineInstr *MI, int OpNum) {
 
142
      O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm() & 0xffff);
 
143
    }
 
144
    void printHex32ImmOperand(const MachineInstr *MI, int OpNum) {
 
145
      O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm() & 0xffffffff);
 
146
    }
 
147
    void printHex64ImmOperand(const MachineInstr *MI, int OpNum) {
 
148
      O << "#0x" << utohexstr(MI->getOperand(OpNum).getImm());
 
149
    }
 
150
 
 
151
    virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
 
152
                                 unsigned AsmVariant, const char *ExtraCode);
 
153
    virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
 
154
                                       unsigned AsmVariant,
 
155
                                       const char *ExtraCode);
 
156
 
 
157
    void printInstruction(const MachineInstr *MI);  // autogenerated.
 
158
    static const char *getRegisterName(unsigned RegNo);
 
159
 
 
160
    virtual void EmitInstruction(const MachineInstr *MI);
 
161
    bool runOnMachineFunction(MachineFunction &F);
 
162
    
 
163
    virtual void EmitConstantPool() {} // we emit constant pools customly!
 
164
    virtual void EmitFunctionEntryLabel();
 
165
    void EmitStartOfAsmFile(Module &M);
 
166
    void EmitEndOfAsmFile(Module &M);
 
167
 
 
168
    MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
 
169
                                          const MachineBasicBlock *MBB) const;
 
170
    MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const;
 
171
 
 
172
    /// EmitMachineConstantPoolValue - Print a machine constantpool value to
 
173
    /// the .s file.
 
174
    virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
 
175
      switch (TM.getTargetData()->getTypeAllocSize(MCPV->getType())) {
 
176
      case 1: O << MAI->getData8bitsDirective(0); break;
 
177
      case 2: O << MAI->getData16bitsDirective(0); break;
 
178
      case 4: O << MAI->getData32bitsDirective(0); break;
 
179
      default: assert(0 && "Unknown CPV size");
 
180
      }
 
181
 
 
182
      ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
 
183
      SmallString<128> TmpNameStr;
 
184
 
 
185
      if (ACPV->isLSDA()) {
 
186
        raw_svector_ostream(TmpNameStr) << MAI->getPrivateGlobalPrefix() <<
 
187
          "_LSDA_" << getFunctionNumber();
 
188
        O << TmpNameStr.str();
 
189
      } else if (ACPV->isBlockAddress()) {
 
190
        O << GetBlockAddressSymbol(ACPV->getBlockAddress())->getName();
 
191
      } else if (ACPV->isGlobalValue()) {
 
192
        GlobalValue *GV = ACPV->getGV();
 
193
        bool isIndirect = Subtarget->isTargetDarwin() &&
 
194
          Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
 
195
        if (!isIndirect)
 
196
          O << *GetGlobalValueSymbol(GV);
 
197
        else {
 
198
          // FIXME: Remove this when Darwin transition to @GOT like syntax.
 
199
          MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
 
200
          O << *Sym;
 
201
          
 
202
          MachineModuleInfoMachO &MMIMachO =
 
203
            MMI->getObjFileInfo<MachineModuleInfoMachO>();
 
204
          MCSymbol *&StubSym =
 
205
            GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(Sym) :
 
206
                                        MMIMachO.getGVStubEntry(Sym);
 
207
          if (StubSym == 0)
 
208
            StubSym = GetGlobalValueSymbol(GV);
 
209
        }
 
210
      } else {
 
211
        assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
 
212
        O << *GetExternalSymbolSymbol(ACPV->getSymbol());
 
213
      }
 
214
 
 
215
      if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
 
216
      if (ACPV->getPCAdjustment() != 0) {
 
217
        O << "-(" << MAI->getPrivateGlobalPrefix() << "PC"
 
218
          << getFunctionNumber() << "_"  << ACPV->getLabelId()
 
219
          << "+" << (unsigned)ACPV->getPCAdjustment();
 
220
         if (ACPV->mustAddCurrentAddress())
 
221
           O << "-.";
 
222
         O << ')';
 
223
      }
 
224
      OutStreamer.AddBlankLine();
 
225
    }
 
226
 
 
227
    void getAnalysisUsage(AnalysisUsage &AU) const {
 
228
      AsmPrinter::getAnalysisUsage(AU);
 
229
      AU.setPreservesAll();
 
230
      AU.addRequired<MachineModuleInfo>();
 
231
      AU.addRequired<DwarfWriter>();
 
232
    }
 
233
  };
 
234
} // end of anonymous namespace
 
235
 
 
236
#include "ARMGenAsmWriter.inc"
 
237
 
 
238
void ARMAsmPrinter::EmitFunctionEntryLabel() {
 
239
  if (AFI->isThumbFunction()) {
 
240
    O << "\t.code\t16\n";
 
241
    O << "\t.thumb_func";
 
242
    if (Subtarget->isTargetDarwin())
 
243
      O << '\t' << *CurrentFnSym;
 
244
    O << '\n';
 
245
  }
 
246
  
 
247
  OutStreamer.EmitLabel(CurrentFnSym);
 
248
}
 
249
 
 
250
/// runOnMachineFunction - This uses the printInstruction()
 
251
/// method to print assembly for each instruction.
 
252
///
 
253
bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
 
254
  AFI = MF.getInfo<ARMFunctionInfo>();
 
255
  MCP = MF.getConstantPool();
 
256
 
 
257
  return AsmPrinter::runOnMachineFunction(MF);
 
258
}
 
259
 
 
260
void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
 
261
                                 const char *Modifier) {
 
262
  const MachineOperand &MO = MI->getOperand(OpNum);
 
263
  unsigned TF = MO.getTargetFlags();
 
264
 
 
265
  switch (MO.getType()) {
 
266
  default:
 
267
    assert(0 && "<unknown operand type>");
 
268
  case MachineOperand::MO_Register: {
 
269
    unsigned Reg = MO.getReg();
 
270
    assert(TargetRegisterInfo::isPhysicalRegister(Reg));
 
271
    if (Modifier && strcmp(Modifier, "dregpair") == 0) {
 
272
      unsigned DRegLo = TRI->getSubReg(Reg, 5); // arm_dsubreg_0
 
273
      unsigned DRegHi = TRI->getSubReg(Reg, 6); // arm_dsubreg_1
 
274
      O << '{'
 
275
        << getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi)
 
276
        << '}';
 
277
    } else if (Modifier && strcmp(Modifier, "lane") == 0) {
 
278
      unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
 
279
      unsigned DReg = TRI->getMatchingSuperReg(Reg, RegNum & 1 ? 2 : 1,
 
280
                                               &ARM::DPR_VFP2RegClass);
 
281
      O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']';
 
282
    } else {
 
283
      assert(!MO.getSubReg() && "Subregs should be eliminated!");
 
284
      O << getRegisterName(Reg);
 
285
    }
 
286
    break;
 
287
  }
 
288
  case MachineOperand::MO_Immediate: {
 
289
    int64_t Imm = MO.getImm();
 
290
    O << '#';
 
291
    if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
 
292
        (TF & ARMII::MO_LO16))
 
293
      O << ":lower16:";
 
294
    else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
 
295
             (TF & ARMII::MO_HI16))
 
296
      O << ":upper16:";
 
297
    O << Imm;
 
298
    break;
 
299
  }
 
300
  case MachineOperand::MO_MachineBasicBlock:
 
301
    O << *MO.getMBB()->getSymbol(OutContext);
 
302
    return;
 
303
  case MachineOperand::MO_GlobalAddress: {
 
304
    bool isCallOp = Modifier && !strcmp(Modifier, "call");
 
305
    GlobalValue *GV = MO.getGlobal();
 
306
 
 
307
    if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
 
308
        (TF & ARMII::MO_LO16))
 
309
      O << ":lower16:";
 
310
    else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
 
311
             (TF & ARMII::MO_HI16))
 
312
      O << ":upper16:";
 
313
    O << *GetGlobalValueSymbol(GV);
 
314
 
 
315
    printOffset(MO.getOffset());
 
316
 
 
317
    if (isCallOp && Subtarget->isTargetELF() &&
 
318
        TM.getRelocationModel() == Reloc::PIC_)
 
319
      O << "(PLT)";
 
320
    break;
 
321
  }
 
322
  case MachineOperand::MO_ExternalSymbol: {
 
323
    bool isCallOp = Modifier && !strcmp(Modifier, "call");
 
324
    O << *GetExternalSymbolSymbol(MO.getSymbolName());
 
325
    
 
326
    if (isCallOp && Subtarget->isTargetELF() &&
 
327
        TM.getRelocationModel() == Reloc::PIC_)
 
328
      O << "(PLT)";
 
329
    break;
 
330
  }
 
331
  case MachineOperand::MO_ConstantPoolIndex:
 
332
    O << *GetCPISymbol(MO.getIndex());
 
333
    break;
 
334
  case MachineOperand::MO_JumpTableIndex:
 
335
    O << *GetJTISymbol(MO.getIndex());
 
336
    break;
 
337
  }
 
338
}
 
339
 
 
340
static void printSOImm(formatted_raw_ostream &O, int64_t V, bool VerboseAsm,
 
341
                       const MCAsmInfo *MAI) {
 
342
  // Break it up into two parts that make up a shifter immediate.
 
343
  V = ARM_AM::getSOImmVal(V);
 
344
  assert(V != -1 && "Not a valid so_imm value!");
 
345
 
 
346
  unsigned Imm = ARM_AM::getSOImmValImm(V);
 
347
  unsigned Rot = ARM_AM::getSOImmValRot(V);
 
348
 
 
349
  // Print low-level immediate formation info, per
 
350
  // A5.1.3: "Data-processing operands - Immediate".
 
351
  if (Rot) {
 
352
    O << "#" << Imm << ", " << Rot;
 
353
    // Pretty printed version.
 
354
    if (VerboseAsm) {
 
355
      O.PadToColumn(MAI->getCommentColumn());
 
356
      O << MAI->getCommentString() << ' ';
 
357
      O << (int)ARM_AM::rotr32(Imm, Rot);
 
358
    }
 
359
  } else {
 
360
    O << "#" << Imm;
 
361
  }
 
362
}
 
363
 
 
364
/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
 
365
/// immediate in bits 0-7.
 
366
void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
 
367
  const MachineOperand &MO = MI->getOperand(OpNum);
 
368
  assert(MO.isImm() && "Not a valid so_imm value!");
 
369
  printSOImm(O, MO.getImm(), VerboseAsm, MAI);
 
370
}
 
371
 
 
372
/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
 
373
/// followed by an 'orr' to materialize.
 
374
void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) {
 
375
  const MachineOperand &MO = MI->getOperand(OpNum);
 
376
  assert(MO.isImm() && "Not a valid so_imm value!");
 
377
  unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm());
 
378
  unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm());
 
379
  printSOImm(O, V1, VerboseAsm, MAI);
 
380
  O << "\n\torr";
 
381
  printPredicateOperand(MI, 2);
 
382
  O << "\t";
 
383
  printOperand(MI, 0);
 
384
  O << ", ";
 
385
  printOperand(MI, 0);
 
386
  O << ", ";
 
387
  printSOImm(O, V2, VerboseAsm, MAI);
 
388
}
 
389
 
 
390
// so_reg is a 4-operand unit corresponding to register forms of the A5.1
 
391
// "Addressing Mode 1 - Data-processing operands" forms.  This includes:
 
392
//    REG 0   0           - e.g. R5
 
393
//    REG REG 0,SH_OPC    - e.g. R5, ROR R3
 
394
//    REG 0   IMM,SH_OPC  - e.g. R5, LSL #3
 
395
void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) {
 
396
  const MachineOperand &MO1 = MI->getOperand(Op);
 
397
  const MachineOperand &MO2 = MI->getOperand(Op+1);
 
398
  const MachineOperand &MO3 = MI->getOperand(Op+2);
 
399
 
 
400
  O << getRegisterName(MO1.getReg());
 
401
 
 
402
  // Print the shift opc.
 
403
  O << ", "
 
404
    << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()))
 
405
    << " ";
 
406
 
 
407
  if (MO2.getReg()) {
 
408
    O << getRegisterName(MO2.getReg());
 
409
    assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
 
410
  } else {
 
411
    O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
 
412
  }
 
413
}
 
414
 
 
415
void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) {
 
416
  const MachineOperand &MO1 = MI->getOperand(Op);
 
417
  const MachineOperand &MO2 = MI->getOperand(Op+1);
 
418
  const MachineOperand &MO3 = MI->getOperand(Op+2);
 
419
 
 
420
  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
 
421
    printOperand(MI, Op);
 
422
    return;
 
423
  }
 
424
 
 
425
  O << "[" << getRegisterName(MO1.getReg());
 
426
 
 
427
  if (!MO2.getReg()) {
 
428
    if (ARM_AM::getAM2Offset(MO3.getImm()))  // Don't print +0.
 
429
      O << ", #"
 
430
        << (char)ARM_AM::getAM2Op(MO3.getImm())
 
431
        << ARM_AM::getAM2Offset(MO3.getImm());
 
432
    O << "]";
 
433
    return;
 
434
  }
 
435
 
 
436
  O << ", "
 
437
    << (char)ARM_AM::getAM2Op(MO3.getImm())
 
438
    << getRegisterName(MO2.getReg());
 
439
 
 
440
  if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
 
441
    O << ", "
 
442
      << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
 
443
      << " #" << ShImm;
 
444
  O << "]";
 
445
}
 
446
 
 
447
void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){
 
448
  const MachineOperand &MO1 = MI->getOperand(Op);
 
449
  const MachineOperand &MO2 = MI->getOperand(Op+1);
 
450
 
 
451
  if (!MO1.getReg()) {
 
452
    unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
 
453
    assert(ImmOffs && "Malformed indexed load / store!");
 
454
    O << "#"
 
455
      << (char)ARM_AM::getAM2Op(MO2.getImm())
 
456
      << ImmOffs;
 
457
    return;
 
458
  }
 
459
 
 
460
  O << (char)ARM_AM::getAM2Op(MO2.getImm())
 
461
    << getRegisterName(MO1.getReg());
 
462
 
 
463
  if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
 
464
    O << ", "
 
465
      << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
 
466
      << " #" << ShImm;
 
467
}
 
468
 
 
469
void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) {
 
470
  const MachineOperand &MO1 = MI->getOperand(Op);
 
471
  const MachineOperand &MO2 = MI->getOperand(Op+1);
 
472
  const MachineOperand &MO3 = MI->getOperand(Op+2);
 
473
 
 
474
  assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
 
475
  O << "[" << getRegisterName(MO1.getReg());
 
476
 
 
477
  if (MO2.getReg()) {
 
478
    O << ", "
 
479
      << (char)ARM_AM::getAM3Op(MO3.getImm())
 
480
      << getRegisterName(MO2.getReg())
 
481
      << "]";
 
482
    return;
 
483
  }
 
484
 
 
485
  if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
 
486
    O << ", #"
 
487
      << (char)ARM_AM::getAM3Op(MO3.getImm())
 
488
      << ImmOffs;
 
489
  O << "]";
 
490
}
 
491
 
 
492
void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){
 
493
  const MachineOperand &MO1 = MI->getOperand(Op);
 
494
  const MachineOperand &MO2 = MI->getOperand(Op+1);
 
495
 
 
496
  if (MO1.getReg()) {
 
497
    O << (char)ARM_AM::getAM3Op(MO2.getImm())
 
498
      << getRegisterName(MO1.getReg());
 
499
    return;
 
500
  }
 
501
 
 
502
  unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
 
503
  assert(ImmOffs && "Malformed indexed load / store!");
 
504
  O << "#"
 
505
    << (char)ARM_AM::getAM3Op(MO2.getImm())
 
506
    << ImmOffs;
 
507
}
 
508
 
 
509
void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op,
 
510
                                          const char *Modifier) {
 
511
  const MachineOperand &MO1 = MI->getOperand(Op);
 
512
  const MachineOperand &MO2 = MI->getOperand(Op+1);
 
513
  ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
 
514
  if (Modifier && strcmp(Modifier, "submode") == 0) {
 
515
    if (MO1.getReg() == ARM::SP) {
 
516
      // FIXME
 
517
      bool isLDM = (MI->getOpcode() == ARM::LDM ||
 
518
                    MI->getOpcode() == ARM::LDM_RET ||
 
519
                    MI->getOpcode() == ARM::t2LDM ||
 
520
                    MI->getOpcode() == ARM::t2LDM_RET);
 
521
      O << ARM_AM::getAMSubModeAltStr(Mode, isLDM);
 
522
    } else
 
523
      O << ARM_AM::getAMSubModeStr(Mode);
 
524
  } else if (Modifier && strcmp(Modifier, "wide") == 0) {
 
525
    ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
 
526
    if (Mode == ARM_AM::ia)
 
527
      O << ".w";
 
528
  } else {
 
529
    printOperand(MI, Op);
 
530
    if (ARM_AM::getAM4WBFlag(MO2.getImm()))
 
531
      O << "!";
 
532
  }
 
533
}
 
534
 
 
535
void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
 
536
                                          const char *Modifier) {
 
537
  const MachineOperand &MO1 = MI->getOperand(Op);
 
538
  const MachineOperand &MO2 = MI->getOperand(Op+1);
 
539
 
 
540
  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
 
541
    printOperand(MI, Op);
 
542
    return;
 
543
  }
 
544
 
 
545
  assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
 
546
 
 
547
  if (Modifier && strcmp(Modifier, "submode") == 0) {
 
548
    ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
 
549
    O << ARM_AM::getAMSubModeStr(Mode);
 
550
    return;
 
551
  } else if (Modifier && strcmp(Modifier, "base") == 0) {
 
552
    // Used for FSTM{D|S} and LSTM{D|S} operations.
 
553
    O << getRegisterName(MO1.getReg());
 
554
    if (ARM_AM::getAM5WBFlag(MO2.getImm()))
 
555
      O << "!";
 
556
    return;
 
557
  }
 
558
 
 
559
  O << "[" << getRegisterName(MO1.getReg());
 
560
 
 
561
  if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
 
562
    O << ", #"
 
563
      << (char)ARM_AM::getAM5Op(MO2.getImm())
 
564
      << ImmOffs*4;
 
565
  }
 
566
  O << "]";
 
567
}
 
568
 
 
569
void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op) {
 
570
  const MachineOperand &MO1 = MI->getOperand(Op);
 
571
  const MachineOperand &MO2 = MI->getOperand(Op+1);
 
572
  const MachineOperand &MO3 = MI->getOperand(Op+2);
 
573
  const MachineOperand &MO4 = MI->getOperand(Op+3);
 
574
 
 
575
  O << "[" << getRegisterName(MO1.getReg());
 
576
  if (MO4.getImm()) {
 
577
    // FIXME: Both darwin as and GNU as violate ARM docs here.
 
578
    O << ", :" << MO4.getImm();
 
579
  }
 
580
  O << "]";
 
581
 
 
582
  if (ARM_AM::getAM6WBFlag(MO3.getImm())) {
 
583
    if (MO2.getReg() == 0)
 
584
      O << "!";
 
585
    else
 
586
      O << ", " << getRegisterName(MO2.getReg());
 
587
  }
 
588
}
 
589
 
 
590
void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op,
 
591
                                           const char *Modifier) {
 
592
  if (Modifier && strcmp(Modifier, "label") == 0) {
 
593
    printPCLabel(MI, Op+1);
 
594
    return;
 
595
  }
 
596
 
 
597
  const MachineOperand &MO1 = MI->getOperand(Op);
 
598
  assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
 
599
  O << "[pc, +" << getRegisterName(MO1.getReg()) << "]";
 
600
}
 
601
 
 
602
void
 
603
ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op) {
 
604
  const MachineOperand &MO = MI->getOperand(Op);
 
605
  uint32_t v = ~MO.getImm();
 
606
  int32_t lsb = CountTrailingZeros_32(v);
 
607
  int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
 
608
  assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
 
609
  O << "#" << lsb << ", #" << width;
 
610
}
 
611
 
 
612
//===--------------------------------------------------------------------===//
 
613
 
 
614
void ARMAsmPrinter::printThumbS4ImmOperand(const MachineInstr *MI, int Op) {
 
615
  O << "#" <<  MI->getOperand(Op).getImm() * 4;
 
616
}
 
617
 
 
618
void
 
619
ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op) {
 
620
  // (3 - the number of trailing zeros) is the number of then / else.
 
621
  unsigned Mask = MI->getOperand(Op).getImm();
 
622
  unsigned NumTZ = CountTrailingZeros_32(Mask);
 
623
  assert(NumTZ <= 3 && "Invalid IT mask!");
 
624
  for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
 
625
    bool T = (Mask & (1 << Pos)) == 0;
 
626
    if (T)
 
627
      O << 't';
 
628
    else
 
629
      O << 'e';
 
630
  }
 
631
}
 
632
 
 
633
void
 
634
ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) {
 
635
  const MachineOperand &MO1 = MI->getOperand(Op);
 
636
  const MachineOperand &MO2 = MI->getOperand(Op+1);
 
637
  O << "[" << getRegisterName(MO1.getReg());
 
638
  O << ", " << getRegisterName(MO2.getReg()) << "]";
 
639
}
 
640
 
 
641
void
 
642
ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op,
 
643
                                            unsigned Scale) {
 
644
  const MachineOperand &MO1 = MI->getOperand(Op);
 
645
  const MachineOperand &MO2 = MI->getOperand(Op+1);
 
646
  const MachineOperand &MO3 = MI->getOperand(Op+2);
 
647
 
 
648
  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
 
649
    printOperand(MI, Op);
 
650
    return;
 
651
  }
 
652
 
 
653
  O << "[" << getRegisterName(MO1.getReg());
 
654
  if (MO3.getReg())
 
655
    O << ", " << getRegisterName(MO3.getReg());
 
656
  else if (unsigned ImmOffs = MO2.getImm())
 
657
    O << ", #+" << ImmOffs * Scale;
 
658
  O << "]";
 
659
}
 
660
 
 
661
void
 
662
ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op) {
 
663
  printThumbAddrModeRI5Operand(MI, Op, 1);
 
664
}
 
665
void
 
666
ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op) {
 
667
  printThumbAddrModeRI5Operand(MI, Op, 2);
 
668
}
 
669
void
 
670
ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op) {
 
671
  printThumbAddrModeRI5Operand(MI, Op, 4);
 
672
}
 
673
 
 
674
void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) {
 
675
  const MachineOperand &MO1 = MI->getOperand(Op);
 
676
  const MachineOperand &MO2 = MI->getOperand(Op+1);
 
677
  O << "[" << getRegisterName(MO1.getReg());
 
678
  if (unsigned ImmOffs = MO2.getImm())
 
679
    O << ", #+" << ImmOffs*4;
 
680
  O << "]";
 
681
}
 
682
 
 
683
//===--------------------------------------------------------------------===//
 
684
 
 
685
// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
 
686
// register with shift forms.
 
687
// REG 0   0           - e.g. R5
 
688
// REG IMM, SH_OPC     - e.g. R5, LSL #3
 
689
void ARMAsmPrinter::printT2SOOperand(const MachineInstr *MI, int OpNum) {
 
690
  const MachineOperand &MO1 = MI->getOperand(OpNum);
 
691
  const MachineOperand &MO2 = MI->getOperand(OpNum+1);
 
692
 
 
693
  unsigned Reg = MO1.getReg();
 
694
  assert(TargetRegisterInfo::isPhysicalRegister(Reg));
 
695
  O << getRegisterName(Reg);
 
696
 
 
697
  // Print the shift opc.
 
698
  O << ", "
 
699
    << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
 
700
    << " ";
 
701
 
 
702
  assert(MO2.isImm() && "Not a valid t2_so_reg value!");
 
703
  O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
 
704
}
 
705
 
 
706
void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI,
 
707
                                                int OpNum) {
 
708
  const MachineOperand &MO1 = MI->getOperand(OpNum);
 
709
  const MachineOperand &MO2 = MI->getOperand(OpNum+1);
 
710
 
 
711
  O << "[" << getRegisterName(MO1.getReg());
 
712
 
 
713
  unsigned OffImm = MO2.getImm();
 
714
  if (OffImm)  // Don't print +0.
 
715
    O << ", #+" << OffImm;
 
716
  O << "]";
 
717
}
 
718
 
 
719
void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI,
 
720
                                               int OpNum) {
 
721
  const MachineOperand &MO1 = MI->getOperand(OpNum);
 
722
  const MachineOperand &MO2 = MI->getOperand(OpNum+1);
 
723
 
 
724
  O << "[" << getRegisterName(MO1.getReg());
 
725
 
 
726
  int32_t OffImm = (int32_t)MO2.getImm();
 
727
  // Don't print +0.
 
728
  if (OffImm < 0)
 
729
    O << ", #-" << -OffImm;
 
730
  else if (OffImm > 0)
 
731
    O << ", #+" << OffImm;
 
732
  O << "]";
 
733
}
 
734
 
 
735
void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr *MI,
 
736
                                                 int OpNum) {
 
737
  const MachineOperand &MO1 = MI->getOperand(OpNum);
 
738
  const MachineOperand &MO2 = MI->getOperand(OpNum+1);
 
739
 
 
740
  O << "[" << getRegisterName(MO1.getReg());
 
741
 
 
742
  int32_t OffImm = (int32_t)MO2.getImm() / 4;
 
743
  // Don't print +0.
 
744
  if (OffImm < 0)
 
745
    O << ", #-" << -OffImm * 4;
 
746
  else if (OffImm > 0)
 
747
    O << ", #+" << OffImm * 4;
 
748
  O << "]";
 
749
}
 
750
 
 
751
void ARMAsmPrinter::printT2AddrModeImm8OffsetOperand(const MachineInstr *MI,
 
752
                                                     int OpNum) {
 
753
  const MachineOperand &MO1 = MI->getOperand(OpNum);
 
754
  int32_t OffImm = (int32_t)MO1.getImm();
 
755
  // Don't print +0.
 
756
  if (OffImm < 0)
 
757
    O << "#-" << -OffImm;
 
758
  else if (OffImm > 0)
 
759
    O << "#+" << OffImm;
 
760
}
 
761
 
 
762
void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI,
 
763
                                                int OpNum) {
 
764
  const MachineOperand &MO1 = MI->getOperand(OpNum);
 
765
  const MachineOperand &MO2 = MI->getOperand(OpNum+1);
 
766
  const MachineOperand &MO3 = MI->getOperand(OpNum+2);
 
767
 
 
768
  O << "[" << getRegisterName(MO1.getReg());
 
769
 
 
770
  assert(MO2.getReg() && "Invalid so_reg load / store address!");
 
771
  O << ", " << getRegisterName(MO2.getReg());
 
772
 
 
773
  unsigned ShAmt = MO3.getImm();
 
774
  if (ShAmt) {
 
775
    assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
 
776
    O << ", lsl #" << ShAmt;
 
777
  }
 
778
  O << "]";
 
779
}
 
780
 
 
781
 
 
782
//===--------------------------------------------------------------------===//
 
783
 
 
784
void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int OpNum) {
 
785
  ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
 
786
  if (CC != ARMCC::AL)
 
787
    O << ARMCondCodeToString(CC);
 
788
}
 
789
 
 
790
void ARMAsmPrinter::printMandatoryPredicateOperand(const MachineInstr *MI,
 
791
                                                   int OpNum) {
 
792
  ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
 
793
  O << ARMCondCodeToString(CC);
 
794
}
 
795
 
 
796
void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum){
 
797
  unsigned Reg = MI->getOperand(OpNum).getReg();
 
798
  if (Reg) {
 
799
    assert(Reg == ARM::CPSR && "Expect ARM CPSR register!");
 
800
    O << 's';
 
801
  }
 
802
}
 
803
 
 
804
void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int OpNum) {
 
805
  int Id = (int)MI->getOperand(OpNum).getImm();
 
806
  O << MAI->getPrivateGlobalPrefix()
 
807
    << "PC" << getFunctionNumber() << "_" << Id;
 
808
}
 
809
 
 
810
void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum) {
 
811
  O << "{";
 
812
  // Always skip the first operand, it's the optional (and implicit writeback).
 
813
  for (unsigned i = OpNum+1, e = MI->getNumOperands(); i != e; ++i) {
 
814
    if (MI->getOperand(i).isImplicit())
 
815
      continue;
 
816
    if ((int)i != OpNum+1) O << ", ";
 
817
    printOperand(MI, i);
 
818
  }
 
819
  O << "}";
 
820
}
 
821
 
 
822
void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum,
 
823
                                       const char *Modifier) {
 
824
  assert(Modifier && "This operand only works with a modifier!");
 
825
  // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
 
826
  // data itself.
 
827
  if (!strcmp(Modifier, "label")) {
 
828
    unsigned ID = MI->getOperand(OpNum).getImm();
 
829
    OutStreamer.EmitLabel(GetCPISymbol(ID));
 
830
  } else {
 
831
    assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
 
832
    unsigned CPI = MI->getOperand(OpNum).getIndex();
 
833
 
 
834
    const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI];
 
835
 
 
836
    if (MCPE.isMachineConstantPoolEntry()) {
 
837
      EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
 
838
    } else {
 
839
      EmitGlobalConstant(MCPE.Val.ConstVal);
 
840
    }
 
841
  }
 
842
}
 
843
 
 
844
MCSymbol *ARMAsmPrinter::
 
845
GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
 
846
                            const MachineBasicBlock *MBB) const {
 
847
  SmallString<60> Name;
 
848
  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
 
849
    << getFunctionNumber() << '_' << uid << '_' << uid2
 
850
    << "_set_" << MBB->getNumber();
 
851
  return OutContext.GetOrCreateSymbol(Name.str());
 
852
}
 
853
 
 
854
MCSymbol *ARMAsmPrinter::
 
855
GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const {
 
856
  SmallString<60> Name;
 
857
  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
 
858
    << getFunctionNumber() << '_' << uid << '_' << uid2;
 
859
  return OutContext.GetOrCreateSymbol(Name.str());
 
860
}
 
861
 
 
862
void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) {
 
863
  assert(!Subtarget->isThumb2() && "Thumb2 should use double-jump jumptables!");
 
864
 
 
865
  const MachineOperand &MO1 = MI->getOperand(OpNum);
 
866
  const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
 
867
  
 
868
  unsigned JTI = MO1.getIndex();
 
869
  MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
 
870
  OutStreamer.EmitLabel(JTISymbol);
 
871
 
 
872
  const char *JTEntryDirective = MAI->getData32bitsDirective();
 
873
 
 
874
  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
 
875
  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
 
876
  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
 
877
  bool UseSet= MAI->hasSetDirective() && TM.getRelocationModel() == Reloc::PIC_;
 
878
  SmallPtrSet<MachineBasicBlock*, 8> JTSets;
 
879
  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
 
880
    MachineBasicBlock *MBB = JTBBs[i];
 
881
    bool isNew = JTSets.insert(MBB);
 
882
 
 
883
    if (UseSet && isNew) {
 
884
      O << "\t.set\t"
 
885
        << *GetARMSetPICJumpTableLabel2(JTI, MO2.getImm(), MBB) << ','
 
886
        << *MBB->getSymbol(OutContext) << '-' << *JTISymbol << '\n';
 
887
    }
 
888
 
 
889
    O << JTEntryDirective << ' ';
 
890
    if (UseSet)
 
891
      O << *GetARMSetPICJumpTableLabel2(JTI, MO2.getImm(), MBB);
 
892
    else if (TM.getRelocationModel() == Reloc::PIC_)
 
893
      O << *MBB->getSymbol(OutContext) << '-' << *JTISymbol;
 
894
    else
 
895
      O << *MBB->getSymbol(OutContext);
 
896
 
 
897
    if (i != e-1)
 
898
      O << '\n';
 
899
  }
 
900
}
 
901
 
 
902
void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr *MI, int OpNum) {
 
903
  const MachineOperand &MO1 = MI->getOperand(OpNum);
 
904
  const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
 
905
  unsigned JTI = MO1.getIndex();
 
906
  
 
907
  MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
 
908
  OutStreamer.EmitLabel(JTISymbol);
 
909
 
 
910
  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
 
911
  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
 
912
  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
 
913
  bool ByteOffset = false, HalfWordOffset = false;
 
914
  if (MI->getOpcode() == ARM::t2TBB)
 
915
    ByteOffset = true;
 
916
  else if (MI->getOpcode() == ARM::t2TBH)
 
917
    HalfWordOffset = true;
 
918
 
 
919
  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
 
920
    MachineBasicBlock *MBB = JTBBs[i];
 
921
    if (ByteOffset)
 
922
      O << MAI->getData8bitsDirective();
 
923
    else if (HalfWordOffset)
 
924
      O << MAI->getData16bitsDirective();
 
925
    
 
926
    if (ByteOffset || HalfWordOffset)
 
927
      O << '(' << *MBB->getSymbol(OutContext) << "-" << *JTISymbol << ")/2";
 
928
    else
 
929
      O << "\tb.w " << *MBB->getSymbol(OutContext);
 
930
 
 
931
    if (i != e-1)
 
932
      O << '\n';
 
933
  }
 
934
 
 
935
  // Make sure the instruction that follows TBB is 2-byte aligned.
 
936
  // FIXME: Constant island pass should insert an "ALIGN" instruction instead.
 
937
  if (ByteOffset && (JTBBs.size() & 1)) {
 
938
    O << '\n';
 
939
    EmitAlignment(1);
 
940
  }
 
941
}
 
942
 
 
943
void ARMAsmPrinter::printTBAddrMode(const MachineInstr *MI, int OpNum) {
 
944
  O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
 
945
  if (MI->getOpcode() == ARM::t2TBH)
 
946
    O << ", lsl #1";
 
947
  O << ']';
 
948
}
 
949
 
 
950
void ARMAsmPrinter::printNoHashImmediate(const MachineInstr *MI, int OpNum) {
 
951
  O << MI->getOperand(OpNum).getImm();
 
952
}
 
953
 
 
954
void ARMAsmPrinter::printVFPf32ImmOperand(const MachineInstr *MI, int OpNum) {
 
955
  const ConstantFP *FP = MI->getOperand(OpNum).getFPImm();
 
956
  O << '#' << FP->getValueAPF().convertToFloat();
 
957
  if (VerboseAsm) {
 
958
    O.PadToColumn(MAI->getCommentColumn());
 
959
    O << MAI->getCommentString() << ' ';
 
960
    WriteAsOperand(O, FP, /*PrintType=*/false);
 
961
  }
 
962
}
 
963
 
 
964
void ARMAsmPrinter::printVFPf64ImmOperand(const MachineInstr *MI, int OpNum) {
 
965
  const ConstantFP *FP = MI->getOperand(OpNum).getFPImm();
 
966
  O << '#' << FP->getValueAPF().convertToDouble();
 
967
  if (VerboseAsm) {
 
968
    O.PadToColumn(MAI->getCommentColumn());
 
969
    O << MAI->getCommentString() << ' ';
 
970
    WriteAsOperand(O, FP, /*PrintType=*/false);
 
971
  }
 
972
}
 
973
 
 
974
bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
 
975
                                    unsigned AsmVariant, const char *ExtraCode){
 
976
  // Does this asm operand have a single letter operand modifier?
 
977
  if (ExtraCode && ExtraCode[0]) {
 
978
    if (ExtraCode[1] != 0) return true; // Unknown modifier.
 
979
 
 
980
    switch (ExtraCode[0]) {
 
981
    default: return true;  // Unknown modifier.
 
982
    case 'a': // Print as a memory address.
 
983
      if (MI->getOperand(OpNum).isReg()) {
 
984
        O << "[" << getRegisterName(MI->getOperand(OpNum).getReg()) << "]";
 
985
        return false;
 
986
      }
 
987
      // Fallthrough
 
988
    case 'c': // Don't print "#" before an immediate operand.
 
989
      if (!MI->getOperand(OpNum).isImm())
 
990
        return true;
 
991
      printNoHashImmediate(MI, OpNum);
 
992
      return false;
 
993
    case 'P': // Print a VFP double precision register.
 
994
    case 'q': // Print a NEON quad precision register.
 
995
      printOperand(MI, OpNum);
 
996
      return false;
 
997
    case 'Q':
 
998
      if (TM.getTargetData()->isLittleEndian())
 
999
        break;
 
1000
      // Fallthrough
 
1001
    case 'R':
 
1002
      if (TM.getTargetData()->isBigEndian())
 
1003
        break;
 
1004
      // Fallthrough
 
1005
    case 'H': // Write second word of DI / DF reference.
 
1006
      // Verify that this operand has two consecutive registers.
 
1007
      if (!MI->getOperand(OpNum).isReg() ||
 
1008
          OpNum+1 == MI->getNumOperands() ||
 
1009
          !MI->getOperand(OpNum+1).isReg())
 
1010
        return true;
 
1011
      ++OpNum;   // Return the high-part.
 
1012
    }
 
1013
  }
 
1014
 
 
1015
  printOperand(MI, OpNum);
 
1016
  return false;
 
1017
}
 
1018
 
 
1019
bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
 
1020
                                          unsigned OpNum, unsigned AsmVariant,
 
1021
                                          const char *ExtraCode) {
 
1022
  if (ExtraCode && ExtraCode[0])
 
1023
    return true; // Unknown modifier.
 
1024
 
 
1025
  const MachineOperand &MO = MI->getOperand(OpNum);
 
1026
  assert(MO.isReg() && "unexpected inline asm memory operand");
 
1027
  O << "[" << getRegisterName(MO.getReg()) << "]";
 
1028
  return false;
 
1029
}
 
1030
 
 
1031
void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
 
1032
  if (EnableMCInst) {
 
1033
    printInstructionThroughMCStreamer(MI);
 
1034
  } else {
 
1035
    int Opc = MI->getOpcode();
 
1036
    if (Opc == ARM::CONSTPOOL_ENTRY)
 
1037
      EmitAlignment(2);
 
1038
    
 
1039
    printInstruction(MI);
 
1040
    OutStreamer.AddBlankLine();
 
1041
  }
 
1042
}
 
1043
 
 
1044
void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
 
1045
  if (Subtarget->isTargetDarwin()) {
 
1046
    Reloc::Model RelocM = TM.getRelocationModel();
 
1047
    if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) {
 
1048
      // Declare all the text sections up front (before the DWARF sections
 
1049
      // emitted by AsmPrinter::doInitialization) so the assembler will keep
 
1050
      // them together at the beginning of the object file.  This helps
 
1051
      // avoid out-of-range branches that are due a fundamental limitation of
 
1052
      // the way symbol offsets are encoded with the current Darwin ARM
 
1053
      // relocations.
 
1054
      TargetLoweringObjectFileMachO &TLOFMacho = 
 
1055
        static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
 
1056
      OutStreamer.SwitchSection(TLOFMacho.getTextSection());
 
1057
      OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection());
 
1058
      OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection());
 
1059
      if (RelocM == Reloc::DynamicNoPIC) {
 
1060
        const MCSection *sect =
 
1061
          TLOFMacho.getMachOSection("__TEXT", "__symbol_stub4",
 
1062
                                    MCSectionMachO::S_SYMBOL_STUBS,
 
1063
                                    12, SectionKind::getText());
 
1064
        OutStreamer.SwitchSection(sect);
 
1065
      } else {
 
1066
        const MCSection *sect =
 
1067
          TLOFMacho.getMachOSection("__TEXT", "__picsymbolstub4",
 
1068
                                    MCSectionMachO::S_SYMBOL_STUBS,
 
1069
                                    16, SectionKind::getText());
 
1070
        OutStreamer.SwitchSection(sect);
 
1071
      }
 
1072
    }
 
1073
  }
 
1074
 
 
1075
  // Use unified assembler syntax.
 
1076
  O << "\t.syntax unified\n";
 
1077
 
 
1078
  // Emit ARM Build Attributes
 
1079
  if (Subtarget->isTargetELF()) {
 
1080
    // CPU Type
 
1081
    std::string CPUString = Subtarget->getCPUString();
 
1082
    if (CPUString != "generic")
 
1083
      O << "\t.cpu " << CPUString << '\n';
 
1084
 
 
1085
    // FIXME: Emit FPU type
 
1086
    if (Subtarget->hasVFP2())
 
1087
      O << "\t.eabi_attribute " << ARMBuildAttrs::VFP_arch << ", 2\n";
 
1088
 
 
1089
    // Signal various FP modes.
 
1090
    if (!UnsafeFPMath)
 
1091
      O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_denormal << ", 1\n"
 
1092
        << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_exceptions << ", 1\n";
 
1093
 
 
1094
    if (FiniteOnlyFPMath())
 
1095
      O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_number_model << ", 1\n";
 
1096
    else
 
1097
      O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_number_model << ", 3\n";
 
1098
 
 
1099
    // 8-bytes alignment stuff.
 
1100
    O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_needed << ", 1\n"
 
1101
      << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_preserved << ", 1\n";
 
1102
 
 
1103
    // Hard float.  Use both S and D registers and conform to AAPCS-VFP.
 
1104
    if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard)
 
1105
      O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_HardFP_use << ", 3\n"
 
1106
        << "\t.eabi_attribute " << ARMBuildAttrs::ABI_VFP_args << ", 1\n";
 
1107
 
 
1108
    // FIXME: Should we signal R9 usage?
 
1109
  }
 
1110
}
 
1111
 
 
1112
 
 
1113
void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
 
1114
  if (Subtarget->isTargetDarwin()) {
 
1115
    // All darwin targets use mach-o.
 
1116
    TargetLoweringObjectFileMachO &TLOFMacho =
 
1117
      static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
 
1118
    MachineModuleInfoMachO &MMIMacho =
 
1119
      MMI->getObjFileInfo<MachineModuleInfoMachO>();
 
1120
 
 
1121
    O << '\n';
 
1122
 
 
1123
    // Output non-lazy-pointers for external and common global variables.
 
1124
    MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();
 
1125
    
 
1126
    if (!Stubs.empty()) {
 
1127
      // Switch with ".non_lazy_symbol_pointer" directive.
 
1128
      OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
 
1129
      EmitAlignment(2);
 
1130
      for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
 
1131
        O << *Stubs[i].first << ":\n\t.indirect_symbol ";
 
1132
        O << *Stubs[i].second << "\n\t.long\t0\n";
 
1133
      }
 
1134
    }
 
1135
 
 
1136
    Stubs = MMIMacho.GetHiddenGVStubList();
 
1137
    if (!Stubs.empty()) {
 
1138
      OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
 
1139
      EmitAlignment(2);
 
1140
      for (unsigned i = 0, e = Stubs.size(); i != e; ++i)
 
1141
        O << *Stubs[i].first << ":\n\t.long " << *Stubs[i].second << "\n";
 
1142
    }
 
1143
 
 
1144
    // Funny Darwin hack: This flag tells the linker that no global symbols
 
1145
    // contain code that falls through to other global symbols (e.g. the obvious
 
1146
    // implementation of multiple entry points).  If this doesn't occur, the
 
1147
    // linker can safely perform dead code stripping.  Since LLVM never
 
1148
    // generates code that does this, it is always safe to set.
 
1149
    OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
 
1150
  }
 
1151
}
 
1152
 
 
1153
//===----------------------------------------------------------------------===//
 
1154
 
 
1155
void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) {
 
1156
  ARMMCInstLower MCInstLowering(OutContext, *Mang, *this);
 
1157
  switch (MI->getOpcode()) {
 
1158
  case ARM::t2MOVi32imm:
 
1159
    assert(0 && "Should be lowered by thumb2it pass");
 
1160
  default: break;
 
1161
  case ARM::PICADD: { // FIXME: Remove asm string from td file.
 
1162
    // This is a pseudo op for a label + instruction sequence, which looks like:
 
1163
    // LPC0:
 
1164
    //     add r0, pc, r0
 
1165
    // This adds the address of LPC0 to r0.
 
1166
    
 
1167
    // Emit the label.
 
1168
    // FIXME: MOVE TO SHARED PLACE.
 
1169
    unsigned Id = (unsigned)MI->getOperand(2).getImm();
 
1170
    const char *Prefix = MAI->getPrivateGlobalPrefix();
 
1171
    MCSymbol *Label =OutContext.GetOrCreateSymbol(Twine(Prefix)
 
1172
                         + "PC" + Twine(getFunctionNumber()) + "_" + Twine(Id));
 
1173
    OutStreamer.EmitLabel(Label);
 
1174
    
 
1175
    
 
1176
    // Form and emit tha dd.
 
1177
    MCInst AddInst;
 
1178
    AddInst.setOpcode(ARM::ADDrr);
 
1179
    AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
 
1180
    AddInst.addOperand(MCOperand::CreateReg(ARM::PC));
 
1181
    AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
 
1182
    OutStreamer.EmitInstruction(AddInst);
 
1183
    return;
 
1184
  }
 
1185
  case ARM::CONSTPOOL_ENTRY: { // FIXME: Remove asm string from td file.
 
1186
    /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
 
1187
    /// in the function.  The first operand is the ID# for this instruction, the
 
1188
    /// second is the index into the MachineConstantPool that this is, the third
 
1189
    /// is the size in bytes of this constant pool entry.
 
1190
    unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
 
1191
    unsigned CPIdx   = (unsigned)MI->getOperand(1).getIndex();
 
1192
 
 
1193
    EmitAlignment(2);
 
1194
    OutStreamer.EmitLabel(GetCPISymbol(LabelId));
 
1195
 
 
1196
    const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
 
1197
    if (MCPE.isMachineConstantPoolEntry())
 
1198
      EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
 
1199
    else
 
1200
      EmitGlobalConstant(MCPE.Val.ConstVal);
 
1201
    
 
1202
    return;
 
1203
  }
 
1204
  case ARM::MOVi2pieces: { // FIXME: Remove asmstring from td file.
 
1205
    // This is a hack that lowers as a two instruction sequence.
 
1206
    unsigned DstReg = MI->getOperand(0).getReg();
 
1207
    unsigned ImmVal = (unsigned)MI->getOperand(1).getImm();
 
1208
 
 
1209
    unsigned SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal);
 
1210
    unsigned SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal);
 
1211
    
 
1212
    {
 
1213
      MCInst TmpInst;
 
1214
      TmpInst.setOpcode(ARM::MOVi);
 
1215
      TmpInst.addOperand(MCOperand::CreateReg(DstReg));
 
1216
      TmpInst.addOperand(MCOperand::CreateImm(SOImmValV1));
 
1217
      
 
1218
      // Predicate.
 
1219
      TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
 
1220
      TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
 
1221
 
 
1222
      TmpInst.addOperand(MCOperand::CreateReg(0));          // cc_out
 
1223
      OutStreamer.EmitInstruction(TmpInst);
 
1224
    }
 
1225
 
 
1226
    {
 
1227
      MCInst TmpInst;
 
1228
      TmpInst.setOpcode(ARM::ORRri);
 
1229
      TmpInst.addOperand(MCOperand::CreateReg(DstReg));     // dstreg
 
1230
      TmpInst.addOperand(MCOperand::CreateReg(DstReg));     // inreg
 
1231
      TmpInst.addOperand(MCOperand::CreateImm(SOImmValV2)); // so_imm
 
1232
      // Predicate.
 
1233
      TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
 
1234
      TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
 
1235
      
 
1236
      TmpInst.addOperand(MCOperand::CreateReg(0));          // cc_out
 
1237
      OutStreamer.EmitInstruction(TmpInst);
 
1238
    }
 
1239
    return; 
 
1240
  }
 
1241
  case ARM::MOVi32imm: { // FIXME: Remove asmstring from td file.
 
1242
    // This is a hack that lowers as a two instruction sequence.
 
1243
    unsigned DstReg = MI->getOperand(0).getReg();
 
1244
    unsigned ImmVal = (unsigned)MI->getOperand(1).getImm();
 
1245
    
 
1246
    {
 
1247
      MCInst TmpInst;
 
1248
      TmpInst.setOpcode(ARM::MOVi16);
 
1249
      TmpInst.addOperand(MCOperand::CreateReg(DstReg));         // dstreg
 
1250
      TmpInst.addOperand(MCOperand::CreateImm(ImmVal & 65535)); // lower16(imm)
 
1251
      
 
1252
      // Predicate.
 
1253
      TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
 
1254
      TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
 
1255
      
 
1256
      OutStreamer.EmitInstruction(TmpInst);
 
1257
    }
 
1258
    
 
1259
    {
 
1260
      MCInst TmpInst;
 
1261
      TmpInst.setOpcode(ARM::MOVTi16);
 
1262
      TmpInst.addOperand(MCOperand::CreateReg(DstReg));         // dstreg
 
1263
      TmpInst.addOperand(MCOperand::CreateReg(DstReg));         // srcreg
 
1264
      TmpInst.addOperand(MCOperand::CreateImm(ImmVal >> 16));   // upper16(imm)
 
1265
      
 
1266
      // Predicate.
 
1267
      TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
 
1268
      TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
 
1269
      
 
1270
      OutStreamer.EmitInstruction(TmpInst);
 
1271
    }
 
1272
    
 
1273
    return;
 
1274
  }
 
1275
  }
 
1276
      
 
1277
  MCInst TmpInst;
 
1278
  MCInstLowering.Lower(MI, TmpInst);
 
1279
  OutStreamer.EmitInstruction(TmpInst);
 
1280
}
 
1281
 
 
1282
//===----------------------------------------------------------------------===//
 
1283
// Target Registry Stuff
 
1284
//===----------------------------------------------------------------------===//
 
1285
 
 
1286
static MCInstPrinter *createARMMCInstPrinter(const Target &T,
 
1287
                                             unsigned SyntaxVariant,
 
1288
                                             const MCAsmInfo &MAI,
 
1289
                                             raw_ostream &O) {
 
1290
  if (SyntaxVariant == 0)
 
1291
    return new ARMInstPrinter(O, MAI, false);
 
1292
  return 0;
 
1293
}
 
1294
 
 
1295
// Force static initialization.
 
1296
extern "C" void LLVMInitializeARMAsmPrinter() {
 
1297
  RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget);
 
1298
  RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget);
 
1299
 
 
1300
  TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter);
 
1301
  TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter);
 
1302
}
 
1303