PPCInstPrinter.cpp [plain text]
#define DEBUG_TYPE "asm-printer"
#include "PPCInstPrinter.h"
#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "MCTargetDesc/PPCPredicates.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetOpcodes.h"
using namespace llvm;
static cl::opt<bool>
FullRegNames("ppc-asm-full-reg-names", cl::Hidden, cl::init(false),
cl::desc("Use full register names when printing assembly"));
#include "PPCGenAsmWriter.inc"
void PPCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
OS << getRegisterName(RegNo);
}
void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
StringRef Annot) {
if (MI->getOpcode() == PPC::RLWINM) {
unsigned char SH = MI->getOperand(2).getImm();
unsigned char MB = MI->getOperand(3).getImm();
unsigned char ME = MI->getOperand(4).getImm();
bool useSubstituteMnemonic = false;
if (SH <= 31 && MB == 0 && ME == (31-SH)) {
O << "\tslwi "; useSubstituteMnemonic = true;
}
if (SH <= 31 && MB == (32-SH) && ME == 31) {
O << "\tsrwi "; useSubstituteMnemonic = true;
SH = 32-SH;
}
if (useSubstituteMnemonic) {
printOperand(MI, 0, O);
O << ", ";
printOperand(MI, 1, O);
O << ", " << (unsigned int)SH;
printAnnotation(O, Annot);
return;
}
}
if ((MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) &&
MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) {
O << "\tmr ";
printOperand(MI, 0, O);
O << ", ";
printOperand(MI, 1, O);
printAnnotation(O, Annot);
return;
}
if (MI->getOpcode() == PPC::RLDICR) {
unsigned char SH = MI->getOperand(2).getImm();
unsigned char ME = MI->getOperand(3).getImm();
if (63-SH == ME) {
O << "\tsldi ";
printOperand(MI, 0, O);
O << ", ";
printOperand(MI, 1, O);
O << ", " << (unsigned int)SH;
printAnnotation(O, Annot);
return;
}
}
if (MI->getOpcode() == TargetOpcode::COPY_TO_REGCLASS)
return;
printInstruction(MI, O);
printAnnotation(O, Annot);
}
void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O,
const char *Modifier) {
unsigned Code = MI->getOperand(OpNo).getImm();
if (StringRef(Modifier) == "cc") {
switch ((PPC::Predicate)Code) {
case PPC::PRED_LT_MINUS:
case PPC::PRED_LT_PLUS:
case PPC::PRED_LT:
O << "lt";
return;
case PPC::PRED_LE_MINUS:
case PPC::PRED_LE_PLUS:
case PPC::PRED_LE:
O << "le";
return;
case PPC::PRED_EQ_MINUS:
case PPC::PRED_EQ_PLUS:
case PPC::PRED_EQ:
O << "eq";
return;
case PPC::PRED_GE_MINUS:
case PPC::PRED_GE_PLUS:
case PPC::PRED_GE:
O << "ge";
return;
case PPC::PRED_GT_MINUS:
case PPC::PRED_GT_PLUS:
case PPC::PRED_GT:
O << "gt";
return;
case PPC::PRED_NE_MINUS:
case PPC::PRED_NE_PLUS:
case PPC::PRED_NE:
O << "ne";
return;
case PPC::PRED_UN_MINUS:
case PPC::PRED_UN_PLUS:
case PPC::PRED_UN:
O << "un";
return;
case PPC::PRED_NU_MINUS:
case PPC::PRED_NU_PLUS:
case PPC::PRED_NU:
O << "nu";
return;
}
llvm_unreachable("Invalid predicate code");
}
if (StringRef(Modifier) == "pm") {
switch ((PPC::Predicate)Code) {
case PPC::PRED_LT:
case PPC::PRED_LE:
case PPC::PRED_EQ:
case PPC::PRED_GE:
case PPC::PRED_GT:
case PPC::PRED_NE:
case PPC::PRED_UN:
case PPC::PRED_NU:
return;
case PPC::PRED_LT_MINUS:
case PPC::PRED_LE_MINUS:
case PPC::PRED_EQ_MINUS:
case PPC::PRED_GE_MINUS:
case PPC::PRED_GT_MINUS:
case PPC::PRED_NE_MINUS:
case PPC::PRED_UN_MINUS:
case PPC::PRED_NU_MINUS:
O << "-";
return;
case PPC::PRED_LT_PLUS:
case PPC::PRED_LE_PLUS:
case PPC::PRED_EQ_PLUS:
case PPC::PRED_GE_PLUS:
case PPC::PRED_GT_PLUS:
case PPC::PRED_NE_PLUS:
case PPC::PRED_UN_PLUS:
case PPC::PRED_NU_PLUS:
O << "+";
return;
}
llvm_unreachable("Invalid predicate code");
}
assert(StringRef(Modifier) == "reg" &&
"Need to specify 'cc', 'pm' or 'reg' as predicate op modifier!");
printOperand(MI, OpNo+1, O);
}
void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
int Value = MI->getOperand(OpNo).getImm();
Value = SignExtend32<5>(Value);
O << (int)Value;
}
void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
unsigned int Value = MI->getOperand(OpNo).getImm();
assert(Value <= 31 && "Invalid u5imm argument!");
O << (unsigned int)Value;
}
void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
unsigned int Value = MI->getOperand(OpNo).getImm();
assert(Value <= 63 && "Invalid u6imm argument!");
O << (unsigned int)Value;
}
void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
if (MI->getOperand(OpNo).isImm())
O << (short)MI->getOperand(OpNo).getImm();
else
printOperand(MI, OpNo, O);
}
void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
if (MI->getOperand(OpNo).isImm())
O << (unsigned short)MI->getOperand(OpNo).getImm();
else
printOperand(MI, OpNo, O);
}
void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
if (!MI->getOperand(OpNo).isImm())
return printOperand(MI, OpNo, O);
O << ".+";
printAbsBranchOperand(MI, OpNo, O);
}
void PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
if (!MI->getOperand(OpNo).isImm())
return printOperand(MI, OpNo, O);
O << (int)MI->getOperand(OpNo).getImm()*4;
}
void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
unsigned CCReg = MI->getOperand(OpNo).getReg();
unsigned RegNo;
switch (CCReg) {
default: llvm_unreachable("Unknown CR register");
case PPC::CR0: RegNo = 0; break;
case PPC::CR1: RegNo = 1; break;
case PPC::CR2: RegNo = 2; break;
case PPC::CR3: RegNo = 3; break;
case PPC::CR4: RegNo = 4; break;
case PPC::CR5: RegNo = 5; break;
case PPC::CR6: RegNo = 6; break;
case PPC::CR7: RegNo = 7; break;
}
O << (0x80 >> RegNo);
}
void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
printS16ImmOperand(MI, OpNo, O);
O << '(';
if (MI->getOperand(OpNo+1).getReg() == PPC::R0)
O << "0";
else
printOperand(MI, OpNo+1, O);
O << ')';
}
void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
if (MI->getOperand(OpNo).getReg() == PPC::R0)
O << "0";
else
printOperand(MI, OpNo, O);
O << ", ";
printOperand(MI, OpNo+1, O);
}
void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
printBranchOperand(MI, OpNo, O);
O << '(';
printOperand(MI, OpNo+1, O);
O << ')';
}
static const char *stripRegisterPrefix(const char *RegName) {
if (FullRegNames)
return RegName;
switch (RegName[0]) {
case 'r':
case 'f':
case 'v': return RegName + 1;
case 'c': if (RegName[1] == 'r') return RegName + 2;
}
return RegName;
}
void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isReg()) {
const char *RegName = getRegisterName(Op.getReg());
if (!isDarwinSyntax())
RegName = stripRegisterPrefix(RegName);
O << RegName;
return;
}
if (Op.isImm()) {
O << Op.getImm();
return;
}
assert(Op.isExpr() && "unknown operand kind in printOperand");
O << *Op.getExpr();
}