LLVM  14.0.0git
M68kInstPrinter.cpp
Go to the documentation of this file.
1 //===-- M68kInstPrinter.cpp - Convert M68k MCInst to asm ----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file contains definitions for an M68k MCInst printer.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 // TODO Conform with all supported Motorola ASM syntax
15 // Motorola's assembly has several syntax variants, especially on
16 // addressing modes.
17 // For example, you can write pc indirect w/ displacement as
18 // `x(%pc)`, where `x` is the displacement imm, or `(x,%pc)`.
19 // Currently we're picking the variant that is different from
20 // GCC, albeit being recognizable by GNU AS.
21 // Not sure what is the impact now (e.g. some syntax might
22 // not be recognized by some old consoles' toolchains, in which
23 // case we can not use our integrated assembler), but either way,
24 // it will be great to support all of the variants in the future.
25 
26 #include "M68kInstPrinter.h"
27 #include "M68kBaseInfo.h"
28 
29 #include "llvm/ADT/StringExtras.h"
30 #include "llvm/MC/MCExpr.h"
31 #include "llvm/MC/MCInst.h"
32 #include "llvm/MC/MCInstrInfo.h"
33 #include "llvm/MC/MCSymbol.h"
36 
37 using namespace llvm;
38 
39 #define DEBUG_TYPE "asm-printer"
40 
41 #define PRINT_ALIAS_INSTR
42 #include "M68kGenAsmWriter.inc"
43 
44 void M68kInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
45  OS << "%" << getRegisterName(RegNo);
46 }
47 
49  StringRef Annot, const MCSubtargetInfo &STI,
50  raw_ostream &O) {
51  if (!printAliasInstr(MI, Address, O))
53 
54  printAnnotation(O, Annot);
55 }
56 
57 void M68kInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
58  raw_ostream &O) {
59  const MCOperand &MO = MI->getOperand(OpNo);
60  if (MO.isReg()) {
61  printRegName(O, MO.getReg());
62  return;
63  }
64 
65  if (MO.isImm()) {
66  printImmediate(MI, OpNo, O);
67  return;
68  }
69 
70  assert(MO.isExpr() && "Unknown operand kind in printOperand");
71  MO.getExpr()->print(O, &MAI);
72 }
73 
74 void M68kInstPrinter::printImmediate(const MCInst *MI, unsigned opNum,
75  raw_ostream &O) {
76  const MCOperand &MO = MI->getOperand(opNum);
77  if (MO.isImm())
78  O << '#' << MO.getImm();
79  else if (MO.isExpr()) {
80  O << '#';
81  MO.getExpr()->print(O, &MAI);
82  } else
83  llvm_unreachable("Unknown immediate kind");
84 }
85 
86 void M68kInstPrinter::printMoveMask(const MCInst *MI, unsigned opNum,
87  raw_ostream &O) {
88  unsigned Mask = MI->getOperand(opNum).getImm();
89  assert((Mask & 0xFFFF) == Mask && "Mask is always 16 bits");
90 
91  // A move mask is splitted into two parts:
92  // bits 0 ~ 7 correspond to D0 ~ D7 regs
93  // bits 8 ~ 15 correspond to A0 ~ A7 regs
94  //
95  // In the assembly syntax, we want to use a dash to replace
96  // a continuous range of registers. For example, if the bit
97  // mask is 0b101110, we want to print "D1-D3,D5" instead of
98  // "D1,D2,D3,D4,D5".
99  //
100  // However, we don't want a dash to cross between data registers
101  // and address registers (i.e. there shouldn't be a dash crossing
102  // bit 7 and 8) since that is not really intuitive. So we simply
103  // print the data register part (bit 0~7) and address register part
104  // separately.
105  uint8_t HalfMask;
106  unsigned Reg;
107  for (int s = 0; s < 16; s += 8) {
108  HalfMask = (Mask >> s) & 0xFF;
109  // Print separation comma only if
110  // both data & register parts have bit(s) set
111  if (s != 0 && (Mask & 0xFF) && HalfMask)
112  O << '/';
113 
114  for (int i = 0; HalfMask; ++i) {
115  if ((HalfMask >> i) & 0b1) {
116  HalfMask ^= 0b1 << i;
118  printRegName(O, Reg);
119 
120  int j = i;
121  while ((HalfMask >> (j + 1)) & 0b1)
122  HalfMask ^= 0b1 << ++j;
123 
124  if (j != i) {
125  O << '-';
127  printRegName(O, Reg);
128  }
129 
130  i = j;
131 
132  if (HalfMask)
133  O << '/';
134  }
135  }
136  }
137 }
138 
139 void M68kInstPrinter::printDisp(const MCInst *MI, unsigned opNum,
140  raw_ostream &O) {
141  const MCOperand &Op = MI->getOperand(opNum);
142  if (Op.isImm()) {
143  O << Op.getImm();
144  return;
145  }
146  assert(Op.isExpr() && "Unknown operand kind in printOperand");
147  Op.getExpr()->print(O, &MAI);
148 }
149 
150 void M68kInstPrinter::printARIMem(const MCInst *MI, unsigned opNum,
151  raw_ostream &O) {
152  O << '(';
153  printOperand(MI, opNum, O);
154  O << ')';
155 }
156 
157 void M68kInstPrinter::printARIPIMem(const MCInst *MI, unsigned opNum,
158  raw_ostream &O) {
159  O << "(";
160  printOperand(MI, opNum, O);
161  O << ")+";
162 }
163 
164 void M68kInstPrinter::printARIPDMem(const MCInst *MI, unsigned opNum,
165  raw_ostream &O) {
166  O << "-(";
167  printOperand(MI, opNum, O);
168  O << ")";
169 }
170 
171 void M68kInstPrinter::printARIDMem(const MCInst *MI, unsigned opNum,
172  raw_ostream &O) {
173  O << '(';
174  printDisp(MI, opNum + M68k::MemDisp, O);
175  O << ',';
176  printOperand(MI, opNum + M68k::MemBase, O);
177  O << ')';
178 }
179 
180 void M68kInstPrinter::printARIIMem(const MCInst *MI, unsigned opNum,
181  raw_ostream &O) {
182  O << '(';
183  printDisp(MI, opNum + M68k::MemDisp, O);
184  O << ',';
185  printOperand(MI, opNum + M68k::MemBase, O);
186  O << ',';
187  printOperand(MI, opNum + M68k::MemIndex, O);
188  O << ')';
189 }
190 
191 // NOTE forcing (W,L) size available since M68020 only
192 void M68kInstPrinter::printAbsMem(const MCInst *MI, unsigned opNum,
193  raw_ostream &O) {
194  const MCOperand &MO = MI->getOperand(opNum);
195 
196  if (MO.isExpr()) {
197  MO.getExpr()->print(O, &MAI);
198  return;
199  }
200 
201  assert(MO.isImm() && "absolute memory addressing needs an immediate");
202  O << format("$%0" PRIx64, (uint64_t)MO.getImm());
203 }
204 
205 void M68kInstPrinter::printPCDMem(const MCInst *MI, uint64_t Address,
206  unsigned opNum, raw_ostream &O) {
207  O << '(';
208  printDisp(MI, opNum + M68k::PCRelDisp, O);
209  O << ",%pc)";
210 }
211 
212 void M68kInstPrinter::printPCIMem(const MCInst *MI, uint64_t Address,
213  unsigned opNum, raw_ostream &O) {
214  O << '(';
215  printDisp(MI, opNum + M68k::PCRelDisp, O);
216  O << ",%pc,";
217  printOperand(MI, opNum + M68k::PCRelIndex, O);
218  O << ')';
219 }
i
i
Definition: README.txt:29
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:103
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
Reg
unsigned Reg
Definition: MachineSink.cpp:1566
llvm::MCOperand::isReg
bool isReg() const
Definition: MCInst.h:61
llvm::M68k::MemBase
@ MemBase
Definition: M68kBaseInfo.h:41
ErrorHandling.h
llvm::M68k::PCRelIndex
@ PCRelIndex
Definition: M68kBaseInfo.h:48
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
llvm::BitmaskEnumDetail::Mask
std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:80
llvm::M68kInstPrinter::printInst
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &O) override
Print the specified MCInst to the specified raw_ostream.
Definition: M68kInstPrinter.cpp:48
MCInstrInfo.h
llvm::MCOperand::getImm
int64_t getImm() const
Definition: MCInst.h:80
MCSymbol.h
llvm::M68kInstPrinter::printRegName
void printRegName(raw_ostream &OS, unsigned RegNo) const override
Print the assembler register name.
Definition: M68kInstPrinter.cpp:44
llvm::M68k::MemIndex
@ MemIndex
Definition: M68kBaseInfo.h:41
MCInst.h
llvm::M68kInstPrinter::getRegisterName
static const char * getRegisterName(unsigned RegNo)
llvm::M68kInstPrinter::printAliasInstr
bool printAliasInstr(const MCInst *MI, uint64_t Address, raw_ostream &OS)
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::MCInstPrinter::printAnnotation
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
Definition: MCInstPrinter.cpp:49
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:192
llvm::MCOperand::isImm
bool isImm() const
Definition: MCInst.h:62
uint64_t
s
multiplies can be turned into SHL s
Definition: README.txt:370
StringExtras.h
llvm::HighlightColor::Address
@ Address
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::M68k::PCRelDisp
@ PCRelDisp
Definition: M68kBaseInfo.h:48
b1
int b1
Definition: README.txt:84
llvm::M68kInstPrinter::printInstruction
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O)
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::M68k::MemDisp
@ MemDisp
Definition: M68kBaseInfo.h:41
j
return j(j<< 16)
llvm::M68kII::getMaskedSpillRegister
static unsigned getMaskedSpillRegister(unsigned order)
Definition: M68kBaseInfo.h:204
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:321
llvm::MCOperand::getExpr
const MCExpr * getExpr() const
Definition: MCInst.h:114
llvm::MCOperand::isExpr
bool isExpr() const
Definition: MCInst.h:65
llvm::MCInstPrinter::MAI
const MCAsmInfo & MAI
Definition: MCInstPrinter.h:49
llvm::MCExpr::print
void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const
Definition: MCExpr.cpp:42
M68kBaseInfo.h
llvm::MCOperand
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
M68kInstPrinter.h
raw_ostream.h
MCExpr.h
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:75
llvm::MCOperand::getReg
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69