mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 11:35:51 -04:00

Future CPU will include support for prefixed instructions. These prefixed instructions are formed by a 4 byte prefix immediately followed by a 4 byte instruction effectively making an 8 byte instruction. The new instruction paddi is a prefixed form of addi. This patch adds paddi and all of the support required for that instruction. The majority of the patch deals with supporting the new prefixed instructions. The addition of paddi is mainly to allow for testing. Differential Revision: https://reviews.llvm.org/D72569
583 lines
18 KiB
C++
583 lines
18 KiB
C++
//===-- PPCInstPrinter.cpp - Convert PPC MCInst to assembly syntax --------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This class prints an PPC MCInst to a .s file.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "MCTargetDesc/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<bool>
|
|
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<bool>
|
|
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<bool>
|
|
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, uint64_t Address,
|
|
StringRef Annot, const MCSubtargetInfo &STI,
|
|
raw_ostream &O) {
|
|
// Customize printing of the addis instruction on AIX. When an operand is a
|
|
// symbol reference, the instruction syntax is changed to look like a load
|
|
// operation, i.e:
|
|
// Transform: addis $rD, $rA, $src --> addis $rD, $src($rA).
|
|
if (TT.isOSAIX() &&
|
|
(MI->getOpcode() == PPC::ADDIS8 || MI->getOpcode() == PPC::ADDIS) &&
|
|
MI->getOperand(2).isExpr()) {
|
|
assert((MI->getOperand(0).isReg() && MI->getOperand(1).isReg()) &&
|
|
"The first and the second operand of an addis instruction"
|
|
" should be registers.");
|
|
|
|
assert(isa<MCSymbolRefExpr>(MI->getOperand(2).getExpr()) &&
|
|
"The third operand of an addis instruction should be a symbol "
|
|
"reference expression if it is an expression at all.");
|
|
|
|
O << "\taddis ";
|
|
printOperand(MI, 0, O);
|
|
O << ", ";
|
|
printOperand(MI, 2, O);
|
|
O << "(";
|
|
printOperand(MI, 1, O);
|
|
O << ")";
|
|
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;
|
|
|
|
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, Address, 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::printImmZeroOperand(const MCInst *MI, unsigned OpNo,
|
|
raw_ostream &O) {
|
|
unsigned int Value = MI->getOperand(OpNo).getImm();
|
|
assert(Value == 0 && "Operand must be zero");
|
|
O << (unsigned 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::printS34ImmOperand(const MCInst *MI, unsigned OpNo,
|
|
raw_ostream &O) {
|
|
long long Value = MI->getOperand(OpNo).getImm();
|
|
assert(isInt<34>(Value) && "Invalid s34imm argument!");
|
|
O << (long long)Value;
|
|
}
|
|
|
|
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 << ".";
|
|
int32_t Imm = SignExtend32<32>((unsigned)MI->getOperand(OpNo).getImm() << 2);
|
|
if (Imm >= 0)
|
|
O << "+";
|
|
O << Imm;
|
|
}
|
|
|
|
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 = nullptr;
|
|
const MCConstantExpr *ConstExp = nullptr;
|
|
if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Op.getExpr())) {
|
|
RefExp = cast<MCSymbolRefExpr>(BinExpr->getLHS());
|
|
ConstExp = cast<MCConstantExpr>(BinExpr->getRHS());
|
|
} else
|
|
RefExp = cast<MCSymbolRefExpr>(Op.getExpr());
|
|
|
|
O << RefExp->getSymbol().getName();
|
|
O << '(';
|
|
printOperand(MI, OpNo+1, O);
|
|
O << ')';
|
|
if (RefExp->getKind() != MCSymbolRefExpr::VK_None)
|
|
O << '@' << MCSymbolRefExpr::getVariantKindName(RefExp->getKind());
|
|
if (ConstExp != nullptr)
|
|
O << '+' << ConstExp->getValue();
|
|
}
|
|
|
|
/// 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;
|
|
|
|
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;
|
|
}
|
|
|
|
void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
|
raw_ostream &O) {
|
|
const MCOperand &Op = MI->getOperand(OpNo);
|
|
if (Op.isReg()) {
|
|
unsigned Reg = Op.getReg();
|
|
if (!ShowVSRNumsAsVR)
|
|
Reg = PPCInstrInfo::getRegNumForOperand(MII.get(MI->getOpcode()),
|
|
Reg, OpNo);
|
|
|
|
const char *RegName;
|
|
RegName = getVerboseConditionRegName(Reg, MRI.getEncodingValue(Reg));
|
|
if (RegName == nullptr)
|
|
RegName = getRegisterName(Reg);
|
|
if (showRegistersWithPercentPrefix(RegName))
|
|
O << "%";
|
|
if (!showRegistersWithPrefix())
|
|
RegName = PPCRegisterInfo::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);
|
|
}
|
|
|