1 //===-- M68kAsmPrinter.cpp - M68k LLVM Assembly Printer ---------*- 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 a printer that converts from our internal representation
11 /// of machine-dependent LLVM code to GAS-format M68k assembly language.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 // TODO Conform to Motorola ASM syntax
16
17 #include "M68kAsmPrinter.h"
18
19 #include "M68k.h"
20 #include "M68kMachineFunction.h"
21 #include "MCTargetDesc/M68kInstPrinter.h"
22 #include "TargetInfo/M68kTargetInfo.h"
23
24 #include "llvm/MC/TargetRegistry.h"
25
26 using namespace llvm;
27
28 #define DEBUG_TYPE "m68k-asm-printer"
29
runOnMachineFunction(MachineFunction & MF)30 bool M68kAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
31 MMFI = MF.getInfo<M68kMachineFunctionInfo>();
32 MCInstLowering = std::make_unique<M68kMCInstLower>(MF, *this);
33 AsmPrinter::runOnMachineFunction(MF);
34 return true;
35 }
36
printOperand(const MachineInstr * MI,int OpNum,raw_ostream & OS)37 void M68kAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
38 raw_ostream &OS) {
39 const MachineOperand &MO = MI->getOperand(OpNum);
40 switch (MO.getType()) {
41 case MachineOperand::MO_Register:
42 OS << "%" << M68kInstPrinter::getRegisterName(MO.getReg());
43 break;
44 case MachineOperand::MO_Immediate:
45 OS << '#' << MO.getImm();
46 break;
47 case MachineOperand::MO_MachineBasicBlock:
48 MO.getMBB()->getSymbol()->print(OS, MAI);
49 break;
50 case MachineOperand::MO_GlobalAddress:
51 PrintSymbolOperand(MO, OS);
52 break;
53 case MachineOperand::MO_BlockAddress:
54 GetBlockAddressSymbol(MO.getBlockAddress())->print(OS, MAI);
55 break;
56 case MachineOperand::MO_ConstantPoolIndex: {
57 const DataLayout &DL = getDataLayout();
58 OS << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
59 << MO.getIndex();
60 break;
61 }
62 default:
63 llvm_unreachable("not implemented");
64 }
65 }
66
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & OS)67 bool M68kAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
68 const char *ExtraCode, raw_ostream &OS) {
69 // Print the operand if there is no operand modifier.
70 if (!ExtraCode || !ExtraCode[0]) {
71 printOperand(MI, OpNo, OS);
72 return false;
73 }
74
75 // Fallback to the default implementation.
76 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
77 }
78
printDisp(const MachineInstr * MI,unsigned opNum,raw_ostream & O)79 void M68kAsmPrinter::printDisp(const MachineInstr *MI, unsigned opNum,
80 raw_ostream &O) {
81 // Print immediate displacement without the '#' predix
82 const MachineOperand &Op = MI->getOperand(opNum);
83 if (Op.isImm()) {
84 O << Op.getImm();
85 return;
86 }
87 // Displacement is relocatable, so we're pretty permissive about what
88 // can be put here.
89 printOperand(MI, opNum, O);
90 }
91
printAbsMem(const MachineInstr * MI,unsigned OpNum,raw_ostream & O)92 void M68kAsmPrinter::printAbsMem(const MachineInstr *MI, unsigned OpNum,
93 raw_ostream &O) {
94 const MachineOperand &MO = MI->getOperand(OpNum);
95 if (MO.isImm())
96 O << format("$%0" PRIx64, (uint64_t)MO.getImm());
97 else
98 PrintAsmMemoryOperand(MI, OpNum, nullptr, O);
99 }
100
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & OS)101 bool M68kAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
102 unsigned OpNo, const char *ExtraCode,
103 raw_ostream &OS) {
104 const MachineOperand &MO = MI->getOperand(OpNo);
105 switch (MO.getType()) {
106 case MachineOperand::MO_Immediate:
107 // Immediate value that goes here is the addressing mode kind we set
108 // in M68kDAGToDAGISel::SelectInlineAsmMemoryOperand.
109 using namespace M68k;
110 // Skip the addressing mode kind operand.
111 ++OpNo;
112 // Decode MemAddrModeKind.
113 switch (static_cast<MemAddrModeKind>(MO.getImm())) {
114 case MemAddrModeKind::j:
115 printARIMem(MI, OpNo, OS);
116 break;
117 case MemAddrModeKind::o:
118 printARIPIMem(MI, OpNo, OS);
119 break;
120 case MemAddrModeKind::e:
121 printARIPDMem(MI, OpNo, OS);
122 break;
123 case MemAddrModeKind::p:
124 printARIDMem(MI, OpNo, OS);
125 break;
126 case MemAddrModeKind::f:
127 case MemAddrModeKind::F:
128 printARIIMem(MI, OpNo, OS);
129 break;
130 case MemAddrModeKind::k:
131 printPCIMem(MI, 0, OpNo, OS);
132 break;
133 case MemAddrModeKind::q:
134 printPCDMem(MI, 0, OpNo, OS);
135 break;
136 case MemAddrModeKind::b:
137 printAbsMem(MI, OpNo, OS);
138 break;
139 default:
140 llvm_unreachable("Unrecognized memory addressing mode");
141 }
142 return false;
143 case MachineOperand::MO_GlobalAddress:
144 PrintSymbolOperand(MO, OS);
145 return false;
146 case MachineOperand::MO_BlockAddress:
147 GetBlockAddressSymbol(MO.getBlockAddress())->print(OS, MAI);
148 return false;
149 case MachineOperand::MO_Register:
150 // This is a special case where it is treated as a memory reference, with
151 // the register holding the address value. Thus, we print it as ARI here.
152 if (M68kII::isAddressRegister(MO.getReg())) {
153 printARIMem(MI, OpNo, OS);
154 return false;
155 }
156 break;
157 default:
158 break;
159 }
160 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
161 }
162
emitInstruction(const MachineInstr * MI)163 void M68kAsmPrinter::emitInstruction(const MachineInstr *MI) {
164 M68k_MC::verifyInstructionPredicates(MI->getOpcode(),
165 getSubtargetInfo().getFeatureBits());
166
167 switch (MI->getOpcode()) {
168 default: {
169 if (MI->isPseudo()) {
170 LLVM_DEBUG(dbgs() << "Pseudo opcode(" << MI->getOpcode()
171 << ") found in EmitInstruction()\n");
172 llvm_unreachable("Cannot proceed");
173 }
174 break;
175 }
176 case M68k::TAILJMPj:
177 case M68k::TAILJMPq:
178 // Lower these as normal, but add some comments.
179 OutStreamer->AddComment("TAILCALL");
180 break;
181 }
182
183 MCInst TmpInst0;
184 MCInstLowering->Lower(MI, TmpInst0);
185 OutStreamer->emitInstruction(TmpInst0, getSubtargetInfo());
186 }
187
emitFunctionBodyStart()188 void M68kAsmPrinter::emitFunctionBodyStart() {}
189
emitFunctionBodyEnd()190 void M68kAsmPrinter::emitFunctionBodyEnd() {}
191
emitStartOfAsmFile(Module & M)192 void M68kAsmPrinter::emitStartOfAsmFile(Module &M) {
193 OutStreamer->emitSyntaxDirective();
194 }
195
emitEndOfAsmFile(Module & M)196 void M68kAsmPrinter::emitEndOfAsmFile(Module &M) {}
197
LLVMInitializeM68kAsmPrinter()198 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmPrinter() {
199 RegisterAsmPrinter<M68kAsmPrinter> X(getTheM68kTarget());
200 }
201