Index: lib/Target/AVR/CMakeLists.txt =================================================================== --- lib/Target/AVR/CMakeLists.txt +++ lib/Target/AVR/CMakeLists.txt @@ -17,7 +17,8 @@ add_dependencies(LLVMAVRCodeGen intrinsics_gen) +add_subdirectory(AsmParser) +add_subdirectory(InstPrinter) add_subdirectory(MCTargetDesc) add_subdirectory(TargetInfo) -add_subdirectory(AsmParser) Index: lib/Target/AVR/InstPrinter/AVRInstPrinter.h =================================================================== --- /dev/null +++ lib/Target/AVR/InstPrinter/AVRInstPrinter.h @@ -0,0 +1,54 @@ +//===- AVRInstPrinter.h - Convert AVR MCInst to assembly syntax -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class prints an AVR MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_AVR_INST_PRINTER_H +#define LLVM_AVR_INST_PRINTER_H + +#include "llvm/MC/MCInstPrinter.h" + +#include "MCTargetDesc/AVRMCTargetDesc.h" + +namespace llvm { + +/// Prints AVR instructions to a textual stream. +class AVRInstPrinter : public MCInstPrinter { +public: + AVRInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, + const MCRegisterInfo &MRI) + : MCInstPrinter(MAI, MII, MRI) {} + + static const char *getPrettyRegisterName(unsigned RegNo, + MCRegisterInfo const &MRI); + + void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, + const MCSubtargetInfo &STI) override; + +private: + static const char *getRegisterName(unsigned RegNo, + unsigned AltIdx = AVR::NoRegAltName); + + void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printPCRelImm(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &O); + + // Autogenerated by TableGen. + void printInstruction(const MCInst *MI, raw_ostream &O); + bool printAliasInstr(const MCInst *MI, raw_ostream &O); + void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx, + unsigned PrintMethodIdx, raw_ostream &O); +}; + +} // end namespace llvm + +#endif // LLVM_AVR_INST_PRINTER_H + Index: lib/Target/AVR/InstPrinter/AVRInstPrinter.cpp =================================================================== --- /dev/null +++ lib/Target/AVR/InstPrinter/AVRInstPrinter.cpp @@ -0,0 +1,172 @@ +//===-- AVRInstPrinter.cpp - Convert AVR MCInst to assembly syntax --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class prints an AVR MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#include "AVRInstPrinter.h" + +#include "MCTargetDesc/AVRMCTargetDesc.h" + +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" + +#include + +#define DEBUG_TYPE "asm-printer" + +namespace llvm { + +// Include the auto-generated portion of the assembly writer. +#define PRINT_ALIAS_INSTR +#include "AVRGenAsmWriter.inc" + +void AVRInstPrinter::printInst(const MCInst *MI, raw_ostream &O, + StringRef Annot, const MCSubtargetInfo &STI) { + unsigned Opcode = MI->getOpcode(); + + // First handle load and store instructions with postinc or predec + // of the form "ld reg, X+". + // TODO: We should be able to rewrite this using TableGen data. + switch (Opcode) { + case AVR::LDRdPtr: + case AVR::LDRdPtrPi: + case AVR::LDRdPtrPd: + O << "\tld\t"; + printOperand(MI, 0, O); + O << ", "; + + if (Opcode == AVR::LDRdPtrPd) + O << '-'; + + printOperand(MI, 1, O); + + if (Opcode == AVR::LDRdPtrPi) + O << '+'; + break; + case AVR::STPtrRr: + O << "\tst\t"; + printOperand(MI, 0, O); + O << ", "; + printOperand(MI, 1, O); + break; + case AVR::STPtrPiRr: + case AVR::STPtrPdRr: + O << "\tst\t"; + + if (Opcode == AVR::STPtrPdRr) + O << '-'; + + printOperand(MI, 1, O); + + if (Opcode == AVR::STPtrPiRr) + O << '+'; + + O << ", "; + printOperand(MI, 2, O); + break; + default: + if (!printAliasInstr(MI, O)) + printInstruction(MI, O); + + printAnnotation(O, Annot); + break; + } +} + +const char *AVRInstPrinter::getPrettyRegisterName(unsigned RegNum, + MCRegisterInfo const &MRI) { + // GCC prints register pairs by just printing the lower register + // If the register contains a subregister, print it instead + if (MRI.getNumSubRegIndices() > 0) { + auto RegLoNum = MRI.getSubReg(RegNum, AVR::sub_lo); + RegNum = (RegLoNum != AVR::NoRegister) ? RegLoNum : RegNum; + } + + return getRegisterName(RegNum); +} + +void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + const MCOperand &Op = MI->getOperand(OpNo); + const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).OpInfo[OpNo]; + + if (Op.isReg()) { + bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) || + (MOI.RegClass == AVR::PTRDISPREGSRegClassID) || + (MOI.RegClass == AVR::ZREGSRegClassID); + + if (isPtrReg) { + O << getRegisterName(Op.getReg(), AVR::ptr); + } else { + O << getPrettyRegisterName(Op.getReg(), MRI); + } + } else if (Op.isImm()) { + O << Op.getImm(); + } else { + assert(Op.isExpr() && "Unknown operand kind in printOperand"); + O << *Op.getExpr(); + } +} + +/// This is used to print an immediate value that ends up +/// being encoded as a pc-relative value. +void AVRInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + const MCOperand &Op = MI->getOperand(OpNo); + + if (Op.isImm()) { + int64_t Imm = Op.getImm(); + O << '.'; + + // Print a position sign if needed. + // Negative values have their sign printed automatically. + if (Imm >= 0) + O << '+'; + + O << Imm; + } else { + assert(Op.isExpr() && "Unknown pcrel immediate operand"); + O << *Op.getExpr(); + } +} + +void AVRInstPrinter::printMemri(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + const MCOperand &RegOp = MI->getOperand(OpNo); + const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); + + assert(RegOp.isReg() && "Expected a register"); + + // Print the register. + printOperand(MI, OpNo, O); + + // Print the {+,-}offset. + if (OffsetOp.isImm()) { + auto Offset = OffsetOp.getImm(); + + if (Offset >= 0) + O << '+'; + + O << Offset; + } else if (OffsetOp.isExpr()) { + O << *OffsetOp.getExpr(); + } else { + llvm_unreachable("unknown type for offset"); + } +} + +} // end of namespace llvm + Index: lib/Target/AVR/InstPrinter/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Target/AVR/InstPrinter/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMAVRAsmPrinter + AVRInstPrinter.cpp + ) + +add_dependencies(LLVMAVRAsmPrinter AVRCommonTableGen) \ No newline at end of file Index: lib/Target/AVR/InstPrinter/LLVMBuild.txt =================================================================== --- lib/Target/AVR/InstPrinter/LLVMBuild.txt +++ lib/Target/AVR/InstPrinter/LLVMBuild.txt @@ -1,4 +1,4 @@ -;===- ./lib/Target/AVR/LLVMBuild.txt ---------------------------*- Conf -*--===; +;===- ./lib/Target/AVR/InstPrinter/LLVMBuild.txt ----------------*- Conf -*--===; ; ; The LLVM Compiler Infrastructure ; @@ -15,19 +15,9 @@ ; ;===------------------------------------------------------------------------===; -[common] -subdirectories = TargetInfo - [component_0] -type = TargetGroup -name = AVR -parent = Target -has_asmprinter = 0 -has_asmparser = 1 - -[component_1] type = Library -name = AVRCodeGen +name = AVRAsmPrinter parent = AVR -required_libraries = AsmPrinter CodeGen Core MC AVRInfo SelectionDAG Support Target -add_to_library_groups = AVR +required_libraries = MC Support +add_to_library_groups = AVR \ No newline at end of file Index: lib/Target/AVR/LLVMBuild.txt =================================================================== --- lib/Target/AVR/LLVMBuild.txt +++ lib/Target/AVR/LLVMBuild.txt @@ -22,7 +22,7 @@ type = TargetGroup name = AVR parent = Target -has_asmprinter = 0 +has_asmprinter = 1 has_asmparser = 1 [component_1]