xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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