SparcInstPrinter.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===-- SparcInstPrinter.cpp - Convert Sparc 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 Sparc MCInst to a .s file.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "asm-printer"
15#include "SparcInstPrinter.h"
16#include "Sparc.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
19#include "llvm/MC/MCSymbol.h"
20#include "llvm/Support/raw_ostream.h"
21using namespace llvm;
22
23// The generated AsmMatcher SparcGenAsmWriter uses "Sparc" as the target
24// namespace. But SPARC backend uses "SP" as its namespace.
25namespace llvm {
26namespace Sparc {
27  using namespace SP;
28}
29}
30
31#define GET_INSTRUCTION_NAME
32#define PRINT_ALIAS_INSTR
33#include "SparcGenAsmWriter.inc"
34
35bool SparcInstPrinter::isV9() const {
36  return (STI.getFeatureBits() & Sparc::FeatureV9) != 0;
37}
38
39void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
40{
41  OS << '%' << StringRef(getRegisterName(RegNo)).lower();
42}
43
44void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
45                               StringRef Annot)
46{
47  if (!printAliasInstr(MI, O) && !printSparcAliasInstr(MI, O))
48    printInstruction(MI, O);
49  printAnnotation(O, Annot);
50}
51
52bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O)
53{
54  switch (MI->getOpcode()) {
55  default: return false;
56  case SP::JMPLrr:
57  case SP::JMPLri: {
58    if (MI->getNumOperands() != 3)
59      return false;
60    if (!MI->getOperand(0).isReg())
61      return false;
62    switch (MI->getOperand(0).getReg()) {
63    default: return false;
64    case SP::G0: // jmp $addr | ret | retl
65      if (MI->getOperand(2).isImm() &&
66          MI->getOperand(2).getImm() == 8) {
67        switch(MI->getOperand(1).getReg()) {
68        default: break;
69        case SP::I7: O << "\tret"; return true;
70        case SP::O7: O << "\tretl"; return true;
71        }
72      }
73      O << "\tjmp "; printMemOperand(MI, 1, O);
74      return true;
75    case SP::O7: // call $addr
76      O << "\tcall "; printMemOperand(MI, 1, O);
77      return true;
78    }
79  }
80  case SP::V9FCMPS:  case SP::V9FCMPD:  case SP::V9FCMPQ:
81  case SP::V9FCMPES: case SP::V9FCMPED: case SP::V9FCMPEQ: {
82    if (isV9()
83        || (MI->getNumOperands() != 3)
84        || (!MI->getOperand(0).isReg())
85        || (MI->getOperand(0).getReg() != SP::FCC0))
86      return false;
87    // if V8, skip printing %fcc0.
88    switch(MI->getOpcode()) {
89    default:
90    case SP::V9FCMPS:  O << "\tfcmps "; break;
91    case SP::V9FCMPD:  O << "\tfcmpd "; break;
92    case SP::V9FCMPQ:  O << "\tfcmpq "; break;
93    case SP::V9FCMPES: O << "\tfcmpes "; break;
94    case SP::V9FCMPED: O << "\tfcmped "; break;
95    case SP::V9FCMPEQ: O << "\tfcmpeq "; break;
96    }
97    printOperand(MI, 1, O);
98    O << ", ";
99    printOperand(MI, 2, O);
100    return true;
101  }
102  }
103}
104
105void SparcInstPrinter::printOperand(const MCInst *MI, int opNum,
106                                    raw_ostream &O)
107{
108  const MCOperand &MO = MI->getOperand (opNum);
109
110  if (MO.isReg()) {
111    printRegName(O, MO.getReg());
112    return ;
113  }
114
115  if (MO.isImm()) {
116    O << (int)MO.getImm();
117    return;
118  }
119
120  assert(MO.isExpr() && "Unknown operand kind in printOperand");
121  MO.getExpr()->print(O);
122}
123
124void SparcInstPrinter::printMemOperand(const MCInst *MI, int opNum,
125                                      raw_ostream &O, const char *Modifier)
126{
127  printOperand(MI, opNum, O);
128
129  // If this is an ADD operand, emit it like normal operands.
130  if (Modifier && !strcmp(Modifier, "arith")) {
131    O << ", ";
132    printOperand(MI, opNum+1, O);
133    return;
134  }
135  const MCOperand &MO = MI->getOperand(opNum+1);
136
137  if (MO.isReg() && MO.getReg() == SP::G0)
138    return;   // don't print "+%g0"
139  if (MO.isImm() && MO.getImm() == 0)
140    return;   // don't print "+0"
141
142  O << "+";
143
144  printOperand(MI, opNum+1, O);
145}
146
147void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum,
148                                     raw_ostream &O)
149{
150  int CC = (int)MI->getOperand(opNum).getImm();
151  switch (MI->getOpcode()) {
152  default: break;
153  case SP::FBCOND:
154  case SP::FBCONDA:
155  case SP::BPFCC:
156  case SP::BPFCCA:
157  case SP::BPFCCNT:
158  case SP::BPFCCANT:
159  case SP::MOVFCCrr:  case SP::V9MOVFCCrr:
160  case SP::MOVFCCri:  case SP::V9MOVFCCri:
161  case SP::FMOVS_FCC: case SP::V9FMOVS_FCC:
162  case SP::FMOVD_FCC: case SP::V9FMOVD_FCC:
163  case SP::FMOVQ_FCC: case SP::V9FMOVQ_FCC:
164    // Make sure CC is a fp conditional flag.
165    CC = (CC < 16) ? (CC + 16) : CC;
166    break;
167  }
168  O << SPARCCondCodeToString((SPCC::CondCodes)CC);
169}
170
171bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum,
172                                  raw_ostream &O)
173{
174  assert(0 && "FIXME: Implement SparcInstPrinter::printGetPCX.");
175  return true;
176}
177