|  | //===-- M68kAsmPrinter.cpp - M68k LLVM Assembly Printer ---------*- C++ -*-===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// | 
|  | /// \file | 
|  | /// This file contains a printer that converts from our internal representation | 
|  | /// of machine-dependent LLVM code to GAS-format M68k assembly language. | 
|  | /// | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | // TODO Conform to Motorola ASM syntax | 
|  |  | 
|  | #include "M68kAsmPrinter.h" | 
|  |  | 
|  | #include "M68k.h" | 
|  | #include "M68kMachineFunction.h" | 
|  | #include "MCTargetDesc/M68kInstPrinter.h" | 
|  | #include "TargetInfo/M68kTargetInfo.h" | 
|  |  | 
|  | #include "llvm/MC/TargetRegistry.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | #define DEBUG_TYPE "m68k-asm-printer" | 
|  |  | 
|  | bool M68kAsmPrinter::runOnMachineFunction(MachineFunction &MF) { | 
|  | MMFI = MF.getInfo<M68kMachineFunctionInfo>(); | 
|  | MCInstLowering = std::make_unique<M68kMCInstLower>(MF, *this); | 
|  | AsmPrinter::runOnMachineFunction(MF); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void M68kAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, | 
|  | raw_ostream &OS) { | 
|  | const MachineOperand &MO = MI->getOperand(OpNum); | 
|  | switch (MO.getType()) { | 
|  | case MachineOperand::MO_Register: | 
|  | OS << "%" << M68kInstPrinter::getRegisterName(MO.getReg()); | 
|  | break; | 
|  | case MachineOperand::MO_Immediate: | 
|  | OS << '#' << MO.getImm(); | 
|  | break; | 
|  | case MachineOperand::MO_MachineBasicBlock: | 
|  | MO.getMBB()->getSymbol()->print(OS, MAI); | 
|  | break; | 
|  | case MachineOperand::MO_GlobalAddress: | 
|  | PrintSymbolOperand(MO, OS); | 
|  | break; | 
|  | case MachineOperand::MO_BlockAddress: | 
|  | GetBlockAddressSymbol(MO.getBlockAddress())->print(OS, MAI); | 
|  | break; | 
|  | case MachineOperand::MO_ConstantPoolIndex: { | 
|  | const DataLayout &DL = getDataLayout(); | 
|  | OS << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' | 
|  | << MO.getIndex(); | 
|  | break; | 
|  | } | 
|  | default: | 
|  | llvm_unreachable("not implemented"); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool M68kAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, | 
|  | const char *ExtraCode, raw_ostream &OS) { | 
|  | // Print the operand if there is no operand modifier. | 
|  | if (!ExtraCode || !ExtraCode[0]) { | 
|  | printOperand(MI, OpNo, OS); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // Fallback to the default implementation. | 
|  | return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); | 
|  | } | 
|  |  | 
|  | void M68kAsmPrinter::printDisp(const MachineInstr *MI, unsigned opNum, | 
|  | raw_ostream &O) { | 
|  | // Print immediate displacement without the '#' predix | 
|  | const MachineOperand &Op = MI->getOperand(opNum); | 
|  | if (Op.isImm()) { | 
|  | O << Op.getImm(); | 
|  | return; | 
|  | } | 
|  | // Displacement is relocatable, so we're pretty permissive about what | 
|  | // can be put here. | 
|  | printOperand(MI, opNum, O); | 
|  | } | 
|  |  | 
|  | void M68kAsmPrinter::printAbsMem(const MachineInstr *MI, unsigned OpNum, | 
|  | raw_ostream &O) { | 
|  | const MachineOperand &MO = MI->getOperand(OpNum); | 
|  | if (MO.isImm()) | 
|  | O << format("$%0" PRIx64, (uint64_t)MO.getImm()); | 
|  | else | 
|  | PrintAsmMemoryOperand(MI, OpNum, nullptr, O); | 
|  | } | 
|  |  | 
|  | bool M68kAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, | 
|  | unsigned OpNo, const char *ExtraCode, | 
|  | raw_ostream &OS) { | 
|  | const MachineOperand &MO = MI->getOperand(OpNo); | 
|  | switch (MO.getType()) { | 
|  | case MachineOperand::MO_Immediate: | 
|  | // Immediate value that goes here is the addressing mode kind we set | 
|  | // in M68kDAGToDAGISel::SelectInlineAsmMemoryOperand. | 
|  | using namespace M68k; | 
|  | // Skip the addressing mode kind operand. | 
|  | ++OpNo; | 
|  | // Decode MemAddrModeKind. | 
|  | switch (static_cast<MemAddrModeKind>(MO.getImm())) { | 
|  | case MemAddrModeKind::j: | 
|  | printARIMem(MI, OpNo, OS); | 
|  | break; | 
|  | case MemAddrModeKind::o: | 
|  | printARIPIMem(MI, OpNo, OS); | 
|  | break; | 
|  | case MemAddrModeKind::e: | 
|  | printARIPDMem(MI, OpNo, OS); | 
|  | break; | 
|  | case MemAddrModeKind::p: | 
|  | printARIDMem(MI, OpNo, OS); | 
|  | break; | 
|  | case MemAddrModeKind::f: | 
|  | case MemAddrModeKind::F: | 
|  | printARIIMem(MI, OpNo, OS); | 
|  | break; | 
|  | case MemAddrModeKind::k: | 
|  | printPCIMem(MI, 0, OpNo, OS); | 
|  | break; | 
|  | case MemAddrModeKind::q: | 
|  | printPCDMem(MI, 0, OpNo, OS); | 
|  | break; | 
|  | case MemAddrModeKind::b: | 
|  | printAbsMem(MI, OpNo, OS); | 
|  | break; | 
|  | default: | 
|  | llvm_unreachable("Unrecognized memory addressing mode"); | 
|  | } | 
|  | return false; | 
|  | case MachineOperand::MO_GlobalAddress: | 
|  | PrintSymbolOperand(MO, OS); | 
|  | return false; | 
|  | case MachineOperand::MO_BlockAddress: | 
|  | GetBlockAddressSymbol(MO.getBlockAddress())->print(OS, MAI); | 
|  | return false; | 
|  | case MachineOperand::MO_Register: | 
|  | // This is a special case where it is treated as a memory reference, with | 
|  | // the register holding the address value. Thus, we print it as ARI here. | 
|  | if (M68kII::isAddressRegister(MO.getReg())) { | 
|  | printARIMem(MI, OpNo, OS); | 
|  | return false; | 
|  | } | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS); | 
|  | } | 
|  |  | 
|  | void M68kAsmPrinter::emitInstruction(const MachineInstr *MI) { | 
|  | M68k_MC::verifyInstructionPredicates(MI->getOpcode(), | 
|  | getSubtargetInfo().getFeatureBits()); | 
|  |  | 
|  | switch (MI->getOpcode()) { | 
|  | default: { | 
|  | if (MI->isPseudo()) { | 
|  | LLVM_DEBUG(dbgs() << "Pseudo opcode(" << MI->getOpcode() | 
|  | << ") found in EmitInstruction()\n"); | 
|  | llvm_unreachable("Cannot proceed"); | 
|  | } | 
|  | break; | 
|  | } | 
|  | case M68k::TAILJMPj: | 
|  | case M68k::TAILJMPq: | 
|  | // Lower these as normal, but add some comments. | 
|  | OutStreamer->AddComment("TAILCALL"); | 
|  | break; | 
|  | } | 
|  |  | 
|  | MCInst TmpInst0; | 
|  | MCInstLowering->Lower(MI, TmpInst0); | 
|  | OutStreamer->emitInstruction(TmpInst0, getSubtargetInfo()); | 
|  | } | 
|  |  | 
|  | void M68kAsmPrinter::emitFunctionBodyStart() {} | 
|  |  | 
|  | void M68kAsmPrinter::emitFunctionBodyEnd() {} | 
|  |  | 
|  | void M68kAsmPrinter::emitStartOfAsmFile(Module &M) { | 
|  | OutStreamer->emitSyntaxDirective(); | 
|  | } | 
|  |  | 
|  | void M68kAsmPrinter::emitEndOfAsmFile(Module &M) {} | 
|  |  | 
|  | extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmPrinter() { | 
|  | RegisterAsmPrinter<M68kAsmPrinter> X(getTheM68kTarget()); | 
|  | } |