1351278Sdim//===- ARCInstPrinter.cpp - ARC MCInst to assembly syntax -------*- C++ -*-===//
2351278Sdim//
3351278Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4351278Sdim// See https://llvm.org/LICENSE.txt for license information.
5351278Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6351278Sdim//
7351278Sdim//===----------------------------------------------------------------------===//
8351278Sdim//
9351278Sdim// This class prints an ARC MCInst to a .s file.
10351278Sdim//
11351278Sdim//===----------------------------------------------------------------------===//
12351278Sdim
13351278Sdim#include "ARCInstPrinter.h"
14351278Sdim#include "MCTargetDesc/ARCInfo.h"
15351278Sdim#include "llvm/ADT/StringExtras.h"
16351278Sdim#include "llvm/MC/MCExpr.h"
17351278Sdim#include "llvm/MC/MCInst.h"
18351278Sdim#include "llvm/MC/MCInstrInfo.h"
19351278Sdim#include "llvm/MC/MCSymbol.h"
20351278Sdim#include "llvm/Support/Casting.h"
21351278Sdim#include "llvm/Support/Debug.h"
22351278Sdim#include "llvm/Support/raw_ostream.h"
23351278Sdim
24351278Sdimusing namespace llvm;
25351278Sdim
26351278Sdim#define DEBUG_TYPE "asm-printer"
27351278Sdim
28351278Sdim#include "ARCGenAsmWriter.inc"
29351278Sdim
30351278Sdimtemplate <class T>
31351278Sdimstatic const char *BadConditionCode(T cc) {
32351278Sdim  LLVM_DEBUG(dbgs() << "Unknown condition code passed: " << cc << "\n");
33351278Sdim  return "{unknown-cc}";
34351278Sdim}
35351278Sdim
36351278Sdimstatic const char *ARCBRCondCodeToString(ARCCC::BRCondCode BRCC) {
37351278Sdim  switch (BRCC) {
38351278Sdim  case ARCCC::BREQ:
39351278Sdim    return "eq";
40351278Sdim  case ARCCC::BRNE:
41351278Sdim    return "ne";
42351278Sdim  case ARCCC::BRLT:
43351278Sdim    return "lt";
44351278Sdim  case ARCCC::BRGE:
45351278Sdim    return "ge";
46351278Sdim  case ARCCC::BRLO:
47351278Sdim    return "lo";
48351278Sdim  case ARCCC::BRHS:
49351278Sdim    return "hs";
50351278Sdim  }
51351278Sdim  return BadConditionCode(BRCC);
52351278Sdim}
53351278Sdim
54351278Sdimstatic const char *ARCCondCodeToString(ARCCC::CondCode CC) {
55351278Sdim  switch (CC) {
56351278Sdim  case ARCCC::EQ:
57351278Sdim    return "eq";
58351278Sdim  case ARCCC::NE:
59351278Sdim    return "ne";
60351278Sdim  case ARCCC::P:
61351278Sdim    return "p";
62351278Sdim  case ARCCC::N:
63351278Sdim    return "n";
64351278Sdim  case ARCCC::HS:
65351278Sdim    return "hs";
66351278Sdim  case ARCCC::LO:
67351278Sdim    return "lo";
68351278Sdim  case ARCCC::GT:
69351278Sdim    return "gt";
70351278Sdim  case ARCCC::GE:
71351278Sdim    return "ge";
72351278Sdim  case ARCCC::VS:
73351278Sdim    return "vs";
74351278Sdim  case ARCCC::VC:
75351278Sdim    return "vc";
76351278Sdim  case ARCCC::LT:
77351278Sdim    return "lt";
78351278Sdim  case ARCCC::LE:
79351278Sdim    return "le";
80351278Sdim  case ARCCC::HI:
81351278Sdim    return "hi";
82351278Sdim  case ARCCC::LS:
83351278Sdim    return "ls";
84351278Sdim  case ARCCC::PNZ:
85351278Sdim    return "pnz";
86351278Sdim  case ARCCC::AL:
87351278Sdim    return "al";
88351278Sdim  case ARCCC::NZ:
89351278Sdim    return "nz";
90351278Sdim  case ARCCC::Z:
91351278Sdim    return "z";
92351278Sdim  }
93351278Sdim  return BadConditionCode(CC);
94351278Sdim}
95351278Sdim
96351278Sdimvoid ARCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
97351278Sdim  OS << StringRef(getRegisterName(RegNo)).lower();
98351278Sdim}
99351278Sdim
100360784Sdimvoid ARCInstPrinter::printInst(const MCInst *MI, uint64_t Address,
101360784Sdim                               StringRef Annot, const MCSubtargetInfo &STI,
102360784Sdim                               raw_ostream &O) {
103360784Sdim  printInstruction(MI, Address, O);
104351278Sdim  printAnnotation(O, Annot);
105351278Sdim}
106351278Sdim
107351278Sdimstatic void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI,
108351278Sdim                      raw_ostream &OS) {
109351278Sdim  int Offset = 0;
110351278Sdim  const MCSymbolRefExpr *SRE;
111351278Sdim
112351278Sdim  if (const auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
113351278Sdim    OS << "0x";
114351278Sdim    OS.write_hex(CE->getValue());
115351278Sdim    return;
116351278Sdim  }
117351278Sdim
118351278Sdim  if (const auto *BE = dyn_cast<MCBinaryExpr>(Expr)) {
119351278Sdim    SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
120351278Sdim    const auto *CE = dyn_cast<MCConstantExpr>(BE->getRHS());
121351278Sdim    assert(SRE && CE && "Binary expression must be sym+const.");
122351278Sdim    Offset = CE->getValue();
123351278Sdim  } else {
124351278Sdim    SRE = dyn_cast<MCSymbolRefExpr>(Expr);
125351278Sdim    assert(SRE && "Unexpected MCExpr type.");
126351278Sdim  }
127351278Sdim  assert(SRE->getKind() == MCSymbolRefExpr::VK_None);
128351278Sdim
129351278Sdim  // Symbols are prefixed with '@'
130351278Sdim  OS << '@';
131351278Sdim  SRE->getSymbol().print(OS, MAI);
132351278Sdim
133351278Sdim  if (Offset) {
134351278Sdim    if (Offset > 0)
135351278Sdim      OS << '+';
136351278Sdim    OS << Offset;
137351278Sdim  }
138351278Sdim}
139351278Sdim
140351278Sdimvoid ARCInstPrinter::printOperand(const MCInst *MI, unsigned OpNum,
141351278Sdim                                  raw_ostream &O) {
142351278Sdim  const MCOperand &Op = MI->getOperand(OpNum);
143351278Sdim  if (Op.isReg()) {
144351278Sdim    printRegName(O, Op.getReg());
145351278Sdim    return;
146351278Sdim  }
147351278Sdim
148351278Sdim  if (Op.isImm()) {
149351278Sdim    O << Op.getImm();
150351278Sdim    return;
151351278Sdim  }
152351278Sdim
153351278Sdim  assert(Op.isExpr() && "unknown operand kind in printOperand");
154351278Sdim  printExpr(Op.getExpr(), &MAI, O);
155351278Sdim}
156351278Sdim
157351278Sdimvoid ARCInstPrinter::printMemOperandRI(const MCInst *MI, unsigned OpNum,
158351278Sdim                                       raw_ostream &O) {
159351278Sdim  const MCOperand &base = MI->getOperand(OpNum);
160351278Sdim  const MCOperand &offset = MI->getOperand(OpNum + 1);
161351278Sdim  assert(base.isReg() && "Base should be register.");
162351278Sdim  assert(offset.isImm() && "Offset should be immediate.");
163351278Sdim  printRegName(O, base.getReg());
164351278Sdim  O << "," << offset.getImm();
165351278Sdim}
166351278Sdim
167351278Sdimvoid ARCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
168351278Sdim                                           raw_ostream &O) {
169351278Sdim
170351278Sdim  const MCOperand &Op = MI->getOperand(OpNum);
171351278Sdim  assert(Op.isImm() && "Predicate operand is immediate.");
172351278Sdim  O << ARCCondCodeToString((ARCCC::CondCode)Op.getImm());
173351278Sdim}
174351278Sdim
175351278Sdimvoid ARCInstPrinter::printBRCCPredicateOperand(const MCInst *MI, unsigned OpNum,
176351278Sdim                                               raw_ostream &O) {
177351278Sdim  const MCOperand &Op = MI->getOperand(OpNum);
178351278Sdim  assert(Op.isImm() && "Predicate operand is immediate.");
179351278Sdim  O << ARCBRCondCodeToString((ARCCC::BRCondCode)Op.getImm());
180351278Sdim}
181