109467b48Spatrick //===-- AVRAsmPrinter.cpp - AVR LLVM assembly writer ----------------------===// 209467b48Spatrick // 309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information. 509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 609467b48Spatrick // 709467b48Spatrick //===----------------------------------------------------------------------===// 809467b48Spatrick // 909467b48Spatrick // This file contains a printer that converts from our internal representation 1009467b48Spatrick // of machine-dependent LLVM code to GAS-format AVR assembly language. 1109467b48Spatrick // 1209467b48Spatrick //===----------------------------------------------------------------------===// 1309467b48Spatrick 1409467b48Spatrick #include "AVR.h" 1509467b48Spatrick #include "AVRMCInstLower.h" 1609467b48Spatrick #include "AVRSubtarget.h" 1709467b48Spatrick #include "MCTargetDesc/AVRInstPrinter.h" 18*73471bf0Spatrick #include "MCTargetDesc/AVRMCExpr.h" 1909467b48Spatrick #include "TargetInfo/AVRTargetInfo.h" 2009467b48Spatrick 2109467b48Spatrick #include "llvm/CodeGen/AsmPrinter.h" 2209467b48Spatrick #include "llvm/CodeGen/MachineFunction.h" 2309467b48Spatrick #include "llvm/CodeGen/MachineInstr.h" 2409467b48Spatrick #include "llvm/CodeGen/TargetRegisterInfo.h" 2509467b48Spatrick #include "llvm/CodeGen/TargetSubtargetInfo.h" 2609467b48Spatrick #include "llvm/IR/Mangler.h" 2709467b48Spatrick #include "llvm/MC/MCInst.h" 2809467b48Spatrick #include "llvm/MC/MCStreamer.h" 2909467b48Spatrick #include "llvm/MC/MCSymbol.h" 3009467b48Spatrick #include "llvm/Support/ErrorHandling.h" 3109467b48Spatrick #include "llvm/Support/TargetRegistry.h" 3209467b48Spatrick #include "llvm/Support/raw_ostream.h" 3309467b48Spatrick 3409467b48Spatrick #define DEBUG_TYPE "avr-asm-printer" 3509467b48Spatrick 3609467b48Spatrick namespace llvm { 3709467b48Spatrick 3809467b48Spatrick /// An AVR assembly code printer. 3909467b48Spatrick class AVRAsmPrinter : public AsmPrinter { 4009467b48Spatrick public: 4109467b48Spatrick AVRAsmPrinter(TargetMachine &TM, 4209467b48Spatrick std::unique_ptr<MCStreamer> Streamer) 4309467b48Spatrick : AsmPrinter(TM, std::move(Streamer)), MRI(*TM.getMCRegisterInfo()) { } 4409467b48Spatrick 4509467b48Spatrick StringRef getPassName() const override { return "AVR Assembly Printer"; } 4609467b48Spatrick 4709467b48Spatrick void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O); 4809467b48Spatrick 4909467b48Spatrick bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, 5009467b48Spatrick const char *ExtraCode, raw_ostream &O) override; 5109467b48Spatrick 5209467b48Spatrick bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, 5309467b48Spatrick const char *ExtraCode, raw_ostream &O) override; 5409467b48Spatrick 55097a140dSpatrick void emitInstruction(const MachineInstr *MI) override; 5609467b48Spatrick 57*73471bf0Spatrick const MCExpr *lowerConstant(const Constant *CV) override; 58*73471bf0Spatrick 5909467b48Spatrick private: 6009467b48Spatrick const MCRegisterInfo &MRI; 6109467b48Spatrick }; 6209467b48Spatrick 6309467b48Spatrick void AVRAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, 6409467b48Spatrick raw_ostream &O) { 6509467b48Spatrick const MachineOperand &MO = MI->getOperand(OpNo); 6609467b48Spatrick 6709467b48Spatrick switch (MO.getType()) { 6809467b48Spatrick case MachineOperand::MO_Register: 6909467b48Spatrick O << AVRInstPrinter::getPrettyRegisterName(MO.getReg(), MRI); 7009467b48Spatrick break; 7109467b48Spatrick case MachineOperand::MO_Immediate: 7209467b48Spatrick O << MO.getImm(); 7309467b48Spatrick break; 7409467b48Spatrick case MachineOperand::MO_GlobalAddress: 7509467b48Spatrick O << getSymbol(MO.getGlobal()); 7609467b48Spatrick break; 7709467b48Spatrick case MachineOperand::MO_ExternalSymbol: 7809467b48Spatrick O << *GetExternalSymbolSymbol(MO.getSymbolName()); 7909467b48Spatrick break; 8009467b48Spatrick case MachineOperand::MO_MachineBasicBlock: 8109467b48Spatrick O << *MO.getMBB()->getSymbol(); 8209467b48Spatrick break; 8309467b48Spatrick default: 8409467b48Spatrick llvm_unreachable("Not implemented yet!"); 8509467b48Spatrick } 8609467b48Spatrick } 8709467b48Spatrick 8809467b48Spatrick bool AVRAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, 8909467b48Spatrick const char *ExtraCode, raw_ostream &O) { 9009467b48Spatrick // Default asm printer can only deal with some extra codes, 9109467b48Spatrick // so try it first. 9209467b48Spatrick bool Error = AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O); 9309467b48Spatrick 9409467b48Spatrick if (Error && ExtraCode && ExtraCode[0]) { 9509467b48Spatrick if (ExtraCode[1] != 0) 9609467b48Spatrick return true; // Unknown modifier. 9709467b48Spatrick 9809467b48Spatrick if (ExtraCode[0] >= 'A' && ExtraCode[0] <= 'Z') { 9909467b48Spatrick const MachineOperand &RegOp = MI->getOperand(OpNum); 10009467b48Spatrick 10109467b48Spatrick assert(RegOp.isReg() && "Operand must be a register when you're" 10209467b48Spatrick "using 'A'..'Z' operand extracodes."); 10309467b48Spatrick Register Reg = RegOp.getReg(); 10409467b48Spatrick 10509467b48Spatrick unsigned ByteNumber = ExtraCode[0] - 'A'; 10609467b48Spatrick 10709467b48Spatrick unsigned OpFlags = MI->getOperand(OpNum - 1).getImm(); 10809467b48Spatrick unsigned NumOpRegs = InlineAsm::getNumOperandRegisters(OpFlags); 10909467b48Spatrick (void)NumOpRegs; 11009467b48Spatrick 11109467b48Spatrick const AVRSubtarget &STI = MF->getSubtarget<AVRSubtarget>(); 11209467b48Spatrick const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 11309467b48Spatrick 11409467b48Spatrick const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(Reg); 11509467b48Spatrick unsigned BytesPerReg = TRI.getRegSizeInBits(*RC) / 8; 11609467b48Spatrick assert(BytesPerReg <= 2 && "Only 8 and 16 bit regs are supported."); 11709467b48Spatrick 11809467b48Spatrick unsigned RegIdx = ByteNumber / BytesPerReg; 11909467b48Spatrick assert(RegIdx < NumOpRegs && "Multibyte index out of range."); 12009467b48Spatrick 12109467b48Spatrick Reg = MI->getOperand(OpNum + RegIdx).getReg(); 12209467b48Spatrick 12309467b48Spatrick if (BytesPerReg == 2) { 12409467b48Spatrick Reg = TRI.getSubReg(Reg, ByteNumber % BytesPerReg ? AVR::sub_hi 12509467b48Spatrick : AVR::sub_lo); 12609467b48Spatrick } 12709467b48Spatrick 12809467b48Spatrick O << AVRInstPrinter::getPrettyRegisterName(Reg, MRI); 12909467b48Spatrick return false; 13009467b48Spatrick } 13109467b48Spatrick } 13209467b48Spatrick 13309467b48Spatrick if (Error) 13409467b48Spatrick printOperand(MI, OpNum, O); 13509467b48Spatrick 13609467b48Spatrick return false; 13709467b48Spatrick } 13809467b48Spatrick 13909467b48Spatrick bool AVRAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 14009467b48Spatrick unsigned OpNum, const char *ExtraCode, 14109467b48Spatrick raw_ostream &O) { 14209467b48Spatrick if (ExtraCode && ExtraCode[0]) { 14309467b48Spatrick llvm_unreachable("This branch is not implemented yet"); 14409467b48Spatrick } 14509467b48Spatrick 14609467b48Spatrick const MachineOperand &MO = MI->getOperand(OpNum); 14709467b48Spatrick (void)MO; 14809467b48Spatrick assert(MO.isReg() && "Unexpected inline asm memory operand"); 14909467b48Spatrick 15009467b48Spatrick // TODO: We should be able to look up the alternative name for 15109467b48Spatrick // the register if it's given. 15209467b48Spatrick // TableGen doesn't expose a way of getting retrieving names 15309467b48Spatrick // for registers. 15409467b48Spatrick if (MI->getOperand(OpNum).getReg() == AVR::R31R30) { 15509467b48Spatrick O << "Z"; 15609467b48Spatrick } else { 15709467b48Spatrick assert(MI->getOperand(OpNum).getReg() == AVR::R29R28 && 15809467b48Spatrick "Wrong register class for memory operand."); 15909467b48Spatrick O << "Y"; 16009467b48Spatrick } 16109467b48Spatrick 16209467b48Spatrick // If NumOpRegs == 2, then we assume it is product of a FrameIndex expansion 16309467b48Spatrick // and the second operand is an Imm. 16409467b48Spatrick unsigned OpFlags = MI->getOperand(OpNum - 1).getImm(); 16509467b48Spatrick unsigned NumOpRegs = InlineAsm::getNumOperandRegisters(OpFlags); 16609467b48Spatrick 16709467b48Spatrick if (NumOpRegs == 2) { 16809467b48Spatrick O << '+' << MI->getOperand(OpNum + 1).getImm(); 16909467b48Spatrick } 17009467b48Spatrick 17109467b48Spatrick return false; 17209467b48Spatrick } 17309467b48Spatrick 174097a140dSpatrick void AVRAsmPrinter::emitInstruction(const MachineInstr *MI) { 17509467b48Spatrick AVRMCInstLower MCInstLowering(OutContext, *this); 17609467b48Spatrick 17709467b48Spatrick MCInst I; 17809467b48Spatrick MCInstLowering.lowerInstruction(*MI, I); 17909467b48Spatrick EmitToStreamer(*OutStreamer, I); 18009467b48Spatrick } 18109467b48Spatrick 182*73471bf0Spatrick const MCExpr *AVRAsmPrinter::lowerConstant(const Constant *CV) { 183*73471bf0Spatrick MCContext &Ctx = OutContext; 184*73471bf0Spatrick 185*73471bf0Spatrick if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) { 186*73471bf0Spatrick bool IsProgMem = GV->getAddressSpace() == AVR::ProgramMemory; 187*73471bf0Spatrick if (IsProgMem) { 188*73471bf0Spatrick const MCExpr *Expr = MCSymbolRefExpr::create(getSymbol(GV), Ctx); 189*73471bf0Spatrick return AVRMCExpr::create(AVRMCExpr::VK_AVR_PM, Expr, false, Ctx); 190*73471bf0Spatrick } 191*73471bf0Spatrick } 192*73471bf0Spatrick 193*73471bf0Spatrick return AsmPrinter::lowerConstant(CV); 194*73471bf0Spatrick } 195*73471bf0Spatrick 19609467b48Spatrick } // end of namespace llvm 19709467b48Spatrick 19809467b48Spatrick extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRAsmPrinter() { 19909467b48Spatrick llvm::RegisterAsmPrinter<llvm::AVRAsmPrinter> X(llvm::getTheAVRTarget()); 20009467b48Spatrick } 20109467b48Spatrick 202