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 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 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 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 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 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 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 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 188 void M68kAsmPrinter::emitFunctionBodyStart() {} 189 190 void M68kAsmPrinter::emitFunctionBodyEnd() {} 191 192 void M68kAsmPrinter::emitStartOfAsmFile(Module &M) { 193 OutStreamer->emitSyntaxDirective(); 194 } 195 196 void M68kAsmPrinter::emitEndOfAsmFile(Module &M) {} 197 198 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmPrinter() { 199 RegisterAsmPrinter<M68kAsmPrinter> X(getTheM68kTarget()); 200 } 201