aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp')
-rw-r--r--llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp124
1 files changed, 122 insertions, 2 deletions
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
index 676efc500455..fb65e7320f2b 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
@@ -48,7 +48,9 @@ getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
// Add a fixup for the branch target.
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
- (MCFixupKind)PPC::fixup_ppc_br24));
+ ((MI.getOpcode() == PPC::BL8_NOTOC)
+ ? (MCFixupKind)PPC::fixup_ppc_br24_notoc
+ : (MCFixupKind)PPC::fixup_ppc_br24)));
return 0;
}
@@ -102,6 +104,20 @@ unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo,
return 0;
}
+uint64_t
+PPCMCCodeEmitter::getImm34Encoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ if (MO.isReg() || MO.isImm())
+ return getMachineOpValue(MI, MO, Fixups, STI);
+
+ // Add a fixup for the immediate field.
+ Fixups.push_back(MCFixup::create(0, MO.getExpr(),
+ (MCFixupKind)PPC::fixup_ppc_pcrel34));
+ return 0;
+}
+
unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
@@ -159,6 +175,104 @@ unsigned PPCMCCodeEmitter::getMemRIX16Encoding(const MCInst &MI, unsigned OpNo,
return RegBits;
}
+uint64_t
+PPCMCCodeEmitter::getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ // Encode the PCRelative version of memri34: imm34(r0).
+ // In the PC relative version the register for the address must be zero.
+ // The 34 bit immediate can fall into one of three cases:
+ // 1) It is a relocation to be filled in by the linker represented as:
+ // (MCExpr::SymbolRef)
+ // 2) It is a relocation + SignedOffset represented as:
+ // (MCExpr::Binary(MCExpr::SymbolRef + MCExpr::Constant))
+ // 3) It is a known value at compile time.
+
+ // Make sure that the register is a zero as expected.
+ assert(MI.getOperand(OpNo + 1).isImm() && "Expecting an immediate.");
+ uint64_t RegBits =
+ getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI) << 34;
+ assert(RegBits == 0 && "Operand must be 0.");
+
+ // If this is not a MCExpr then we are in case 3) and we are dealing with
+ // a value known at compile time, not a relocation.
+ const MCOperand &MO = MI.getOperand(OpNo);
+ if (!MO.isExpr())
+ return ((getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL) | RegBits;
+
+ // At this point in the function it is known that MO is of type MCExpr.
+ // Therefore we are dealing with either case 1) a symbol ref or
+ // case 2) a symbol ref plus a constant.
+ const MCExpr *Expr = MO.getExpr();
+ switch (Expr->getKind()) {
+ default:
+ llvm_unreachable("Unsupported MCExpr for getMemRI34PCRelEncoding.");
+ case MCExpr::SymbolRef: {
+ // Relocation alone.
+ const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Expr);
+ (void)SRE;
+ // Currently these are the only valid PCRelative Relocations.
+ assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL ||
+ SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL) &&
+ "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL");
+ // Generate the fixup for the relocation.
+ Fixups.push_back(
+ MCFixup::create(0, Expr,
+ static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34)));
+ // Put zero in the location of the immediate. The linker will fill in the
+ // correct value based on the relocation.
+ return 0;
+ }
+ case MCExpr::Binary: {
+ // Relocation plus some offset.
+ const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
+ assert(BE->getOpcode() == MCBinaryExpr::Add &&
+ "Binary expression opcode must be an add.");
+
+ const MCExpr *LHS = BE->getLHS();
+ const MCExpr *RHS = BE->getRHS();
+
+ // Need to check in both directions. Reloc+Offset and Offset+Reloc.
+ if (LHS->getKind() != MCExpr::SymbolRef)
+ std::swap(LHS, RHS);
+
+ if (LHS->getKind() != MCExpr::SymbolRef ||
+ RHS->getKind() != MCExpr::Constant)
+ llvm_unreachable("Expecting to have one constant and one relocation.");
+
+ const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(LHS);
+ (void)SRE;
+ assert(isInt<34>(cast<MCConstantExpr>(RHS)->getValue()) &&
+ "Value must fit in 34 bits.");
+
+ // Currently these are the only valid PCRelative Relocations.
+ assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL ||
+ SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL) &&
+ "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL");
+ // Generate the fixup for the relocation.
+ Fixups.push_back(
+ MCFixup::create(0, Expr,
+ static_cast<MCFixupKind>(PPC::fixup_ppc_pcrel34)));
+ // Put zero in the location of the immediate. The linker will fill in the
+ // correct value based on the relocation.
+ return 0;
+ }
+ }
+}
+
+uint64_t
+PPCMCCodeEmitter::getMemRI34Encoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ // Encode (imm, reg) as a memri34, which has the low 34-bits as the
+ // displacement and the next 5 bits as the register #.
+ assert(MI.getOperand(OpNo + 1).isReg() && "Expecting a register.");
+ uint64_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI)
+ << 34;
+ const MCOperand &MO = MI.getOperand(OpNo);
+ return ((getMachineOpValue(MI, MO, Fixups, STI)) & 0x3FFFFFFFFUL) | RegBits;
+}
+
unsigned PPCMCCodeEmitter::getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI)
@@ -257,7 +371,7 @@ static unsigned getOpIdxForMO(const MCInst &MI, const MCOperand &MO) {
return ~0U; // Silence any warnings about no return.
}
-unsigned PPCMCCodeEmitter::
+uint64_t PPCMCCodeEmitter::
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
@@ -316,5 +430,11 @@ unsigned PPCMCCodeEmitter::getInstSizeInBytes(const MCInst &MI) const {
return Desc.getSize();
}
+bool PPCMCCodeEmitter::isPrefixedInstruction(const MCInst &MI) const {
+ unsigned Opcode = MI.getOpcode();
+ const PPCInstrInfo *InstrInfo = static_cast<const PPCInstrInfo*>(&MCII);
+ return InstrInfo->isPrefixed(Opcode);
+}
+
#define ENABLE_INSTR_PREDICATE_VERIFIER
#include "PPCGenMCCodeEmitter.inc"