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:
Bruno Cardoso Lopes 2008-07-14 14:42:54 +00:00
parent 91e1c32dd0
commit 43d526d162
9 changed files with 200 additions and 116 deletions

View File

@ -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);
} }

View File

@ -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;

View File

@ -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

View File

@ -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::

View File

@ -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;

View File

@ -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;
} }

View File

@ -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

View File

@ -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;
} }

View File

@ -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);
} }