diff --git a/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp b/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp index be6fe7b7ad65..ea709a73ebf2 100644 --- a/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp +++ b/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp @@ -1,522 +1,561 @@ //===-- PPCInstPrinter.cpp - Convert PPC MCInst to assembly syntax --------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This class prints an PPC MCInst to a .s file. // //===----------------------------------------------------------------------===// #include "PPCInstPrinter.h" #include "MCTargetDesc/PPCMCTargetDesc.h" #include "MCTargetDesc/PPCPredicates.h" #include "PPCInstrInfo.h" #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; #define DEBUG_TYPE "asm-printer" // FIXME: Once the integrated assembler supports full register names, tie this // to the verbose-asm setting. static cl::opt FullRegNames("ppc-asm-full-reg-names", cl::Hidden, cl::init(false), cl::desc("Use full register names when printing assembly")); // Useful for testing purposes. Prints vs{31-63} as v{0-31} respectively. static cl::opt ShowVSRNumsAsVR("ppc-vsr-nums-as-vr", cl::Hidden, cl::init(false), cl::desc("Prints full register names with vs{31-63} as v{0-31}")); +// Prints full register names with percent symbol. +static cl::opt +FullRegNamesWithPercent("ppc-reg-with-percent-prefix", cl::Hidden, + cl::init(false), + cl::desc("Prints full register names with percent")); + #define PRINT_ALIAS_INSTR #include "PPCGenAsmWriter.inc" void PPCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { const char *RegName = getRegisterName(RegNo); if (RegName[0] == 'q' /* QPX */) { // The system toolchain on the BG/Q does not understand QPX register names // in .cfi_* directives, so print the name of the floating-point // subregister instead. std::string RN(RegName); RN[0] = 'f'; OS << RN; return; } OS << RegName; } void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, const MCSubtargetInfo &STI) { // 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; 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 || MI->getOpcode() == PPC::RLDICR_32) { 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; printAnnotation(O, Annot); return; } } // dcbt[st] is printed manually here because: // 1. The assembly syntax is different between embedded and server targets // 2. We must print the short mnemonics for TH == 0 because the // embedded/server syntax default will not be stable across assemblers // The syntax for dcbt is: // dcbt ra, rb, th [server] // dcbt th, ra, rb [embedded] // where th can be omitted when it is 0. dcbtst is the same. if (MI->getOpcode() == PPC::DCBT || MI->getOpcode() == PPC::DCBTST) { unsigned char TH = MI->getOperand(0).getImm(); O << "\tdcbt"; if (MI->getOpcode() == PPC::DCBTST) O << "st"; if (TH == 16) O << "t"; O << " "; bool IsBookE = STI.getFeatureBits()[PPC::FeatureBookE]; if (IsBookE && TH != 0 && TH != 16) O << (unsigned int) TH << ", "; printOperand(MI, 1, O); O << ", "; printOperand(MI, 2, O); if (!IsBookE && TH != 0 && TH != 16) O << ", " << (unsigned int) TH; printAnnotation(O, Annot); return; } if (MI->getOpcode() == PPC::DCBF) { unsigned char L = MI->getOperand(0).getImm(); if (!L || L == 1 || L == 3) { O << "\tdcbf"; if (L == 1 || L == 3) O << "l"; if (L == 3) O << "p"; O << " "; printOperand(MI, 1, O); O << ", "; printOperand(MI, 2, O); printAnnotation(O, Annot); return; } } if (!printAliasInstr(MI, O)) 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; case PPC::PRED_BIT_SET: case PPC::PRED_BIT_UNSET: llvm_unreachable("Invalid use of bit predicate code"); } 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; case PPC::PRED_BIT_SET: case PPC::PRED_BIT_UNSET: llvm_unreachable("Invalid use of bit predicate code"); } 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::printATBitsAsHint(const MCInst *MI, unsigned OpNo, raw_ostream &O) { unsigned Code = MI->getOperand(OpNo).getImm(); if (Code == 2) O << "-"; else if (Code == 3) O << "+"; } void PPCInstPrinter::printU1ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { unsigned int Value = MI->getOperand(OpNo).getImm(); assert(Value <= 1 && "Invalid u1imm argument!"); O << (unsigned int)Value; } void PPCInstPrinter::printU2ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { unsigned int Value = MI->getOperand(OpNo).getImm(); assert(Value <= 3 && "Invalid u2imm argument!"); O << (unsigned int)Value; } void PPCInstPrinter::printU3ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { unsigned int Value = MI->getOperand(OpNo).getImm(); assert(Value <= 8 && "Invalid u3imm argument!"); O << (unsigned int)Value; } void PPCInstPrinter::printU4ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { unsigned int Value = MI->getOperand(OpNo).getImm(); assert(Value <= 15 && "Invalid u4imm argument!"); O << (unsigned int)Value; } 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::printU7ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { unsigned int Value = MI->getOperand(OpNo).getImm(); assert(Value <= 127 && "Invalid u7imm argument!"); O << (unsigned int)Value; } // Operands of BUILD_VECTOR are signed and we use this to print operands // of XXSPLTIB which are unsigned. So we simply truncate to 8 bits and // print as unsigned. void PPCInstPrinter::printU8ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { unsigned char Value = MI->getOperand(OpNo).getImm(); O << (unsigned int)Value; } void PPCInstPrinter::printU10ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { unsigned short Value = MI->getOperand(OpNo).getImm(); assert(Value <= 1023 && "Invalid u10imm argument!"); O << (unsigned short)Value; } void PPCInstPrinter::printU12ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { unsigned short Value = MI->getOperand(OpNo).getImm(); assert(Value <= 4095 && "Invalid u12imm argument!"); O << (unsigned short)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); // Branches can take an immediate operand. This is used by the branch // selection pass to print .+8, an eight byte displacement from the PC. 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 << SignExtend32<32>((unsigned)MI->getOperand(OpNo).getImm() << 2); } 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) { // 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. 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) { // On PPC64, VariantKind is VK_None, but on PPC32, it's VK_PLT, and it must // come at the _end_ of the expression. const MCOperand &Op = MI->getOperand(OpNo); const MCSymbolRefExpr &refExp = cast(*Op.getExpr()); O << refExp.getSymbol().getName(); O << '('; printOperand(MI, OpNo+1, O); O << ')'; if (refExp.getKind() != MCSymbolRefExpr::VK_None) O << '@' << MCSymbolRefExpr::getVariantKindName(refExp.getKind()); } +/// showRegistersWithPercentPrefix - Check if this register name should be +/// printed with a percentage symbol as prefix. +bool PPCInstPrinter::showRegistersWithPercentPrefix(const char *RegName) const { + if (!FullRegNamesWithPercent || TT.isOSDarwin() || TT.getOS() == Triple::AIX) + return false; -/// 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, unsigned RegNum, - unsigned RegEncoding) { - if (FullRegNames) { - if (RegNum >= PPC::CR0EQ && RegNum <= PPC::CR7UN) { - const char *CRBits[] = - { "lt", "gt", "eq", "un", - "4*cr1+lt", "4*cr1+gt", "4*cr1+eq", "4*cr1+un", - "4*cr2+lt", "4*cr2+gt", "4*cr2+eq", "4*cr2+un", - "4*cr3+lt", "4*cr3+gt", "4*cr3+eq", "4*cr3+un", - "4*cr4+lt", "4*cr4+gt", "4*cr4+eq", "4*cr4+un", - "4*cr5+lt", "4*cr5+gt", "4*cr5+eq", "4*cr5+un", - "4*cr6+lt", "4*cr6+gt", "4*cr6+eq", "4*cr6+un", - "4*cr7+lt", "4*cr7+gt", "4*cr7+eq", "4*cr7+un" - }; - return CRBits[RegEncoding]; - } - return RegName; + switch (RegName[0]) { + default: + return false; + case 'r': + case 'f': + case 'q': + case 'v': + case 'c': + return true; } +} + +/// getVerboseConditionalRegName - This method expands the condition register +/// when requested explicitly or targetting Darwin. +const char *PPCInstPrinter::getVerboseConditionRegName(unsigned RegNum, + unsigned RegEncoding) + const { + if (!TT.isOSDarwin() && !FullRegNames) + return nullptr; + if (RegNum < PPC::CR0EQ || RegNum > PPC::CR7UN) + return nullptr; + const char *CRBits[] = { + "lt", "gt", "eq", "un", + "4*cr1+lt", "4*cr1+gt", "4*cr1+eq", "4*cr1+un", + "4*cr2+lt", "4*cr2+gt", "4*cr2+eq", "4*cr2+un", + "4*cr3+lt", "4*cr3+gt", "4*cr3+eq", "4*cr3+un", + "4*cr4+lt", "4*cr4+gt", "4*cr4+eq", "4*cr4+un", + "4*cr5+lt", "4*cr5+gt", "4*cr5+eq", "4*cr5+un", + "4*cr6+lt", "4*cr6+gt", "4*cr6+eq", "4*cr6+un", + "4*cr7+lt", "4*cr7+gt", "4*cr7+eq", "4*cr7+un" + }; + return CRBits[RegEncoding]; +} +// showRegistersWithPrefix - This method determines whether registers +// should be number-only or include the prefix. +bool PPCInstPrinter::showRegistersWithPrefix() const { + if (TT.getOS() == Triple::AIX) + return false; + return TT.isOSDarwin() || FullRegNamesWithPercent || FullRegNames; +} + +/// stripRegisterPrefix - This method strips the character prefix from a +/// register name so that only the number is left. +static const char *stripRegisterPrefix(const char *RegName) { switch (RegName[0]) { case 'r': case 'f': case 'q': // for QPX case 'v': if (RegName[1] == 's') return RegName + 2; 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()) { unsigned Reg = Op.getReg(); // There are VSX instructions that use VSX register numbering (vs0 - vs63) // as well as those that use VMX register numbering (v0 - v31 which // correspond to vs32 - vs63). If we have an instruction that uses VSX // numbering, we need to convert the VMX registers to VSX registers. // Namely, we print 32-63 when the instruction operates on one of the // VMX registers. // (Please synchronize with PPCAsmPrinter::printOperand) if ((MII.get(MI->getOpcode()).TSFlags & PPCII::UseVSXReg) && !ShowVSRNumsAsVR) { if (PPCInstrInfo::isVRRegister(Reg)) Reg = PPC::VSX32 + (Reg - PPC::V0); else if (PPCInstrInfo::isVFRegister(Reg)) Reg = PPC::VSX32 + (Reg - PPC::VF0); } - const char *RegName = getRegisterName(Reg); - // The linux and AIX assembler does not take register prefixes. - if (!isDarwinSyntax()) - RegName = stripRegisterPrefix(RegName, Reg, MRI.getEncodingValue(Reg)); + const char *RegName; + RegName = getVerboseConditionRegName(Reg, MRI.getEncodingValue(Reg)); + if (RegName == nullptr) + RegName = getRegisterName(Reg); + if (showRegistersWithPercentPrefix(RegName)) + O << "%"; + if (!showRegistersWithPrefix()) + RegName = stripRegisterPrefix(RegName); O << RegName; return; } if (Op.isImm()) { O << Op.getImm(); return; } assert(Op.isExpr() && "unknown operand kind in printOperand"); Op.getExpr()->print(O, &MAI); } diff --git a/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h b/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h index 9c79ffb1176c..f000fbb98110 100644 --- a/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h +++ b/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h @@ -1,74 +1,77 @@ //===- PPCInstPrinter.h - Convert PPC MCInst to assembly syntax -*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This class prints an PPC MCInst to a .s file. // //===----------------------------------------------------------------------===// #ifndef LLVM_LIB_TARGET_POWERPC_INSTPRINTER_PPCINSTPRINTER_H #define LLVM_LIB_TARGET_POWERPC_INSTPRINTER_PPCINSTPRINTER_H +#include "llvm/ADT/Triple.h" #include "llvm/MC/MCInstPrinter.h" namespace llvm { class PPCInstPrinter : public MCInstPrinter { - bool IsDarwin; + Triple TT; +private: + bool showRegistersWithPercentPrefix(const char *RegName) const; + bool showRegistersWithPrefix() const; + const char *getVerboseConditionRegName(unsigned RegNum, + unsigned RegEncoding) const; + public: PPCInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, - const MCRegisterInfo &MRI, bool isDarwin) - : MCInstPrinter(MAI, MII, MRI), IsDarwin(isDarwin) {} - - bool isDarwinSyntax() const { - return IsDarwin; - } - + const MCRegisterInfo &MRI, Triple T) + : MCInstPrinter(MAI, MII, MRI), TT(T) {} + void printRegName(raw_ostream &OS, unsigned RegNo) const override; void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, const MCSubtargetInfo &STI) override; // Autogenerated by tblgen. void printInstruction(const MCInst *MI, raw_ostream &O); static const char *getRegisterName(unsigned RegNo); bool printAliasInstr(const MCInst *MI, raw_ostream &OS); void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx, unsigned PrintMethodIdx, raw_ostream &OS); void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printPredicateOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, const char *Modifier = nullptr); void printATBitsAsHint(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU1ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU2ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU3ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU4ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printS5ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU5ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU6ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU7ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU8ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU10ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU12ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printS16ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU16ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printBranchOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printAbsBranchOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printTLSCall(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printcrbitm(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printMemRegImm(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printMemRegReg(const MCInst *MI, unsigned OpNo, raw_ostream &O); }; } // end namespace llvm #endif diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp index 7044835cb8a9..a1e4e07b25af 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -1,276 +1,276 @@ //===-- PPCMCTargetDesc.cpp - PowerPC Target Descriptions -----------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file provides PowerPC specific target descriptions. // //===----------------------------------------------------------------------===// #include "MCTargetDesc/PPCMCTargetDesc.h" #include "InstPrinter/PPCInstPrinter.h" #include "MCTargetDesc/PPCMCAsmInfo.h" #include "PPCTargetStreamer.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; #define GET_INSTRINFO_MC_DESC #include "PPCGenInstrInfo.inc" #define GET_SUBTARGETINFO_MC_DESC #include "PPCGenSubtargetInfo.inc" #define GET_REGINFO_MC_DESC #include "PPCGenRegisterInfo.inc" // Pin the vtable to this file. PPCTargetStreamer::PPCTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} PPCTargetStreamer::~PPCTargetStreamer() = default; static MCInstrInfo *createPPCMCInstrInfo() { MCInstrInfo *X = new MCInstrInfo(); InitPPCMCInstrInfo(X); return X; } static MCRegisterInfo *createPPCMCRegisterInfo(const Triple &TT) { bool isPPC64 = (TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le); unsigned Flavour = isPPC64 ? 0 : 1; unsigned RA = isPPC64 ? PPC::LR8 : PPC::LR; MCRegisterInfo *X = new MCRegisterInfo(); InitPPCMCRegisterInfo(X, RA, Flavour, Flavour); return X; } static MCSubtargetInfo *createPPCMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { return createPPCMCSubtargetInfoImpl(TT, CPU, FS); } static MCAsmInfo *createPPCMCAsmInfo(const MCRegisterInfo &MRI, const Triple &TheTriple) { bool isPPC64 = (TheTriple.getArch() == Triple::ppc64 || TheTriple.getArch() == Triple::ppc64le); MCAsmInfo *MAI; if (TheTriple.isOSDarwin()) MAI = new PPCMCAsmInfoDarwin(isPPC64, TheTriple); else MAI = new PPCELFMCAsmInfo(isPPC64, TheTriple); // Initial state of the frame pointer is R1. unsigned Reg = isPPC64 ? PPC::X1 : PPC::R1; MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, MRI.getDwarfRegNum(Reg, true), 0); MAI->addInitialFrameState(Inst); return MAI; } namespace { class PPCTargetAsmStreamer : public PPCTargetStreamer { formatted_raw_ostream &OS; public: PPCTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS) : PPCTargetStreamer(S), OS(OS) {} void emitTCEntry(const MCSymbol &S) override { OS << "\t.tc "; OS << S.getName(); OS << "[TC],"; OS << S.getName(); OS << '\n'; } void emitMachine(StringRef CPU) override { OS << "\t.machine " << CPU << '\n'; } void emitAbiVersion(int AbiVersion) override { OS << "\t.abiversion " << AbiVersion << '\n'; } void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override { const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo(); OS << "\t.localentry\t"; S->print(OS, MAI); OS << ", "; LocalOffset->print(OS, MAI); OS << '\n'; } }; class PPCTargetELFStreamer : public PPCTargetStreamer { public: PPCTargetELFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {} MCELFStreamer &getStreamer() { return static_cast(Streamer); } void emitTCEntry(const MCSymbol &S) override { // Creates a R_PPC64_TOC relocation Streamer.EmitValueToAlignment(8); Streamer.EmitSymbolValue(&S, 8); } void emitMachine(StringRef CPU) override { // FIXME: Is there anything to do in here or does this directive only // limit the parser? } void emitAbiVersion(int AbiVersion) override { MCAssembler &MCA = getStreamer().getAssembler(); unsigned Flags = MCA.getELFHeaderEFlags(); Flags &= ~ELF::EF_PPC64_ABI; Flags |= (AbiVersion & ELF::EF_PPC64_ABI); MCA.setELFHeaderEFlags(Flags); } void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override { MCAssembler &MCA = getStreamer().getAssembler(); int64_t Res; if (!LocalOffset->evaluateAsAbsolute(Res, MCA)) report_fatal_error(".localentry expression must be absolute."); unsigned Encoded = ELF::encodePPC64LocalEntryOffset(Res); if (Res != ELF::decodePPC64LocalEntryOffset(Encoded)) report_fatal_error(".localentry expression cannot be encoded."); unsigned Other = S->getOther(); Other &= ~ELF::STO_PPC64_LOCAL_MASK; Other |= Encoded; S->setOther(Other); // For GAS compatibility, unless we already saw a .abiversion directive, // set e_flags to indicate ELFv2 ABI. unsigned Flags = MCA.getELFHeaderEFlags(); if ((Flags & ELF::EF_PPC64_ABI) == 0) MCA.setELFHeaderEFlags(Flags | 2); } void emitAssignment(MCSymbol *S, const MCExpr *Value) override { auto *Symbol = cast(S); // When encoding an assignment to set symbol A to symbol B, also copy // the st_other bits encoding the local entry point offset. if (Value->getKind() != MCExpr::SymbolRef) return; const auto &RhsSym = cast( static_cast(Value)->getSymbol()); unsigned Other = Symbol->getOther(); Other &= ~ELF::STO_PPC64_LOCAL_MASK; Other |= RhsSym.getOther() & ELF::STO_PPC64_LOCAL_MASK; Symbol->setOther(Other); } }; class PPCTargetMachOStreamer : public PPCTargetStreamer { public: PPCTargetMachOStreamer(MCStreamer &S) : PPCTargetStreamer(S) {} void emitTCEntry(const MCSymbol &S) override { llvm_unreachable("Unknown pseudo-op: .tc"); } void emitMachine(StringRef CPU) override { // FIXME: We should update the CPUType, CPUSubType in the Object file if // the new values are different from the defaults. } void emitAbiVersion(int AbiVersion) override { llvm_unreachable("Unknown pseudo-op: .abiversion"); } void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override { llvm_unreachable("Unknown pseudo-op: .localentry"); } }; } // end anonymous namespace static MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint, bool isVerboseAsm) { return new PPCTargetAsmStreamer(S, OS); } static MCTargetStreamer * createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { const Triple &TT = STI.getTargetTriple(); if (TT.isOSBinFormatELF()) return new PPCTargetELFStreamer(S); return new PPCTargetMachOStreamer(S); } static MCInstPrinter *createPPCMCInstPrinter(const Triple &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI) { - return new PPCInstPrinter(MAI, MII, MRI, T.isOSDarwin()); + return new PPCInstPrinter(MAI, MII, MRI, T); } extern "C" void LLVMInitializePowerPCTargetMC() { for (Target *T : {&getThePPC32Target(), &getThePPC64Target(), &getThePPC64LETarget()}) { // Register the MC asm info. RegisterMCAsmInfoFn C(*T, createPPCMCAsmInfo); // Register the MC instruction info. TargetRegistry::RegisterMCInstrInfo(*T, createPPCMCInstrInfo); // Register the MC register info. TargetRegistry::RegisterMCRegInfo(*T, createPPCMCRegisterInfo); // Register the MC subtarget info. TargetRegistry::RegisterMCSubtargetInfo(*T, createPPCMCSubtargetInfo); // Register the MC Code Emitter TargetRegistry::RegisterMCCodeEmitter(*T, createPPCMCCodeEmitter); // Register the asm backend. TargetRegistry::RegisterMCAsmBackend(*T, createPPCAsmBackend); // Register the object target streamer. TargetRegistry::RegisterObjectTargetStreamer(*T, createObjectTargetStreamer); // Register the asm target streamer. TargetRegistry::RegisterAsmTargetStreamer(*T, createAsmTargetStreamer); // Register the MCInstPrinter. TargetRegistry::RegisterMCInstPrinter(*T, createPPCMCInstPrinter); } } diff --git a/llvm/test/CodeGen/PowerPC/reg-names.ll b/llvm/test/CodeGen/PowerPC/reg-names.ll index 0ad11312513b..70c3b6087d48 100644 --- a/llvm/test/CodeGen/PowerPC/reg-names.ll +++ b/llvm/test/CodeGen/PowerPC/reg-names.ll @@ -1,17 +1,20 @@ ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu < %s | FileCheck %s ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -ppc-asm-full-reg-names < %s | FileCheck -check-prefix=CHECK-FN %s +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -ppc-reg-with-percent-prefix < %s | FileCheck -check-prefix=CHECK-PN %s define i64 @test1(i64 %a, i64 %b) { ; CHECK-LABEL: @test1 ; CHECK-FN-LABEL: @test1 entry: ret i64 %b ; CHECK: mr 3, 4 ; CHECK-FN: mr r3, r4 +; CHECK-PN: mr %r3, %r4 ; CHECK: blr ; CHECK-FN: blr +; CHECK-PN: blr }