mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-27 14:34:58 +00:00
Mips MC object code emission improvements:
"With this patch we can now generate runnable Mips code through LLVM direct object emission. We have run numerous simple programs, both C and C++ and with -O0 and -O3 from the output. The code is not production ready, but quite useful for experimentation." Patch and message by Jack Carter git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@144414 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bee515f66b
commit
47b92f3d83
@ -1,5 +1,21 @@
|
||||
//===-- MipsASMBackend.cpp - ---------===//
|
||||
//
|
||||
// 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 MipsAsmBackend and MipsELFObjectWriter classes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
||||
#include "MipsFixupKinds.h"
|
||||
#include "MCTargetDesc/MipsMCTargetDesc.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCDirectives.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
@ -8,7 +24,6 @@
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCSectionELF.h"
|
||||
#include "llvm/MC/MCSectionMachO.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Object/MachOFormat.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
@ -16,7 +31,50 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
||||
|
||||
// Add/subtract and shift
|
||||
switch (Kind) {
|
||||
default:
|
||||
break;
|
||||
case Mips::fixup_Mips_PC16:
|
||||
// So far we are only using this type for branches.
|
||||
// For branches we start 1 instruction after the branch
|
||||
// so the displacement will be one instruction size less.
|
||||
Value -= 4;
|
||||
// The displacement is then divided by 4 to give us an 18 bit
|
||||
// address range.
|
||||
Value >>= 2;
|
||||
break;
|
||||
case Mips::fixup_Mips_26:
|
||||
// So far we are only using this type for jumps.
|
||||
// The displacement is then divided by 4 to give us an 28 bit
|
||||
// address range.
|
||||
Value >>= 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Mask off value for placement as an operand
|
||||
switch (Kind) {
|
||||
default:
|
||||
break;
|
||||
case FK_Data_4:
|
||||
Value &= 0xffffffff;
|
||||
break;
|
||||
case Mips::fixup_Mips_26:
|
||||
Value &= 0x03ffffff;
|
||||
break;
|
||||
case Mips::fixup_Mips_LO16:
|
||||
case Mips::fixup_Mips_PC16:
|
||||
Value &= 0x0000ffff;
|
||||
break;
|
||||
}
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class MipsELFObjectWriter : public MCELFObjectTargetWriter {
|
||||
public:
|
||||
MipsELFObjectWriter(bool is64Bit, Triple::OSType OSType, uint16_t EMachine,
|
||||
@ -27,18 +85,75 @@ public:
|
||||
|
||||
class MipsAsmBackend : public MCAsmBackend {
|
||||
public:
|
||||
MipsAsmBackend(const Target &T)
|
||||
: MCAsmBackend() {}
|
||||
|
||||
unsigned getNumFixupKinds() const {
|
||||
return 1; //tbd
|
||||
}
|
||||
MipsAsmBackend(const Target &T) : MCAsmBackend() {}
|
||||
|
||||
/// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided
|
||||
/// data fragment, at the offset specified by the fixup and following the
|
||||
/// fixup kind as appropriate.
|
||||
void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
|
||||
uint64_t Value) const {
|
||||
unsigned Kind = (unsigned)Fixup.getKind();
|
||||
Value = adjustFixupValue(Kind, Value);
|
||||
|
||||
if (!Value)
|
||||
return; // Doesn't change encoding.
|
||||
|
||||
unsigned Offset = Fixup.getOffset();
|
||||
switch (Kind) {
|
||||
default:
|
||||
llvm_unreachable("Unknown fixup kind!");
|
||||
case Mips::fixup_Mips_GOT16: // This will be fixed up at link time
|
||||
break;
|
||||
case FK_Data_4:
|
||||
case Mips::fixup_Mips_26:
|
||||
case Mips::fixup_Mips_LO16:
|
||||
case Mips::fixup_Mips_PC16:
|
||||
// For each byte of the fragment that the fixup touches, mask i
|
||||
// the fixup value. The Value has been "split up" into the appr
|
||||
// bitfields above.
|
||||
for (unsigned i = 0; i != 4; ++i) // FIXME - Need to support 2 and 8 bytes
|
||||
Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned getNumFixupKinds() const { return Mips::NumTargetFixupKinds; }
|
||||
|
||||
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
|
||||
const static MCFixupKindInfo Infos[Mips::NumTargetFixupKinds] = {
|
||||
// This table *must* be in the order that the fixup_* kinds a
|
||||
// MipsFixupKinds.h.
|
||||
//
|
||||
// name offset bits flags
|
||||
{ "fixup_Mips_NONE", 0, 0, 0 },
|
||||
{ "fixup_Mips_16", 0, 16, 0 },
|
||||
{ "fixup_Mips_32", 0, 32, 0 },
|
||||
{ "fixup_Mips_REL32", 0, 32, 0 },
|
||||
{ "fixup_Mips_26", 0, 26, 0 },
|
||||
{ "fixup_Mips_HI16", 0, 16, 0 },
|
||||
{ "fixup_Mips_LO16", 0, 16, 0 },
|
||||
{ "fixup_Mips_GPREL16", 0, 16, 0 },
|
||||
{ "fixup_Mips_LITERAL", 0, 16, 0 },
|
||||
{ "fixup_Mips_GOT16", 0, 16, 0 },
|
||||
{ "fixup_Mips_PC16", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Mips_CALL16", 0, 16, 0 },
|
||||
{ "fixup_Mips_GPREL32", 0, 32, 0 },
|
||||
{ "fixup_Mips_SHIFT5", 6, 5, 0 },
|
||||
{ "fixup_Mips_SHIFT6", 6, 5, 0 },
|
||||
{ "fixup_Mips_64", 0, 64, 0 },
|
||||
{ "fixup_Mips_TLSGD", 0, 16, 0 },
|
||||
{ "fixup_Mips_GOTTPREL", 0, 16, 0 },
|
||||
{ "fixup_Mips_TPREL_HI", 0, 16, 0 },
|
||||
{ "fixup_Mips_TPREL_LO", 0, 16, 0 },
|
||||
{ "fixup_Mips_Branch_PCRel", 0, 16, MCFixupKindInfo::FKF_IsPCRel }
|
||||
};
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
return MCAsmBackend::getFixupKindInfo(Kind);
|
||||
|
||||
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
|
||||
"Invalid kind!");
|
||||
return Infos[Kind - FirstTargetFixupKind];
|
||||
}
|
||||
|
||||
/// @name Target Relaxation Interfaces
|
||||
@ -52,24 +167,24 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/// RelaxInstruction - Relax the instruction in the given fragment to the next
|
||||
/// wider instruction.
|
||||
/// RelaxInstruction - Relax the instruction in the given fragment
|
||||
/// to the next wider instruction.
|
||||
///
|
||||
/// \param Inst - The instruction to relax, which may be the same as the
|
||||
/// output.
|
||||
/// \param Inst - The instruction to relax, which may be the same
|
||||
/// as the output.
|
||||
/// \parm Res [output] - On return, the relaxed instruction.
|
||||
void RelaxInstruction(const MCInst &Inst, MCInst &Res) const {
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// WriteNopData - Write an (optimal) nop sequence of Count bytes to the given
|
||||
/// output. If the target cannot generate such a sequence, it should return an
|
||||
/// error.
|
||||
/// WriteNopData - Write an (optimal) nop sequence of Count bytes
|
||||
/// to the given output. If the target cannot generate such a sequence,
|
||||
/// it should return an error.
|
||||
///
|
||||
/// \return - True on success.
|
||||
bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@ -106,7 +221,7 @@ public:
|
||||
return new MipsELFObjectWriter(false, OSType, ELF::EM_MIPS, false);
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
MCAsmBackend *llvm::createMipsAsmBackend(const Target &T, StringRef TT) {
|
||||
Triple TheTriple(TT);
|
||||
|
@ -19,6 +19,88 @@
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// MipsII - This namespace holds all of the target specific flags that
|
||||
/// instruction info tracks.
|
||||
///
|
||||
namespace MipsII {
|
||||
/// Target Operand Flag enum.
|
||||
enum TOF {
|
||||
//===------------------------------------------------------------------===//
|
||||
// Mips Specific MachineOperand flags.
|
||||
|
||||
MO_NO_FLAG,
|
||||
|
||||
/// MO_GOT - Represents the offset into the global offset table at which
|
||||
/// the address the relocation entry symbol resides during execution.
|
||||
MO_GOT,
|
||||
|
||||
/// MO_GOT_CALL - Represents the offset into the global offset table at
|
||||
/// which the address of a call site relocation entry symbol resides
|
||||
/// during execution. This is different from the above since this flag
|
||||
/// can only be present in call instructions.
|
||||
MO_GOT_CALL,
|
||||
|
||||
/// MO_GPREL - Represents the offset from the current gp value to be used
|
||||
/// for the relocatable object file being produced.
|
||||
MO_GPREL,
|
||||
|
||||
/// MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol
|
||||
/// address.
|
||||
MO_ABS_HI,
|
||||
MO_ABS_LO,
|
||||
|
||||
/// MO_TLSGD - Represents the offset into the global offset table at which
|
||||
// the module ID and TSL block offset reside during execution (General
|
||||
// Dynamic TLS).
|
||||
MO_TLSGD,
|
||||
|
||||
/// MO_GOTTPREL - Represents the offset from the thread pointer (Initial
|
||||
// Exec TLS).
|
||||
MO_GOTTPREL,
|
||||
|
||||
/// MO_TPREL_HI/LO - Represents the hi and low part of the offset from
|
||||
// the thread pointer (Local Exec TLS).
|
||||
MO_TPREL_HI,
|
||||
MO_TPREL_LO,
|
||||
|
||||
// N32/64 Flags.
|
||||
MO_GPOFF_HI,
|
||||
MO_GPOFF_LO,
|
||||
MO_GOT_DISP,
|
||||
MO_GOT_PAGE,
|
||||
MO_GOT_OFST
|
||||
};
|
||||
|
||||
enum {
|
||||
//===------------------------------------------------------------------===//
|
||||
// Instruction encodings. These are the standard/most common forms for
|
||||
// Mips instructions.
|
||||
//
|
||||
|
||||
// Pseudo - This represents an instruction that is a pseudo instruction
|
||||
// or one that has not been implemented yet. It is illegal to code generate
|
||||
// it, but tolerated for intermediate implementation stages.
|
||||
Pseudo = 0,
|
||||
|
||||
/// FrmR - This form is for instructions of the format R.
|
||||
FrmR = 1,
|
||||
/// FrmI - This form is for instructions of the format I.
|
||||
FrmI = 2,
|
||||
/// FrmJ - This form is for instructions of the format J.
|
||||
FrmJ = 3,
|
||||
/// FrmFR - This form is for instructions of the format FR.
|
||||
FrmFR = 4,
|
||||
/// FrmFI - This form is for instructions of the format FI.
|
||||
FrmFI = 5,
|
||||
/// FrmOther - This form is for instructions that have no specific format.
|
||||
FrmOther = 6,
|
||||
|
||||
FormMask = 15
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// getMipsRegisterNumbering - Given the enum value for some register,
|
||||
/// return the number that it corresponds to.
|
||||
inline static unsigned getMipsRegisterNumbering(unsigned RegEnum)
|
||||
|
@ -12,16 +12,18 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
#define DEBUG_TYPE "mccodeemitter"
|
||||
#include "MCTargetDesc/MipsBaseInfo.h"
|
||||
#include "MCTargetDesc/MipsFixupKinds.h"
|
||||
#include "MCTargetDesc/MipsMCTargetDesc.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "MCTargetDesc/MipsMCTargetDesc.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -31,22 +33,217 @@ class MipsMCCodeEmitter : public MCCodeEmitter {
|
||||
void operator=(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT
|
||||
const MCInstrInfo &MCII;
|
||||
const MCSubtargetInfo &STI;
|
||||
MCContext &Ctx;
|
||||
|
||||
public:
|
||||
MipsMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
|
||||
MCContext &ctx)
|
||||
: MCII(mcii), STI(sti) {}
|
||||
MCContext &ctx) : MCII(mcii), STI(sti) , Ctx(ctx) {}
|
||||
|
||||
~MipsMCCodeEmitter() {}
|
||||
|
||||
void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
void EmitByte(unsigned char C, raw_ostream &OS) const {
|
||||
OS << (char)C;
|
||||
}
|
||||
|
||||
void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const {
|
||||
// Output the instruction encoding in little endian byte order.
|
||||
for (unsigned i = 0; i != Size; ++i) {
|
||||
EmitByte(Val & 255, OS);
|
||||
Val >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
// getBinaryCodeForInstr - TableGen'erated function for getting the
|
||||
// binary encoding for an instruction.
|
||||
unsigned getBinaryCodeForInstr(const MCInst &MI,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
// getBranchJumpOpValue - Return binary encoding of the jump
|
||||
// target operand. If the machine operand requires relocation,
|
||||
// record the relocation and return zero.
|
||||
unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
// getBranchTargetOpValue - Return binary encoding of the branch
|
||||
// target operand. If the machine operand requires relocation,
|
||||
// record the relocation and return zero.
|
||||
unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
// getMachineOpValue - Return binary encoding of operand. If the machin
|
||||
// operand requires relocation, record the relocation and return zero.
|
||||
unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
}; // class MipsMCCodeEmitter
|
||||
} // namespace
|
||||
|
||||
MCCodeEmitter *llvm::createMipsMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCSubtargetInfo &STI,
|
||||
MCContext &Ctx) {
|
||||
MCContext &Ctx)
|
||||
{
|
||||
return new MipsMCCodeEmitter(MCII, STI, Ctx);
|
||||
}
|
||||
|
||||
/// EncodeInstruction - Emit the instruction.
|
||||
/// Size the instruction (currently only 4 bytes
|
||||
void MipsMCCodeEmitter::
|
||||
EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const
|
||||
{
|
||||
uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
|
||||
|
||||
// Check for unimplemented opcodes.
|
||||
// Unfortunately in MIPS both NOT and SLL will come in with Binary == 0
|
||||
// so we have to special check for them.
|
||||
unsigned Opcode = MI.getOpcode();
|
||||
if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary)
|
||||
llvm_unreachable("unimplemented opcode in EncodeInstruction()");
|
||||
|
||||
const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
|
||||
uint64_t TSFlags = Desc.TSFlags;
|
||||
|
||||
// Pseudo instructions don't get encoded and shouldn't be here
|
||||
// in the first place!
|
||||
if ((TSFlags & MipsII::FormMask) == MipsII::Pseudo)
|
||||
llvm_unreachable("Pseudo opcode found in EncodeInstruction()");
|
||||
|
||||
// For now all instructions are 4 bytes
|
||||
int Size = 4; // FIXME: Have Desc.getSize() return the correct value!
|
||||
|
||||
EmitInstruction(Binary, Size, OS);
|
||||
}
|
||||
|
||||
/// getBranchTargetOpValue - Return binary encoding of the branch
|
||||
/// target operand. If the machine operand requires relocation,
|
||||
/// record the relocation and return zero.
|
||||
unsigned MipsMCCodeEmitter::
|
||||
getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
assert(MO.isExpr() && "getBranchTargetOpValue expects only expressions");
|
||||
|
||||
const MCExpr *Expr = MO.getExpr();
|
||||
Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
MCFixupKind(Mips::fixup_Mips_PC16)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getJumpTargetOpValue - Return binary encoding of the jump
|
||||
/// target operand. If the machine operand requires relocation,
|
||||
/// record the relocation and return zero.
|
||||
unsigned MipsMCCodeEmitter::
|
||||
getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
assert(MO.isExpr() && "getJumpTargetOpValue expects only expressions");
|
||||
|
||||
const MCExpr *Expr = MO.getExpr();
|
||||
Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
MCFixupKind(Mips::fixup_Mips_26)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getMachineOpValue - Return binary encoding of operand. If the machine
|
||||
/// operand requires relocation, record the relocation and return zero.
|
||||
unsigned MipsMCCodeEmitter::
|
||||
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
if (MO.isReg()) {
|
||||
unsigned Reg = MO.getReg();
|
||||
unsigned RegNo = getMipsRegisterNumbering(Reg);
|
||||
return RegNo;
|
||||
} else if (MO.isImm()) {
|
||||
return static_cast<unsigned>(MO.getImm());
|
||||
} else if (MO.isFPImm()) {
|
||||
return static_cast<unsigned>(APFloat(MO.getFPImm())
|
||||
.bitcastToAPInt().getHiBits(32).getLimitedValue());
|
||||
} else if (MO.isExpr()) {
|
||||
const MCExpr *Expr = MO.getExpr();
|
||||
MCExpr::ExprKind Kind = Expr->getKind();
|
||||
if (Kind == MCExpr::SymbolRef) {
|
||||
Mips::Fixups FixupKind = Mips::fixup_Mips_NONE;
|
||||
MCSymbolRefExpr::VariantKind SymRefKind =
|
||||
cast<MCSymbolRefExpr>(Expr)->getKind();
|
||||
switch(SymRefKind) {
|
||||
case MCSymbolRefExpr::VK_Mips_GPREL:
|
||||
FixupKind = Mips::fixup_Mips_GPREL16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_Mips_GOT_CALL:
|
||||
FixupKind = Mips::fixup_Mips_CALL16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_Mips_GOT:
|
||||
FixupKind = Mips::fixup_Mips_GOT16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_Mips_ABS_HI:
|
||||
FixupKind = Mips::fixup_Mips_HI16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_Mips_ABS_LO:
|
||||
FixupKind = Mips::fixup_Mips_LO16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_Mips_TLSGD:
|
||||
FixupKind = Mips::fixup_Mips_TLSGD;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_Mips_GOTTPREL:
|
||||
FixupKind = Mips::fixup_Mips_GOTTPREL;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_Mips_TPREL_HI:
|
||||
FixupKind = Mips::fixup_Mips_TPREL_HI;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_Mips_TPREL_LO:
|
||||
FixupKind = Mips::fixup_Mips_TPREL_LO;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
} // switch
|
||||
Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind)));
|
||||
} // if SymbolRef
|
||||
// All of the information is in the fixup.
|
||||
return 0;
|
||||
}
|
||||
llvm_unreachable("Unable to encode MCOperand!");
|
||||
// Not reached
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getMemEncoding - Return binary encoding of memory related operand.
|
||||
/// If the offset operand requires relocation, record the relocation.
|
||||
unsigned
|
||||
MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
// Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
|
||||
assert(MI.getOperand(OpNo).isReg());
|
||||
unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16;
|
||||
unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups);
|
||||
|
||||
return (OffBits & 0xFFFF) | RegBits;
|
||||
}
|
||||
|
||||
unsigned
|
||||
MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
// FIXME: implement
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned
|
||||
MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
// FIXME: implement
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "MipsGenMCCodeEmitter.inc"
|
||||
|
||||
|
@ -11,8 +11,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MipsMCTargetDesc.h"
|
||||
#include "MipsMCAsmInfo.h"
|
||||
#include "MipsMCTargetDesc.h"
|
||||
#include "InstPrinter/MipsInstPrinter.h"
|
||||
#include "llvm/MC/MachineLocation.h"
|
||||
#include "llvm/MC/MCCodeGenInfo.h"
|
||||
@ -140,6 +140,9 @@ extern "C" void LLVMInitializeMipsTargetMC() {
|
||||
TargetRegistry::RegisterMCAsmBackend(TheMips64Target, createMipsAsmBackend);
|
||||
TargetRegistry::RegisterMCAsmBackend(TheMips64elTarget, createMipsAsmBackend);
|
||||
|
||||
TargetRegistry::RegisterMCCodeEmitter(TheMipsTarget, createMipsMCCodeEmitter);
|
||||
TargetRegistry::RegisterMCCodeEmitter(TheMipselTarget, createMipsMCCodeEmitter);
|
||||
|
||||
// Register the MC subtarget info.
|
||||
TargetRegistry::RegisterMCSubtargetInfo(TheMipsTarget,
|
||||
createMipsMCSubtargetInfo);
|
||||
|
@ -16,12 +16,14 @@
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmBackend;
|
||||
class MCInstrInfo;
|
||||
class MCCodeEmitter;
|
||||
class MCContext;
|
||||
class MCInstrInfo;
|
||||
class MCObjectWriter;
|
||||
class MCSubtargetInfo;
|
||||
class StringRef;
|
||||
class Target;
|
||||
class raw_ostream;
|
||||
|
||||
extern Target TheMipsTarget;
|
||||
extern Target TheMipselTarget;
|
||||
@ -33,6 +35,7 @@ MCCodeEmitter *createMipsMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
MCContext &Ctx);
|
||||
|
||||
MCAsmBackend *createMipsAsmBackend(const Target &T, StringRef TT);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
// Defines symbolic names for Mips registers. This defines a mapping from
|
||||
|
@ -15,7 +15,7 @@ TARGET = Mips
|
||||
BUILT_SOURCES = MipsGenRegisterInfo.inc MipsGenInstrInfo.inc \
|
||||
MipsGenAsmWriter.inc MipsGenCodeEmitter.inc \
|
||||
MipsGenDAGISel.inc MipsGenCallingConv.inc \
|
||||
MipsGenSubtargetInfo.inc
|
||||
MipsGenSubtargetInfo.inc MipsGenMCCodeEmitter.inc
|
||||
|
||||
DIRS = InstPrinter TargetInfo MCTargetDesc
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "MipsMCInstLower.h"
|
||||
#include "MipsMCSymbolRefExpr.h"
|
||||
#include "InstPrinter/MipsInstPrinter.h"
|
||||
#include "MCTargetDesc/MipsBaseInfo.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
|
@ -18,18 +18,20 @@
|
||||
#include "MipsRelocations.h"
|
||||
#include "MipsSubtarget.h"
|
||||
#include "MipsTargetMachine.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/PassManager.h"
|
||||
#include "MCTargetDesc/MipsBaseInfo.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/CodeGen/JITCodeEmitter.h"
|
||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineJumpTableInfo.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/CodeGen/MachineOperand.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/PassManager.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
@ -37,8 +39,6 @@
|
||||
#include <iomanip>
|
||||
#endif
|
||||
|
||||
#include "llvm/CodeGen/MachineOperand.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(NumEmitted, "Number of machine instructions emitted");
|
||||
@ -66,9 +66,9 @@ class MipsCodeEmitter : public MachineFunctionPass {
|
||||
public:
|
||||
MipsCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) :
|
||||
MachineFunctionPass(ID), JTI(0),
|
||||
II((const MipsInstrInfo *) tm.getInstrInfo()),
|
||||
TD(tm.getTargetData()), TM(tm), MCE(mce), MCPEs(0), MJTEs(0),
|
||||
IsPIC(TM.getRelocationModel() == Reloc::PIC_) {
|
||||
II((const MipsInstrInfo *) tm.getInstrInfo()),
|
||||
TD(tm.getTargetData()), TM(tm), MCE(mce), MCPEs(0), MJTEs(0),
|
||||
IsPIC(TM.getRelocationModel() == Reloc::PIC_) {
|
||||
}
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF);
|
||||
@ -91,7 +91,7 @@ class MipsCodeEmitter : public MachineFunctionPass {
|
||||
/// Routines that handle operands which add machine relocations which are
|
||||
/// fixed up by the relocation stage.
|
||||
void emitGlobalAddress(const GlobalValue *GV, unsigned Reloc,
|
||||
bool MayNeedFarStub) const;
|
||||
bool MayNeedFarStub) const;
|
||||
void emitExternalSymbolAddress(const char *ES, unsigned Reloc) const;
|
||||
void emitConstPoolAddress(unsigned CPI, unsigned Reloc) const;
|
||||
void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const;
|
||||
@ -105,6 +105,9 @@ class MipsCodeEmitter : public MachineFunctionPass {
|
||||
unsigned getRelocation(const MachineInstr &MI,
|
||||
const MachineOperand &MO) const;
|
||||
|
||||
unsigned getJumpTargetOpValue(const MachineInstr &MI, unsigned OpNo) const;
|
||||
|
||||
unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const;
|
||||
unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const;
|
||||
unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const;
|
||||
unsigned getSizeInsEncoding(const MachineInstr &MI, unsigned OpNo) const;
|
||||
@ -165,23 +168,34 @@ unsigned MipsCodeEmitter::getRelocation(const MachineInstr &MI,
|
||||
return Mips::reloc_mips_lo;
|
||||
}
|
||||
|
||||
unsigned MipsCodeEmitter::getJumpTargetOpValue(const MachineInstr &MI,
|
||||
unsigned OpNo) const {
|
||||
// FIXME: implement
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned MipsCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI,
|
||||
unsigned OpNo) const {
|
||||
// FIXME: implement
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned MipsCodeEmitter::getMemEncoding(const MachineInstr &MI,
|
||||
unsigned OpNo) const {
|
||||
unsigned OpNo) const {
|
||||
// Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
|
||||
assert(MI.getOperand(OpNo).isReg());
|
||||
unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo)) << 16;
|
||||
return
|
||||
(getMachineOpValue(MI, MI.getOperand(OpNo+1)) & 0xFFFF) | RegBits;
|
||||
return (getMachineOpValue(MI, MI.getOperand(OpNo+1)) & 0xFFFF) | RegBits;
|
||||
}
|
||||
|
||||
unsigned MipsCodeEmitter::getSizeExtEncoding(const MachineInstr &MI,
|
||||
unsigned OpNo) const {
|
||||
unsigned OpNo) const {
|
||||
// size is encoded as size-1.
|
||||
return getMachineOpValue(MI, MI.getOperand(OpNo)) - 1;
|
||||
}
|
||||
|
||||
unsigned MipsCodeEmitter::getSizeInsEncoding(const MachineInstr &MI,
|
||||
unsigned OpNo) const {
|
||||
unsigned OpNo) const {
|
||||
// size is encoded as pos+size-1.
|
||||
return getMachineOpValue(MI, MI.getOperand(OpNo-1)) +
|
||||
getMachineOpValue(MI, MI.getOperand(OpNo)) - 1;
|
||||
@ -190,7 +204,7 @@ unsigned MipsCodeEmitter::getSizeInsEncoding(const MachineInstr &MI,
|
||||
/// getMachineOpValue - Return binary encoding of operand. If the machine
|
||||
/// operand requires relocation, record the relocation and return zero.
|
||||
unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI,
|
||||
const MachineOperand &MO) const {
|
||||
const MachineOperand &MO) const {
|
||||
if (MO.isReg())
|
||||
return MipsRegisterInfo::getRegisterNumbering(MO.getReg());
|
||||
else if (MO.isImm())
|
||||
@ -217,9 +231,10 @@ unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI,
|
||||
}
|
||||
|
||||
void MipsCodeEmitter::emitGlobalAddress(const GlobalValue *GV, unsigned Reloc,
|
||||
bool MayNeedFarStub) const {
|
||||
bool MayNeedFarStub) const {
|
||||
MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
|
||||
const_cast<GlobalValue *>(GV), 0, MayNeedFarStub));
|
||||
const_cast<GlobalValue *>(GV), 0,
|
||||
MayNeedFarStub));
|
||||
}
|
||||
|
||||
void MipsCodeEmitter::emitGlobalAddressUnaligned(const GlobalValue *GV,
|
||||
@ -248,7 +263,7 @@ emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const {
|
||||
}
|
||||
|
||||
void MipsCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB,
|
||||
unsigned Reloc) const {
|
||||
unsigned Reloc) const {
|
||||
MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(),
|
||||
Reloc, BB));
|
||||
}
|
||||
@ -395,7 +410,7 @@ void MipsCodeEmitter::emitWordLE(unsigned Word) {
|
||||
/// createMipsJITCodeEmitterPass - Return a pass that emits the collected Mips
|
||||
/// code to the specified MCE object.
|
||||
FunctionPass *llvm::createMipsJITCodeEmitterPass(MipsTargetMachine &TM,
|
||||
JITCodeEmitter &JCE) {
|
||||
JITCodeEmitter &JCE) {
|
||||
return new MipsCodeEmitter(TM, JCE);
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "MipsFrameLowering.h"
|
||||
#include "MipsInstrInfo.h"
|
||||
#include "MipsMachineFunction.h"
|
||||
#include "MCTargetDesc/MipsBaseInfo.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "llvm/Intrinsics.h"
|
||||
#include "llvm/CallingConv.h"
|
||||
#include "InstPrinter/MipsInstPrinter.h"
|
||||
#include "MCTargetDesc/MipsBaseInfo.h"
|
||||
#include "llvm/CodeGen/CallingConvLower.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
|
@ -30,86 +30,6 @@ namespace Mips {
|
||||
unsigned GetOppositeBranchOpc(unsigned Opc);
|
||||
}
|
||||
|
||||
/// MipsII - This namespace holds all of the target specific flags that
|
||||
/// instruction info tracks.
|
||||
///
|
||||
namespace MipsII {
|
||||
/// Target Operand Flag enum.
|
||||
enum TOF {
|
||||
//===------------------------------------------------------------------===//
|
||||
// Mips Specific MachineOperand flags.
|
||||
|
||||
MO_NO_FLAG,
|
||||
|
||||
/// MO_GOT - Represents the offset into the global offset table at which
|
||||
/// the address the relocation entry symbol resides during execution.
|
||||
MO_GOT,
|
||||
|
||||
/// MO_GOT_CALL - Represents the offset into the global offset table at
|
||||
/// which the address of a call site relocation entry symbol resides
|
||||
/// during execution. This is different from the above since this flag
|
||||
/// can only be present in call instructions.
|
||||
MO_GOT_CALL,
|
||||
|
||||
/// MO_GPREL - Represents the offset from the current gp value to be used
|
||||
/// for the relocatable object file being produced.
|
||||
MO_GPREL,
|
||||
|
||||
/// MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol
|
||||
/// address.
|
||||
MO_ABS_HI,
|
||||
MO_ABS_LO,
|
||||
|
||||
/// MO_TLSGD - Represents the offset into the global offset table at which
|
||||
// the module ID and TSL block offset reside during execution (General
|
||||
// Dynamic TLS).
|
||||
MO_TLSGD,
|
||||
|
||||
/// MO_GOTTPREL - Represents the offset from the thread pointer (Initial
|
||||
// Exec TLS).
|
||||
MO_GOTTPREL,
|
||||
|
||||
/// MO_TPREL_HI/LO - Represents the hi and low part of the offset from
|
||||
// the thread pointer (Local Exec TLS).
|
||||
MO_TPREL_HI,
|
||||
MO_TPREL_LO,
|
||||
|
||||
// N32/64 Flags.
|
||||
MO_GPOFF_HI,
|
||||
MO_GPOFF_LO,
|
||||
MO_GOT_DISP,
|
||||
MO_GOT_PAGE,
|
||||
MO_GOT_OFST
|
||||
};
|
||||
|
||||
enum {
|
||||
//===------------------------------------------------------------------===//
|
||||
// Instruction encodings. These are the standard/most common forms for
|
||||
// Mips instructions.
|
||||
//
|
||||
|
||||
// Pseudo - This represents an instruction that is a pseudo instruction
|
||||
// or one that has not been implemented yet. It is illegal to code generate
|
||||
// it, but tolerated for intermediate implementation stages.
|
||||
Pseudo = 0,
|
||||
|
||||
/// FrmR - This form is for instructions of the format R.
|
||||
FrmR = 1,
|
||||
/// FrmI - This form is for instructions of the format I.
|
||||
FrmI = 2,
|
||||
/// FrmJ - This form is for instructions of the format J.
|
||||
FrmJ = 3,
|
||||
/// FrmFR - This form is for instructions of the format FR.
|
||||
FrmFR = 4,
|
||||
/// FrmFI - This form is for instructions of the format FI.
|
||||
FrmFI = 5,
|
||||
/// FrmOther - This form is for instructions that have no specific format.
|
||||
FrmOther = 6,
|
||||
|
||||
FormMask = 15
|
||||
};
|
||||
}
|
||||
|
||||
class MipsInstrInfo : public MipsGenInstrInfo {
|
||||
MipsTargetMachine &TM;
|
||||
bool IsN64;
|
||||
|
@ -138,7 +138,13 @@ def NotN64 : Predicate<"!Subtarget.isABI_N64()">;
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Instruction operand types
|
||||
def brtarget : Operand<OtherVT>;
|
||||
def jmptarget : Operand<OtherVT> {
|
||||
let EncoderMethod = "getJumpTargetOpValue";
|
||||
}
|
||||
def brtarget : Operand<OtherVT> {
|
||||
let EncoderMethod = "getBranchTargetOpValue";
|
||||
let OperandType = "OPERAND_PCREL";
|
||||
}
|
||||
def calltarget : Operand<i32>;
|
||||
def calltarget64: Operand<i64>;
|
||||
def simm16 : Operand<i32>;
|
||||
@ -449,7 +455,7 @@ class SetCC_I<bits<6> op, string instr_asm, PatFrag cond_op, Operand Od,
|
||||
// Unconditional branch
|
||||
let isBranch=1, isTerminator=1, isBarrier=1, hasDelaySlot = 1 in
|
||||
class JumpFJ<bits<6> op, string instr_asm>:
|
||||
FJ<op, (outs), (ins brtarget:$target),
|
||||
FJ<op, (outs), (ins jmptarget:$target),
|
||||
!strconcat(instr_asm, "\t$target"), [(br bb:$target)], IIBranch>;
|
||||
|
||||
let isBranch=1, isTerminator=1, isBarrier=1, rd=0, hasDelaySlot = 1 in
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "MipsAsmPrinter.h"
|
||||
#include "MipsInstrInfo.h"
|
||||
#include "MipsMCInstLower.h"
|
||||
#include "MCTargetDesc/MipsBaseInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineOperand.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user