You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
@ -1,10 +0,0 @@
|
||||
add_llvm_library(LLVMPowerPCDesc
|
||||
PPCAsmBackend.cpp
|
||||
PPCMCTargetDesc.cpp
|
||||
PPCMCAsmInfo.cpp
|
||||
PPCMCCodeEmitter.cpp
|
||||
PPCMCExpr.cpp
|
||||
PPCPredicates.cpp
|
||||
PPCMachObjectWriter.cpp
|
||||
PPCELFObjectWriter.cpp
|
||||
)
|
@ -1,23 +0,0 @@
|
||||
;===- ./lib/Target/PowerPC/MCTargetDesc/LLVMBuild.txt ----------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Library
|
||||
name = PowerPCDesc
|
||||
parent = PowerPC
|
||||
required_libraries = MC PowerPCAsmPrinter PowerPCInfo Support
|
||||
add_to_library_groups = PowerPC
|
@ -1,245 +0,0 @@
|
||||
//===-- PPCAsmBackend.cpp - PPC Assembler Backend -------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/PPCFixupKinds.h"
|
||||
#include "MCTargetDesc/PPCMCTargetDesc.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCFixupKindInfo.h"
|
||||
#include "llvm/MC/MCMachObjectWriter.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCSectionMachO.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/MCSymbolELF.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
using namespace llvm;
|
||||
|
||||
static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
|
||||
switch (Kind) {
|
||||
default:
|
||||
llvm_unreachable("Unknown fixup kind!");
|
||||
case FK_Data_1:
|
||||
case FK_Data_2:
|
||||
case FK_Data_4:
|
||||
case FK_Data_8:
|
||||
case PPC::fixup_ppc_nofixup:
|
||||
return Value;
|
||||
case PPC::fixup_ppc_brcond14:
|
||||
case PPC::fixup_ppc_brcond14abs:
|
||||
return Value & 0xfffc;
|
||||
case PPC::fixup_ppc_br24:
|
||||
case PPC::fixup_ppc_br24abs:
|
||||
return Value & 0x3fffffc;
|
||||
case PPC::fixup_ppc_half16:
|
||||
return Value & 0xffff;
|
||||
case PPC::fixup_ppc_half16ds:
|
||||
return Value & 0xfffc;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned getFixupKindNumBytes(unsigned Kind) {
|
||||
switch (Kind) {
|
||||
default:
|
||||
llvm_unreachable("Unknown fixup kind!");
|
||||
case FK_Data_1:
|
||||
return 1;
|
||||
case FK_Data_2:
|
||||
case PPC::fixup_ppc_half16:
|
||||
case PPC::fixup_ppc_half16ds:
|
||||
return 2;
|
||||
case FK_Data_4:
|
||||
case PPC::fixup_ppc_brcond14:
|
||||
case PPC::fixup_ppc_brcond14abs:
|
||||
case PPC::fixup_ppc_br24:
|
||||
case PPC::fixup_ppc_br24abs:
|
||||
return 4;
|
||||
case FK_Data_8:
|
||||
return 8;
|
||||
case PPC::fixup_ppc_nofixup:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class PPCAsmBackend : public MCAsmBackend {
|
||||
const Target &TheTarget;
|
||||
bool IsLittleEndian;
|
||||
public:
|
||||
PPCAsmBackend(const Target &T, bool isLittle) : MCAsmBackend(), TheTarget(T),
|
||||
IsLittleEndian(isLittle) {}
|
||||
|
||||
unsigned getNumFixupKinds() const override {
|
||||
return PPC::NumTargetFixupKinds;
|
||||
}
|
||||
|
||||
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
|
||||
const static MCFixupKindInfo InfosBE[PPC::NumTargetFixupKinds] = {
|
||||
// name offset bits flags
|
||||
{ "fixup_ppc_br24", 6, 24, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_ppc_brcond14", 16, 14, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_ppc_br24abs", 6, 24, 0 },
|
||||
{ "fixup_ppc_brcond14abs", 16, 14, 0 },
|
||||
{ "fixup_ppc_half16", 0, 16, 0 },
|
||||
{ "fixup_ppc_half16ds", 0, 14, 0 },
|
||||
{ "fixup_ppc_nofixup", 0, 0, 0 }
|
||||
};
|
||||
const static MCFixupKindInfo InfosLE[PPC::NumTargetFixupKinds] = {
|
||||
// name offset bits flags
|
||||
{ "fixup_ppc_br24", 2, 24, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_ppc_brcond14", 2, 14, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_ppc_br24abs", 2, 24, 0 },
|
||||
{ "fixup_ppc_brcond14abs", 2, 14, 0 },
|
||||
{ "fixup_ppc_half16", 0, 16, 0 },
|
||||
{ "fixup_ppc_half16ds", 2, 14, 0 },
|
||||
{ "fixup_ppc_nofixup", 0, 0, 0 }
|
||||
};
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
return MCAsmBackend::getFixupKindInfo(Kind);
|
||||
|
||||
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
|
||||
"Invalid kind!");
|
||||
return (IsLittleEndian? InfosLE : InfosBE)[Kind - FirstTargetFixupKind];
|
||||
}
|
||||
|
||||
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target, MutableArrayRef<char> Data,
|
||||
uint64_t Value, bool IsResolved) const override {
|
||||
Value = adjustFixupValue(Fixup.getKind(), Value);
|
||||
if (!Value) return; // Doesn't change encoding.
|
||||
|
||||
unsigned Offset = Fixup.getOffset();
|
||||
unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
|
||||
|
||||
// For each byte of the fragment that the fixup touches, mask in the bits
|
||||
// from the fixup value. The Value has been "split up" into the appropriate
|
||||
// bitfields above.
|
||||
for (unsigned i = 0; i != NumBytes; ++i) {
|
||||
unsigned Idx = IsLittleEndian ? i : (NumBytes - 1 - i);
|
||||
Data[Offset + i] |= uint8_t((Value >> (Idx * 8)) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target) override {
|
||||
switch ((PPC::Fixups)Fixup.getKind()) {
|
||||
default:
|
||||
return false;
|
||||
case PPC::fixup_ppc_br24:
|
||||
case PPC::fixup_ppc_br24abs:
|
||||
// If the target symbol has a local entry point we must not attempt
|
||||
// to resolve the fixup directly. Emit a relocation and leave
|
||||
// resolution of the final target address to the linker.
|
||||
if (const MCSymbolRefExpr *A = Target.getSymA()) {
|
||||
if (const auto *S = dyn_cast<MCSymbolELF>(&A->getSymbol())) {
|
||||
// The "other" values are stored in the last 6 bits of the second
|
||||
// byte. The traditional defines for STO values assume the full byte
|
||||
// and thus the shift to pack it.
|
||||
unsigned Other = S->getOther() << 2;
|
||||
if ((Other & ELF::STO_PPC64_LOCAL_MASK) != 0)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool mayNeedRelaxation(const MCInst &Inst) const override {
|
||||
// FIXME.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fixupNeedsRelaxation(const MCFixup &Fixup,
|
||||
uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const override {
|
||||
// FIXME.
|
||||
llvm_unreachable("relaxInstruction() unimplemented");
|
||||
}
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override {
|
||||
// FIXME.
|
||||
llvm_unreachable("relaxInstruction() unimplemented");
|
||||
}
|
||||
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override {
|
||||
uint64_t NumNops = Count / 4;
|
||||
for (uint64_t i = 0; i != NumNops; ++i)
|
||||
OW->write32(0x60000000);
|
||||
|
||||
OW->WriteZeros(Count % 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned getPointerSize() const {
|
||||
StringRef Name = TheTarget.getName();
|
||||
if (Name == "ppc64" || Name == "ppc64le") return 8;
|
||||
assert(Name == "ppc32" && "Unknown target name!");
|
||||
return 4;
|
||||
}
|
||||
|
||||
bool isLittleEndian() const {
|
||||
return IsLittleEndian;
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
// FIXME: This should be in a separate file.
|
||||
namespace {
|
||||
class DarwinPPCAsmBackend : public PPCAsmBackend {
|
||||
public:
|
||||
DarwinPPCAsmBackend(const Target &T) : PPCAsmBackend(T, false) { }
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
createObjectWriter(raw_pwrite_stream &OS) const override {
|
||||
bool is64 = getPointerSize() == 8;
|
||||
return createPPCMachObjectWriter(
|
||||
OS,
|
||||
/*Is64Bit=*/is64,
|
||||
(is64 ? MachO::CPU_TYPE_POWERPC64 : MachO::CPU_TYPE_POWERPC),
|
||||
MachO::CPU_SUBTYPE_POWERPC_ALL);
|
||||
}
|
||||
};
|
||||
|
||||
class ELFPPCAsmBackend : public PPCAsmBackend {
|
||||
uint8_t OSABI;
|
||||
public:
|
||||
ELFPPCAsmBackend(const Target &T, bool IsLittleEndian, uint8_t OSABI) :
|
||||
PPCAsmBackend(T, IsLittleEndian), OSABI(OSABI) { }
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
createObjectWriter(raw_pwrite_stream &OS) const override {
|
||||
bool is64 = getPointerSize() == 8;
|
||||
return createPPCELFObjectWriter(OS, is64, isLittleEndian(), OSABI);
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
MCAsmBackend *llvm::createPPCAsmBackend(const Target &T,
|
||||
const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI,
|
||||
const MCTargetOptions &Options) {
|
||||
const Triple &TT = STI.getTargetTriple();
|
||||
if (TT.isOSDarwin())
|
||||
return new DarwinPPCAsmBackend(T);
|
||||
|
||||
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
|
||||
bool IsLittleEndian = TT.getArch() == Triple::ppc64le;
|
||||
return new ELFPPCAsmBackend(T, IsLittleEndian, OSABI);
|
||||
}
|
@ -1,425 +0,0 @@
|
||||
//===-- PPCELFObjectWriter.cpp - PPC ELF Writer ---------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/PPCFixupKinds.h"
|
||||
#include "MCTargetDesc/PPCMCExpr.h"
|
||||
#include "MCTargetDesc/PPCMCTargetDesc.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCSymbolELF.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class PPCELFObjectWriter : public MCELFObjectTargetWriter {
|
||||
public:
|
||||
PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
|
||||
|
||||
protected:
|
||||
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
|
||||
const MCFixup &Fixup, bool IsPCRel) const override;
|
||||
|
||||
bool needsRelocateWithSymbol(const MCSymbol &Sym,
|
||||
unsigned Type) const override;
|
||||
};
|
||||
}
|
||||
|
||||
PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
|
||||
: MCELFObjectTargetWriter(Is64Bit, OSABI,
|
||||
Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC,
|
||||
/*HasRelocationAddend*/ true) {}
|
||||
|
||||
static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target,
|
||||
const MCFixup &Fixup) {
|
||||
const MCExpr *Expr = Fixup.getValue();
|
||||
|
||||
if (Expr->getKind() != MCExpr::Target)
|
||||
return Target.getAccessVariant();
|
||||
|
||||
switch (cast<PPCMCExpr>(Expr)->getKind()) {
|
||||
case PPCMCExpr::VK_PPC_None:
|
||||
return MCSymbolRefExpr::VK_None;
|
||||
case PPCMCExpr::VK_PPC_LO:
|
||||
return MCSymbolRefExpr::VK_PPC_LO;
|
||||
case PPCMCExpr::VK_PPC_HI:
|
||||
return MCSymbolRefExpr::VK_PPC_HI;
|
||||
case PPCMCExpr::VK_PPC_HA:
|
||||
return MCSymbolRefExpr::VK_PPC_HA;
|
||||
case PPCMCExpr::VK_PPC_HIGHERA:
|
||||
return MCSymbolRefExpr::VK_PPC_HIGHERA;
|
||||
case PPCMCExpr::VK_PPC_HIGHER:
|
||||
return MCSymbolRefExpr::VK_PPC_HIGHER;
|
||||
case PPCMCExpr::VK_PPC_HIGHEST:
|
||||
return MCSymbolRefExpr::VK_PPC_HIGHEST;
|
||||
case PPCMCExpr::VK_PPC_HIGHESTA:
|
||||
return MCSymbolRefExpr::VK_PPC_HIGHESTA;
|
||||
}
|
||||
llvm_unreachable("unknown PPCMCExpr kind");
|
||||
}
|
||||
|
||||
unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);
|
||||
|
||||
// determine the type of the relocation
|
||||
unsigned Type;
|
||||
if (IsPCRel) {
|
||||
switch ((unsigned)Fixup.getKind()) {
|
||||
default:
|
||||
llvm_unreachable("Unimplemented");
|
||||
case PPC::fixup_ppc_br24:
|
||||
case PPC::fixup_ppc_br24abs:
|
||||
switch (Modifier) {
|
||||
default: llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
Type = ELF::R_PPC_REL24;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PLT:
|
||||
Type = ELF::R_PPC_PLTREL24;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_LOCAL:
|
||||
Type = ELF::R_PPC_LOCAL24PC;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PPC::fixup_ppc_brcond14:
|
||||
case PPC::fixup_ppc_brcond14abs:
|
||||
Type = ELF::R_PPC_REL14;
|
||||
break;
|
||||
case PPC::fixup_ppc_half16:
|
||||
switch (Modifier) {
|
||||
default: llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
Type = ELF::R_PPC_REL16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_LO:
|
||||
Type = ELF::R_PPC_REL16_LO;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_HI:
|
||||
Type = ELF::R_PPC_REL16_HI;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_HA:
|
||||
Type = ELF::R_PPC_REL16_HA;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PPC::fixup_ppc_half16ds:
|
||||
Target.print(errs());
|
||||
errs() << '\n';
|
||||
report_fatal_error("Invalid PC-relative half16ds relocation");
|
||||
case FK_Data_4:
|
||||
case FK_PCRel_4:
|
||||
Type = ELF::R_PPC_REL32;
|
||||
break;
|
||||
case FK_Data_8:
|
||||
case FK_PCRel_8:
|
||||
Type = ELF::R_PPC64_REL64;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch ((unsigned)Fixup.getKind()) {
|
||||
default: llvm_unreachable("invalid fixup kind!");
|
||||
case PPC::fixup_ppc_br24abs:
|
||||
Type = ELF::R_PPC_ADDR24;
|
||||
break;
|
||||
case PPC::fixup_ppc_brcond14abs:
|
||||
Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
|
||||
break;
|
||||
case PPC::fixup_ppc_half16:
|
||||
switch (Modifier) {
|
||||
default: llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
Type = ELF::R_PPC_ADDR16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_LO:
|
||||
Type = ELF::R_PPC_ADDR16_LO;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_HI:
|
||||
Type = ELF::R_PPC_ADDR16_HI;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_HA:
|
||||
Type = ELF::R_PPC_ADDR16_HA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_HIGHER:
|
||||
Type = ELF::R_PPC64_ADDR16_HIGHER;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_HIGHERA:
|
||||
Type = ELF::R_PPC64_ADDR16_HIGHERA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_HIGHEST:
|
||||
Type = ELF::R_PPC64_ADDR16_HIGHEST;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_HIGHESTA:
|
||||
Type = ELF::R_PPC64_ADDR16_HIGHESTA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_GOT:
|
||||
Type = ELF::R_PPC_GOT16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_LO:
|
||||
Type = ELF::R_PPC_GOT16_LO;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_HI:
|
||||
Type = ELF::R_PPC_GOT16_HI;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_HA:
|
||||
Type = ELF::R_PPC_GOT16_HA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TOC:
|
||||
Type = ELF::R_PPC64_TOC16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TOC_LO:
|
||||
Type = ELF::R_PPC64_TOC16_LO;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TOC_HI:
|
||||
Type = ELF::R_PPC64_TOC16_HI;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TOC_HA:
|
||||
Type = ELF::R_PPC64_TOC16_HA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_TPREL:
|
||||
Type = ELF::R_PPC_TPREL16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TPREL_LO:
|
||||
Type = ELF::R_PPC_TPREL16_LO;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TPREL_HI:
|
||||
Type = ELF::R_PPC_TPREL16_HI;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TPREL_HA:
|
||||
Type = ELF::R_PPC_TPREL16_HA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
|
||||
Type = ELF::R_PPC64_TPREL16_HIGHER;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
|
||||
Type = ELF::R_PPC64_TPREL16_HIGHERA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
|
||||
Type = ELF::R_PPC64_TPREL16_HIGHEST;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
|
||||
Type = ELF::R_PPC64_TPREL16_HIGHESTA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_DTPREL:
|
||||
Type = ELF::R_PPC64_DTPREL16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
|
||||
Type = ELF::R_PPC64_DTPREL16_LO;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
|
||||
Type = ELF::R_PPC64_DTPREL16_HI;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
|
||||
Type = ELF::R_PPC64_DTPREL16_HA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
|
||||
Type = ELF::R_PPC64_DTPREL16_HIGHER;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
|
||||
Type = ELF::R_PPC64_DTPREL16_HIGHERA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
|
||||
Type = ELF::R_PPC64_DTPREL16_HIGHEST;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
|
||||
Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
|
||||
if (is64Bit())
|
||||
Type = ELF::R_PPC64_GOT_TLSGD16;
|
||||
else
|
||||
Type = ELF::R_PPC_GOT_TLSGD16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
|
||||
Type = ELF::R_PPC64_GOT_TLSGD16_LO;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
|
||||
Type = ELF::R_PPC64_GOT_TLSGD16_HI;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
|
||||
Type = ELF::R_PPC64_GOT_TLSGD16_HA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
|
||||
if (is64Bit())
|
||||
Type = ELF::R_PPC64_GOT_TLSLD16;
|
||||
else
|
||||
Type = ELF::R_PPC_GOT_TLSLD16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
|
||||
Type = ELF::R_PPC64_GOT_TLSLD16_LO;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
|
||||
Type = ELF::R_PPC64_GOT_TLSLD16_HI;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
|
||||
Type = ELF::R_PPC64_GOT_TLSLD16_HA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
|
||||
/* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
|
||||
are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */
|
||||
Type = ELF::R_PPC64_GOT_TPREL16_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
|
||||
/* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
|
||||
are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */
|
||||
Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
|
||||
Type = ELF::R_PPC64_GOT_TPREL16_HI;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
|
||||
/* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
|
||||
are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */
|
||||
Type = ELF::R_PPC64_GOT_DTPREL16_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
|
||||
/* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
|
||||
are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */
|
||||
Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
|
||||
Type = ELF::R_PPC64_GOT_TPREL16_HA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
|
||||
Type = ELF::R_PPC64_GOT_DTPREL16_HI;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
|
||||
Type = ELF::R_PPC64_GOT_DTPREL16_HA;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PPC::fixup_ppc_half16ds:
|
||||
switch (Modifier) {
|
||||
default: llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
Type = ELF::R_PPC64_ADDR16_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_LO:
|
||||
Type = ELF::R_PPC64_ADDR16_LO_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_GOT:
|
||||
Type = ELF::R_PPC64_GOT16_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_LO:
|
||||
Type = ELF::R_PPC64_GOT16_LO_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TOC:
|
||||
Type = ELF::R_PPC64_TOC16_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TOC_LO:
|
||||
Type = ELF::R_PPC64_TOC16_LO_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_TPREL:
|
||||
Type = ELF::R_PPC64_TPREL16_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TPREL_LO:
|
||||
Type = ELF::R_PPC64_TPREL16_LO_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_DTPREL:
|
||||
Type = ELF::R_PPC64_DTPREL16_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
|
||||
Type = ELF::R_PPC64_DTPREL16_LO_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
|
||||
Type = ELF::R_PPC64_GOT_TPREL16_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
|
||||
Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
|
||||
Type = ELF::R_PPC64_GOT_DTPREL16_DS;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
|
||||
Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PPC::fixup_ppc_nofixup:
|
||||
switch (Modifier) {
|
||||
default: llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_PPC_TLSGD:
|
||||
if (is64Bit())
|
||||
Type = ELF::R_PPC64_TLSGD;
|
||||
else
|
||||
Type = ELF::R_PPC_TLSGD;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TLSLD:
|
||||
if (is64Bit())
|
||||
Type = ELF::R_PPC64_TLSLD;
|
||||
else
|
||||
Type = ELF::R_PPC_TLSLD;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TLS:
|
||||
if (is64Bit())
|
||||
Type = ELF::R_PPC64_TLS;
|
||||
else
|
||||
Type = ELF::R_PPC_TLS;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FK_Data_8:
|
||||
switch (Modifier) {
|
||||
default: llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_PPC_TOCBASE:
|
||||
Type = ELF::R_PPC64_TOC;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
Type = ELF::R_PPC64_ADDR64;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_DTPMOD:
|
||||
Type = ELF::R_PPC64_DTPMOD64;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_TPREL:
|
||||
Type = ELF::R_PPC64_TPREL64;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_DTPREL:
|
||||
Type = ELF::R_PPC64_DTPREL64;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FK_Data_4:
|
||||
Type = ELF::R_PPC_ADDR32;
|
||||
break;
|
||||
case FK_Data_2:
|
||||
Type = ELF::R_PPC_ADDR16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Type;
|
||||
}
|
||||
|
||||
bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
|
||||
unsigned Type) const {
|
||||
switch (Type) {
|
||||
default:
|
||||
return false;
|
||||
|
||||
case ELF::R_PPC_REL24:
|
||||
// If the target symbol has a local entry point, we must keep the
|
||||
// target symbol to preserve that information for the linker.
|
||||
// The "other" values are stored in the last 6 bits of the second byte.
|
||||
// The traditional defines for STO values assume the full byte and thus
|
||||
// the shift to pack it.
|
||||
unsigned Other = cast<MCSymbolELF>(Sym).getOther() << 2;
|
||||
return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
llvm::createPPCELFObjectWriter(raw_pwrite_stream &OS, bool Is64Bit,
|
||||
bool IsLittleEndian, uint8_t OSABI) {
|
||||
auto MOTW = llvm::make_unique<PPCELFObjectWriter>(Is64Bit, OSABI);
|
||||
return createELFObjectWriter(std::move(MOTW), OS, IsLittleEndian);
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
//===-- PPCFixupKinds.h - PPC Specific Fixup Entries ------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCFIXUPKINDS_H
|
||||
#define LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCFIXUPKINDS_H
|
||||
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
|
||||
#undef PPC
|
||||
|
||||
namespace llvm {
|
||||
namespace PPC {
|
||||
enum Fixups {
|
||||
// 24-bit PC relative relocation for direct branches like 'b' and 'bl'.
|
||||
fixup_ppc_br24 = FirstTargetFixupKind,
|
||||
|
||||
/// 14-bit PC relative relocation for conditional branches.
|
||||
fixup_ppc_brcond14,
|
||||
|
||||
/// 24-bit absolute relocation for direct branches like 'ba' and 'bla'.
|
||||
fixup_ppc_br24abs,
|
||||
|
||||
/// 14-bit absolute relocation for conditional branches.
|
||||
fixup_ppc_brcond14abs,
|
||||
|
||||
/// A 16-bit fixup corresponding to lo16(_foo) or ha16(_foo) for instrs like
|
||||
/// 'li' or 'addis'.
|
||||
fixup_ppc_half16,
|
||||
|
||||
/// A 14-bit fixup corresponding to lo16(_foo) with implied 2 zero bits for
|
||||
/// instrs like 'std'.
|
||||
fixup_ppc_half16ds,
|
||||
|
||||
/// Not a true fixup, but ties a symbol to a call to __tls_get_addr for the
|
||||
/// TLS general and local dynamic models, or inserts the thread-pointer
|
||||
/// register number.
|
||||
fixup_ppc_nofixup,
|
||||
|
||||
// Marker
|
||||
LastTargetFixupKind,
|
||||
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,84 +0,0 @@
|
||||
//===-- PPCMCAsmInfo.cpp - PPC asm properties -----------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declarations of the MCAsmInfoDarwin properties.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "PPCMCAsmInfo.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void PPCMCAsmInfoDarwin::anchor() { }
|
||||
|
||||
PPCMCAsmInfoDarwin::PPCMCAsmInfoDarwin(bool is64Bit, const Triple& T) {
|
||||
if (is64Bit) {
|
||||
CodePointerSize = CalleeSaveStackSlotSize = 8;
|
||||
}
|
||||
IsLittleEndian = false;
|
||||
|
||||
SeparatorString = "@";
|
||||
CommentString = ";";
|
||||
ExceptionsType = ExceptionHandling::DwarfCFI;
|
||||
|
||||
if (!is64Bit)
|
||||
Data64bitsDirective = nullptr; // We can't emit a 64-bit unit in PPC32 mode.
|
||||
|
||||
AssemblerDialect = 1; // New-Style mnemonics.
|
||||
SupportsDebugInformation= true; // Debug information.
|
||||
|
||||
// The installed assembler for OSX < 10.6 lacks some directives.
|
||||
// FIXME: this should really be a check on the assembler characteristics
|
||||
// rather than OS version
|
||||
if (T.isMacOSX() && T.isMacOSXVersionLT(10, 6))
|
||||
HasWeakDefCanBeHiddenDirective = false;
|
||||
|
||||
UseIntegratedAssembler = true;
|
||||
}
|
||||
|
||||
void PPCELFMCAsmInfo::anchor() { }
|
||||
|
||||
PPCELFMCAsmInfo::PPCELFMCAsmInfo(bool is64Bit, const Triple& T) {
|
||||
// FIXME: This is not always needed. For example, it is not needed in the
|
||||
// v2 abi.
|
||||
NeedsLocalForSize = true;
|
||||
|
||||
if (is64Bit) {
|
||||
CodePointerSize = CalleeSaveStackSlotSize = 8;
|
||||
}
|
||||
IsLittleEndian = T.getArch() == Triple::ppc64le;
|
||||
|
||||
// ".comm align is in bytes but .align is pow-2."
|
||||
AlignmentIsInBytes = false;
|
||||
|
||||
CommentString = "#";
|
||||
|
||||
// Uses '.section' before '.bss' directive
|
||||
UsesELFSectionDirectiveForBSS = true;
|
||||
|
||||
// Debug Information
|
||||
SupportsDebugInformation = true;
|
||||
|
||||
DollarIsPC = true;
|
||||
|
||||
// Set up DWARF directives
|
||||
MinInstAlignment = 4;
|
||||
|
||||
// Exceptions handling
|
||||
ExceptionsType = ExceptionHandling::DwarfCFI;
|
||||
|
||||
ZeroDirective = "\t.space\t";
|
||||
Data64bitsDirective = is64Bit ? "\t.quad\t" : nullptr;
|
||||
AssemblerDialect = 1; // New-Style mnemonics.
|
||||
LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment;
|
||||
|
||||
UseIntegratedAssembler = true;
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
//===-- PPCMCAsmInfo.h - PPC asm properties --------------------*- C++ -*--===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declaration of the MCAsmInfoDarwin class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCMCASMINFO_H
|
||||
#define LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCMCASMINFO_H
|
||||
|
||||
#include "llvm/MC/MCAsmInfoDarwin.h"
|
||||
#include "llvm/MC/MCAsmInfoELF.h"
|
||||
|
||||
namespace llvm {
|
||||
class Triple;
|
||||
|
||||
class PPCMCAsmInfoDarwin : public MCAsmInfoDarwin {
|
||||
virtual void anchor();
|
||||
|
||||
public:
|
||||
explicit PPCMCAsmInfoDarwin(bool is64Bit, const Triple &);
|
||||
};
|
||||
|
||||
class PPCELFMCAsmInfo : public MCAsmInfoELF {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
explicit PPCELFMCAsmInfo(bool is64Bit, const Triple &);
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
@ -1,390 +0,0 @@
|
||||
//===-- PPCMCCodeEmitter.cpp - Convert PPC code to machine code -----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the PPCMCCodeEmitter class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/PPCFixupKinds.h"
|
||||
#include "PPCInstrInfo.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCInstrDesc.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/EndianStream.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "mccodeemitter"
|
||||
|
||||
STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
|
||||
|
||||
namespace {
|
||||
|
||||
class PPCMCCodeEmitter : public MCCodeEmitter {
|
||||
const MCInstrInfo &MCII;
|
||||
const MCContext &CTX;
|
||||
bool IsLittleEndian;
|
||||
|
||||
public:
|
||||
PPCMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
|
||||
: MCII(mcii), CTX(ctx),
|
||||
IsLittleEndian(ctx.getAsmInfo()->isLittleEndian()) {}
|
||||
PPCMCCodeEmitter(const PPCMCCodeEmitter &) = delete;
|
||||
void operator=(const PPCMCCodeEmitter &) = delete;
|
||||
~PPCMCCodeEmitter() override = default;
|
||||
|
||||
unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getImm16Encoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getMemRIX16Encoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getSPE4DisEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getSPE2DisEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
/// getMachineOpValue - Return binary encoding of operand. If the machine
|
||||
/// operand requires relocation, record the relocation and return zero.
|
||||
unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
// getBinaryCodeForInstr - TableGen'erated function for getting the
|
||||
// binary encoding for an instruction.
|
||||
uint64_t getBinaryCodeForInstr(const MCInst &MI,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
void encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const override {
|
||||
verifyInstructionPredicates(MI,
|
||||
computeAvailableFeatures(STI.getFeatureBits()));
|
||||
|
||||
unsigned Opcode = MI.getOpcode();
|
||||
const MCInstrDesc &Desc = MCII.get(Opcode);
|
||||
|
||||
uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
|
||||
|
||||
// Output the constant in big/little endian byte order.
|
||||
unsigned Size = Desc.getSize();
|
||||
switch (Size) {
|
||||
case 0:
|
||||
break;
|
||||
case 4:
|
||||
if (IsLittleEndian) {
|
||||
support::endian::Writer<support::little>(OS).write<uint32_t>(Bits);
|
||||
} else {
|
||||
support::endian::Writer<support::big>(OS).write<uint32_t>(Bits);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
// If we emit a pair of instructions, the first one is
|
||||
// always in the top 32 bits, even on little-endian.
|
||||
if (IsLittleEndian) {
|
||||
uint64_t Swapped = (Bits << 32) | (Bits >> 32);
|
||||
support::endian::Writer<support::little>(OS).write<uint64_t>(Swapped);
|
||||
} else {
|
||||
support::endian::Writer<support::big>(OS).write<uint64_t>(Bits);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Invalid instruction size");
|
||||
}
|
||||
|
||||
++MCNumEmitted; // Keep track of the # of mi's emitted.
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t computeAvailableFeatures(const FeatureBitset &FB) const;
|
||||
void verifyInstructionPredicates(const MCInst &MI,
|
||||
uint64_t AvailableFeatures) const;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
MCContext &Ctx) {
|
||||
return new PPCMCCodeEmitter(MCII, Ctx);
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::
|
||||
getDirectBrEncoding(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 branch target.
|
||||
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_br24));
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::getCondBrEncoding(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 branch target.
|
||||
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_brcond14));
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::
|
||||
getAbsDirectBrEncoding(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 branch target.
|
||||
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_br24abs));
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::
|
||||
getAbsCondBrEncoding(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 branch target.
|
||||
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_brcond14abs));
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::getImm16Encoding(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(IsLittleEndian? 0 : 2, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_half16));
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
// Encode (imm, reg) as a memri, which has the low 16-bits as the
|
||||
// displacement and the next 5 bits as the register #.
|
||||
assert(MI.getOperand(OpNo+1).isReg());
|
||||
unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 16;
|
||||
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
if (MO.isImm())
|
||||
return (getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF) | RegBits;
|
||||
|
||||
// Add a fixup for the displacement field.
|
||||
Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_half16));
|
||||
return RegBits;
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
// Encode (imm, reg) as a memrix, which has the low 14-bits as the
|
||||
// displacement and the next 5 bits as the register #.
|
||||
assert(MI.getOperand(OpNo+1).isReg());
|
||||
unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 14;
|
||||
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
if (MO.isImm())
|
||||
return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF) | RegBits;
|
||||
|
||||
// Add a fixup for the displacement field.
|
||||
Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_half16ds));
|
||||
return RegBits;
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::getMemRIX16Encoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
// Encode (imm, reg) as a memrix16, which has the low 12-bits as the
|
||||
// displacement and the next 5 bits as the register #.
|
||||
assert(MI.getOperand(OpNo+1).isReg());
|
||||
unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 12;
|
||||
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
assert(MO.isImm() && !(MO.getImm() % 16) &&
|
||||
"Expecting an immediate that is a multiple of 16");
|
||||
|
||||
return ((getMachineOpValue(MI, MO, Fixups, STI) >> 4) & 0xFFF) | RegBits;
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI)
|
||||
const {
|
||||
// Encode (imm, reg) as a spe8dis, which has the low 5-bits of (imm / 8)
|
||||
// as the displacement and the next 5 bits as the register #.
|
||||
assert(MI.getOperand(OpNo+1).isReg());
|
||||
uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
|
||||
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
assert(MO.isImm());
|
||||
uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 3;
|
||||
return reverseBits(Imm | RegBits) >> 22;
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::getSPE4DisEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI)
|
||||
const {
|
||||
// Encode (imm, reg) as a spe4dis, which has the low 5-bits of (imm / 4)
|
||||
// as the displacement and the next 5 bits as the register #.
|
||||
assert(MI.getOperand(OpNo+1).isReg());
|
||||
uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
|
||||
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
assert(MO.isImm());
|
||||
uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 2;
|
||||
return reverseBits(Imm | RegBits) >> 22;
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::getSPE2DisEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI)
|
||||
const {
|
||||
// Encode (imm, reg) as a spe2dis, which has the low 5-bits of (imm / 2)
|
||||
// as the displacement and the next 5 bits as the register #.
|
||||
assert(MI.getOperand(OpNo+1).isReg());
|
||||
uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
|
||||
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
assert(MO.isImm());
|
||||
uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 1;
|
||||
return reverseBits(Imm | RegBits) >> 22;
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI);
|
||||
|
||||
// Add a fixup for the TLS register, which simply provides a relocation
|
||||
// hint to the linker that this statement is part of a relocation sequence.
|
||||
// Return the thread-pointer register's encoding.
|
||||
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_nofixup));
|
||||
const Triple &TT = STI.getTargetTriple();
|
||||
bool isPPC64 = TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le;
|
||||
return CTX.getRegisterInfo()->getEncodingValue(isPPC64 ? PPC::X13 : PPC::R2);
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
// For special TLS calls, we need two fixups; one for the branch target
|
||||
// (__tls_get_addr), which we create via getDirectBrEncoding as usual,
|
||||
// and one for the TLSGD or TLSLD symbol, which is emitted here.
|
||||
const MCOperand &MO = MI.getOperand(OpNo+1);
|
||||
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_nofixup));
|
||||
return getDirectBrEncoding(MI, OpNo, Fixups, STI);
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::
|
||||
get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 ||
|
||||
MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) &&
|
||||
(MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
|
||||
return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
|
||||
}
|
||||
|
||||
unsigned PPCMCCodeEmitter::
|
||||
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
if (MO.isReg()) {
|
||||
// MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
|
||||
// The GPR operand should come through here though.
|
||||
assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&
|
||||
MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||
|
||||
MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
|
||||
unsigned Reg = MO.getReg();
|
||||
unsigned Encode = CTX.getRegisterInfo()->getEncodingValue(Reg);
|
||||
|
||||
if ((MCII.get(MI.getOpcode()).TSFlags & PPCII::UseVSXReg))
|
||||
if (PPCInstrInfo::isVRRegister(Reg))
|
||||
Encode += 32;
|
||||
|
||||
return Encode;
|
||||
}
|
||||
|
||||
assert(MO.isImm() &&
|
||||
"Relocation required in an instruction that we cannot encode!");
|
||||
return MO.getImm();
|
||||
}
|
||||
|
||||
#define ENABLE_INSTR_PREDICATE_VERIFIER
|
||||
#include "PPCGenMCCodeEmitter.inc"
|
@ -1,150 +0,0 @@
|
||||
//===-- PPCMCExpr.cpp - PPC specific MC expression classes ----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "PPCMCExpr.h"
|
||||
#include "PPCFixupKinds.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCObjectStreamer.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "ppcmcexpr"
|
||||
|
||||
const PPCMCExpr*
|
||||
PPCMCExpr::create(VariantKind Kind, const MCExpr *Expr,
|
||||
bool isDarwin, MCContext &Ctx) {
|
||||
return new (Ctx) PPCMCExpr(Kind, Expr, isDarwin);
|
||||
}
|
||||
|
||||
void PPCMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
|
||||
if (isDarwinSyntax()) {
|
||||
switch (Kind) {
|
||||
default: llvm_unreachable("Invalid kind!");
|
||||
case VK_PPC_LO: OS << "lo16"; break;
|
||||
case VK_PPC_HI: OS << "hi16"; break;
|
||||
case VK_PPC_HA: OS << "ha16"; break;
|
||||
}
|
||||
|
||||
OS << '(';
|
||||
getSubExpr()->print(OS, MAI);
|
||||
OS << ')';
|
||||
} else {
|
||||
getSubExpr()->print(OS, MAI);
|
||||
|
||||
switch (Kind) {
|
||||
default: llvm_unreachable("Invalid kind!");
|
||||
case VK_PPC_LO: OS << "@l"; break;
|
||||
case VK_PPC_HI: OS << "@h"; break;
|
||||
case VK_PPC_HA: OS << "@ha"; break;
|
||||
case VK_PPC_HIGHER: OS << "@higher"; break;
|
||||
case VK_PPC_HIGHERA: OS << "@highera"; break;
|
||||
case VK_PPC_HIGHEST: OS << "@highest"; break;
|
||||
case VK_PPC_HIGHESTA: OS << "@highesta"; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PPCMCExpr::evaluateAsConstant(int64_t &Res) const {
|
||||
MCValue Value;
|
||||
|
||||
if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
|
||||
return false;
|
||||
|
||||
if (!Value.isAbsolute())
|
||||
return false;
|
||||
|
||||
Res = evaluateAsInt64(Value.getConstant());
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t
|
||||
PPCMCExpr::evaluateAsInt64(int64_t Value) const {
|
||||
switch (Kind) {
|
||||
case VK_PPC_LO:
|
||||
return Value & 0xffff;
|
||||
case VK_PPC_HI:
|
||||
return (Value >> 16) & 0xffff;
|
||||
case VK_PPC_HA:
|
||||
return ((Value + 0x8000) >> 16) & 0xffff;
|
||||
case VK_PPC_HIGHER:
|
||||
return (Value >> 32) & 0xffff;
|
||||
case VK_PPC_HIGHERA:
|
||||
return ((Value + 0x8000) >> 32) & 0xffff;
|
||||
case VK_PPC_HIGHEST:
|
||||
return (Value >> 48) & 0xffff;
|
||||
case VK_PPC_HIGHESTA:
|
||||
return ((Value + 0x8000) >> 48) & 0xffff;
|
||||
case VK_PPC_None:
|
||||
break;
|
||||
}
|
||||
llvm_unreachable("Invalid kind!");
|
||||
}
|
||||
|
||||
bool
|
||||
PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
|
||||
const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) const {
|
||||
MCValue Value;
|
||||
|
||||
if (!getSubExpr()->evaluateAsRelocatable(Value, Layout, Fixup))
|
||||
return false;
|
||||
|
||||
if (Value.isAbsolute()) {
|
||||
int64_t Result = evaluateAsInt64(Value.getConstant());
|
||||
if ((Fixup == nullptr || (unsigned)Fixup->getKind() != PPC::fixup_ppc_half16) &&
|
||||
(Result >= 0x8000))
|
||||
return false;
|
||||
Res = MCValue::get(Result);
|
||||
} else {
|
||||
if (!Layout)
|
||||
return false;
|
||||
|
||||
MCContext &Context = Layout->getAssembler().getContext();
|
||||
const MCSymbolRefExpr *Sym = Value.getSymA();
|
||||
MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
|
||||
if (Modifier != MCSymbolRefExpr::VK_None)
|
||||
return false;
|
||||
switch (Kind) {
|
||||
default:
|
||||
llvm_unreachable("Invalid kind!");
|
||||
case VK_PPC_LO:
|
||||
Modifier = MCSymbolRefExpr::VK_PPC_LO;
|
||||
break;
|
||||
case VK_PPC_HI:
|
||||
Modifier = MCSymbolRefExpr::VK_PPC_HI;
|
||||
break;
|
||||
case VK_PPC_HA:
|
||||
Modifier = MCSymbolRefExpr::VK_PPC_HA;
|
||||
break;
|
||||
case VK_PPC_HIGHERA:
|
||||
Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
|
||||
break;
|
||||
case VK_PPC_HIGHER:
|
||||
Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
|
||||
break;
|
||||
case VK_PPC_HIGHEST:
|
||||
Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
|
||||
break;
|
||||
case VK_PPC_HIGHESTA:
|
||||
Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
|
||||
break;
|
||||
}
|
||||
Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context);
|
||||
Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
|
||||
Streamer.visitUsedExpr(*getSubExpr());
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
//===-- PPCMCExpr.h - PPC specific MC expression classes --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCMCEXPR_H
|
||||
#define LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCMCEXPR_H
|
||||
|
||||
#include "llvm/MC/MCAsmLayout.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class PPCMCExpr : public MCTargetExpr {
|
||||
public:
|
||||
enum VariantKind {
|
||||
VK_PPC_None,
|
||||
VK_PPC_LO,
|
||||
VK_PPC_HI,
|
||||
VK_PPC_HA,
|
||||
VK_PPC_HIGHER,
|
||||
VK_PPC_HIGHERA,
|
||||
VK_PPC_HIGHEST,
|
||||
VK_PPC_HIGHESTA
|
||||
};
|
||||
|
||||
private:
|
||||
const VariantKind Kind;
|
||||
const MCExpr *Expr;
|
||||
bool IsDarwin;
|
||||
|
||||
int64_t evaluateAsInt64(int64_t Value) const;
|
||||
|
||||
explicit PPCMCExpr(VariantKind Kind, const MCExpr *Expr, bool IsDarwin)
|
||||
: Kind(Kind), Expr(Expr), IsDarwin(IsDarwin) {}
|
||||
|
||||
public:
|
||||
/// @name Construction
|
||||
/// @{
|
||||
|
||||
static const PPCMCExpr *create(VariantKind Kind, const MCExpr *Expr,
|
||||
bool isDarwin, MCContext &Ctx);
|
||||
|
||||
static const PPCMCExpr *createLo(const MCExpr *Expr,
|
||||
bool isDarwin, MCContext &Ctx) {
|
||||
return create(VK_PPC_LO, Expr, isDarwin, Ctx);
|
||||
}
|
||||
|
||||
static const PPCMCExpr *createHi(const MCExpr *Expr,
|
||||
bool isDarwin, MCContext &Ctx) {
|
||||
return create(VK_PPC_HI, Expr, isDarwin, Ctx);
|
||||
}
|
||||
|
||||
static const PPCMCExpr *createHa(const MCExpr *Expr,
|
||||
bool isDarwin, MCContext &Ctx) {
|
||||
return create(VK_PPC_HA, Expr, isDarwin, Ctx);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
/// getOpcode - Get the kind of this expression.
|
||||
VariantKind getKind() const { return Kind; }
|
||||
|
||||
/// getSubExpr - Get the child of this expression.
|
||||
const MCExpr *getSubExpr() const { return Expr; }
|
||||
|
||||
/// isDarwinSyntax - True if expression is to be printed using Darwin syntax.
|
||||
bool isDarwinSyntax() const { return IsDarwin; }
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
|
||||
bool evaluateAsRelocatableImpl(MCValue &Res,
|
||||
const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) const override;
|
||||
void visitUsedExpr(MCStreamer &Streamer) const override;
|
||||
MCFragment *findAssociatedFragment() const override {
|
||||
return getSubExpr()->findAssociatedFragment();
|
||||
}
|
||||
|
||||
// There are no TLS PPCMCExprs at the moment.
|
||||
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
|
||||
|
||||
bool evaluateAsConstant(int64_t &Res) const;
|
||||
|
||||
static bool classof(const MCExpr *E) {
|
||||
return E->getKind() == MCExpr::Target;
|
||||
}
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -1,276 +0,0 @@
|
||||
//===-- 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<MCELFStreamer &>(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<MCSymbolELF>(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<MCSymbolELF>(
|
||||
static_cast<const MCSymbolRefExpr *>(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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
//===-- PPCMCTargetDesc.h - PowerPC Target Descriptions ---------*- C++ -*-===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCMCTARGETDESC_H
|
||||
#define LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCMCTARGETDESC_H
|
||||
|
||||
// GCC #defines PPC on Linux but we use it as our namespace name
|
||||
#undef PPC
|
||||
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCAsmBackend;
|
||||
class MCCodeEmitter;
|
||||
class MCContext;
|
||||
class MCInstrInfo;
|
||||
class MCObjectWriter;
|
||||
class MCRegisterInfo;
|
||||
class MCSubtargetInfo;
|
||||
class MCTargetOptions;
|
||||
class Target;
|
||||
class Triple;
|
||||
class StringRef;
|
||||
class raw_pwrite_stream;
|
||||
|
||||
Target &getThePPC32Target();
|
||||
Target &getThePPC64Target();
|
||||
Target &getThePPC64LETarget();
|
||||
|
||||
MCCodeEmitter *createPPCMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
MCContext &Ctx);
|
||||
|
||||
MCAsmBackend *createPPCAsmBackend(const Target &T, const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI,
|
||||
const MCTargetOptions &Options);
|
||||
|
||||
/// Construct an PPC ELF object writer.
|
||||
std::unique_ptr<MCObjectWriter> createPPCELFObjectWriter(raw_pwrite_stream &OS,
|
||||
bool Is64Bit,
|
||||
bool IsLittleEndian,
|
||||
uint8_t OSABI);
|
||||
/// Construct a PPC Mach-O object writer.
|
||||
std::unique_ptr<MCObjectWriter> createPPCMachObjectWriter(raw_pwrite_stream &OS,
|
||||
bool Is64Bit,
|
||||
uint32_t CPUType,
|
||||
uint32_t CPUSubtype);
|
||||
|
||||
/// Returns true iff Val consists of one contiguous run of 1s with any number of
|
||||
/// 0s on either side. The 1s are allowed to wrap from LSB to MSB, so
|
||||
/// 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs. 0x0F0F0000 is not,
|
||||
/// since all 1s are not contiguous.
|
||||
static inline bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) {
|
||||
if (!Val)
|
||||
return false;
|
||||
|
||||
if (isShiftedMask_32(Val)) {
|
||||
// look for the first non-zero bit
|
||||
MB = countLeadingZeros(Val);
|
||||
// look for the first zero bit after the run of ones
|
||||
ME = countLeadingZeros((Val - 1) ^ Val);
|
||||
return true;
|
||||
} else {
|
||||
Val = ~Val; // invert mask
|
||||
if (isShiftedMask_32(Val)) {
|
||||
// effectively look for the first zero bit
|
||||
ME = countLeadingZeros(Val) - 1;
|
||||
// effectively look for the first one bit after the run of zeros
|
||||
MB = countLeadingZeros((Val - 1) ^ Val) + 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// no run present
|
||||
return false;
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
// Generated files will use "namespace PPC". To avoid symbol clash,
|
||||
// undefine PPC here. PPC may be predefined on some hosts.
|
||||
#undef PPC
|
||||
|
||||
// Defines symbolic names for PowerPC registers. This defines a mapping from
|
||||
// register name to register number.
|
||||
//
|
||||
#define GET_REGINFO_ENUM
|
||||
#include "PPCGenRegisterInfo.inc"
|
||||
|
||||
// Defines symbolic names for the PowerPC instructions.
|
||||
//
|
||||
#define GET_INSTRINFO_ENUM
|
||||
#define GET_INSTRINFO_SCHED_ENUM
|
||||
#include "PPCGenInstrInfo.inc"
|
||||
|
||||
#define GET_SUBTARGETINFO_ENUM
|
||||
#include "PPCGenSubtargetInfo.inc"
|
||||
|
||||
#endif // LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCMCTARGETDESC_H
|
@ -1,383 +0,0 @@
|
||||
//===-- PPCMachObjectWriter.cpp - PPC Mach-O Writer -----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/PPCFixupKinds.h"
|
||||
#include "MCTargetDesc/PPCMCTargetDesc.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/MC/MCAsmLayout.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCMachObjectWriter.h"
|
||||
#include "llvm/MC/MCSectionMachO.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class PPCMachObjectWriter : public MCMachObjectTargetWriter {
|
||||
bool recordScatteredRelocation(MachObjectWriter *Writer,
|
||||
const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
unsigned Log2Size, uint64_t &FixedValue);
|
||||
|
||||
void RecordPPCRelocation(MachObjectWriter *Writer, const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment, const MCFixup &Fixup,
|
||||
MCValue Target, uint64_t &FixedValue);
|
||||
|
||||
public:
|
||||
PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype)
|
||||
: MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {}
|
||||
|
||||
void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout, const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue) override {
|
||||
if (Writer->is64Bit()) {
|
||||
report_fatal_error("Relocation emission for MachO/PPC64 unimplemented.");
|
||||
} else
|
||||
RecordPPCRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
|
||||
FixedValue);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// computes the log2 of the size of the relocation,
|
||||
/// used for relocation_info::r_length.
|
||||
static unsigned getFixupKindLog2Size(unsigned Kind) {
|
||||
switch (Kind) {
|
||||
default:
|
||||
report_fatal_error("log2size(FixupKind): Unhandled fixup kind!");
|
||||
case FK_PCRel_1:
|
||||
case FK_Data_1:
|
||||
return 0;
|
||||
case FK_PCRel_2:
|
||||
case FK_Data_2:
|
||||
return 1;
|
||||
case FK_PCRel_4:
|
||||
case PPC::fixup_ppc_brcond14:
|
||||
case PPC::fixup_ppc_half16:
|
||||
case PPC::fixup_ppc_br24:
|
||||
case FK_Data_4:
|
||||
return 2;
|
||||
case FK_PCRel_8:
|
||||
case FK_Data_8:
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Translates generic PPC fixup kind to Mach-O/PPC relocation type enum.
|
||||
/// Outline based on PPCELFObjectWriter::getRelocType().
|
||||
static unsigned getRelocType(const MCValue &Target,
|
||||
const MCFixupKind FixupKind, // from
|
||||
// Fixup.getKind()
|
||||
const bool IsPCRel) {
|
||||
const MCSymbolRefExpr::VariantKind Modifier =
|
||||
Target.isAbsolute() ? MCSymbolRefExpr::VK_None
|
||||
: Target.getSymA()->getKind();
|
||||
// determine the type of the relocation
|
||||
unsigned Type = MachO::GENERIC_RELOC_VANILLA;
|
||||
if (IsPCRel) { // relative to PC
|
||||
switch ((unsigned)FixupKind) {
|
||||
default:
|
||||
report_fatal_error("Unimplemented fixup kind (relative)");
|
||||
case PPC::fixup_ppc_br24:
|
||||
Type = MachO::PPC_RELOC_BR24; // R_PPC_REL24
|
||||
break;
|
||||
case PPC::fixup_ppc_brcond14:
|
||||
Type = MachO::PPC_RELOC_BR14;
|
||||
break;
|
||||
case PPC::fixup_ppc_half16:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported modifier for half16 fixup");
|
||||
case MCSymbolRefExpr::VK_PPC_HA:
|
||||
Type = MachO::PPC_RELOC_HA16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_LO:
|
||||
Type = MachO::PPC_RELOC_LO16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_HI:
|
||||
Type = MachO::PPC_RELOC_HI16;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch ((unsigned)FixupKind) {
|
||||
default:
|
||||
report_fatal_error("Unimplemented fixup kind (absolute)!");
|
||||
case PPC::fixup_ppc_half16:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported modifier for half16 fixup");
|
||||
case MCSymbolRefExpr::VK_PPC_HA:
|
||||
Type = MachO::PPC_RELOC_HA16_SECTDIFF;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_LO:
|
||||
Type = MachO::PPC_RELOC_LO16_SECTDIFF;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_HI:
|
||||
Type = MachO::PPC_RELOC_HI16_SECTDIFF;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FK_Data_4:
|
||||
break;
|
||||
case FK_Data_2:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Type;
|
||||
}
|
||||
|
||||
static void makeRelocationInfo(MachO::any_relocation_info &MRE,
|
||||
const uint32_t FixupOffset, const uint32_t Index,
|
||||
const unsigned IsPCRel, const unsigned Log2Size,
|
||||
const unsigned IsExtern, const unsigned Type) {
|
||||
MRE.r_word0 = FixupOffset;
|
||||
// The bitfield offsets that work (as determined by trial-and-error)
|
||||
// are different than what is documented in the mach-o manuals.
|
||||
// This appears to be an endianness issue; reversing the order of the
|
||||
// documented bitfields in <llvm/BinaryFormat/MachO.h> fixes this (but
|
||||
// breaks x86/ARM assembly).
|
||||
MRE.r_word1 = ((Index << 8) | // was << 0
|
||||
(IsPCRel << 7) | // was << 24
|
||||
(Log2Size << 5) | // was << 25
|
||||
(IsExtern << 4) | // was << 27
|
||||
(Type << 0)); // was << 28
|
||||
}
|
||||
|
||||
static void
|
||||
makeScatteredRelocationInfo(MachO::any_relocation_info &MRE,
|
||||
const uint32_t Addr, const unsigned Type,
|
||||
const unsigned Log2Size, const unsigned IsPCRel,
|
||||
const uint32_t Value2) {
|
||||
// For notes on bitfield positions and endianness, see:
|
||||
// https://developer.apple.com/library/mac/documentation/developertools/conceptual/MachORuntime/Reference/reference.html#//apple_ref/doc/uid/20001298-scattered_relocation_entry
|
||||
MRE.r_word0 = ((Addr << 0) | (Type << 24) | (Log2Size << 28) |
|
||||
(IsPCRel << 30) | MachO::R_SCATTERED);
|
||||
MRE.r_word1 = Value2;
|
||||
}
|
||||
|
||||
/// Compute fixup offset (address).
|
||||
static uint32_t getFixupOffset(const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup) {
|
||||
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
|
||||
// On Mach-O, ppc_fixup_half16 relocations must refer to the
|
||||
// start of the instruction, not the second halfword, as ELF does
|
||||
if (unsigned(Fixup.getKind()) == PPC::fixup_ppc_half16)
|
||||
FixupOffset &= ~uint32_t(3);
|
||||
return FixupOffset;
|
||||
}
|
||||
|
||||
/// \return false if falling back to using non-scattered relocation,
|
||||
/// otherwise true for normal scattered relocation.
|
||||
/// based on X86MachObjectWriter::recordScatteredRelocation
|
||||
/// and ARMMachObjectWriter::recordScatteredRelocation
|
||||
bool PPCMachObjectWriter::recordScatteredRelocation(
|
||||
MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
|
||||
unsigned Log2Size, uint64_t &FixedValue) {
|
||||
// caller already computes these, can we just pass and reuse?
|
||||
const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup);
|
||||
const MCFixupKind FK = Fixup.getKind();
|
||||
const unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, FK);
|
||||
const unsigned Type = getRelocType(Target, FK, IsPCRel);
|
||||
|
||||
// Is this a local or SECTDIFF relocation entry?
|
||||
// SECTDIFF relocation entries have symbol subtractions,
|
||||
// and require two entries, the first for the add-symbol value,
|
||||
// the second for the subtract-symbol value.
|
||||
|
||||
// See <reloc.h>.
|
||||
const MCSymbol *A = &Target.getSymA()->getSymbol();
|
||||
|
||||
if (!A->getFragment())
|
||||
report_fatal_error("symbol '" + A->getName() +
|
||||
"' can not be undefined in a subtraction expression");
|
||||
|
||||
uint32_t Value = Writer->getSymbolAddress(*A, Layout);
|
||||
uint64_t SecAddr = Writer->getSectionAddress(A->getFragment()->getParent());
|
||||
FixedValue += SecAddr;
|
||||
uint32_t Value2 = 0;
|
||||
|
||||
if (const MCSymbolRefExpr *B = Target.getSymB()) {
|
||||
const MCSymbol *SB = &B->getSymbol();
|
||||
|
||||
if (!SB->getFragment())
|
||||
report_fatal_error("symbol '" + SB->getName() +
|
||||
"' can not be undefined in a subtraction expression");
|
||||
|
||||
// FIXME: is Type correct? see include/llvm/BinaryFormat/MachO.h
|
||||
Value2 = Writer->getSymbolAddress(*SB, Layout);
|
||||
FixedValue -= Writer->getSectionAddress(SB->getFragment()->getParent());
|
||||
}
|
||||
// FIXME: does FixedValue get used??
|
||||
|
||||
// Relocations are written out in reverse order, so the PAIR comes first.
|
||||
if (Type == MachO::PPC_RELOC_SECTDIFF ||
|
||||
Type == MachO::PPC_RELOC_HI16_SECTDIFF ||
|
||||
Type == MachO::PPC_RELOC_LO16_SECTDIFF ||
|
||||
Type == MachO::PPC_RELOC_HA16_SECTDIFF ||
|
||||
Type == MachO::PPC_RELOC_LO14_SECTDIFF ||
|
||||
Type == MachO::PPC_RELOC_LOCAL_SECTDIFF) {
|
||||
// X86 had this piece, but ARM does not
|
||||
// If the offset is too large to fit in a scattered relocation,
|
||||
// we're hosed. It's an unfortunate limitation of the MachO format.
|
||||
if (FixupOffset > 0xffffff) {
|
||||
char Buffer[32];
|
||||
format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer));
|
||||
Asm.getContext().reportError(Fixup.getLoc(),
|
||||
Twine("Section too large, can't encode "
|
||||
"r_address (") +
|
||||
Buffer + ") into 24 bits of scattered "
|
||||
"relocation entry.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is this supposed to follow MCTarget/PPCAsmBackend.cpp:adjustFixupValue()?
|
||||
// see PPCMCExpr::evaluateAsRelocatableImpl()
|
||||
uint32_t other_half = 0;
|
||||
switch (Type) {
|
||||
case MachO::PPC_RELOC_LO16_SECTDIFF:
|
||||
other_half = (FixedValue >> 16) & 0xffff;
|
||||
// applyFixupOffset longer extracts the high part because it now assumes
|
||||
// this was already done.
|
||||
// It looks like this is not true for the FixedValue needed with Mach-O
|
||||
// relocs.
|
||||
// So we need to adjust FixedValue again here.
|
||||
FixedValue &= 0xffff;
|
||||
break;
|
||||
case MachO::PPC_RELOC_HA16_SECTDIFF:
|
||||
other_half = FixedValue & 0xffff;
|
||||
FixedValue =
|
||||
((FixedValue >> 16) + ((FixedValue & 0x8000) ? 1 : 0)) & 0xffff;
|
||||
break;
|
||||
case MachO::PPC_RELOC_HI16_SECTDIFF:
|
||||
other_half = FixedValue & 0xffff;
|
||||
FixedValue = (FixedValue >> 16) & 0xffff;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Invalid PPC scattered relocation type.");
|
||||
break;
|
||||
}
|
||||
|
||||
MachO::any_relocation_info MRE;
|
||||
makeScatteredRelocationInfo(MRE, other_half, MachO::GENERIC_RELOC_PAIR,
|
||||
Log2Size, IsPCRel, Value2);
|
||||
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
|
||||
} else {
|
||||
// If the offset is more than 24-bits, it won't fit in a scattered
|
||||
// relocation offset field, so we fall back to using a non-scattered
|
||||
// relocation. This is a bit risky, as if the offset reaches out of
|
||||
// the block and the linker is doing scattered loading on this
|
||||
// symbol, things can go badly.
|
||||
//
|
||||
// Required for 'as' compatibility.
|
||||
if (FixupOffset > 0xffffff)
|
||||
return false;
|
||||
}
|
||||
MachO::any_relocation_info MRE;
|
||||
makeScatteredRelocationInfo(MRE, FixupOffset, Type, Log2Size, IsPCRel, Value);
|
||||
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// see PPCELFObjectWriter for a general outline of cases
|
||||
void PPCMachObjectWriter::RecordPPCRelocation(
|
||||
MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue) {
|
||||
const MCFixupKind FK = Fixup.getKind(); // unsigned
|
||||
const unsigned Log2Size = getFixupKindLog2Size(FK);
|
||||
const bool IsPCRel = Writer->isFixupKindPCRel(Asm, FK);
|
||||
const unsigned RelocType = getRelocType(Target, FK, IsPCRel);
|
||||
|
||||
// If this is a difference or a defined symbol plus an offset, then we need a
|
||||
// scattered relocation entry. Differences always require scattered
|
||||
// relocations.
|
||||
if (Target.getSymB() &&
|
||||
// Q: are branch targets ever scattered?
|
||||
RelocType != MachO::PPC_RELOC_BR24 &&
|
||||
RelocType != MachO::PPC_RELOC_BR14) {
|
||||
recordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
|
||||
Log2Size, FixedValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// this doesn't seem right for RIT_PPC_BR24
|
||||
// Get the symbol data, if any.
|
||||
const MCSymbol *A = nullptr;
|
||||
if (Target.getSymA())
|
||||
A = &Target.getSymA()->getSymbol();
|
||||
|
||||
// See <reloc.h>.
|
||||
const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup);
|
||||
unsigned Index = 0;
|
||||
unsigned Type = RelocType;
|
||||
|
||||
const MCSymbol *RelSymbol = nullptr;
|
||||
if (Target.isAbsolute()) { // constant
|
||||
// SymbolNum of 0 indicates the absolute section.
|
||||
//
|
||||
// FIXME: Currently, these are never generated (see code below). I cannot
|
||||
// find a case where they are actually emitted.
|
||||
report_fatal_error("FIXME: relocations to absolute targets "
|
||||
"not yet implemented");
|
||||
// the above line stolen from ARM, not sure
|
||||
} else {
|
||||
// Resolve constant variables.
|
||||
if (A->isVariable()) {
|
||||
int64_t Res;
|
||||
if (A->getVariableValue()->evaluateAsAbsolute(
|
||||
Res, Layout, Writer->getSectionAddressMap())) {
|
||||
FixedValue = Res;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether we need an external or internal relocation.
|
||||
if (Writer->doesSymbolRequireExternRelocation(*A)) {
|
||||
RelSymbol = A;
|
||||
// For external relocations, make sure to offset the fixup value to
|
||||
// compensate for the addend of the symbol address, if it was
|
||||
// undefined. This occurs with weak definitions, for example.
|
||||
if (!A->isUndefined())
|
||||
FixedValue -= Layout.getSymbolOffset(*A);
|
||||
} else {
|
||||
// The index is the section ordinal (1-based).
|
||||
const MCSection &Sec = A->getSection();
|
||||
Index = Sec.getOrdinal() + 1;
|
||||
FixedValue += Writer->getSectionAddress(&Sec);
|
||||
}
|
||||
if (IsPCRel)
|
||||
FixedValue -= Writer->getSectionAddress(Fragment->getParent());
|
||||
}
|
||||
|
||||
// struct relocation_info (8 bytes)
|
||||
MachO::any_relocation_info MRE;
|
||||
makeRelocationInfo(MRE, FixupOffset, Index, IsPCRel, Log2Size, false, Type);
|
||||
Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
|
||||
}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
llvm::createPPCMachObjectWriter(raw_pwrite_stream &OS, bool Is64Bit,
|
||||
uint32_t CPUType, uint32_t CPUSubtype) {
|
||||
return createMachObjectWriter(
|
||||
llvm::make_unique<PPCMachObjectWriter>(Is64Bit, CPUType, CPUSubtype), OS,
|
||||
/*IsLittleEndian=*/false);
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
//===-- PPCPredicates.cpp - PPC Branch Predicate Information --------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the PowerPC branch predicates.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "PPCPredicates.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <cassert>
|
||||
using namespace llvm;
|
||||
|
||||
PPC::Predicate PPC::InvertPredicate(PPC::Predicate Opcode) {
|
||||
switch (Opcode) {
|
||||
case PPC::PRED_EQ: return PPC::PRED_NE;
|
||||
case PPC::PRED_NE: return PPC::PRED_EQ;
|
||||
case PPC::PRED_LT: return PPC::PRED_GE;
|
||||
case PPC::PRED_GE: return PPC::PRED_LT;
|
||||
case PPC::PRED_GT: return PPC::PRED_LE;
|
||||
case PPC::PRED_LE: return PPC::PRED_GT;
|
||||
case PPC::PRED_NU: return PPC::PRED_UN;
|
||||
case PPC::PRED_UN: return PPC::PRED_NU;
|
||||
case PPC::PRED_EQ_MINUS: return PPC::PRED_NE_PLUS;
|
||||
case PPC::PRED_NE_MINUS: return PPC::PRED_EQ_PLUS;
|
||||
case PPC::PRED_LT_MINUS: return PPC::PRED_GE_PLUS;
|
||||
case PPC::PRED_GE_MINUS: return PPC::PRED_LT_PLUS;
|
||||
case PPC::PRED_GT_MINUS: return PPC::PRED_LE_PLUS;
|
||||
case PPC::PRED_LE_MINUS: return PPC::PRED_GT_PLUS;
|
||||
case PPC::PRED_NU_MINUS: return PPC::PRED_UN_PLUS;
|
||||
case PPC::PRED_UN_MINUS: return PPC::PRED_NU_PLUS;
|
||||
case PPC::PRED_EQ_PLUS: return PPC::PRED_NE_MINUS;
|
||||
case PPC::PRED_NE_PLUS: return PPC::PRED_EQ_MINUS;
|
||||
case PPC::PRED_LT_PLUS: return PPC::PRED_GE_MINUS;
|
||||
case PPC::PRED_GE_PLUS: return PPC::PRED_LT_MINUS;
|
||||
case PPC::PRED_GT_PLUS: return PPC::PRED_LE_MINUS;
|
||||
case PPC::PRED_LE_PLUS: return PPC::PRED_GT_MINUS;
|
||||
case PPC::PRED_NU_PLUS: return PPC::PRED_UN_MINUS;
|
||||
case PPC::PRED_UN_PLUS: return PPC::PRED_NU_MINUS;
|
||||
|
||||
// Simple predicates for single condition-register bits.
|
||||
case PPC::PRED_BIT_SET: return PPC::PRED_BIT_UNSET;
|
||||
case PPC::PRED_BIT_UNSET: return PPC::PRED_BIT_SET;
|
||||
}
|
||||
llvm_unreachable("Unknown PPC branch opcode!");
|
||||
}
|
||||
|
||||
PPC::Predicate PPC::getSwappedPredicate(PPC::Predicate Opcode) {
|
||||
switch (Opcode) {
|
||||
case PPC::PRED_EQ: return PPC::PRED_EQ;
|
||||
case PPC::PRED_NE: return PPC::PRED_NE;
|
||||
case PPC::PRED_LT: return PPC::PRED_GT;
|
||||
case PPC::PRED_GE: return PPC::PRED_LE;
|
||||
case PPC::PRED_GT: return PPC::PRED_LT;
|
||||
case PPC::PRED_LE: return PPC::PRED_GE;
|
||||
case PPC::PRED_NU: return PPC::PRED_NU;
|
||||
case PPC::PRED_UN: return PPC::PRED_UN;
|
||||
case PPC::PRED_EQ_MINUS: return PPC::PRED_EQ_MINUS;
|
||||
case PPC::PRED_NE_MINUS: return PPC::PRED_NE_MINUS;
|
||||
case PPC::PRED_LT_MINUS: return PPC::PRED_GT_MINUS;
|
||||
case PPC::PRED_GE_MINUS: return PPC::PRED_LE_MINUS;
|
||||
case PPC::PRED_GT_MINUS: return PPC::PRED_LT_MINUS;
|
||||
case PPC::PRED_LE_MINUS: return PPC::PRED_GE_MINUS;
|
||||
case PPC::PRED_NU_MINUS: return PPC::PRED_NU_MINUS;
|
||||
case PPC::PRED_UN_MINUS: return PPC::PRED_UN_MINUS;
|
||||
case PPC::PRED_EQ_PLUS: return PPC::PRED_EQ_PLUS;
|
||||
case PPC::PRED_NE_PLUS: return PPC::PRED_NE_PLUS;
|
||||
case PPC::PRED_LT_PLUS: return PPC::PRED_GT_PLUS;
|
||||
case PPC::PRED_GE_PLUS: return PPC::PRED_LE_PLUS;
|
||||
case PPC::PRED_GT_PLUS: return PPC::PRED_LT_PLUS;
|
||||
case PPC::PRED_LE_PLUS: return PPC::PRED_GE_PLUS;
|
||||
case PPC::PRED_NU_PLUS: return PPC::PRED_NU_PLUS;
|
||||
case PPC::PRED_UN_PLUS: return PPC::PRED_UN_PLUS;
|
||||
|
||||
case PPC::PRED_BIT_SET:
|
||||
case PPC::PRED_BIT_UNSET:
|
||||
llvm_unreachable("Invalid use of bit predicate code");
|
||||
}
|
||||
llvm_unreachable("Unknown PPC branch opcode!");
|
||||
}
|
||||
|
@ -1,92 +0,0 @@
|
||||
//===-- PPCPredicates.h - PPC Branch Predicate Information ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file describes the PowerPC branch predicates.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCPREDICATES_H
|
||||
#define LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCPREDICATES_H
|
||||
|
||||
// GCC #defines PPC on Linux but we use it as our namespace name
|
||||
#undef PPC
|
||||
|
||||
// Generated files will use "namespace PPC". To avoid symbol clash,
|
||||
// undefine PPC here. PPC may be predefined on some hosts.
|
||||
#undef PPC
|
||||
|
||||
namespace llvm {
|
||||
namespace PPC {
|
||||
/// Predicate - These are "(BI << 5) | BO" for various predicates.
|
||||
enum Predicate {
|
||||
PRED_LT = (0 << 5) | 12,
|
||||
PRED_LE = (1 << 5) | 4,
|
||||
PRED_EQ = (2 << 5) | 12,
|
||||
PRED_GE = (0 << 5) | 4,
|
||||
PRED_GT = (1 << 5) | 12,
|
||||
PRED_NE = (2 << 5) | 4,
|
||||
PRED_UN = (3 << 5) | 12,
|
||||
PRED_NU = (3 << 5) | 4,
|
||||
PRED_LT_MINUS = (0 << 5) | 14,
|
||||
PRED_LE_MINUS = (1 << 5) | 6,
|
||||
PRED_EQ_MINUS = (2 << 5) | 14,
|
||||
PRED_GE_MINUS = (0 << 5) | 6,
|
||||
PRED_GT_MINUS = (1 << 5) | 14,
|
||||
PRED_NE_MINUS = (2 << 5) | 6,
|
||||
PRED_UN_MINUS = (3 << 5) | 14,
|
||||
PRED_NU_MINUS = (3 << 5) | 6,
|
||||
PRED_LT_PLUS = (0 << 5) | 15,
|
||||
PRED_LE_PLUS = (1 << 5) | 7,
|
||||
PRED_EQ_PLUS = (2 << 5) | 15,
|
||||
PRED_GE_PLUS = (0 << 5) | 7,
|
||||
PRED_GT_PLUS = (1 << 5) | 15,
|
||||
PRED_NE_PLUS = (2 << 5) | 7,
|
||||
PRED_UN_PLUS = (3 << 5) | 15,
|
||||
PRED_NU_PLUS = (3 << 5) | 7,
|
||||
|
||||
// When dealing with individual condition-register bits, we have simple set
|
||||
// and unset predicates.
|
||||
PRED_BIT_SET = 1024,
|
||||
PRED_BIT_UNSET = 1025
|
||||
};
|
||||
|
||||
// Bit for branch taken (plus) or not-taken (minus) hint
|
||||
enum BranchHintBit {
|
||||
BR_NO_HINT = 0x0,
|
||||
BR_NONTAKEN_HINT = 0x2,
|
||||
BR_TAKEN_HINT = 0x3,
|
||||
BR_HINT_MASK = 0X3
|
||||
};
|
||||
|
||||
/// Invert the specified predicate. != -> ==, < -> >=.
|
||||
Predicate InvertPredicate(Predicate Opcode);
|
||||
|
||||
/// Assume the condition register is set by MI(a,b), return the predicate if
|
||||
/// we modify the instructions such that condition register is set by MI(b,a).
|
||||
Predicate getSwappedPredicate(Predicate Opcode);
|
||||
|
||||
/// Return the condition without hint bits.
|
||||
inline unsigned getPredicateCondition(Predicate Opcode) {
|
||||
return (unsigned)(Opcode & ~BR_HINT_MASK);
|
||||
}
|
||||
|
||||
/// Return the hint bits of the predicate.
|
||||
inline unsigned getPredicateHint(Predicate Opcode) {
|
||||
return (unsigned)(Opcode & BR_HINT_MASK);
|
||||
}
|
||||
|
||||
/// Return predicate consisting of specified condition and hint bits.
|
||||
inline Predicate getPredicate(unsigned Condition, unsigned Hint) {
|
||||
return (Predicate)((Condition & ~BR_HINT_MASK) |
|
||||
(Hint & BR_HINT_MASK));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user