#include "M68kInstPrinter.h"
#include "M68kBaseInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "asm-printer"
#define PRINT_ALIAS_INSTR
#include "M68kGenAsmWriter.inc"
void M68kInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
OS << "%" << getRegisterName(RegNo);
}
void M68kInstPrinter::printInst(const MCInst *MI, uint64_t Address,
StringRef Annot, const MCSubtargetInfo &STI,
raw_ostream &O) {
if (!printAliasInstr(MI, Address, O))
printInstruction(MI, Address, O);
printAnnotation(O, Annot);
}
void M68kInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
const MCOperand &MO = MI->getOperand(OpNo);
if (MO.isReg()) {
printRegName(O, MO.getReg());
return;
}
if (MO.isImm()) {
printImmediate(MI, OpNo, O);
return;
}
assert(MO.isExpr() && "Unknown operand kind in printOperand");
MO.getExpr()->print(O, &MAI);
}
void M68kInstPrinter::printImmediate(const MCInst *MI, unsigned opNum,
raw_ostream &O) {
const MCOperand &MO = MI->getOperand(opNum);
if (MO.isImm())
O << '#' << MO.getImm();
else if (MO.isExpr()) {
O << '#';
MO.getExpr()->print(O, &MAI);
} else
llvm_unreachable("Unknown immediate kind");
}
void M68kInstPrinter::printMoveMask(const MCInst *MI, unsigned opNum,
raw_ostream &O) {
unsigned Mask = MI->getOperand(opNum).getImm();
assert((Mask & 0xFFFF) == Mask && "Mask is always 16 bits");
uint8_t HalfMask;
unsigned Reg;
for (int s = 0; s < 16; s += 8) {
HalfMask = (Mask >> s) & 0xFF;
if (s != 0 && (Mask & 0xFF) && HalfMask)
O << '/';
for (int i = 0; HalfMask; ++i) {
if ((HalfMask >> i) & 0b1) {
HalfMask ^= 0b1 << i;
Reg = M68kII::getMaskedSpillRegister(i + s);
printRegName(O, Reg);
int j = i;
while ((HalfMask >> (j + 1)) & 0b1)
HalfMask ^= 0b1 << ++j;
if (j != i) {
O << '-';
Reg = M68kII::getMaskedSpillRegister(j + s);
printRegName(O, Reg);
}
i = j;
if (HalfMask)
O << '/';
}
}
}
}
void M68kInstPrinter::printDisp(const MCInst *MI, unsigned opNum,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(opNum);
if (Op.isImm()) {
O << Op.getImm();
return;
}
assert(Op.isExpr() && "Unknown operand kind in printOperand");
Op.getExpr()->print(O, &MAI);
}
void M68kInstPrinter::printARIMem(const MCInst *MI, unsigned opNum,
raw_ostream &O) {
O << '(';
printOperand(MI, opNum, O);
O << ')';
}
void M68kInstPrinter::printARIPIMem(const MCInst *MI, unsigned opNum,
raw_ostream &O) {
O << "(";
printOperand(MI, opNum, O);
O << ")+";
}
void M68kInstPrinter::printARIPDMem(const MCInst *MI, unsigned opNum,
raw_ostream &O) {
O << "-(";
printOperand(MI, opNum, O);
O << ")";
}
void M68kInstPrinter::printARIDMem(const MCInst *MI, unsigned opNum,
raw_ostream &O) {
O << '(';
printDisp(MI, opNum + M68k::MemDisp, O);
O << ',';
printOperand(MI, opNum + M68k::MemBase, O);
O << ')';
}
void M68kInstPrinter::printARIIMem(const MCInst *MI, unsigned opNum,
raw_ostream &O) {
O << '(';
printDisp(MI, opNum + M68k::MemDisp, O);
O << ',';
printOperand(MI, opNum + M68k::MemBase, O);
O << ',';
printOperand(MI, opNum + M68k::MemIndex, O);
O << ')';
}
void M68kInstPrinter::printAbsMem(const MCInst *MI, unsigned opNum,
raw_ostream &O) {
const MCOperand &MO = MI->getOperand(opNum);
if (MO.isExpr()) {
MO.getExpr()->print(O, &MAI);
return;
}
assert(MO.isImm() && "absolute memory addressing needs an immediate");
O << format("$%0" PRIx64, (uint64_t)MO.getImm());
}
void M68kInstPrinter::printPCDMem(const MCInst *MI, uint64_t Address,
unsigned opNum, raw_ostream &O) {
O << '(';
printDisp(MI, opNum + M68k::PCRelDisp, O);
O << ",%pc)";
}
void M68kInstPrinter::printPCIMem(const MCInst *MI, uint64_t Address,
unsigned opNum, raw_ostream &O) {
O << '(';
printDisp(MI, opNum + M68k::PCRelDisp, O);
O << ",%pc,";
printOperand(MI, opNum + M68k::PCRelIndex, O);
O << ')';
}