mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-10-10 12:55:00 +00:00
[AVR] Add the assembly instruction printer
Summary: This change adds the AVR assembly instruction printer. No tests are included in this patch. I have left them downstream so we can add them once `llc` successfully runs (there's very few components left to upstream until this). Reviewers: arsenm, kparzysz Subscribers: wdng, beanz, mgorny Differential Revision: https://reviews.llvm.org/D25028 llvm-svn: 282854
This commit is contained in:
parent
77394f1394
commit
1a7bd84a92
@ -17,7 +17,8 @@ add_llvm_target(AVRCodeGen
|
||||
|
||||
add_dependencies(LLVMAVRCodeGen intrinsics_gen)
|
||||
|
||||
add_subdirectory(AsmParser)
|
||||
add_subdirectory(InstPrinter)
|
||||
add_subdirectory(MCTargetDesc)
|
||||
add_subdirectory(TargetInfo)
|
||||
add_subdirectory(AsmParser)
|
||||
|
||||
|
172
llvm/lib/Target/AVR/InstPrinter/AVRInstPrinter.cpp
Normal file
172
llvm/lib/Target/AVR/InstPrinter/AVRInstPrinter.cpp
Normal file
@ -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 <cstring>
|
||||
|
||||
#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) {
|
||||
unsigned 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()) {
|
||||
int64_t 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
|
||||
|
54
llvm/lib/Target/AVR/InstPrinter/AVRInstPrinter.h
Normal file
54
llvm/lib/Target/AVR/InstPrinter/AVRInstPrinter.h
Normal file
@ -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
|
||||
|
8
llvm/lib/Target/AVR/InstPrinter/CMakeLists.txt
Normal file
8
llvm/lib/Target/AVR/InstPrinter/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/.. )
|
||||
|
||||
add_llvm_library(LLVMAVRAsmPrinter
|
||||
AVRInstPrinter.cpp
|
||||
)
|
||||
|
||||
add_dependencies(LLVMAVRAsmPrinter AVRCommonTableGen)
|
23
llvm/lib/Target/AVR/InstPrinter/LLVMBuild.txt
Normal file
23
llvm/lib/Target/AVR/InstPrinter/LLVMBuild.txt
Normal file
@ -0,0 +1,23 @@
|
||||
;===- ./lib/Target/AVR/InstPrinter/LLVMBuild.txt ----------------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Library
|
||||
name = AVRAsmPrinter
|
||||
parent = AVR
|
||||
required_libraries = MC Support
|
||||
add_to_library_groups = AVR
|
@ -22,7 +22,7 @@ subdirectories = TargetInfo
|
||||
type = TargetGroup
|
||||
name = AVR
|
||||
parent = Target
|
||||
has_asmprinter = 0
|
||||
has_asmprinter = 1
|
||||
has_asmparser = 1
|
||||
|
||||
[component_1]
|
||||
|
Loading…
Reference in New Issue
Block a user