1//===-- HexagonAsmPrinter.h - Print machine code to an Hexagon .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// Hexagon Assembly printer class.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef HEXAGONASMPRINTER_H
15#define HEXAGONASMPRINTER_H
16
17#include "Hexagon.h"
18#include "HexagonTargetMachine.h"
19#include "llvm/CodeGen/AsmPrinter.h"
20#include "llvm/Support/Compiler.h"
21#include "llvm/Support/raw_ostream.h"
22
23namespace llvm {
24  class HexagonAsmPrinter : public AsmPrinter {
25    const HexagonSubtarget *Subtarget;
26
27  public:
28    explicit HexagonAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
29      : AsmPrinter(TM, Streamer) {
30      Subtarget = &TM.getSubtarget<HexagonSubtarget>();
31    }
32
33    virtual const char *getPassName() const {
34      return "Hexagon Assembly Printer";
35    }
36
37    bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const;
38
39    virtual void EmitInstruction(const MachineInstr *MI);
40    virtual void EmitAlignment(unsigned NumBits,
41                               const GlobalValue *GV = 0) const;
42
43    void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
44    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
45                         unsigned AsmVariant, const char *ExtraCode,
46                         raw_ostream &OS);
47    bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
48                               unsigned AsmVariant, const char *ExtraCode,
49                               raw_ostream &OS);
50
51    /// printInstruction - This method is automatically generated by tablegen
52    /// from the instruction set description.  This method returns true if the
53    /// machine instruction was sufficiently described to print it, otherwise it
54    /// returns false.
55    void printInstruction(const MachineInstr *MI, raw_ostream &O);
56
57    //    void printMachineInstruction(const MachineInstr *MI);
58    void printOp(const MachineOperand &MO, raw_ostream &O);
59
60    /// printRegister - Print register according to target requirements.
61    ///
62    void printRegister(const MachineOperand &MO, bool R0AsZero,
63                       raw_ostream &O) {
64      unsigned RegNo = MO.getReg();
65      assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??");
66      O << getRegisterName(RegNo);
67    }
68
69    void printImmOperand(const MachineInstr *MI, unsigned OpNo,
70                                raw_ostream &O) {
71      int value = MI->getOperand(OpNo).getImm();
72      O << value;
73    }
74
75    void printNegImmOperand(const MachineInstr *MI, unsigned OpNo,
76                                   raw_ostream &O) {
77      int value = MI->getOperand(OpNo).getImm();
78      O << -value;
79    }
80
81    void printMEMriOperand(const MachineInstr *MI, unsigned OpNo,
82                                  raw_ostream &O) {
83      const MachineOperand &MO1 = MI->getOperand(OpNo);
84      const MachineOperand &MO2 = MI->getOperand(OpNo+1);
85
86      O << getRegisterName(MO1.getReg())
87        << " + #"
88        << (int) MO2.getImm();
89    }
90
91    void printFrameIndexOperand(const MachineInstr *MI, unsigned OpNo,
92                                       raw_ostream &O) {
93      const MachineOperand &MO1 = MI->getOperand(OpNo);
94      const MachineOperand &MO2 = MI->getOperand(OpNo+1);
95
96      O << getRegisterName(MO1.getReg())
97        << ", #"
98        << MO2.getImm();
99    }
100
101    void printBranchOperand(const MachineInstr *MI, unsigned OpNo,
102                            raw_ostream &O) {
103      // Branches can take an immediate operand.  This is used by the branch
104      // selection pass to print $+8, an eight byte displacement from the PC.
105      if (MI->getOperand(OpNo).isImm()) {
106        O << "$+" << MI->getOperand(OpNo).getImm()*4;
107      } else {
108        printOp(MI->getOperand(OpNo), O);
109      }
110    }
111
112    void printCallOperand(const MachineInstr *MI, unsigned OpNo,
113                          raw_ostream &O) {
114    }
115
116    void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo,
117                             raw_ostream &O) {
118    }
119
120    void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
121      O << "#HI(";
122      if (MI->getOperand(OpNo).isImm()) {
123        printImmOperand(MI, OpNo, O);
124      }
125      else {
126        printOp(MI->getOperand(OpNo), O);
127      }
128      O << ")";
129    }
130
131    void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
132      O << "#HI(";
133      if (MI->getOperand(OpNo).isImm()) {
134        printImmOperand(MI, OpNo, O);
135      }
136      else {
137        printOp(MI->getOperand(OpNo), O);
138      }
139      O << ")";
140    }
141
142    void printPredicateOperand(const MachineInstr *MI, unsigned OpNo,
143                               raw_ostream &O);
144
145#if 0
146    void printModuleLevelGV(const GlobalVariable* GVar, raw_ostream &O);
147#endif
148
149    void printAddrModeBasePlusOffset(const MachineInstr *MI, int OpNo,
150                                     raw_ostream &O);
151
152    void printGlobalOperand(const MachineInstr *MI, int OpNo, raw_ostream &O);
153    void printJumpTable(const MachineInstr *MI, int OpNo, raw_ostream &O);
154    void printConstantPool(const MachineInstr *MI, int OpNo, raw_ostream &O);
155
156    static const char *getRegisterName(unsigned RegNo);
157
158#if 0
159    void EmitStartOfAsmFile(Module &M);
160#endif
161  };
162
163} // end of llvm namespace
164
165#endif
166