forked from OSchip/llvm-project
rip out a ton of old instruction printing junk now that the
new instprinting logic is there. llvm-svn: 119111
This commit is contained in:
parent
f4a6a14c93
commit
510c66f549
|
@ -55,13 +55,6 @@
|
|||
#include "InstPrinter/PPCInstPrinter.h"
|
||||
using namespace llvm;
|
||||
|
||||
// This option tells the asmprinter to use the new (experimental) MCInstPrinter
|
||||
// path.
|
||||
static cl::opt<bool> UseInstPrinter("enable-ppc-inst-printer",
|
||||
cl::ReallyHidden
|
||||
, cl::init(true)
|
||||
);
|
||||
|
||||
namespace {
|
||||
class PPCAsmPrinter : public AsmPrinter {
|
||||
protected:
|
||||
|
@ -77,74 +70,10 @@ namespace {
|
|||
return "PowerPC Assembly Printer";
|
||||
}
|
||||
|
||||
unsigned enumRegToMachineReg(unsigned enumReg) {
|
||||
switch (enumReg) {
|
||||
default: llvm_unreachable("Unhandled register!");
|
||||
case PPC::CR0: return 0;
|
||||
case PPC::CR1: return 1;
|
||||
case PPC::CR2: return 2;
|
||||
case PPC::CR3: return 3;
|
||||
case PPC::CR4: return 4;
|
||||
case PPC::CR5: return 5;
|
||||
case PPC::CR6: return 6;
|
||||
case PPC::CR7: return 7;
|
||||
}
|
||||
llvm_unreachable(0);
|
||||
}
|
||||
|
||||
/// printInstruction - This method is automatically generated by tablegen
|
||||
/// from the instruction set description. This method returns true if the
|
||||
/// machine instruction was sufficiently described to print it, otherwise it
|
||||
/// returns false.
|
||||
void printInstruction(const MachineInstr *MI, raw_ostream &O);
|
||||
static const char *getRegisterName(unsigned RegNo);
|
||||
|
||||
|
||||
virtual void EmitInstruction(const MachineInstr *MI);
|
||||
void printOp(const MachineOperand &MO, raw_ostream &O);
|
||||
|
||||
/// stripRegisterPrefix - This method strips the character prefix from a
|
||||
/// register name so that only the number is left. Used by for linux asm.
|
||||
const char *stripRegisterPrefix(const char *RegName) {
|
||||
switch (RegName[0]) {
|
||||
case 'r':
|
||||
case 'f':
|
||||
case 'v': return RegName + 1;
|
||||
case 'c': if (RegName[1] == 'r') return RegName + 2;
|
||||
}
|
||||
|
||||
return RegName;
|
||||
}
|
||||
|
||||
/// printRegister - Print register according to target requirements.
|
||||
///
|
||||
void printRegister(const MachineOperand &MO, bool R0AsZero, raw_ostream &O){
|
||||
unsigned RegNo = MO.getReg();
|
||||
assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??");
|
||||
|
||||
// If we should use 0 for R0.
|
||||
if (R0AsZero && RegNo == PPC::R0) {
|
||||
O << "0";
|
||||
return;
|
||||
}
|
||||
|
||||
const char *RegName = getRegisterName(RegNo);
|
||||
// Linux assembler (Others?) does not take register mnemonics.
|
||||
// FIXME - What about special registers used in mfspr/mtspr?
|
||||
if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName);
|
||||
O << RegName;
|
||||
}
|
||||
|
||||
void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
if (MO.isReg()) {
|
||||
printRegister(MO, false, O);
|
||||
} else if (MO.isImm()) {
|
||||
O << MO.getImm();
|
||||
} else {
|
||||
printOp(MO, O);
|
||||
}
|
||||
}
|
||||
void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
|
||||
|
||||
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant, const char *ExtraCode,
|
||||
|
@ -153,192 +82,9 @@ namespace {
|
|||
unsigned AsmVariant, const char *ExtraCode,
|
||||
raw_ostream &O);
|
||||
|
||||
|
||||
void printS5ImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
char value = MI->getOperand(OpNo).getImm();
|
||||
value = (value << (32-5)) >> (32-5);
|
||||
O << (int)value;
|
||||
}
|
||||
void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
unsigned char value = MI->getOperand(OpNo).getImm();
|
||||
assert(value <= 31 && "Invalid u5imm argument!");
|
||||
O << (unsigned int)value;
|
||||
}
|
||||
void printU6ImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
unsigned char value = MI->getOperand(OpNo).getImm();
|
||||
assert(value <= 63 && "Invalid u6imm argument!");
|
||||
O << (unsigned int)value;
|
||||
}
|
||||
void printS16ImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
O << (short)MI->getOperand(OpNo).getImm();
|
||||
}
|
||||
void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
O << (unsigned short)MI->getOperand(OpNo).getImm();
|
||||
}
|
||||
void printS16X4ImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
if (MI->getOperand(OpNo).isImm()) {
|
||||
O << (short)(MI->getOperand(OpNo).getImm()*4);
|
||||
} else {
|
||||
O << "lo16(";
|
||||
printOp(MI->getOperand(OpNo), O);
|
||||
if (TM.getRelocationModel() == Reloc::PIC_)
|
||||
O << "-\"L" << getFunctionNumber() << "$pb\")";
|
||||
else
|
||||
O << ')';
|
||||
}
|
||||
}
|
||||
void printBranchOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
// Branches can take an immediate operand. This is used by the branch
|
||||
// selection pass to print $+8, an eight byte displacement from the PC.
|
||||
if (MI->getOperand(OpNo).isImm()) {
|
||||
O << "$+" << MI->getOperand(OpNo).getImm()*4;
|
||||
} else {
|
||||
printOp(MI->getOperand(OpNo), O);
|
||||
}
|
||||
}
|
||||
void printCallOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
if (TM.getRelocationModel() != Reloc::Static) {
|
||||
if (MO.isGlobal()) {
|
||||
const GlobalValue *GV = MO.getGlobal();
|
||||
if (GV->isDeclaration() || GV->isWeakForLinker()) {
|
||||
// Dynamically-resolved functions need a stub for the function.
|
||||
MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$stub");
|
||||
MachineModuleInfoImpl::StubValueTy &StubSym =
|
||||
MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym);
|
||||
if (StubSym.getPointer() == 0)
|
||||
StubSym = MachineModuleInfoImpl::
|
||||
StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
|
||||
O << *Sym;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (MO.isSymbol()) {
|
||||
SmallString<128> TempNameStr;
|
||||
TempNameStr += StringRef(MO.getSymbolName());
|
||||
TempNameStr += StringRef("$stub");
|
||||
|
||||
MCSymbol *Sym = GetExternalSymbolSymbol(TempNameStr.str());
|
||||
MachineModuleInfoImpl::StubValueTy &StubSym =
|
||||
MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym);
|
||||
if (StubSym.getPointer() == 0)
|
||||
StubSym = MachineModuleInfoImpl::
|
||||
StubValueTy(GetExternalSymbolSymbol(MO.getSymbolName()), true);
|
||||
O << *Sym;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printOp(MI->getOperand(OpNo), O);
|
||||
}
|
||||
void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
O << (int)MI->getOperand(OpNo).getImm()*4;
|
||||
}
|
||||
void printPICLabel(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
|
||||
O << "\"L" << getFunctionNumber() << "$pb\"\n";
|
||||
O << "\"L" << getFunctionNumber() << "$pb\":";
|
||||
}
|
||||
void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
|
||||
if (MI->getOperand(OpNo).isImm()) {
|
||||
printS16ImmOperand(MI, OpNo, O);
|
||||
} else {
|
||||
if (Subtarget.isDarwin()) O << "ha16(";
|
||||
printOp(MI->getOperand(OpNo), O);
|
||||
if (TM.getRelocationModel() == Reloc::PIC_)
|
||||
O << "-L" << getFunctionNumber() << "$pb";
|
||||
if (Subtarget.isDarwin())
|
||||
O << ')';
|
||||
else
|
||||
O << "@ha";
|
||||
}
|
||||
}
|
||||
void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
|
||||
if (MI->getOperand(OpNo).isImm()) {
|
||||
printS16ImmOperand(MI, OpNo, O);
|
||||
} else {
|
||||
if (Subtarget.isDarwin()) O << "lo16(";
|
||||
printOp(MI->getOperand(OpNo), O);
|
||||
if (TM.getRelocationModel() == Reloc::PIC_)
|
||||
O << "-L" << getFunctionNumber() << "$pb";
|
||||
if (Subtarget.isDarwin())
|
||||
O << ')';
|
||||
else
|
||||
O << "@l";
|
||||
}
|
||||
}
|
||||
void printcrbitm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
|
||||
unsigned CCReg = MI->getOperand(OpNo).getReg();
|
||||
unsigned RegNo = enumRegToMachineReg(CCReg);
|
||||
O << (0x80 >> RegNo);
|
||||
}
|
||||
// The new addressing mode printers.
|
||||
void printMemRegImm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
|
||||
printSymbolLo(MI, OpNo, O);
|
||||
O << '(';
|
||||
if (MI->getOperand(OpNo+1).isReg() &&
|
||||
MI->getOperand(OpNo+1).getReg() == PPC::R0)
|
||||
O << "0";
|
||||
else
|
||||
printOperand(MI, OpNo+1, O);
|
||||
O << ')';
|
||||
}
|
||||
void printMemRegImmShifted(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
if (MI->getOperand(OpNo).isImm())
|
||||
printS16X4ImmOperand(MI, OpNo, O);
|
||||
else
|
||||
printSymbolLo(MI, OpNo, O);
|
||||
O << '(';
|
||||
if (MI->getOperand(OpNo+1).isReg() &&
|
||||
MI->getOperand(OpNo+1).getReg() == PPC::R0)
|
||||
O << "0";
|
||||
else
|
||||
printOperand(MI, OpNo+1, O);
|
||||
O << ')';
|
||||
}
|
||||
|
||||
void printMemRegReg(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
|
||||
// When used as the base register, r0 reads constant zero rather than
|
||||
// the value contained in the register. For this reason, the darwin
|
||||
// assembler requires that we print r0 as 0 (no r) when used as the base.
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
printRegister(MO, true, O);
|
||||
O << ", ";
|
||||
printOperand(MI, OpNo+1, O);
|
||||
}
|
||||
|
||||
void printTOCEntryLabel(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
assert(MO.isGlobal());
|
||||
MCSymbol *Sym = Mang->getSymbol(MO.getGlobal());
|
||||
|
||||
// Map symbol -> label of TOC entry.
|
||||
MCSymbol *&TOCEntry = TOC[Sym];
|
||||
if (TOCEntry == 0)
|
||||
TOCEntry = OutContext.
|
||||
GetOrCreateSymbol(StringRef(MAI->getPrivateGlobalPrefix()) +
|
||||
"C" + Twine(LabelID++));
|
||||
|
||||
O << *TOCEntry << "@toc";
|
||||
}
|
||||
|
||||
void printPredicateOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O, const char *Modifier);
|
||||
|
||||
MachineLocation getDebugValueLocation(const MachineInstr *MI) const {
|
||||
|
||||
MachineLocation Location;
|
||||
assert (MI->getNumOperands() == 4 && "Invalid no. of machine operands!");
|
||||
assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!");
|
||||
// Frame address. Currently handles register +- offset only.
|
||||
if (MI->getOperand(0).isReg() && MI->getOperand(2).isImm())
|
||||
Location.set(MI->getOperand(0).getReg(), MI->getOperand(2).getImm());
|
||||
|
@ -382,13 +128,35 @@ namespace {
|
|||
};
|
||||
} // end of anonymous namespace
|
||||
|
||||
// Include the auto-generated portion of the assembly writer
|
||||
#include "PPCGenAsmWriter.inc"
|
||||
/// stripRegisterPrefix - This method strips the character prefix from a
|
||||
/// register name so that only the number is left. Used by for linux asm.
|
||||
static const char *stripRegisterPrefix(const char *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 PPCAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) {
|
||||
void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
|
||||
switch (MO.getType()) {
|
||||
case MachineOperand::MO_Register: {
|
||||
const char *RegName = PPCInstPrinter::getRegisterName(MO.getReg());
|
||||
// Linux assembler (Others?) does not take register mnemonics.
|
||||
// FIXME - What about special registers used in mfspr/mtspr?
|
||||
if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName);
|
||||
O << RegName;
|
||||
return;
|
||||
}
|
||||
case MachineOperand::MO_Immediate:
|
||||
llvm_unreachable("printOp() does not handle immediate values");
|
||||
O << MO.getImm();
|
||||
return;
|
||||
|
||||
case MachineOperand::MO_MachineBasicBlock:
|
||||
O << *MO.getMBB()->getSymbol();
|
||||
|
@ -481,9 +249,7 @@ bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
|||
switch (ExtraCode[0]) {
|
||||
default: return true; // Unknown modifier.
|
||||
case 'c': // Don't print "$" before a global var name or constant.
|
||||
// PPC never has a prefix.
|
||||
printOperand(MI, OpNo, O);
|
||||
return false;
|
||||
break; // PPC never has a prefix.
|
||||
case 'L': // Write second word of DImode reference.
|
||||
// Verify that this operand has two consecutive registers.
|
||||
if (!MI->getOperand(OpNo).isReg() ||
|
||||
|
@ -515,183 +281,84 @@ bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
|
|||
raw_ostream &O) {
|
||||
if (ExtraCode && ExtraCode[0])
|
||||
return true; // Unknown modifier.
|
||||
assert (MI->getOperand(OpNo).isReg());
|
||||
assert(MI->getOperand(OpNo).isReg());
|
||||
O << "0(";
|
||||
printOperand(MI, OpNo, O);
|
||||
O << ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
void PPCAsmPrinter::printPredicateOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O, const char *Modifier){
|
||||
assert(Modifier && "Must specify 'cc' or 'reg' as predicate op modifier!");
|
||||
unsigned Code = MI->getOperand(OpNo).getImm();
|
||||
if (!strcmp(Modifier, "cc")) {
|
||||
switch ((PPC::Predicate)Code) {
|
||||
case PPC::PRED_ALWAYS: return; // Don't print anything for always.
|
||||
case PPC::PRED_LT: O << "lt"; return;
|
||||
case PPC::PRED_LE: O << "le"; return;
|
||||
case PPC::PRED_EQ: O << "eq"; return;
|
||||
case PPC::PRED_GE: O << "ge"; return;
|
||||
case PPC::PRED_GT: O << "gt"; return;
|
||||
case PPC::PRED_NE: O << "ne"; return;
|
||||
case PPC::PRED_UN: O << "un"; return;
|
||||
case PPC::PRED_NU: O << "nu"; return;
|
||||
}
|
||||
|
||||
} else {
|
||||
assert(!strcmp(Modifier, "reg") &&
|
||||
"Need to specify 'cc' or 'reg' as predicate op modifier!");
|
||||
// Don't print the register for 'always'.
|
||||
if (Code == PPC::PRED_ALWAYS) return;
|
||||
printOperand(MI, OpNo+1, O);
|
||||
}
|
||||
}
|
||||
|
||||
/// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to
|
||||
/// the current output stream.
|
||||
///
|
||||
void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
if (UseInstPrinter) {
|
||||
MCInst TmpInst;
|
||||
MCInst TmpInst;
|
||||
|
||||
// Lower multi-instruction pseudo operations.
|
||||
switch (MI->getOpcode()) {
|
||||
default: break;
|
||||
case PPC::MovePCtoLR:
|
||||
case PPC::MovePCtoLR8: {
|
||||
// Transform %LR = MovePCtoLR
|
||||
// Into this, where the label is the PIC base:
|
||||
// bl L1$pb
|
||||
// L1$pb:
|
||||
MCSymbol *PICBase = MF->getPICBaseSymbol();
|
||||
|
||||
// Lower multi-instruction pseudo operations.
|
||||
switch (MI->getOpcode()) {
|
||||
default: break;
|
||||
case PPC::MovePCtoLR:
|
||||
case PPC::MovePCtoLR8: {
|
||||
// Transform %LR = MovePCtoLR
|
||||
// Into this, where the label is the PIC base:
|
||||
// bl L1$pb
|
||||
// L1$pb:
|
||||
MCSymbol *PICBase = MF->getPICBaseSymbol();
|
||||
|
||||
// Emit the 'bl'.
|
||||
TmpInst.setOpcode(PPC::BL_Darwin); // Darwin vs SVR4 doesn't matter here.
|
||||
|
||||
|
||||
// FIXME: We would like an efficient form for this, so we don't have to do
|
||||
// a lot of extra uniquing.
|
||||
TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr::
|
||||
Create(PICBase, OutContext)));
|
||||
OutStreamer.EmitInstruction(TmpInst);
|
||||
|
||||
// Emit the label.
|
||||
OutStreamer.EmitLabel(PICBase);
|
||||
return;
|
||||
}
|
||||
case PPC::LDtoc: {
|
||||
// Transform %X3 = LDtoc <ga:@min1>, %X2
|
||||
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
|
||||
|
||||
// Change the opcode to LD, and the global address operand to be a
|
||||
// reference to the TOC entry we will synthesize later.
|
||||
TmpInst.setOpcode(PPC::LD);
|
||||
const MachineOperand &MO = MI->getOperand(1);
|
||||
assert(MO.isGlobal());
|
||||
|
||||
// Map symbol -> label of TOC entry.
|
||||
MCSymbol *&TOCEntry = TOC[Mang->getSymbol(MO.getGlobal())];
|
||||
if (TOCEntry == 0) {
|
||||
TOCEntry = OutContext.
|
||||
GetOrCreateSymbol(StringRef(MAI->getPrivateGlobalPrefix()) +
|
||||
"C" + Twine(LabelID++));
|
||||
}
|
||||
|
||||
const MCExpr *Exp =
|
||||
MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC,
|
||||
OutContext);
|
||||
TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp);
|
||||
OutStreamer.EmitInstruction(TmpInst);
|
||||
return;
|
||||
}
|
||||
|
||||
case PPC::MFCRpseud:
|
||||
// Transform: %R3 = MFCRpseud %CR7
|
||||
// Into: %R3 = MFCR ;; cr7
|
||||
OutStreamer.AddComment(getRegisterName(MI->getOperand(1).getReg()));
|
||||
TmpInst.setOpcode(PPC::MFCR);
|
||||
TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
|
||||
OutStreamer.EmitInstruction(TmpInst);
|
||||
return;
|
||||
}
|
||||
|
||||
// Emit the 'bl'.
|
||||
TmpInst.setOpcode(PPC::BL_Darwin); // Darwin vs SVR4 doesn't matter here.
|
||||
|
||||
|
||||
// FIXME: We would like an efficient form for this, so we don't have to do
|
||||
// a lot of extra uniquing.
|
||||
TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr::
|
||||
Create(PICBase, OutContext)));
|
||||
OutStreamer.EmitInstruction(TmpInst);
|
||||
|
||||
// Emit the label.
|
||||
OutStreamer.EmitLabel(PICBase);
|
||||
return;
|
||||
}
|
||||
case PPC::LDtoc: {
|
||||
// Transform %X3 = LDtoc <ga:@min1>, %X2
|
||||
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
|
||||
|
||||
// Change the opcode to LD, and the global address operand to be a
|
||||
// reference to the TOC entry we will synthesize later.
|
||||
TmpInst.setOpcode(PPC::LD);
|
||||
const MachineOperand &MO = MI->getOperand(1);
|
||||
assert(MO.isGlobal());
|
||||
|
||||
// Map symbol -> label of TOC entry.
|
||||
MCSymbol *&TOCEntry = TOC[Mang->getSymbol(MO.getGlobal())];
|
||||
if (TOCEntry == 0) {
|
||||
TOCEntry = OutContext.
|
||||
GetOrCreateSymbol(StringRef(MAI->getPrivateGlobalPrefix()) +
|
||||
"C" + Twine(LabelID++));
|
||||
}
|
||||
|
||||
const MCExpr *Exp =
|
||||
MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC,
|
||||
OutContext);
|
||||
TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp);
|
||||
OutStreamer.EmitInstruction(TmpInst);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SmallString<128> Str;
|
||||
raw_svector_ostream O(Str);
|
||||
|
||||
if (MI->getOpcode() == TargetOpcode::DBG_VALUE) {
|
||||
unsigned NOps = MI->getNumOperands();
|
||||
assert(NOps==4);
|
||||
O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
|
||||
// cast away const; DIetc do not take const operands for some reason.
|
||||
DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata()));
|
||||
O << V.getName();
|
||||
O << " <- ";
|
||||
// Frame address. Currently handles register +- offset only.
|
||||
assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
|
||||
O << '['; printOperand(MI, 0, O); O << '+'; printOperand(MI, 1, O);
|
||||
O << ']';
|
||||
O << "+";
|
||||
printOperand(MI, NOps-2, O);
|
||||
OutStreamer.EmitRawText(O.str());
|
||||
|
||||
case PPC::MFCRpseud:
|
||||
// Transform: %R3 = MFCRpseud %CR7
|
||||
// Into: %R3 = MFCR ;; cr7
|
||||
OutStreamer.AddComment(PPCInstPrinter::
|
||||
getRegisterName(MI->getOperand(1).getReg()));
|
||||
TmpInst.setOpcode(PPC::MFCR);
|
||||
TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
|
||||
OutStreamer.EmitInstruction(TmpInst);
|
||||
return;
|
||||
}
|
||||
// Check for slwi/srwi mnemonics.
|
||||
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;
|
||||
OutStreamer.EmitRawText(O.str());
|
||||
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);
|
||||
OutStreamer.EmitRawText(O.str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (MI->getOpcode() == PPC::RLDICR) {
|
||||
unsigned char SH = MI->getOperand(2).getImm();
|
||||
unsigned char ME = MI->getOperand(3).getImm();
|
||||
// rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH
|
||||
if (63-SH == ME) {
|
||||
O << "\tsldi ";
|
||||
printOperand(MI, 0, O);
|
||||
O << ", ";
|
||||
printOperand(MI, 1, O);
|
||||
O << ", " << (unsigned int)SH;
|
||||
OutStreamer.EmitRawText(O.str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printInstruction(MI, O);
|
||||
OutStreamer.EmitRawText(O.str());
|
||||
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
|
||||
OutStreamer.EmitInstruction(TmpInst);
|
||||
}
|
||||
|
||||
void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {
|
||||
|
|
Loading…
Reference in New Issue