mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-10-20 09:24:58 +00:00
Added Subtarget support into RegisterInfo
Added HasABICall and HasAbsoluteCall (equivalent to gcc -mabicall and -mno-shared). HasAbsoluteCall is not implemented but HasABICall is the default for o32 ABI. Now, both should help into a more accurate relocation types implementation. Added IsLinux is needed to choose between asm directives. Instruction name strings cleanup. AsmPrinter improved. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53551 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
91e1c32dd0
commit
43d526d162
@ -15,6 +15,7 @@
|
|||||||
#define DEBUG_TYPE "mips-asm-printer"
|
#define DEBUG_TYPE "mips-asm-printer"
|
||||||
|
|
||||||
#include "Mips.h"
|
#include "Mips.h"
|
||||||
|
#include "MipsSubtarget.h"
|
||||||
#include "MipsInstrInfo.h"
|
#include "MipsInstrInfo.h"
|
||||||
#include "MipsTargetMachine.h"
|
#include "MipsTargetMachine.h"
|
||||||
#include "MipsMachineFunction.h"
|
#include "MipsMachineFunction.h"
|
||||||
@ -44,21 +45,19 @@ STATISTIC(EmittedInsts, "Number of machine instrs printed");
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct VISIBILITY_HIDDEN MipsAsmPrinter : public AsmPrinter {
|
struct VISIBILITY_HIDDEN MipsAsmPrinter : public AsmPrinter {
|
||||||
|
|
||||||
|
const MipsSubtarget *Subtarget;
|
||||||
|
|
||||||
MipsAsmPrinter(std::ostream &O, MipsTargetMachine &TM,
|
MipsAsmPrinter(std::ostream &O, MipsTargetMachine &TM,
|
||||||
const TargetAsmInfo *T):
|
const TargetAsmInfo *T):
|
||||||
AsmPrinter(O, TM, T) {}
|
AsmPrinter(O, TM, T) {
|
||||||
|
Subtarget = &TM.getSubtarget<MipsSubtarget>();
|
||||||
|
}
|
||||||
|
|
||||||
virtual const char *getPassName() const {
|
virtual const char *getPassName() const {
|
||||||
return "Mips Assembly Printer";
|
return "Mips Assembly Printer";
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SetDirectiveFlags {
|
|
||||||
REORDER, // enables instruction reordering.
|
|
||||||
NOREORDER, // disables instruction reordering.
|
|
||||||
MACRO, // enables GAS macros.
|
|
||||||
NOMACRO // disables GAS macros.
|
|
||||||
};
|
|
||||||
|
|
||||||
void printOperand(const MachineInstr *MI, int opNum);
|
void printOperand(const MachineInstr *MI, int opNum);
|
||||||
void printMemOperand(const MachineInstr *MI, int opNum,
|
void printMemOperand(const MachineInstr *MI, int opNum,
|
||||||
const char *Modifier = 0);
|
const char *Modifier = 0);
|
||||||
@ -68,13 +67,13 @@ namespace {
|
|||||||
unsigned int getSavedRegsBitmask(bool isFloat, MachineFunction &MF);
|
unsigned int getSavedRegsBitmask(bool isFloat, MachineFunction &MF);
|
||||||
void printHex32(unsigned int Value);
|
void printHex32(unsigned int Value);
|
||||||
|
|
||||||
|
const char *emitCurrentABIString(void);
|
||||||
void emitFunctionStart(MachineFunction &MF);
|
void emitFunctionStart(MachineFunction &MF);
|
||||||
void emitFunctionEnd(MachineFunction &MF);
|
void emitFunctionEnd(MachineFunction &MF);
|
||||||
void emitFrameDirective(MachineFunction &MF);
|
void emitFrameDirective(MachineFunction &MF);
|
||||||
void emitMaskDirective(MachineFunction &MF);
|
void emitMaskDirective(MachineFunction &MF);
|
||||||
void emitFMaskDirective(MachineFunction &MF);
|
void emitFMaskDirective(MachineFunction &MF);
|
||||||
void emitSetDirective(SetDirectiveFlags Flag);
|
|
||||||
|
|
||||||
bool printInstruction(const MachineInstr *MI); // autogenerated.
|
bool printInstruction(const MachineInstr *MI); // autogenerated.
|
||||||
bool runOnMachineFunction(MachineFunction &F);
|
bool runOnMachineFunction(MachineFunction &F);
|
||||||
bool doInitialization(Module &M);
|
bool doInitialization(Module &M);
|
||||||
@ -125,6 +124,10 @@ FunctionPass *llvm::createMipsCodePrinterPass(std::ostream &o,
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Mask directives
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// Mask directive for GPR
|
/// Mask directive for GPR
|
||||||
void MipsAsmPrinter::
|
void MipsAsmPrinter::
|
||||||
emitMaskDirective(MachineFunction &MF)
|
emitMaskDirective(MachineFunction &MF)
|
||||||
@ -159,37 +162,6 @@ emitFMaskDirective(MachineFunction &MF)
|
|||||||
O << ",0" << "\n";
|
O << ",0" << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Frame Directive
|
|
||||||
void MipsAsmPrinter::
|
|
||||||
emitFrameDirective(MachineFunction &MF)
|
|
||||||
{
|
|
||||||
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
|
|
||||||
|
|
||||||
unsigned stackReg = RI.getFrameRegister(MF);
|
|
||||||
unsigned returnReg = RI.getRARegister();
|
|
||||||
unsigned stackSize = MF.getFrameInfo()->getStackSize();
|
|
||||||
|
|
||||||
|
|
||||||
O << "\t.frame\t" << "$" << LowercaseString(RI.get(stackReg).AsmName)
|
|
||||||
<< "," << stackSize << ","
|
|
||||||
<< "$" << LowercaseString(RI.get(returnReg).AsmName)
|
|
||||||
<< "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Emit Set directives.
|
|
||||||
void MipsAsmPrinter::
|
|
||||||
emitSetDirective(SetDirectiveFlags Flag)
|
|
||||||
{
|
|
||||||
O << "\t.set\t";
|
|
||||||
switch(Flag) {
|
|
||||||
case REORDER: O << "reorder" << "\n"; break;
|
|
||||||
case NOREORDER: O << "noreorder" << "\n"; break;
|
|
||||||
case MACRO: O << "macro" << "\n"; break;
|
|
||||||
case NOMACRO: O << "nomacro" << "\n"; break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a bitmask with all callee saved registers for CPU
|
// Create a bitmask with all callee saved registers for CPU
|
||||||
// or Floating Point registers. For CPU registers consider RA,
|
// or Floating Point registers. For CPU registers consider RA,
|
||||||
// GP and FP for saving if necessary.
|
// GP and FP for saving if necessary.
|
||||||
@ -231,6 +203,44 @@ printHex32(unsigned int Value)
|
|||||||
O << std::dec;
|
O << std::dec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Frame and Set directives
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
/// Frame Directive
|
||||||
|
void MipsAsmPrinter::
|
||||||
|
emitFrameDirective(MachineFunction &MF)
|
||||||
|
{
|
||||||
|
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
|
||||||
|
|
||||||
|
unsigned stackReg = RI.getFrameRegister(MF);
|
||||||
|
unsigned returnReg = RI.getRARegister();
|
||||||
|
unsigned stackSize = MF.getFrameInfo()->getStackSize();
|
||||||
|
|
||||||
|
|
||||||
|
O << "\t.frame\t" << "$" << LowercaseString(RI.get(stackReg).AsmName)
|
||||||
|
<< "," << stackSize << ","
|
||||||
|
<< "$" << LowercaseString(RI.get(returnReg).AsmName)
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Emit Set directives.
|
||||||
|
const char * MipsAsmPrinter::
|
||||||
|
emitCurrentABIString(void)
|
||||||
|
{
|
||||||
|
switch(Subtarget->getTargetABI()) {
|
||||||
|
case MipsSubtarget::O32: return "abi32";
|
||||||
|
case MipsSubtarget::O64: return "abiO64";
|
||||||
|
case MipsSubtarget::N32: return "abiN32";
|
||||||
|
case MipsSubtarget::N64: return "abi64";
|
||||||
|
case MipsSubtarget::EABI: return "eabi32"; // TODO: handle eabi64
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(0 && "Unknown Mips ABI");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/// Emit the directives used by GAS on the start of functions
|
/// Emit the directives used by GAS on the start of functions
|
||||||
void MipsAsmPrinter::
|
void MipsAsmPrinter::
|
||||||
emitFunctionStart(MachineFunction &MF)
|
emitFunctionStart(MachineFunction &MF)
|
||||||
@ -244,18 +254,16 @@ emitFunctionStart(MachineFunction &MF)
|
|||||||
|
|
||||||
O << "\t.globl\t" << CurrentFnName << "\n";
|
O << "\t.globl\t" << CurrentFnName << "\n";
|
||||||
O << "\t.ent\t" << CurrentFnName << "\n";
|
O << "\t.ent\t" << CurrentFnName << "\n";
|
||||||
O << "\t.type\t" << CurrentFnName << ", @function\n";
|
|
||||||
|
if ((TAI->hasDotTypeDotSizeDirective()) && Subtarget->isLinux())
|
||||||
|
O << "\t.type\t" << CurrentFnName << ", @function\n";
|
||||||
|
|
||||||
O << CurrentFnName << ":\n";
|
O << CurrentFnName << ":\n";
|
||||||
|
|
||||||
emitFrameDirective(MF);
|
emitFrameDirective(MF);
|
||||||
emitMaskDirective(MF);
|
emitMaskDirective(MF);
|
||||||
emitFMaskDirective(MF);
|
emitFMaskDirective(MF);
|
||||||
|
|
||||||
if (TM.getRelocationModel() == Reloc::Static) {
|
|
||||||
emitSetDirective(NOREORDER);
|
|
||||||
emitSetDirective(NOMACRO);
|
|
||||||
}
|
|
||||||
|
|
||||||
O << "\n";
|
O << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,12 +271,15 @@ emitFunctionStart(MachineFunction &MF)
|
|||||||
void MipsAsmPrinter::
|
void MipsAsmPrinter::
|
||||||
emitFunctionEnd(MachineFunction &MF)
|
emitFunctionEnd(MachineFunction &MF)
|
||||||
{
|
{
|
||||||
if (TM.getRelocationModel() == Reloc::Static) {
|
// There are instruction for this macros, but they must
|
||||||
emitSetDirective(MACRO);
|
// always be at the function end, and we can't emit and
|
||||||
emitSetDirective(REORDER);
|
// break with BB logic.
|
||||||
}
|
O << "\t.set\tmacro\n";
|
||||||
|
O << "\t.set\treorder\n";
|
||||||
|
|
||||||
O << "\t.end\t" << CurrentFnName << "\n";
|
O << "\t.end\t" << CurrentFnName << "\n";
|
||||||
|
if (TAI->hasDotTypeDotSizeDirective() && !Subtarget->isLinux())
|
||||||
|
O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// runOnMachineFunction - This uses the printMachineInstruction()
|
/// runOnMachineFunction - This uses the printMachineInstruction()
|
||||||
@ -441,6 +452,18 @@ bool MipsAsmPrinter::
|
|||||||
doInitialization(Module &M)
|
doInitialization(Module &M)
|
||||||
{
|
{
|
||||||
Mang = new Mangler(M);
|
Mang = new Mangler(M);
|
||||||
|
|
||||||
|
// Tell the assembler which ABI we are using
|
||||||
|
O << "\t.section .mdebug." << emitCurrentABIString() << "\n";
|
||||||
|
|
||||||
|
// TODO: handle O64 ABI
|
||||||
|
if (Subtarget->isABI_EABI())
|
||||||
|
O << "\t.section .gcc_compiled_long" <<
|
||||||
|
(Subtarget->isGP32bit() ? "32" : "64") << "\n";
|
||||||
|
|
||||||
|
// return to previous section
|
||||||
|
O << "\t.previous" << "\n";
|
||||||
|
|
||||||
return false; // success
|
return false; // success
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,8 +571,11 @@ doFinalization(Module &M)
|
|||||||
}
|
}
|
||||||
|
|
||||||
O << "\t.align " << Align << "\n";
|
O << "\t.align " << Align << "\n";
|
||||||
O << "\t.type " << name << ",@object\n";
|
|
||||||
O << "\t.size " << name << "," << Size << "\n";
|
if (TAI->hasDotTypeDotSizeDirective()) {
|
||||||
|
O << "\t.type " << name << ",@object\n";
|
||||||
|
O << "\t.size " << name << "," << Size << "\n";
|
||||||
|
}
|
||||||
O << name << ":\n";
|
O << name << ":\n";
|
||||||
EmitGlobalConstant(C);
|
EmitGlobalConstant(C);
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,9 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "Mips.h"
|
//#include "Mips.h"
|
||||||
#include "MipsInstrInfo.h"
|
#include "MipsInstrInfo.h"
|
||||||
|
#include "MipsTargetMachine.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "MipsGenInstrInfo.inc"
|
#include "MipsGenInstrInfo.inc"
|
||||||
@ -21,7 +22,7 @@ using namespace llvm;
|
|||||||
|
|
||||||
MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm)
|
MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm)
|
||||||
: TargetInstrInfoImpl(MipsInsts, array_lengthof(MipsInsts)),
|
: TargetInstrInfoImpl(MipsInsts, array_lengthof(MipsInsts)),
|
||||||
TM(tm), RI(*this) {}
|
TM(tm), RI(*TM.getSubtargetImpl(), *this) {}
|
||||||
|
|
||||||
static bool isZeroImm(const MachineOperand &op) {
|
static bool isZeroImm(const MachineOperand &op) {
|
||||||
return op.isImmediate() && op.getImm() == 0;
|
return op.isImmediate() && op.getImm() == 0;
|
||||||
|
@ -31,7 +31,8 @@ def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,
|
|||||||
// Hi and Lo nodes are used to handle global addresses. Used on
|
// Hi and Lo nodes are used to handle global addresses. Used on
|
||||||
// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
|
// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
|
||||||
// static model. (nothing to do with Mips Registers Hi and Lo)
|
// static model. (nothing to do with Mips Registers Hi and Lo)
|
||||||
def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>;
|
//def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>;
|
||||||
|
def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>;
|
||||||
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
|
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
@ -125,7 +126,7 @@ class ArithR<bits<6> op, bits<6> func, string instr_asm, SDNode OpNode,
|
|||||||
func,
|
func,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins CPURegs:$b, CPURegs:$c),
|
(ins CPURegs:$b, CPURegs:$c),
|
||||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
!strconcat(instr_asm, "\t$dst, $b, $c"),
|
||||||
[(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin>;
|
[(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin>;
|
||||||
|
|
||||||
let isCommutable = 1 in
|
let isCommutable = 1 in
|
||||||
@ -134,7 +135,7 @@ class ArithOverflowR<bits<6> op, bits<6> func, string instr_asm>:
|
|||||||
func,
|
func,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins CPURegs:$b, CPURegs:$c),
|
(ins CPURegs:$b, CPURegs:$c),
|
||||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
!strconcat(instr_asm, "\t$dst, $b, $c"),
|
||||||
[], IIAlu>;
|
[], IIAlu>;
|
||||||
|
|
||||||
// Arithmetic 2 register operands
|
// Arithmetic 2 register operands
|
||||||
@ -143,7 +144,7 @@ class ArithI<bits<6> op, string instr_asm, SDNode OpNode,
|
|||||||
FI< op,
|
FI< op,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins CPURegs:$b, Od:$c),
|
(ins CPURegs:$b, Od:$c),
|
||||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
!strconcat(instr_asm, "\t$dst, $b, $c"),
|
||||||
[(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>;
|
[(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>;
|
||||||
|
|
||||||
// Arithmetic Multiply ADD/SUB
|
// Arithmetic Multiply ADD/SUB
|
||||||
@ -153,7 +154,7 @@ class MArithR<bits<6> func, string instr_asm> :
|
|||||||
func,
|
func,
|
||||||
(outs CPURegs:$rs),
|
(outs CPURegs:$rs),
|
||||||
(ins CPURegs:$rt),
|
(ins CPURegs:$rt),
|
||||||
!strconcat(instr_asm, " $rs, $rt"),
|
!strconcat(instr_asm, "\t$rs, $rt"),
|
||||||
[], IIImul>;
|
[], IIImul>;
|
||||||
|
|
||||||
// Logical
|
// Logical
|
||||||
@ -162,14 +163,14 @@ class LogicR<bits<6> func, string instr_asm, SDNode OpNode>:
|
|||||||
func,
|
func,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins CPURegs:$b, CPURegs:$c),
|
(ins CPURegs:$b, CPURegs:$c),
|
||||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
!strconcat(instr_asm, "\t$dst, $b, $c"),
|
||||||
[(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>;
|
[(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>;
|
||||||
|
|
||||||
class LogicI<bits<6> op, string instr_asm, SDNode OpNode>:
|
class LogicI<bits<6> op, string instr_asm, SDNode OpNode>:
|
||||||
FI< op,
|
FI< op,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins CPURegs:$b, uimm16:$c),
|
(ins CPURegs:$b, uimm16:$c),
|
||||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
!strconcat(instr_asm, "\t$dst, $b, $c"),
|
||||||
[(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], IIAlu>;
|
[(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], IIAlu>;
|
||||||
|
|
||||||
class LogicNOR<bits<6> op, bits<6> func, string instr_asm>:
|
class LogicNOR<bits<6> op, bits<6> func, string instr_asm>:
|
||||||
@ -177,7 +178,7 @@ class LogicNOR<bits<6> op, bits<6> func, string instr_asm>:
|
|||||||
func,
|
func,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins CPURegs:$b, CPURegs:$c),
|
(ins CPURegs:$b, CPURegs:$c),
|
||||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
!strconcat(instr_asm, "\t$dst, $b, $c"),
|
||||||
[(set CPURegs:$dst, (not (or CPURegs:$b, CPURegs:$c)))], IIAlu>;
|
[(set CPURegs:$dst, (not (or CPURegs:$b, CPURegs:$c)))], IIAlu>;
|
||||||
|
|
||||||
// Shifts
|
// Shifts
|
||||||
@ -187,7 +188,7 @@ class LogicR_shift_imm<bits<6> func, string instr_asm, SDNode OpNode>:
|
|||||||
func,
|
func,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins CPURegs:$b, shamt:$c),
|
(ins CPURegs:$b, shamt:$c),
|
||||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
!strconcat(instr_asm, "\t$dst, $b, $c"),
|
||||||
[(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt5:$c))], IIAlu>;
|
[(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt5:$c))], IIAlu>;
|
||||||
|
|
||||||
class LogicR_shift_reg<bits<6> func, string instr_asm, SDNode OpNode>:
|
class LogicR_shift_reg<bits<6> func, string instr_asm, SDNode OpNode>:
|
||||||
@ -195,7 +196,7 @@ class LogicR_shift_reg<bits<6> func, string instr_asm, SDNode OpNode>:
|
|||||||
func,
|
func,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins CPURegs:$b, CPURegs:$c),
|
(ins CPURegs:$b, CPURegs:$c),
|
||||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
!strconcat(instr_asm, "\t$dst, $b, $c"),
|
||||||
[(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>;
|
[(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>;
|
||||||
|
|
||||||
// Load Upper Imediate
|
// Load Upper Imediate
|
||||||
@ -203,7 +204,7 @@ class LoadUpper<bits<6> op, string instr_asm>:
|
|||||||
FI< op,
|
FI< op,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins uimm16:$imm),
|
(ins uimm16:$imm),
|
||||||
!strconcat(instr_asm, " $dst, $imm"),
|
!strconcat(instr_asm, "\t$dst, $imm"),
|
||||||
[], IIAlu>;
|
[], IIAlu>;
|
||||||
|
|
||||||
// Memory Load/Store
|
// Memory Load/Store
|
||||||
@ -212,14 +213,14 @@ class LoadM<bits<6> op, string instr_asm, PatFrag OpNode>:
|
|||||||
FI< op,
|
FI< op,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins mem:$addr),
|
(ins mem:$addr),
|
||||||
!strconcat(instr_asm, " $dst, $addr"),
|
!strconcat(instr_asm, "\t$dst, $addr"),
|
||||||
[(set CPURegs:$dst, (OpNode addr:$addr))], IILoad>;
|
[(set CPURegs:$dst, (OpNode addr:$addr))], IILoad>;
|
||||||
|
|
||||||
class StoreM<bits<6> op, string instr_asm, PatFrag OpNode>:
|
class StoreM<bits<6> op, string instr_asm, PatFrag OpNode>:
|
||||||
FI< op,
|
FI< op,
|
||||||
(outs),
|
(outs),
|
||||||
(ins CPURegs:$dst, mem:$addr),
|
(ins CPURegs:$dst, mem:$addr),
|
||||||
!strconcat(instr_asm, " $dst, $addr"),
|
!strconcat(instr_asm, "\t$dst, $addr"),
|
||||||
[(OpNode CPURegs:$dst, addr:$addr)], IIStore>;
|
[(OpNode CPURegs:$dst, addr:$addr)], IIStore>;
|
||||||
|
|
||||||
// Conditional Branch
|
// Conditional Branch
|
||||||
@ -228,7 +229,7 @@ class CBranch<bits<6> op, string instr_asm, PatFrag cond_op>:
|
|||||||
FI< op,
|
FI< op,
|
||||||
(outs),
|
(outs),
|
||||||
(ins CPURegs:$a, CPURegs:$b, brtarget:$offset),
|
(ins CPURegs:$a, CPURegs:$b, brtarget:$offset),
|
||||||
!strconcat(instr_asm, " $a, $b, $offset"),
|
!strconcat(instr_asm, "\t$a, $b, $offset"),
|
||||||
[(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)],
|
[(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)],
|
||||||
IIBranch>;
|
IIBranch>;
|
||||||
|
|
||||||
@ -237,7 +238,7 @@ class CBranchZero<bits<6> op, string instr_asm, PatFrag cond_op>:
|
|||||||
FI< op,
|
FI< op,
|
||||||
(outs),
|
(outs),
|
||||||
(ins CPURegs:$src, brtarget:$offset),
|
(ins CPURegs:$src, brtarget:$offset),
|
||||||
!strconcat(instr_asm, " $src, $offset"),
|
!strconcat(instr_asm, "\t$src, $offset"),
|
||||||
[(brcond (cond_op CPURegs:$src, 0), bb:$offset)],
|
[(brcond (cond_op CPURegs:$src, 0), bb:$offset)],
|
||||||
IIBranch>;
|
IIBranch>;
|
||||||
}
|
}
|
||||||
@ -249,7 +250,7 @@ class SetCC_R<bits<6> op, bits<6> func, string instr_asm,
|
|||||||
func,
|
func,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins CPURegs:$b, CPURegs:$c),
|
(ins CPURegs:$b, CPURegs:$c),
|
||||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
!strconcat(instr_asm, "\t$dst, $b, $c"),
|
||||||
[(set CPURegs:$dst, (cond_op CPURegs:$b, CPURegs:$c))],
|
[(set CPURegs:$dst, (cond_op CPURegs:$b, CPURegs:$c))],
|
||||||
IIAlu>;
|
IIAlu>;
|
||||||
|
|
||||||
@ -258,7 +259,7 @@ class SetCC_I<bits<6> op, string instr_asm, PatFrag cond_op,
|
|||||||
FI< op,
|
FI< op,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins CPURegs:$b, Od:$c),
|
(ins CPURegs:$b, Od:$c),
|
||||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
!strconcat(instr_asm, "\t$dst, $b, $c"),
|
||||||
[(set CPURegs:$dst, (cond_op CPURegs:$b, imm_type:$c))],
|
[(set CPURegs:$dst, (cond_op CPURegs:$b, imm_type:$c))],
|
||||||
IIAlu>;
|
IIAlu>;
|
||||||
|
|
||||||
@ -268,7 +269,7 @@ class JumpFJ<bits<6> op, string instr_asm>:
|
|||||||
FJ< op,
|
FJ< op,
|
||||||
(outs),
|
(outs),
|
||||||
(ins brtarget:$target),
|
(ins brtarget:$target),
|
||||||
!strconcat(instr_asm, " $target"),
|
!strconcat(instr_asm, "\t$target"),
|
||||||
[(br bb:$target)], IIBranch>;
|
[(br bb:$target)], IIBranch>;
|
||||||
|
|
||||||
let isBranch=1, isTerminator=1, isBarrier=1, rd=0, hasDelaySlot = 1 in
|
let isBranch=1, isTerminator=1, isBarrier=1, rd=0, hasDelaySlot = 1 in
|
||||||
@ -277,7 +278,7 @@ class JumpFR<bits<6> op, bits<6> func, string instr_asm>:
|
|||||||
func,
|
func,
|
||||||
(outs),
|
(outs),
|
||||||
(ins CPURegs:$target),
|
(ins CPURegs:$target),
|
||||||
!strconcat(instr_asm, " $target"),
|
!strconcat(instr_asm, "\t$target"),
|
||||||
[(brind CPURegs:$target)], IIBranch>;
|
[(brind CPURegs:$target)], IIBranch>;
|
||||||
|
|
||||||
// Jump and Link (Call)
|
// Jump and Link (Call)
|
||||||
@ -289,7 +290,7 @@ let isCall=1, hasDelaySlot=1,
|
|||||||
FJ< op,
|
FJ< op,
|
||||||
(outs),
|
(outs),
|
||||||
(ins calltarget:$target),
|
(ins calltarget:$target),
|
||||||
!strconcat(instr_asm, " $target"),
|
!strconcat(instr_asm, "\t$target"),
|
||||||
[(MipsJmpLink imm:$target)], IIBranch>;
|
[(MipsJmpLink imm:$target)], IIBranch>;
|
||||||
|
|
||||||
let rd=31 in
|
let rd=31 in
|
||||||
@ -298,14 +299,14 @@ let isCall=1, hasDelaySlot=1,
|
|||||||
func,
|
func,
|
||||||
(outs),
|
(outs),
|
||||||
(ins CPURegs:$rs),
|
(ins CPURegs:$rs),
|
||||||
!strconcat(instr_asm, " $rs"),
|
!strconcat(instr_asm, "\t$rs"),
|
||||||
[(MipsJmpLink CPURegs:$rs)], IIBranch>;
|
[(MipsJmpLink CPURegs:$rs)], IIBranch>;
|
||||||
|
|
||||||
class BranchLink<string instr_asm>:
|
class BranchLink<string instr_asm>:
|
||||||
FI< 0x1,
|
FI< 0x1,
|
||||||
(outs),
|
(outs),
|
||||||
(ins CPURegs:$rs, brtarget:$target),
|
(ins CPURegs:$rs, brtarget:$target),
|
||||||
!strconcat(instr_asm, " $rs, $target"),
|
!strconcat(instr_asm, "\t$rs, $target"),
|
||||||
[], IIBranch>;
|
[], IIBranch>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +316,7 @@ class MulDiv<bits<6> func, string instr_asm, InstrItinClass itin>:
|
|||||||
func,
|
func,
|
||||||
(outs),
|
(outs),
|
||||||
(ins CPURegs:$a, CPURegs:$b),
|
(ins CPURegs:$a, CPURegs:$b),
|
||||||
!strconcat(instr_asm, " $a, $b"),
|
!strconcat(instr_asm, "\t$a, $b"),
|
||||||
[], itin>;
|
[], itin>;
|
||||||
|
|
||||||
// Move from Hi/Lo
|
// Move from Hi/Lo
|
||||||
@ -324,7 +325,7 @@ class MoveFromTo<bits<6> func, string instr_asm>:
|
|||||||
func,
|
func,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins),
|
(ins),
|
||||||
!strconcat(instr_asm, " $dst"),
|
!strconcat(instr_asm, "\t$dst"),
|
||||||
[], IIHiLo>;
|
[], IIHiLo>;
|
||||||
|
|
||||||
// Count Leading Ones/Zeros in Word
|
// Count Leading Ones/Zeros in Word
|
||||||
@ -333,7 +334,7 @@ class CountLeading<bits<6> func, string instr_asm>:
|
|||||||
func,
|
func,
|
||||||
(outs CPURegs:$dst),
|
(outs CPURegs:$dst),
|
||||||
(ins CPURegs:$src),
|
(ins CPURegs:$src),
|
||||||
!strconcat(instr_asm, " $dst, $src"),
|
!strconcat(instr_asm, "\t$dst, $src"),
|
||||||
[], IIAlu>;
|
[], IIAlu>;
|
||||||
|
|
||||||
class EffectiveAddress<string instr_asm> :
|
class EffectiveAddress<string instr_asm> :
|
||||||
@ -345,7 +346,7 @@ class EffectiveAddress<string instr_asm> :
|
|||||||
|
|
||||||
class SignExtInReg<bits<6> func, string instr_asm, ValueType vt>:
|
class SignExtInReg<bits<6> func, string instr_asm, ValueType vt>:
|
||||||
FR< 0x3f, func, (outs CPURegs:$dst), (ins CPURegs:$src),
|
FR< 0x3f, func, (outs CPURegs:$dst), (ins CPURegs:$src),
|
||||||
!strconcat(instr_asm, " $dst, $src"),
|
!strconcat(instr_asm, "\t$dst, $src"),
|
||||||
[(set CPURegs:$dst, (sext_inreg CPURegs:$src, vt))], NoItinerary>;
|
[(set CPURegs:$dst, (sext_inreg CPURegs:$src, vt))], NoItinerary>;
|
||||||
|
|
||||||
|
|
||||||
@ -363,15 +364,19 @@ def ADJCALLSTACKUP : MipsPseudo<(outs), (ins uimm16:$amt1, uimm16:$amt2),
|
|||||||
[(callseq_end imm:$amt1, imm:$amt2)]>;
|
[(callseq_end imm:$amt1, imm:$amt2)]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some assembly macros need to avoid pseudoinstructions and assembler
|
||||||
|
// automatic reodering, we should reorder ourselves.
|
||||||
|
def MACRO : MipsPseudo<(outs), (ins), ".set\tmacro", []>;
|
||||||
|
def REORDER : MipsPseudo<(outs), (ins), ".set\treorder", []>;
|
||||||
|
def NOMACRO : MipsPseudo<(outs), (ins), ".set\tnomacro", []>;
|
||||||
|
def NOREORDER : MipsPseudo<(outs), (ins), ".set\tnoreorder", []>;
|
||||||
|
|
||||||
// When handling PIC code the assembler needs .cpload and .cprestore
|
// When handling PIC code the assembler needs .cpload and .cprestore
|
||||||
// directives. If the real instructions corresponding these directives
|
// directives. If the real instructions corresponding these directives
|
||||||
// are used, we have the same behavior, but get also a bunch of warnings
|
// are used, we have the same behavior, but get also a bunch of warnings
|
||||||
// from the assembler.
|
// from the assembler.
|
||||||
def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$reg),
|
def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>;
|
||||||
".set noreorder\n\t.cpload $reg\n\t.set reorder\n",
|
def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc), ".cprestore\t$loc\n", []>;
|
||||||
[]>;
|
|
||||||
def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc),
|
|
||||||
".cprestore $loc\n", []>;
|
|
||||||
|
|
||||||
// The supported Mips ISAs dont have any instruction close to the SELECT_CC
|
// The supported Mips ISAs dont have any instruction close to the SELECT_CC
|
||||||
// operation. The solution is to create a Mips pseudo SELECT_CC instruction
|
// operation. The solution is to create a Mips pseudo SELECT_CC instruction
|
||||||
@ -488,14 +493,14 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1,
|
|||||||
isBarrier=1, hasCtrlDep=1, rs=0, rt=0, shamt=0 in
|
isBarrier=1, hasCtrlDep=1, rs=0, rt=0, shamt=0 in
|
||||||
{
|
{
|
||||||
def RET : FR <0x00, 0x02, (outs), (ins CPURegs:$target),
|
def RET : FR <0x00, 0x02, (outs), (ins CPURegs:$target),
|
||||||
"jr $target", [(MipsRet CPURegs:$target)], IIBranch>;
|
"jr\t$target", [(MipsRet CPURegs:$target)], IIBranch>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FrameIndexes are legalized when they are operands from load/store
|
// FrameIndexes are legalized when they are operands from load/store
|
||||||
// instructions. The same not happens for stack address copies, so an
|
// instructions. The same not happens for stack address copies, so an
|
||||||
// add op with mem ComplexPattern is used and the stack address copy
|
// add op with mem ComplexPattern is used and the stack address copy
|
||||||
// can be matched. It's similar to Sparc LEA_ADDRi
|
// can be matched. It's similar to Sparc LEA_ADDRi
|
||||||
def LEA_ADDiu : EffectiveAddress<"addiu $dst, ${addr:stackloc}">;
|
def LEA_ADDiu : EffectiveAddress<"addiu\t$dst, ${addr:stackloc}">;
|
||||||
|
|
||||||
// Count Leading
|
// Count Leading
|
||||||
// CLO/CLZ are part of the newer MIPS32(tm) instruction
|
// CLO/CLZ are part of the newer MIPS32(tm) instruction
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#define DEBUG_TYPE "mips-reg-info"
|
#define DEBUG_TYPE "mips-reg-info"
|
||||||
|
|
||||||
#include "Mips.h"
|
#include "Mips.h"
|
||||||
|
#include "MipsSubtarget.h"
|
||||||
#include "MipsRegisterInfo.h"
|
#include "MipsRegisterInfo.h"
|
||||||
#include "MipsMachineFunction.h"
|
#include "MipsMachineFunction.h"
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
@ -35,9 +36,10 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
MipsRegisterInfo::MipsRegisterInfo(const TargetInstrInfo &tii)
|
MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST,
|
||||||
|
const TargetInstrInfo &tii)
|
||||||
: MipsGenRegisterInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP),
|
: MipsGenRegisterInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP),
|
||||||
TII(tii) {}
|
Subtarget(ST), TII(tii) {}
|
||||||
|
|
||||||
/// getRegisterNumbering - Given the enum value for some register, e.g.
|
/// getRegisterNumbering - Given the enum value for some register, e.g.
|
||||||
/// Mips::RA, return the number that it corresponds to (e.g. 31).
|
/// Mips::RA, return the number that it corresponds to (e.g. 31).
|
||||||
@ -82,10 +84,10 @@ getRegisterNumbering(unsigned RegEnum)
|
|||||||
return 0; // Not reached
|
return 0; // Not reached
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned MipsRegisterInfo::getPICCallReg(void) { return Mips::T9; }
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
|
||||||
// Callee Saved Registers methods
|
// Callee Saved Registers methods
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// Mips Callee Saved Registers
|
/// Mips Callee Saved Registers
|
||||||
@ -306,9 +308,12 @@ emitPrologue(MachineFunction &MF) const
|
|||||||
// Update frame info
|
// Update frame info
|
||||||
MFI->setStackSize(NumBytes);
|
MFI->setStackSize(NumBytes);
|
||||||
|
|
||||||
// PIC speficic function prologue
|
BuildMI(MBB, MBBI, TII.get(Mips::NOREORDER));
|
||||||
if (isPIC)
|
|
||||||
BuildMI(MBB, MBBI, TII.get(Mips::CPLOAD)).addReg(Mips::T9);
|
// TODO: check need from GP here.
|
||||||
|
if (isPIC && Subtarget.isABI_O32())
|
||||||
|
BuildMI(MBB, MBBI, TII.get(Mips::CPLOAD)).addReg(getPICCallReg());
|
||||||
|
BuildMI(MBB, MBBI, TII.get(Mips::NOMACRO));
|
||||||
|
|
||||||
// Adjust stack : addi sp, sp, (-imm)
|
// Adjust stack : addi sp, sp, (-imm)
|
||||||
BuildMI(MBB, MBBI, TII.get(Mips::ADDiu), Mips::SP)
|
BuildMI(MBB, MBBI, TII.get(Mips::ADDiu), Mips::SP)
|
||||||
@ -334,9 +339,10 @@ emitPrologue(MachineFunction &MF) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PIC speficic function prologue
|
// PIC speficic function prologue
|
||||||
if ((isPIC) && (MFI->hasCalls()))
|
if ((isPIC) && (MFI->hasCalls())) {
|
||||||
BuildMI(MBB, MBBI, TII.get(Mips::CPRESTORE))
|
BuildMI(MBB, MBBI, TII.get(Mips::CPRESTORE))
|
||||||
.addImm(MipsFI->getGPStackOffset());
|
.addImm(MipsFI->getGPStackOffset());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MipsRegisterInfo::
|
void MipsRegisterInfo::
|
||||||
|
@ -14,23 +14,28 @@
|
|||||||
#ifndef MIPSREGISTERINFO_H
|
#ifndef MIPSREGISTERINFO_H
|
||||||
#define MIPSREGISTERINFO_H
|
#define MIPSREGISTERINFO_H
|
||||||
|
|
||||||
|
#include "Mips.h"
|
||||||
#include "llvm/Target/TargetRegisterInfo.h"
|
#include "llvm/Target/TargetRegisterInfo.h"
|
||||||
#include "MipsGenRegisterInfo.h.inc"
|
#include "MipsGenRegisterInfo.h.inc"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
class MipsSubtarget;
|
||||||
class TargetInstrInfo;
|
class TargetInstrInfo;
|
||||||
class Type;
|
class Type;
|
||||||
|
|
||||||
struct MipsRegisterInfo : public MipsGenRegisterInfo {
|
struct MipsRegisterInfo : public MipsGenRegisterInfo {
|
||||||
|
const MipsSubtarget &Subtarget;
|
||||||
const TargetInstrInfo &TII;
|
const TargetInstrInfo &TII;
|
||||||
|
|
||||||
MipsRegisterInfo(const TargetInstrInfo &tii);
|
MipsRegisterInfo(const MipsSubtarget &Subtarget, const TargetInstrInfo &tii);
|
||||||
|
|
||||||
/// getRegisterNumbering - Given the enum value for some register, e.g.
|
/// getRegisterNumbering - Given the enum value for some register, e.g.
|
||||||
/// Mips::RA, return the number that it corresponds to (e.g. 31).
|
/// Mips::RA, return the number that it corresponds to (e.g. 31).
|
||||||
static unsigned getRegisterNumbering(unsigned RegEnum);
|
static unsigned getRegisterNumbering(unsigned RegEnum);
|
||||||
|
|
||||||
|
/// Get PIC indirect call register
|
||||||
|
static unsigned getPICCallReg(void);
|
||||||
|
|
||||||
/// Code Generation virtual methods...
|
/// Code Generation virtual methods...
|
||||||
const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const;
|
const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const;
|
||||||
|
|
||||||
|
@ -15,23 +15,34 @@
|
|||||||
#include "Mips.h"
|
#include "Mips.h"
|
||||||
#include "MipsGenSubtarget.inc"
|
#include "MipsGenSubtarget.inc"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
cl::opt<bool> NotABICall("disable-mips-abicall", cl::Hidden,
|
||||||
|
cl::desc("Disable code for SVR4-style dynamic objects"));
|
||||||
|
cl::opt<bool> AbsoluteCall("enable-mips-absolute-call", cl::Hidden,
|
||||||
|
cl::desc("Enable absolute call within abicall"));
|
||||||
|
|
||||||
MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M,
|
MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M,
|
||||||
const std::string &FS, bool little) :
|
const std::string &FS, bool little) :
|
||||||
MipsArchVersion(Mips1), MipsABI(O32), IsLittle(little), IsSingleFloat(false),
|
MipsArchVersion(Mips1), MipsABI(O32), IsLittle(little), IsSingleFloat(false),
|
||||||
IsFP64bit(false), IsGP64bit(false), HasVFPU(false), HasSEInReg(false)
|
IsFP64bit(false), IsGP64bit(false), HasVFPU(false), HasSEInReg(false),
|
||||||
|
HasABICall(true), HasAbsoluteCall(false), IsLinux(true)
|
||||||
{
|
{
|
||||||
std::string CPU = "mips1";
|
std::string CPU = "mips1";
|
||||||
|
|
||||||
// Parse features string.
|
// Parse features string.
|
||||||
ParseSubtargetFeatures(FS, CPU);
|
ParseSubtargetFeatures(FS, CPU);
|
||||||
|
const std::string& TT = M.getTargetTriple();
|
||||||
|
|
||||||
|
// Is the target system Linux ?
|
||||||
|
if (TT.find("linux") == std::string::npos)
|
||||||
|
IsLinux = false;
|
||||||
|
|
||||||
// When only the target triple is specified and is
|
// When only the target triple is specified and is
|
||||||
// a allegrex target, set the features. We also match
|
// a allegrex target, set the features. We also match
|
||||||
// big and little endian allegrex cores (dont really
|
// big and little endian allegrex cores (dont really
|
||||||
// know if a big one exists)
|
// know if a big one exists)
|
||||||
const std::string& TT = M.getTargetTriple();
|
|
||||||
if (TT.find("mipsallegrex") != std::string::npos) {
|
if (TT.find("mipsallegrex") != std::string::npos) {
|
||||||
MipsABI = EABI;
|
MipsABI = EABI;
|
||||||
IsSingleFloat = true;
|
IsSingleFloat = true;
|
||||||
@ -39,4 +50,13 @@ MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M,
|
|||||||
HasVFPU = true; // Enables Allegrex Vector FPU (not supported yet)
|
HasVFPU = true; // Enables Allegrex Vector FPU (not supported yet)
|
||||||
HasSEInReg = true;
|
HasSEInReg = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Abicall is the default for O32 ABI and is ignored
|
||||||
|
// for EABI.
|
||||||
|
if (NotABICall || isABI_EABI())
|
||||||
|
HasABICall = false;
|
||||||
|
|
||||||
|
// TODO: disable when handling 64 bit symbols in the future.
|
||||||
|
if (HasABICall && AbsoluteCall)
|
||||||
|
HasAbsoluteCall = true;
|
||||||
}
|
}
|
||||||
|
@ -24,16 +24,17 @@ class Module;
|
|||||||
|
|
||||||
class MipsSubtarget : public TargetSubtarget {
|
class MipsSubtarget : public TargetSubtarget {
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum MipsABIEnum {
|
||||||
|
O32, O64, N32, N64, EABI
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
enum MipsArchEnum {
|
enum MipsArchEnum {
|
||||||
Mips1, Mips2, Mips3, Mips4, Mips32, Mips32r2, Mips64, Mips64r2
|
Mips1, Mips2, Mips3, Mips4, Mips32, Mips32r2, Mips64, Mips64r2
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MipsABIEnum {
|
|
||||||
O32, EABI
|
|
||||||
};
|
|
||||||
|
|
||||||
// Mips architecture version
|
// Mips architecture version
|
||||||
MipsArchEnum MipsArchVersion;
|
MipsArchEnum MipsArchVersion;
|
||||||
|
|
||||||
@ -60,6 +61,16 @@ protected:
|
|||||||
// HasSEInReg - Target has SEB and SEH (signext in register) instructions.
|
// HasSEInReg - Target has SEB and SEH (signext in register) instructions.
|
||||||
bool HasSEInReg;
|
bool HasSEInReg;
|
||||||
|
|
||||||
|
// IsABICall - Enable SRV4 code for SVR4-style dynamic objects
|
||||||
|
bool HasABICall;
|
||||||
|
|
||||||
|
// HasAbsoluteCall - Enable code that is not fully position-independent.
|
||||||
|
// Only works with HasABICall enabled.
|
||||||
|
bool HasAbsoluteCall;
|
||||||
|
|
||||||
|
// isLinux - Target system is Linux. Is false we consider ELFOS for now.
|
||||||
|
bool IsLinux;
|
||||||
|
|
||||||
InstrItineraryData InstrItins;
|
InstrItineraryData InstrItins;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -67,6 +78,7 @@ public:
|
|||||||
/// Only O32 and EABI supported right now.
|
/// Only O32 and EABI supported right now.
|
||||||
bool isABI_EABI() const { return MipsABI == EABI; }
|
bool isABI_EABI() const { return MipsABI == EABI; }
|
||||||
bool isABI_O32() const { return MipsABI == O32; }
|
bool isABI_O32() const { return MipsABI == O32; }
|
||||||
|
unsigned getTargetABI() const { return MipsABI; }
|
||||||
|
|
||||||
/// This constructor initializes the data members to match that
|
/// This constructor initializes the data members to match that
|
||||||
/// of the specified module.
|
/// of the specified module.
|
||||||
@ -87,6 +99,9 @@ public:
|
|||||||
bool isNotSingleFloat() const { return !IsSingleFloat; };
|
bool isNotSingleFloat() const { return !IsSingleFloat; };
|
||||||
bool hasVFPU() const { return HasVFPU; };
|
bool hasVFPU() const { return HasVFPU; };
|
||||||
bool hasSEInReg() const { return HasSEInReg; };
|
bool hasSEInReg() const { return HasSEInReg; };
|
||||||
|
bool hasABICall() const { return HasABICall; };
|
||||||
|
bool hasAbsoluteCall() const { return HasAbsoluteCall; };
|
||||||
|
bool isLinux() const { return IsLinux; };
|
||||||
|
|
||||||
};
|
};
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
@ -17,21 +17,23 @@
|
|||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
MipsTargetAsmInfo::MipsTargetAsmInfo(const MipsTargetMachine &TM) {
|
MipsTargetAsmInfo::MipsTargetAsmInfo(const MipsTargetMachine &TM) {
|
||||||
AlignmentIsInBytes = false;
|
|
||||||
Data16bitsDirective = "\t.half\t";
|
AlignmentIsInBytes = false;
|
||||||
Data32bitsDirective = "\t.word\t";
|
COMMDirectiveTakesAlignment = true;
|
||||||
PrivateGlobalPrefix = "$";
|
Data16bitsDirective = "\t.half\t";
|
||||||
JumpTableDataSection = "\t.rdata";
|
Data32bitsDirective = "\t.word\t";
|
||||||
CommentString = "#";
|
Data64bitsDirective = NULL;
|
||||||
ReadOnlySection = "\t.rdata";
|
PrivateGlobalPrefix = "$";
|
||||||
ZeroDirective = "\t.space\t";
|
JumpTableDataSection = "\t.rdata";
|
||||||
BSSSection = "\t.section\t.bss";
|
CommentString = "#";
|
||||||
LCOMMDirective = "\t.lcomm\t";
|
ReadOnlySection = "\t.rdata";
|
||||||
|
ZeroDirective = "\t.space\t";
|
||||||
|
BSSSection = "\t.section\t.bss";
|
||||||
|
LCOMMDirective = "\t.lcomm\t";
|
||||||
|
|
||||||
if (TM.getRelocationModel() == Reloc::Static)
|
if (TM.getRelocationModel() == Reloc::Static)
|
||||||
JumpTableDirective = "\t.word\t";
|
JumpTableDirective = "\t.word\t";
|
||||||
else
|
else
|
||||||
JumpTableDirective = "\t.gpword\t";
|
JumpTableDirective = "\t.gpword\t";
|
||||||
|
|
||||||
COMMDirectiveTakesAlignment = true;
|
|
||||||
}
|
}
|
||||||
|
@ -44,8 +44,12 @@ MipsTargetMachine(const Module &M, const std::string &FS, bool isLittle=false):
|
|||||||
FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0),
|
FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0),
|
||||||
TLInfo(*this)
|
TLInfo(*this)
|
||||||
{
|
{
|
||||||
if (getRelocationModel() != Reloc::Static)
|
// Abicall enables PIC by default
|
||||||
|
if (Subtarget.hasABICall() && (getRelocationModel() != Reloc::Static))
|
||||||
setRelocationModel(Reloc::PIC_);
|
setRelocationModel(Reloc::PIC_);
|
||||||
|
|
||||||
|
// TODO: create an option to enable long calls, like -mlong-calls,
|
||||||
|
// that would be our CodeModel::Large. It must not work with Abicall.
|
||||||
if (getCodeModel() == CodeModel::Default)
|
if (getCodeModel() == CodeModel::Default)
|
||||||
setCodeModel(CodeModel::Small);
|
setCodeModel(CodeModel::Small);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user