181ad6265SDimitry Andric //===- LoongArchAsmPrinter.cpp - LoongArch LLVM Assembly Printer -*- C++ -*--=// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // This file contains a printer that converts from our internal representation 1081ad6265SDimitry Andric // of machine-dependent LLVM code to GAS-format LoongArch assembly language. 1181ad6265SDimitry Andric // 1281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1381ad6265SDimitry Andric 1481ad6265SDimitry Andric #include "LoongArchAsmPrinter.h" 1581ad6265SDimitry Andric #include "LoongArch.h" 1681ad6265SDimitry Andric #include "LoongArchTargetMachine.h" 17*bdd1243dSDimitry Andric #include "MCTargetDesc/LoongArchInstPrinter.h" 1881ad6265SDimitry Andric #include "TargetInfo/LoongArchTargetInfo.h" 1981ad6265SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 2081ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h" 2181ad6265SDimitry Andric 2281ad6265SDimitry Andric using namespace llvm; 2381ad6265SDimitry Andric 2481ad6265SDimitry Andric #define DEBUG_TYPE "loongarch-asm-printer" 2581ad6265SDimitry Andric 2681ad6265SDimitry Andric // Simple pseudo-instructions have their lowering (with expansion to real 2781ad6265SDimitry Andric // instructions) auto-generated. 2881ad6265SDimitry Andric #include "LoongArchGenMCPseudoLowering.inc" 2981ad6265SDimitry Andric 3081ad6265SDimitry Andric void LoongArchAsmPrinter::emitInstruction(const MachineInstr *MI) { 31753f127fSDimitry Andric LoongArch_MC::verifyInstructionPredicates( 32753f127fSDimitry Andric MI->getOpcode(), getSubtargetInfo().getFeatureBits()); 33753f127fSDimitry Andric 3481ad6265SDimitry Andric // Do any auto-generated pseudo lowerings. 3581ad6265SDimitry Andric if (emitPseudoExpansionLowering(*OutStreamer, MI)) 3681ad6265SDimitry Andric return; 3781ad6265SDimitry Andric 3881ad6265SDimitry Andric MCInst TmpInst; 3981ad6265SDimitry Andric if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this)) 4081ad6265SDimitry Andric EmitToStreamer(*OutStreamer, TmpInst); 4181ad6265SDimitry Andric } 4281ad6265SDimitry Andric 43*bdd1243dSDimitry Andric bool LoongArchAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 44*bdd1243dSDimitry Andric const char *ExtraCode, 45*bdd1243dSDimitry Andric raw_ostream &OS) { 46*bdd1243dSDimitry Andric // First try the generic code, which knows about modifiers like 'c' and 'n'. 47*bdd1243dSDimitry Andric if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS)) 48*bdd1243dSDimitry Andric return false; 49*bdd1243dSDimitry Andric 50*bdd1243dSDimitry Andric const MachineOperand &MO = MI->getOperand(OpNo); 51*bdd1243dSDimitry Andric if (ExtraCode && ExtraCode[0]) { 52*bdd1243dSDimitry Andric if (ExtraCode[1] != 0) 53*bdd1243dSDimitry Andric return true; // Unknown modifier. 54*bdd1243dSDimitry Andric 55*bdd1243dSDimitry Andric switch (ExtraCode[0]) { 56*bdd1243dSDimitry Andric default: 57*bdd1243dSDimitry Andric return true; // Unknown modifier. 58*bdd1243dSDimitry Andric case 'z': // Print $zero register if zero, regular printing otherwise. 59*bdd1243dSDimitry Andric if (MO.isImm() && MO.getImm() == 0) { 60*bdd1243dSDimitry Andric OS << '$' << LoongArchInstPrinter::getRegisterName(LoongArch::R0); 61*bdd1243dSDimitry Andric return false; 62*bdd1243dSDimitry Andric } 63*bdd1243dSDimitry Andric break; 64*bdd1243dSDimitry Andric // TODO: handle other extra codes if any. 65*bdd1243dSDimitry Andric } 66*bdd1243dSDimitry Andric } 67*bdd1243dSDimitry Andric 68*bdd1243dSDimitry Andric switch (MO.getType()) { 69*bdd1243dSDimitry Andric case MachineOperand::MO_Immediate: 70*bdd1243dSDimitry Andric OS << MO.getImm(); 71*bdd1243dSDimitry Andric return false; 72*bdd1243dSDimitry Andric case MachineOperand::MO_Register: 73*bdd1243dSDimitry Andric OS << '$' << LoongArchInstPrinter::getRegisterName(MO.getReg()); 74*bdd1243dSDimitry Andric return false; 75*bdd1243dSDimitry Andric case MachineOperand::MO_GlobalAddress: 76*bdd1243dSDimitry Andric PrintSymbolOperand(MO, OS); 77*bdd1243dSDimitry Andric return false; 78*bdd1243dSDimitry Andric default: 79*bdd1243dSDimitry Andric llvm_unreachable("not implemented"); 80*bdd1243dSDimitry Andric } 81*bdd1243dSDimitry Andric 82*bdd1243dSDimitry Andric return true; 83*bdd1243dSDimitry Andric } 84*bdd1243dSDimitry Andric 85*bdd1243dSDimitry Andric bool LoongArchAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 86*bdd1243dSDimitry Andric unsigned OpNo, 87*bdd1243dSDimitry Andric const char *ExtraCode, 88*bdd1243dSDimitry Andric raw_ostream &OS) { 89*bdd1243dSDimitry Andric // TODO: handle extra code. 90*bdd1243dSDimitry Andric if (ExtraCode) 91*bdd1243dSDimitry Andric return true; 92*bdd1243dSDimitry Andric 93*bdd1243dSDimitry Andric // We only support memory operands like "Base + Offset", where base must be a 94*bdd1243dSDimitry Andric // register, and offset can be a register or an immediate value. 95*bdd1243dSDimitry Andric const MachineOperand &BaseMO = MI->getOperand(OpNo); 96*bdd1243dSDimitry Andric // Base address must be a register. 97*bdd1243dSDimitry Andric if (!BaseMO.isReg()) 98*bdd1243dSDimitry Andric return true; 99*bdd1243dSDimitry Andric // Print the base address register. 100*bdd1243dSDimitry Andric OS << "$" << LoongArchInstPrinter::getRegisterName(BaseMO.getReg()); 101*bdd1243dSDimitry Andric // Print the offset operand. 102*bdd1243dSDimitry Andric const MachineOperand &OffsetMO = MI->getOperand(OpNo + 1); 103*bdd1243dSDimitry Andric if (OffsetMO.isReg()) 104*bdd1243dSDimitry Andric OS << ", $" << LoongArchInstPrinter::getRegisterName(OffsetMO.getReg()); 105*bdd1243dSDimitry Andric else if (OffsetMO.isImm()) 106*bdd1243dSDimitry Andric OS << ", " << OffsetMO.getImm(); 107*bdd1243dSDimitry Andric else 108*bdd1243dSDimitry Andric return true; 109*bdd1243dSDimitry Andric 110*bdd1243dSDimitry Andric return false; 111*bdd1243dSDimitry Andric } 112*bdd1243dSDimitry Andric 11381ad6265SDimitry Andric bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 11481ad6265SDimitry Andric AsmPrinter::runOnMachineFunction(MF); 11581ad6265SDimitry Andric return true; 11681ad6265SDimitry Andric } 11781ad6265SDimitry Andric 11881ad6265SDimitry Andric // Force static initialization. 11981ad6265SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmPrinter() { 12081ad6265SDimitry Andric RegisterAsmPrinter<LoongArchAsmPrinter> X(getTheLoongArch32Target()); 12181ad6265SDimitry Andric RegisterAsmPrinter<LoongArchAsmPrinter> Y(getTheLoongArch64Target()); 12281ad6265SDimitry Andric } 123