X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FPowerPC%2FPPCAsmPrinter.cpp;h=09a9be998247cad6949064d3c9427ec20ad6f93d;hb=aa4e6afc9be330770e0b5d41e79aa26c3115bcca;hp=833a83ede62a487a423c77adec82c2dbdb8c48c5;hpb=60d5b5fdeec64b69c92db60242d3d90b3f978e69;p=oota-llvm.git diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index 833a83ede62..09a9be99824 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -35,6 +35,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" @@ -43,6 +44,7 @@ #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/ErrorHandling.h" @@ -58,84 +60,20 @@ namespace { protected: DenseMap TOC; const PPCSubtarget &Subtarget; - uint64_t LabelID; + uint64_t TOCLabelID; public: explicit PPCAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) : AsmPrinter(TM, Streamer), - Subtarget(TM.getSubtarget()), LabelID(0) {} + Subtarget(TM.getSubtarget()), TOCLabelID(0) {} virtual const char *getPassName() const { 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, @@ -144,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().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().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()); @@ -373,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(); @@ -472,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() || @@ -506,48 +281,28 @@ 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) { - SmallString<128> Str; - raw_svector_ostream O(Str); - - if (MI->getOpcode() == TargetOpcode::DBG_VALUE) { + MCInst TmpInst; + + // Lower multi-instruction pseudo operations. + switch (MI->getOpcode()) { + default: break; + case TargetOpcode::DBG_VALUE: { + if (!isVerbose() || !OutStreamer.hasRawTextSupport()) return; + + SmallString<32> Str; + raw_svector_ostream O(Str); unsigned NOps = MI->getNumOperands(); assert(NOps==4); O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: "; @@ -564,56 +319,65 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { OutStreamer.EmitRawText(O.str()); 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; - } + + 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; } - - 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()); + case PPC::LDtoc: { + // Transform %X3 = LDtoc , %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 = GetTempSymbol("C", TOCLabelID++); + + const MCExpr *Exp = + MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC, + OutContext); + TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); + OutStreamer.EmitInstruction(TmpInst); 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; - } + + 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; } - printInstruction(MI, O); - OutStreamer.EmitRawText(O.str()); + LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); + OutStreamer.EmitInstruction(TmpInst); } void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() { @@ -674,7 +438,10 @@ void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) { if (Subtarget.isPPC64() && Directive < PPC::DIR_970) Directive = PPC::DIR_64; assert(Directive <= PPC::DIR_64 && "Directive out of range."); - OutStreamer.EmitRawText("\t.machine " + Twine(CPUDirectives[Directive])); + + // FIXME: This is a total hack, finish mc'izing the PPC backend. + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText("\t.machine " + Twine(CPUDirectives[Directive])); // Prime text sections so they are adjacent. This reduces the likelihood a // large data or debug section causes a branch to exceed 16M limit. @@ -913,11 +680,10 @@ static AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm, } static MCInstPrinter *createPPCMCInstPrinter(const Target &T, + TargetMachine &TM, unsigned SyntaxVariant, const MCAsmInfo &MAI) { - if (SyntaxVariant == 0) - return new PPCInstPrinter(MAI); - return 0; + return new PPCInstPrinter(TM, MAI, SyntaxVariant); } @@ -927,5 +693,5 @@ extern "C" void LLVMInitializePowerPCAsmPrinter() { TargetRegistry::RegisterAsmPrinter(ThePPC64Target, createPPCAsmPrinterPass); TargetRegistry::RegisterMCInstPrinter(ThePPC32Target, createPPCMCInstPrinter); - TargetRegistry::RegisterMCInstPrinter(ThePPC32Target, createPPCMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(ThePPC64Target, createPPCMCInstPrinter); }