forked from OSchip/llvm-project
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. llvm-svn: 53551
This commit is contained in:
parent
a696ca66e9
commit
80ab8f9649
|
@ -15,6 +15,7 @@
|
|||
#define DEBUG_TYPE "mips-asm-printer"
|
||||
|
||||
#include "Mips.h"
|
||||
#include "MipsSubtarget.h"
|
||||
#include "MipsInstrInfo.h"
|
||||
#include "MipsTargetMachine.h"
|
||||
#include "MipsMachineFunction.h"
|
||||
|
@ -44,21 +45,19 @@ STATISTIC(EmittedInsts, "Number of machine instrs printed");
|
|||
|
||||
namespace {
|
||||
struct VISIBILITY_HIDDEN MipsAsmPrinter : public AsmPrinter {
|
||||
|
||||
const MipsSubtarget *Subtarget;
|
||||
|
||||
MipsAsmPrinter(std::ostream &O, MipsTargetMachine &TM,
|
||||
const TargetAsmInfo *T):
|
||||
AsmPrinter(O, TM, T) {}
|
||||
AsmPrinter(O, TM, T) {
|
||||
Subtarget = &TM.getSubtarget<MipsSubtarget>();
|
||||
}
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
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 printMemOperand(const MachineInstr *MI, int opNum,
|
||||
const char *Modifier = 0);
|
||||
|
@ -68,13 +67,13 @@ namespace {
|
|||
unsigned int getSavedRegsBitmask(bool isFloat, MachineFunction &MF);
|
||||
void printHex32(unsigned int Value);
|
||||
|
||||
const char *emitCurrentABIString(void);
|
||||
void emitFunctionStart(MachineFunction &MF);
|
||||
void emitFunctionEnd(MachineFunction &MF);
|
||||
void emitFrameDirective(MachineFunction &MF);
|
||||
void emitMaskDirective(MachineFunction &MF);
|
||||
void emitFMaskDirective(MachineFunction &MF);
|
||||
void emitSetDirective(SetDirectiveFlags Flag);
|
||||
|
||||
|
||||
bool printInstruction(const MachineInstr *MI); // autogenerated.
|
||||
bool runOnMachineFunction(MachineFunction &F);
|
||||
bool doInitialization(Module &M);
|
||||
|
@ -125,6 +124,10 @@ FunctionPass *llvm::createMipsCodePrinterPass(std::ostream &o,
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Mask directives
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Mask directive for GPR
|
||||
void MipsAsmPrinter::
|
||||
emitMaskDirective(MachineFunction &MF)
|
||||
|
@ -159,37 +162,6 @@ emitFMaskDirective(MachineFunction &MF)
|
|||
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
|
||||
// or Floating Point registers. For CPU registers consider RA,
|
||||
// GP and FP for saving if necessary.
|
||||
|
@ -231,6 +203,44 @@ printHex32(unsigned int Value)
|
|||
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
|
||||
void MipsAsmPrinter::
|
||||
emitFunctionStart(MachineFunction &MF)
|
||||
|
@ -244,18 +254,16 @@ emitFunctionStart(MachineFunction &MF)
|
|||
|
||||
O << "\t.globl\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";
|
||||
|
||||
emitFrameDirective(MF);
|
||||
emitMaskDirective(MF);
|
||||
emitFMaskDirective(MF);
|
||||
|
||||
if (TM.getRelocationModel() == Reloc::Static) {
|
||||
emitSetDirective(NOREORDER);
|
||||
emitSetDirective(NOMACRO);
|
||||
}
|
||||
|
||||
O << "\n";
|
||||
}
|
||||
|
||||
|
@ -263,12 +271,15 @@ emitFunctionStart(MachineFunction &MF)
|
|||
void MipsAsmPrinter::
|
||||
emitFunctionEnd(MachineFunction &MF)
|
||||
{
|
||||
if (TM.getRelocationModel() == Reloc::Static) {
|
||||
emitSetDirective(MACRO);
|
||||
emitSetDirective(REORDER);
|
||||
}
|
||||
// There are instruction for this macros, but they must
|
||||
// always be at the function end, and we can't emit and
|
||||
// break with BB logic.
|
||||
O << "\t.set\tmacro\n";
|
||||
O << "\t.set\treorder\n";
|
||||
|
||||
O << "\t.end\t" << CurrentFnName << "\n";
|
||||
if (TAI->hasDotTypeDotSizeDirective() && !Subtarget->isLinux())
|
||||
O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << "\n";
|
||||
}
|
||||
|
||||
/// runOnMachineFunction - This uses the printMachineInstruction()
|
||||
|
@ -441,6 +452,18 @@ bool MipsAsmPrinter::
|
|||
doInitialization(Module &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
|
||||
}
|
||||
|
||||
|
@ -548,8 +571,11 @@ doFinalization(Module &M)
|
|||
}
|
||||
|
||||
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";
|
||||
EmitGlobalConstant(C);
|
||||
}
|
||||
|
|
|
@ -11,8 +11,9 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Mips.h"
|
||||
//#include "Mips.h"
|
||||
#include "MipsInstrInfo.h"
|
||||
#include "MipsTargetMachine.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "MipsGenInstrInfo.inc"
|
||||
|
@ -21,7 +22,7 @@ using namespace llvm;
|
|||
|
||||
MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm)
|
||||
: TargetInstrInfoImpl(MipsInsts, array_lengthof(MipsInsts)),
|
||||
TM(tm), RI(*this) {}
|
||||
TM(tm), RI(*TM.getSubtargetImpl(), *this) {}
|
||||
|
||||
static bool isZeroImm(const MachineOperand &op) {
|
||||
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
|
||||
// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
|
||||
// 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>;
|
||||
|
||||
// Return
|
||||
|
@ -125,7 +126,7 @@ class ArithR<bits<6> op, bits<6> func, string instr_asm, SDNode OpNode,
|
|||
func,
|
||||
(outs CPURegs:$dst),
|
||||
(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>;
|
||||
|
||||
let isCommutable = 1 in
|
||||
|
@ -134,7 +135,7 @@ class ArithOverflowR<bits<6> op, bits<6> func, string instr_asm>:
|
|||
func,
|
||||
(outs CPURegs:$dst),
|
||||
(ins CPURegs:$b, CPURegs:$c),
|
||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
||||
!strconcat(instr_asm, "\t$dst, $b, $c"),
|
||||
[], IIAlu>;
|
||||
|
||||
// Arithmetic 2 register operands
|
||||
|
@ -143,7 +144,7 @@ class ArithI<bits<6> op, string instr_asm, SDNode OpNode,
|
|||
FI< op,
|
||||
(outs CPURegs:$dst),
|
||||
(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>;
|
||||
|
||||
// Arithmetic Multiply ADD/SUB
|
||||
|
@ -153,7 +154,7 @@ class MArithR<bits<6> func, string instr_asm> :
|
|||
func,
|
||||
(outs CPURegs:$rs),
|
||||
(ins CPURegs:$rt),
|
||||
!strconcat(instr_asm, " $rs, $rt"),
|
||||
!strconcat(instr_asm, "\t$rs, $rt"),
|
||||
[], IIImul>;
|
||||
|
||||
// Logical
|
||||
|
@ -162,14 +163,14 @@ class LogicR<bits<6> func, string instr_asm, SDNode OpNode>:
|
|||
func,
|
||||
(outs CPURegs:$dst),
|
||||
(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>;
|
||||
|
||||
class LogicI<bits<6> op, string instr_asm, SDNode OpNode>:
|
||||
FI< op,
|
||||
(outs CPURegs:$dst),
|
||||
(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>;
|
||||
|
||||
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,
|
||||
(outs CPURegs:$dst),
|
||||
(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>;
|
||||
|
||||
// Shifts
|
||||
|
@ -187,7 +188,7 @@ class LogicR_shift_imm<bits<6> func, string instr_asm, SDNode OpNode>:
|
|||
func,
|
||||
(outs CPURegs:$dst),
|
||||
(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>;
|
||||
|
||||
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,
|
||||
(outs CPURegs:$dst),
|
||||
(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>;
|
||||
|
||||
// Load Upper Imediate
|
||||
|
@ -203,7 +204,7 @@ class LoadUpper<bits<6> op, string instr_asm>:
|
|||
FI< op,
|
||||
(outs CPURegs:$dst),
|
||||
(ins uimm16:$imm),
|
||||
!strconcat(instr_asm, " $dst, $imm"),
|
||||
!strconcat(instr_asm, "\t$dst, $imm"),
|
||||
[], IIAlu>;
|
||||
|
||||
// Memory Load/Store
|
||||
|
@ -212,14 +213,14 @@ class LoadM<bits<6> op, string instr_asm, PatFrag OpNode>:
|
|||
FI< op,
|
||||
(outs CPURegs:$dst),
|
||||
(ins mem:$addr),
|
||||
!strconcat(instr_asm, " $dst, $addr"),
|
||||
!strconcat(instr_asm, "\t$dst, $addr"),
|
||||
[(set CPURegs:$dst, (OpNode addr:$addr))], IILoad>;
|
||||
|
||||
class StoreM<bits<6> op, string instr_asm, PatFrag OpNode>:
|
||||
FI< op,
|
||||
(outs),
|
||||
(ins CPURegs:$dst, mem:$addr),
|
||||
!strconcat(instr_asm, " $dst, $addr"),
|
||||
!strconcat(instr_asm, "\t$dst, $addr"),
|
||||
[(OpNode CPURegs:$dst, addr:$addr)], IIStore>;
|
||||
|
||||
// Conditional Branch
|
||||
|
@ -228,7 +229,7 @@ class CBranch<bits<6> op, string instr_asm, PatFrag cond_op>:
|
|||
FI< op,
|
||||
(outs),
|
||||
(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)],
|
||||
IIBranch>;
|
||||
|
||||
|
@ -237,7 +238,7 @@ class CBranchZero<bits<6> op, string instr_asm, PatFrag cond_op>:
|
|||
FI< op,
|
||||
(outs),
|
||||
(ins CPURegs:$src, brtarget:$offset),
|
||||
!strconcat(instr_asm, " $src, $offset"),
|
||||
!strconcat(instr_asm, "\t$src, $offset"),
|
||||
[(brcond (cond_op CPURegs:$src, 0), bb:$offset)],
|
||||
IIBranch>;
|
||||
}
|
||||
|
@ -249,7 +250,7 @@ class SetCC_R<bits<6> op, bits<6> func, string instr_asm,
|
|||
func,
|
||||
(outs CPURegs:$dst),
|
||||
(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))],
|
||||
IIAlu>;
|
||||
|
||||
|
@ -258,7 +259,7 @@ class SetCC_I<bits<6> op, string instr_asm, PatFrag cond_op,
|
|||
FI< op,
|
||||
(outs CPURegs:$dst),
|
||||
(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))],
|
||||
IIAlu>;
|
||||
|
||||
|
@ -268,7 +269,7 @@ class JumpFJ<bits<6> op, string instr_asm>:
|
|||
FJ< op,
|
||||
(outs),
|
||||
(ins brtarget:$target),
|
||||
!strconcat(instr_asm, " $target"),
|
||||
!strconcat(instr_asm, "\t$target"),
|
||||
[(br bb:$target)], IIBranch>;
|
||||
|
||||
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,
|
||||
(outs),
|
||||
(ins CPURegs:$target),
|
||||
!strconcat(instr_asm, " $target"),
|
||||
!strconcat(instr_asm, "\t$target"),
|
||||
[(brind CPURegs:$target)], IIBranch>;
|
||||
|
||||
// Jump and Link (Call)
|
||||
|
@ -289,7 +290,7 @@ let isCall=1, hasDelaySlot=1,
|
|||
FJ< op,
|
||||
(outs),
|
||||
(ins calltarget:$target),
|
||||
!strconcat(instr_asm, " $target"),
|
||||
!strconcat(instr_asm, "\t$target"),
|
||||
[(MipsJmpLink imm:$target)], IIBranch>;
|
||||
|
||||
let rd=31 in
|
||||
|
@ -298,14 +299,14 @@ let isCall=1, hasDelaySlot=1,
|
|||
func,
|
||||
(outs),
|
||||
(ins CPURegs:$rs),
|
||||
!strconcat(instr_asm, " $rs"),
|
||||
!strconcat(instr_asm, "\t$rs"),
|
||||
[(MipsJmpLink CPURegs:$rs)], IIBranch>;
|
||||
|
||||
class BranchLink<string instr_asm>:
|
||||
FI< 0x1,
|
||||
(outs),
|
||||
(ins CPURegs:$rs, brtarget:$target),
|
||||
!strconcat(instr_asm, " $rs, $target"),
|
||||
!strconcat(instr_asm, "\t$rs, $target"),
|
||||
[], IIBranch>;
|
||||
}
|
||||
|
||||
|
@ -315,7 +316,7 @@ class MulDiv<bits<6> func, string instr_asm, InstrItinClass itin>:
|
|||
func,
|
||||
(outs),
|
||||
(ins CPURegs:$a, CPURegs:$b),
|
||||
!strconcat(instr_asm, " $a, $b"),
|
||||
!strconcat(instr_asm, "\t$a, $b"),
|
||||
[], itin>;
|
||||
|
||||
// Move from Hi/Lo
|
||||
|
@ -324,7 +325,7 @@ class MoveFromTo<bits<6> func, string instr_asm>:
|
|||
func,
|
||||
(outs CPURegs:$dst),
|
||||
(ins),
|
||||
!strconcat(instr_asm, " $dst"),
|
||||
!strconcat(instr_asm, "\t$dst"),
|
||||
[], IIHiLo>;
|
||||
|
||||
// Count Leading Ones/Zeros in Word
|
||||
|
@ -333,7 +334,7 @@ class CountLeading<bits<6> func, string instr_asm>:
|
|||
func,
|
||||
(outs CPURegs:$dst),
|
||||
(ins CPURegs:$src),
|
||||
!strconcat(instr_asm, " $dst, $src"),
|
||||
!strconcat(instr_asm, "\t$dst, $src"),
|
||||
[], IIAlu>;
|
||||
|
||||
class EffectiveAddress<string instr_asm> :
|
||||
|
@ -345,7 +346,7 @@ class EffectiveAddress<string instr_asm> :
|
|||
|
||||
class SignExtInReg<bits<6> func, string instr_asm, ValueType vt>:
|
||||
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>;
|
||||
|
||||
|
||||
|
@ -363,15 +364,19 @@ def ADJCALLSTACKUP : MipsPseudo<(outs), (ins uimm16:$amt1, uimm16:$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
|
||||
// directives. If the real instructions corresponding these directives
|
||||
// are used, we have the same behavior, but get also a bunch of warnings
|
||||
// from the assembler.
|
||||
def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$reg),
|
||||
".set noreorder\n\t.cpload $reg\n\t.set reorder\n",
|
||||
[]>;
|
||||
def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc),
|
||||
".cprestore $loc\n", []>;
|
||||
def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>;
|
||||
def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc), ".cprestore\t$loc\n", []>;
|
||||
|
||||
// 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
|
||||
|
@ -488,14 +493,14 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1,
|
|||
isBarrier=1, hasCtrlDep=1, rs=0, rt=0, shamt=0 in
|
||||
{
|
||||
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
|
||||
// instructions. The same not happens for stack address copies, so an
|
||||
// add op with mem ComplexPattern is used and the stack address copy
|
||||
// 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
|
||||
// CLO/CLZ are part of the newer MIPS32(tm) instruction
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#define DEBUG_TYPE "mips-reg-info"
|
||||
|
||||
#include "Mips.h"
|
||||
#include "MipsSubtarget.h"
|
||||
#include "MipsRegisterInfo.h"
|
||||
#include "MipsMachineFunction.h"
|
||||
#include "llvm/Constants.h"
|
||||
|
@ -35,9 +36,10 @@
|
|||
|
||||
using namespace llvm;
|
||||
|
||||
MipsRegisterInfo::MipsRegisterInfo(const TargetInstrInfo &tii)
|
||||
MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST,
|
||||
const TargetInstrInfo &tii)
|
||||
: MipsGenRegisterInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP),
|
||||
TII(tii) {}
|
||||
Subtarget(ST), TII(tii) {}
|
||||
|
||||
/// getRegisterNumbering - Given the enum value for some register, e.g.
|
||||
/// Mips::RA, return the number that it corresponds to (e.g. 31).
|
||||
|
@ -82,10 +84,10 @@ getRegisterNumbering(unsigned RegEnum)
|
|||
return 0; // Not reached
|
||||
}
|
||||
|
||||
unsigned MipsRegisterInfo::getPICCallReg(void) { return Mips::T9; }
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Callee Saved Registers methods
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Mips Callee Saved Registers
|
||||
|
@ -306,9 +308,12 @@ emitPrologue(MachineFunction &MF) const
|
|||
// Update frame info
|
||||
MFI->setStackSize(NumBytes);
|
||||
|
||||
// PIC speficic function prologue
|
||||
if (isPIC)
|
||||
BuildMI(MBB, MBBI, TII.get(Mips::CPLOAD)).addReg(Mips::T9);
|
||||
BuildMI(MBB, MBBI, TII.get(Mips::NOREORDER));
|
||||
|
||||
// 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)
|
||||
BuildMI(MBB, MBBI, TII.get(Mips::ADDiu), Mips::SP)
|
||||
|
@ -334,9 +339,10 @@ emitPrologue(MachineFunction &MF) const
|
|||
}
|
||||
|
||||
// PIC speficic function prologue
|
||||
if ((isPIC) && (MFI->hasCalls()))
|
||||
if ((isPIC) && (MFI->hasCalls())) {
|
||||
BuildMI(MBB, MBBI, TII.get(Mips::CPRESTORE))
|
||||
.addImm(MipsFI->getGPStackOffset());
|
||||
}
|
||||
}
|
||||
|
||||
void MipsRegisterInfo::
|
||||
|
|
|
@ -14,23 +14,28 @@
|
|||
#ifndef MIPSREGISTERINFO_H
|
||||
#define MIPSREGISTERINFO_H
|
||||
|
||||
#include "Mips.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "MipsGenRegisterInfo.h.inc"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MipsSubtarget;
|
||||
class TargetInstrInfo;
|
||||
class Type;
|
||||
|
||||
struct MipsRegisterInfo : public MipsGenRegisterInfo {
|
||||
const MipsSubtarget &Subtarget;
|
||||
const TargetInstrInfo &TII;
|
||||
|
||||
MipsRegisterInfo(const TargetInstrInfo &tii);
|
||||
MipsRegisterInfo(const MipsSubtarget &Subtarget, const TargetInstrInfo &tii);
|
||||
|
||||
/// getRegisterNumbering - Given the enum value for some register, e.g.
|
||||
/// Mips::RA, return the number that it corresponds to (e.g. 31).
|
||||
static unsigned getRegisterNumbering(unsigned RegEnum);
|
||||
|
||||
/// Get PIC indirect call register
|
||||
static unsigned getPICCallReg(void);
|
||||
|
||||
/// Code Generation virtual methods...
|
||||
const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const;
|
||||
|
||||
|
|
|
@ -15,23 +15,34 @@
|
|||
#include "Mips.h"
|
||||
#include "MipsGenSubtarget.inc"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
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,
|
||||
const std::string &FS, bool little) :
|
||||
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";
|
||||
|
||||
// Parse features string.
|
||||
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
|
||||
// a allegrex target, set the features. We also match
|
||||
// big and little endian allegrex cores (dont really
|
||||
// know if a big one exists)
|
||||
const std::string& TT = M.getTargetTriple();
|
||||
if (TT.find("mipsallegrex") != std::string::npos) {
|
||||
MipsABI = EABI;
|
||||
IsSingleFloat = true;
|
||||
|
@ -39,4 +50,13 @@ MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M,
|
|||
HasVFPU = true; // Enables Allegrex Vector FPU (not supported yet)
|
||||
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 {
|
||||
|
||||
public:
|
||||
enum MipsABIEnum {
|
||||
O32, O64, N32, N64, EABI
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
enum MipsArchEnum {
|
||||
Mips1, Mips2, Mips3, Mips4, Mips32, Mips32r2, Mips64, Mips64r2
|
||||
};
|
||||
|
||||
enum MipsABIEnum {
|
||||
O32, EABI
|
||||
};
|
||||
|
||||
// Mips architecture version
|
||||
MipsArchEnum MipsArchVersion;
|
||||
|
||||
|
@ -60,6 +61,16 @@ protected:
|
|||
// HasSEInReg - Target has SEB and SEH (signext in register) instructions.
|
||||
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;
|
||||
|
||||
public:
|
||||
|
@ -67,6 +78,7 @@ public:
|
|||
/// Only O32 and EABI supported right now.
|
||||
bool isABI_EABI() const { return MipsABI == EABI; }
|
||||
bool isABI_O32() const { return MipsABI == O32; }
|
||||
unsigned getTargetABI() const { return MipsABI; }
|
||||
|
||||
/// This constructor initializes the data members to match that
|
||||
/// of the specified module.
|
||||
|
@ -87,6 +99,9 @@ public:
|
|||
bool isNotSingleFloat() const { return !IsSingleFloat; };
|
||||
bool hasVFPU() const { return HasVFPU; };
|
||||
bool hasSEInReg() const { return HasSEInReg; };
|
||||
bool hasABICall() const { return HasABICall; };
|
||||
bool hasAbsoluteCall() const { return HasAbsoluteCall; };
|
||||
bool isLinux() const { return IsLinux; };
|
||||
|
||||
};
|
||||
} // End llvm namespace
|
||||
|
|
|
@ -17,21 +17,23 @@
|
|||
using namespace llvm;
|
||||
|
||||
MipsTargetAsmInfo::MipsTargetAsmInfo(const MipsTargetMachine &TM) {
|
||||
AlignmentIsInBytes = false;
|
||||
Data16bitsDirective = "\t.half\t";
|
||||
Data32bitsDirective = "\t.word\t";
|
||||
PrivateGlobalPrefix = "$";
|
||||
JumpTableDataSection = "\t.rdata";
|
||||
CommentString = "#";
|
||||
ReadOnlySection = "\t.rdata";
|
||||
ZeroDirective = "\t.space\t";
|
||||
BSSSection = "\t.section\t.bss";
|
||||
LCOMMDirective = "\t.lcomm\t";
|
||||
|
||||
AlignmentIsInBytes = false;
|
||||
COMMDirectiveTakesAlignment = true;
|
||||
Data16bitsDirective = "\t.half\t";
|
||||
Data32bitsDirective = "\t.word\t";
|
||||
Data64bitsDirective = NULL;
|
||||
PrivateGlobalPrefix = "$";
|
||||
JumpTableDataSection = "\t.rdata";
|
||||
CommentString = "#";
|
||||
ReadOnlySection = "\t.rdata";
|
||||
ZeroDirective = "\t.space\t";
|
||||
BSSSection = "\t.section\t.bss";
|
||||
LCOMMDirective = "\t.lcomm\t";
|
||||
|
||||
if (TM.getRelocationModel() == Reloc::Static)
|
||||
JumpTableDirective = "\t.word\t";
|
||||
else
|
||||
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),
|
||||
TLInfo(*this)
|
||||
{
|
||||
if (getRelocationModel() != Reloc::Static)
|
||||
// Abicall enables PIC by default
|
||||
if (Subtarget.hasABICall() && (getRelocationModel() != Reloc::Static))
|
||||
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)
|
||||
setCodeModel(CodeModel::Small);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue