1 //===-- M68kAsmPrinter.cpp - M68k LLVM Assembly Printer ---------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file contains a printer that converts from our internal representation
11 /// of machine-dependent LLVM code to GAS-format M68k assembly language.
13 //===----------------------------------------------------------------------===//
15 // TODO Conform to Motorola ASM syntax
17 #include "M68kAsmPrinter.h"
20 #include "M68kMachineFunction.h"
21 #include "MCTargetDesc/M68kInstPrinter.h"
22 #include "TargetInfo/M68kTargetInfo.h"
24 #include "llvm/MC/TargetRegistry.h"
28 #define DEBUG_TYPE "m68k-asm-printer"
30 bool M68kAsmPrinter::runOnMachineFunction(MachineFunction
&MF
) {
31 MMFI
= MF
.getInfo
<M68kMachineFunctionInfo
>();
32 MCInstLowering
= std::make_unique
<M68kMCInstLower
>(MF
, *this);
33 AsmPrinter::runOnMachineFunction(MF
);
37 void M68kAsmPrinter::printOperand(const MachineInstr
*MI
, int OpNum
,
39 const MachineOperand
&MO
= MI
->getOperand(OpNum
);
40 switch (MO
.getType()) {
41 case MachineOperand::MO_Register
:
42 OS
<< "%" << M68kInstPrinter::getRegisterName(MO
.getReg());
44 case MachineOperand::MO_Immediate
:
45 OS
<< '#' << MO
.getImm();
47 case MachineOperand::MO_MachineBasicBlock
:
48 MO
.getMBB()->getSymbol()->print(OS
, MAI
);
50 case MachineOperand::MO_GlobalAddress
:
51 PrintSymbolOperand(MO
, OS
);
53 case MachineOperand::MO_BlockAddress
:
54 GetBlockAddressSymbol(MO
.getBlockAddress())->print(OS
, MAI
);
56 case MachineOperand::MO_ConstantPoolIndex
: {
57 const DataLayout
&DL
= getDataLayout();
58 OS
<< DL
.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
63 llvm_unreachable("not implemented");
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
);
75 // Fallback to the default implementation.
76 return AsmPrinter::PrintAsmOperand(MI
, OpNo
, ExtraCode
, OS
);
79 void M68kAsmPrinter::printDisp(const MachineInstr
*MI
, unsigned opNum
,
81 // Print immediate displacement without the '#' predix
82 const MachineOperand
&Op
= MI
->getOperand(opNum
);
87 // Displacement is relocatable, so we're pretty permissive about what
89 printOperand(MI
, opNum
, O
);
92 void M68kAsmPrinter::printAbsMem(const MachineInstr
*MI
, unsigned OpNum
,
94 const MachineOperand
&MO
= MI
->getOperand(OpNum
);
96 O
<< format("$%0" PRIx64
, (uint64_t)MO
.getImm());
98 PrintAsmMemoryOperand(MI
, OpNum
, nullptr, O
);
101 bool M68kAsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
,
102 unsigned OpNo
, const char *ExtraCode
,
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.
112 // Decode MemAddrModeKind.
113 switch (static_cast<MemAddrModeKind
>(MO
.getImm())) {
114 case MemAddrModeKind::j
:
115 printARIMem(MI
, OpNo
, OS
);
117 case MemAddrModeKind::o
:
118 printARIPIMem(MI
, OpNo
, OS
);
120 case MemAddrModeKind::e
:
121 printARIPDMem(MI
, OpNo
, OS
);
123 case MemAddrModeKind::p
:
124 printARIDMem(MI
, OpNo
, OS
);
126 case MemAddrModeKind::f
:
127 case MemAddrModeKind::F
:
128 printARIIMem(MI
, OpNo
, OS
);
130 case MemAddrModeKind::k
:
131 printPCIMem(MI
, 0, OpNo
, OS
);
133 case MemAddrModeKind::q
:
134 printPCDMem(MI
, 0, OpNo
, OS
);
136 case MemAddrModeKind::b
:
137 printAbsMem(MI
, OpNo
, OS
);
140 llvm_unreachable("Unrecognized memory addressing mode");
143 case MachineOperand::MO_GlobalAddress
:
144 PrintSymbolOperand(MO
, OS
);
146 case MachineOperand::MO_BlockAddress
:
147 GetBlockAddressSymbol(MO
.getBlockAddress())->print(OS
, MAI
);
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
);
160 return AsmPrinter::PrintAsmMemoryOperand(MI
, OpNo
, ExtraCode
, OS
);
163 void M68kAsmPrinter::emitInstruction(const MachineInstr
*MI
) {
164 M68k_MC::verifyInstructionPredicates(MI
->getOpcode(),
165 getSubtargetInfo().getFeatureBits());
167 switch (MI
->getOpcode()) {
169 if (MI
->isPseudo()) {
170 LLVM_DEBUG(dbgs() << "Pseudo opcode(" << MI
->getOpcode()
171 << ") found in EmitInstruction()\n");
172 llvm_unreachable("Cannot proceed");
178 // Lower these as normal, but add some comments.
179 OutStreamer
->AddComment("TAILCALL");
184 MCInstLowering
->Lower(MI
, TmpInst0
);
185 OutStreamer
->emitInstruction(TmpInst0
, getSubtargetInfo());
188 void M68kAsmPrinter::emitFunctionBodyStart() {}
190 void M68kAsmPrinter::emitFunctionBodyEnd() {}
192 void M68kAsmPrinter::emitStartOfAsmFile(Module
&M
) {
193 OutStreamer
->emitSyntaxDirective();
196 void M68kAsmPrinter::emitEndOfAsmFile(Module
&M
) {}
198 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeM68kAsmPrinter() {
199 RegisterAsmPrinter
<M68kAsmPrinter
> X(getTheM68kTarget());