LLVM 20.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/MCExpr.h"
31#include "llvm/MC/MCInst.h"
32#include "llvm/MC/MCInstrInfo.h"
33#include "llvm/MC/MCSymbol.h"
36
37using namespace llvm;
38
39#define DEBUG_TYPE "asm-printer"
40
41#define PRINT_ALIAS_INSTR
42#include "M68kGenAsmWriter.inc"
43
45 OS << "%" << getRegisterName(Reg);
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
57void 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
74void 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
86void 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
139void 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// NOTE forcing (W,L) size available since M68020 only
151void M68kInstPrinter::printAbsMem(const MCInst *MI, unsigned opNum,
152 raw_ostream &O) {
153 const MCOperand &MO = MI->getOperand(opNum);
154
155 if (MO.isExpr()) {
156 MO.getExpr()->print(O, &MAI);
157 return;
158 }
159
160 assert(MO.isImm() && "absolute memory addressing needs an immediate");
161 O << format("$%0" PRIx64, (uint64_t)MO.getImm());
162}
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.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file contains some functions that are useful when dealing with strings.
This class represents an Operation in the Expression.
bool print(raw_ostream &OS, DIDumpOptions DumpOpts, const DWARFExpression *Expr, DWARFUnit *U) const
bool printAliasInstr(const MCInst *MI, uint64_t Address, raw_ostream &OS)
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 printRegName(raw_ostream &OS, MCRegister Reg) const override
Print the assembler register name.
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O)
static const char * getRegisterName(MCRegister Reg)
void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const
Definition: MCExpr.cpp:40
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
const MCAsmInfo & MAI
Definition: MCInstPrinter.h:51
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
int64_t getImm() const
Definition: MCInst.h:80
bool isImm() const
Definition: MCInst.h:62
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
bool isReg() const
Definition: MCInst.h:61
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Generic base class for all target subtargets.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#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.
Definition: BitmaskEnum.h:121
static unsigned getMaskedSpillRegister(unsigned order)
Definition: M68kBaseInfo.h:280
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125