1234285Sdim//===-- HexagonAsmPrinter.h - Print machine code to an Hexagon .s file ----===//
2234285Sdim//
3234285Sdim//                     The LLVM Compiler Infrastructure
4234285Sdim//
5234285Sdim// This file is distributed under the University of Illinois Open Source
6234285Sdim// License. See LICENSE.TXT for details.
7234285Sdim//
8234285Sdim//===----------------------------------------------------------------------===//
9234285Sdim//
10234285Sdim// Hexagon Assembly printer class.
11234285Sdim//
12234285Sdim//===----------------------------------------------------------------------===//
13234285Sdim
14234285Sdim#ifndef HEXAGONASMPRINTER_H
15234285Sdim#define HEXAGONASMPRINTER_H
16234285Sdim
17234285Sdim#include "Hexagon.h"
18234285Sdim#include "HexagonTargetMachine.h"
19234285Sdim#include "llvm/CodeGen/AsmPrinter.h"
20234285Sdim#include "llvm/Support/Compiler.h"
21234285Sdim#include "llvm/Support/raw_ostream.h"
22234285Sdim
23234285Sdimnamespace llvm {
24234285Sdim  class HexagonAsmPrinter : public AsmPrinter {
25234285Sdim    const HexagonSubtarget *Subtarget;
26234285Sdim
27234285Sdim  public:
28234285Sdim    explicit HexagonAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
29234285Sdim      : AsmPrinter(TM, Streamer) {
30234285Sdim      Subtarget = &TM.getSubtarget<HexagonSubtarget>();
31234285Sdim    }
32234285Sdim
33234285Sdim    virtual const char *getPassName() const {
34234285Sdim      return "Hexagon Assembly Printer";
35234285Sdim    }
36234285Sdim
37234285Sdim    bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const;
38234285Sdim
39234285Sdim    virtual void EmitInstruction(const MachineInstr *MI);
40234285Sdim    virtual void EmitAlignment(unsigned NumBits,
41234285Sdim                               const GlobalValue *GV = 0) const;
42234285Sdim
43234285Sdim    void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
44234285Sdim    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
45234285Sdim                         unsigned AsmVariant, const char *ExtraCode,
46234285Sdim                         raw_ostream &OS);
47234285Sdim    bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
48234285Sdim                               unsigned AsmVariant, const char *ExtraCode,
49234285Sdim                               raw_ostream &OS);
50234285Sdim
51234285Sdim    /// printInstruction - This method is automatically generated by tablegen
52234285Sdim    /// from the instruction set description.  This method returns true if the
53234285Sdim    /// machine instruction was sufficiently described to print it, otherwise it
54234285Sdim    /// returns false.
55234285Sdim    void printInstruction(const MachineInstr *MI, raw_ostream &O);
56234285Sdim
57234285Sdim    //    void printMachineInstruction(const MachineInstr *MI);
58234285Sdim    void printOp(const MachineOperand &MO, raw_ostream &O);
59234285Sdim
60234285Sdim    /// printRegister - Print register according to target requirements.
61234285Sdim    ///
62234285Sdim    void printRegister(const MachineOperand &MO, bool R0AsZero,
63234285Sdim                       raw_ostream &O) {
64234285Sdim      unsigned RegNo = MO.getReg();
65234285Sdim      assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??");
66234285Sdim      O << getRegisterName(RegNo);
67234285Sdim    }
68234285Sdim
69234285Sdim    void printImmOperand(const MachineInstr *MI, unsigned OpNo,
70234285Sdim                                raw_ostream &O) {
71234285Sdim      int value = MI->getOperand(OpNo).getImm();
72234285Sdim      O << value;
73234285Sdim    }
74234285Sdim
75234285Sdim    void printNegImmOperand(const MachineInstr *MI, unsigned OpNo,
76234285Sdim                                   raw_ostream &O) {
77234285Sdim      int value = MI->getOperand(OpNo).getImm();
78234285Sdim      O << -value;
79234285Sdim    }
80234285Sdim
81234285Sdim    void printMEMriOperand(const MachineInstr *MI, unsigned OpNo,
82234285Sdim                                  raw_ostream &O) {
83234285Sdim      const MachineOperand &MO1 = MI->getOperand(OpNo);
84234285Sdim      const MachineOperand &MO2 = MI->getOperand(OpNo+1);
85234285Sdim
86234285Sdim      O << getRegisterName(MO1.getReg())
87234285Sdim        << " + #"
88234285Sdim        << (int) MO2.getImm();
89234285Sdim    }
90234285Sdim
91234285Sdim    void printFrameIndexOperand(const MachineInstr *MI, unsigned OpNo,
92234285Sdim                                       raw_ostream &O) {
93234285Sdim      const MachineOperand &MO1 = MI->getOperand(OpNo);
94234285Sdim      const MachineOperand &MO2 = MI->getOperand(OpNo+1);
95234285Sdim
96234285Sdim      O << getRegisterName(MO1.getReg())
97234285Sdim        << ", #"
98234285Sdim        << MO2.getImm();
99234285Sdim    }
100234285Sdim
101234285Sdim    void printBranchOperand(const MachineInstr *MI, unsigned OpNo,
102234285Sdim                            raw_ostream &O) {
103234285Sdim      // Branches can take an immediate operand.  This is used by the branch
104234285Sdim      // selection pass to print $+8, an eight byte displacement from the PC.
105234285Sdim      if (MI->getOperand(OpNo).isImm()) {
106234285Sdim        O << "$+" << MI->getOperand(OpNo).getImm()*4;
107234285Sdim      } else {
108234285Sdim        printOp(MI->getOperand(OpNo), O);
109234285Sdim      }
110234285Sdim    }
111234285Sdim
112234285Sdim    void printCallOperand(const MachineInstr *MI, unsigned OpNo,
113234285Sdim                          raw_ostream &O) {
114234285Sdim    }
115234285Sdim
116234285Sdim    void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo,
117234285Sdim                             raw_ostream &O) {
118234285Sdim    }
119234285Sdim
120234285Sdim    void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
121234285Sdim      O << "#HI(";
122234285Sdim      if (MI->getOperand(OpNo).isImm()) {
123234285Sdim        printImmOperand(MI, OpNo, O);
124234285Sdim      }
125234285Sdim      else {
126234285Sdim        printOp(MI->getOperand(OpNo), O);
127234285Sdim      }
128234285Sdim      O << ")";
129234285Sdim    }
130234285Sdim
131234285Sdim    void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
132234285Sdim      O << "#HI(";
133234285Sdim      if (MI->getOperand(OpNo).isImm()) {
134234285Sdim        printImmOperand(MI, OpNo, O);
135234285Sdim      }
136234285Sdim      else {
137234285Sdim        printOp(MI->getOperand(OpNo), O);
138234285Sdim      }
139234285Sdim      O << ")";
140234285Sdim    }
141234285Sdim
142234285Sdim    void printPredicateOperand(const MachineInstr *MI, unsigned OpNo,
143234285Sdim                               raw_ostream &O);
144234285Sdim
145234285Sdim#if 0
146234285Sdim    void printModuleLevelGV(const GlobalVariable* GVar, raw_ostream &O);
147234285Sdim#endif
148234285Sdim
149234285Sdim    void printAddrModeBasePlusOffset(const MachineInstr *MI, int OpNo,
150234285Sdim                                     raw_ostream &O);
151234285Sdim
152234285Sdim    void printGlobalOperand(const MachineInstr *MI, int OpNo, raw_ostream &O);
153234285Sdim    void printJumpTable(const MachineInstr *MI, int OpNo, raw_ostream &O);
154234285Sdim    void printConstantPool(const MachineInstr *MI, int OpNo, raw_ostream &O);
155234285Sdim
156234285Sdim    static const char *getRegisterName(unsigned RegNo);
157234285Sdim
158234285Sdim#if 0
159234285Sdim    void EmitStartOfAsmFile(Module &M);
160234285Sdim#endif
161234285Sdim  };
162234285Sdim
163234285Sdim} // end of llvm namespace
164234285Sdim
165234285Sdim#endif
166