#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 {
#define PRINT_ALIAS_INSTR
#include "AVRGenAsmWriter.inc"
void AVRInstPrinter::printInst(const MCInst *MI, uint64_t Address,
StringRef Annot, const MCSubtargetInfo &STI,
raw_ostream &O) {
unsigned Opcode = MI->getOpcode();
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, Address, O))
printInstruction(MI, Address, O);
printAnnotation(O, Annot);
break;
}
}
const char *AVRInstPrinter::getPrettyRegisterName(unsigned RegNum,
MCRegisterInfo const &MRI) {
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 MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).OpInfo[OpNo];
if (MOI.RegClass == AVR::ZREGRegClassID) {
O << "Z";
return;
}
if (OpNo >= MI->size()) {
O << "<unknown>";
return;
}
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isReg()) {
bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) ||
(MOI.RegClass == AVR::PTRDISPREGSRegClassID) ||
(MOI.RegClass == AVR::ZREGRegClassID);
if (isPtrReg) {
O << getRegisterName(Op.getReg(), AVR::ptr);
} else {
O << getPrettyRegisterName(Op.getReg(), MRI);
}
} else if (Op.isImm()) {
O << formatImm(Op.getImm());
} else {
assert(Op.isExpr() && "Unknown operand kind in printOperand");
O << *Op.getExpr();
}
}
void AVRInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
if (OpNo >= MI->size()) {
O << "<unknown>";
return;
}
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isImm()) {
int64_t Imm = Op.getImm();
O << '.';
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) {
assert(MI->getOperand(OpNo).isReg() &&
"Expected a register for the first operand");
const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
printOperand(MI, OpNo, O);
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");
}
}
}