LLVM 23.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
30#include "llvm/MC/MCAsmInfo.h"
31#include "llvm/MC/MCExpr.h"
32#include "llvm/MC/MCInst.h"
33#include "llvm/MC/MCInstrInfo.h"
34#include "llvm/MC/MCSymbol.h"
37
38using namespace llvm;
39
40#define DEBUG_TYPE "asm-printer"
41
42#define PRINT_ALIAS_INSTR
43#include "M68kGenAsmWriter.inc"
44
46 OS << "%" << getRegisterName(Reg);
47}
48
50 StringRef Annot, const MCSubtargetInfo &STI,
51 raw_ostream &O) {
52 if (!printAliasInstr(MI, Address, O))
54
55 printAnnotation(O, Annot);
56}
57
58void M68kInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
59 raw_ostream &O) {
60 const MCOperand &MO = MI->getOperand(OpNo);
61 if (MO.isReg()) {
62 MCRegister Reg = MO.getReg();
63 if (Reg.isValid())
64 printRegName(O, Reg);
65 return;
66 }
67
68 if (MO.isImm()) {
69 printImmediate(MI, OpNo, O);
70 return;
71 }
72
73 assert(MO.isExpr() && "Unknown operand kind in printOperand");
74 MAI.printExpr(O, *MO.getExpr());
75}
76
77void M68kInstPrinter::printImmediate(const MCInst *MI, unsigned opNum,
78 raw_ostream &O) {
79 const MCOperand &MO = MI->getOperand(opNum);
80 if (MO.isImm())
81 O << '#' << MO.getImm();
82 else if (MO.isExpr()) {
83 O << '#';
84 MAI.printExpr(O, *MO.getExpr());
85 } else
86 llvm_unreachable("Unknown immediate kind");
87}
88
89void M68kInstPrinter::printMoveMask(const MCInst *MI, unsigned opNum,
90 raw_ostream &O) {
91 unsigned Mask = MI->getOperand(opNum).getImm();
92 assert((Mask & 0xFFFF) == Mask && "Mask is always 16 bits");
93
94 // A move mask is splitted into two parts:
95 // bits 0 ~ 7 correspond to D0 ~ D7 regs
96 // bits 8 ~ 15 correspond to A0 ~ A7 regs
97 //
98 // In the assembly syntax, we want to use a dash to replace
99 // a continuous range of registers. For example, if the bit
100 // mask is 0b101110, we want to print "D1-D3,D5" instead of
101 // "D1,D2,D3,D4,D5".
102 //
103 // However, we don't want a dash to cross between data registers
104 // and address registers (i.e. there shouldn't be a dash crossing
105 // bit 7 and 8) since that is not really intuitive. So we simply
106 // print the data register part (bit 0~7) and address register part
107 // separately.
108 uint8_t HalfMask;
109 unsigned Reg;
110 for (int s = 0; s < 16; s += 8) {
111 HalfMask = (Mask >> s) & 0xFF;
112 // Print separation comma only if
113 // both data & register parts have bit(s) set
114 if (s != 0 && (Mask & 0xFF) && HalfMask)
115 O << '/';
116
117 for (int i = 0; HalfMask; ++i) {
118 if ((HalfMask >> i) & 0b1) {
119 HalfMask ^= 0b1 << i;
121 printRegName(O, Reg);
122
123 int j = i;
124 while ((HalfMask >> (j + 1)) & 0b1)
125 HalfMask ^= 0b1 << ++j;
126
127 if (j != i) {
128 O << '-';
130 printRegName(O, Reg);
131 }
132
133 i = j;
134
135 if (HalfMask)
136 O << '/';
137 }
138 }
139 }
140}
141
142void M68kInstPrinter::printDisp(const MCInst *MI, unsigned opNum,
143 raw_ostream &O) {
144 const MCOperand &Op = MI->getOperand(opNum);
145 if (Op.isImm()) {
146 O << Op.getImm();
147 return;
148 }
149 assert(Op.isExpr() && "Unknown operand kind in printOperand");
150 MAI.printExpr(O, *Op.getExpr());
151}
152
153void M68kInstPrinter::printScale(const MCInst *MI, unsigned opNum,
154 raw_ostream &O) {
155 const MCOperand &Op = MI->getOperand(opNum);
156 // Scale has to be an immediate.
157 unsigned Scale = Op.getImm();
158 // We only print it out when it's larger than 1
159 if (Scale > 1)
160 O << "*" << Scale;
161}
162
163// NOTE forcing (W,L) size available since M68020 only
164void M68kInstPrinter::printAbsMem(const MCInst *MI, unsigned opNum,
165 raw_ostream &O) {
166 const MCOperand &MO = MI->getOperand(opNum);
167
168 if (MO.isExpr()) {
169 MAI.printExpr(O, *MO.getExpr());
170 return;
171 }
172
173 assert(MO.isImm() && "absolute memory addressing needs an immediate");
174 O << format("$%0" PRIx64, (uint64_t)MO.getImm());
175}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
IRTranslator LLVM IR MI
This file contains small standalone helper functions and enum definitions for the M68k target useful ...
This file contains declarations for an M68k MCInst printer.
Register Reg
This file contains some functions that are useful when dealing with strings.
bool printAliasInstr(const MCInst *MI, uint64_t Address, raw_ostream &OS)
void printRegName(raw_ostream &OS, MCRegister Reg) override
Print the assembler register name.
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.
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O)
static const char * getRegisterName(MCRegister Reg)
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
const MCAsmInfo & MAI
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
int64_t getImm() const
Definition MCInst.h:84
bool isImm() const
Definition MCInst.h:66
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
Generic base class for all target subtargets.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr 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.
static unsigned getMaskedSpillRegister(unsigned order)
This is an optimization pass for GlobalISel generic memory operations.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:129
DWARFExpression::Operation Op