mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2026-04-21 23:17:16 +00:00
several major improvements to the sparc backend: support for weak linkage
and PIC codegen. Patch by Venkatraman Govindaraju! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@81877 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -75,12 +75,14 @@ namespace {
|
||||
unsigned AsmVariant, const char *ExtraCode);
|
||||
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant, const char *ExtraCode);
|
||||
|
||||
void emitFunctionHeader(const MachineFunction &MF);
|
||||
bool printGetPCX(const MachineInstr *MI, unsigned OpNo);
|
||||
};
|
||||
} // end of anonymous namespace
|
||||
|
||||
#include "SparcGenAsmWriter.inc"
|
||||
|
||||
|
||||
/// runOnMachineFunction - This uses the printInstruction()
|
||||
/// method to print assembly for each instruction.
|
||||
///
|
||||
@@ -96,17 +98,9 @@ bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
||||
// BBs the same name. (If you have a better way, please let me know!)
|
||||
|
||||
O << "\n\n";
|
||||
|
||||
// Print out the label for the function.
|
||||
const Function *F = MF.getFunction();
|
||||
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
|
||||
EmitAlignment(MF.getAlignment(), F);
|
||||
O << "\t.globl\t" << CurrentFnName << '\n';
|
||||
|
||||
printVisibility(CurrentFnName, F->getVisibility());
|
||||
|
||||
O << "\t.type\t" << CurrentFnName << ", #function\n";
|
||||
O << CurrentFnName << ":\n";
|
||||
emitFunctionHeader(MF);
|
||||
|
||||
|
||||
// Emit pre-function debug information.
|
||||
DW->BeginFunction(&MF);
|
||||
|
||||
@@ -145,9 +139,43 @@ bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
||||
DW->EndFunction(&MF);
|
||||
|
||||
// We didn't modify anything.
|
||||
O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
|
||||
return false;
|
||||
}
|
||||
|
||||
void SparcAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
|
||||
const Function *F = MF.getFunction();
|
||||
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
|
||||
EmitAlignment(MF.getAlignment(), F);
|
||||
|
||||
switch (F->getLinkage()) {
|
||||
default: llvm_unreachable("Unknown linkage type");
|
||||
case Function::PrivateLinkage:
|
||||
case Function::InternalLinkage:
|
||||
// Function is internal.
|
||||
break;
|
||||
case Function::DLLExportLinkage:
|
||||
case Function::ExternalLinkage:
|
||||
// Function is externally visible
|
||||
O << "\t.global\t" << CurrentFnName << '\n';
|
||||
break;
|
||||
case Function::LinkerPrivateLinkage:
|
||||
case Function::LinkOnceAnyLinkage:
|
||||
case Function::LinkOnceODRLinkage:
|
||||
case Function::WeakAnyLinkage:
|
||||
case Function::WeakODRLinkage:
|
||||
// Function is weak
|
||||
O << "\t.weak\t" << CurrentFnName << '\n' ;
|
||||
break;
|
||||
}
|
||||
|
||||
printVisibility(CurrentFnName, F->getVisibility());
|
||||
|
||||
O << "\t.type\t" << CurrentFnName << ", #function\n";
|
||||
O << CurrentFnName << ":\n";
|
||||
}
|
||||
|
||||
|
||||
void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
|
||||
const MachineOperand &MO = MI->getOperand (opNum);
|
||||
bool CloseParen = false;
|
||||
@@ -215,6 +243,36 @@ void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
|
||||
}
|
||||
}
|
||||
|
||||
bool SparcAsmPrinter::printGetPCX(const MachineInstr *MI, unsigned opNum) {
|
||||
std::string operand = "";
|
||||
const MachineOperand &MO = MI->getOperand(opNum);
|
||||
switch (MO.getType()) {
|
||||
default: assert(0 && "Operand is not a register ");
|
||||
case MachineOperand::MO_Register:
|
||||
assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
|
||||
"Operand is not a physical register ");
|
||||
operand = "%" + LowercaseString(getRegisterName(MO.getReg()));
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned bbNum = NumberForBB[MI->getParent()->getBasicBlock()];
|
||||
|
||||
O << '\n' << ".LLGETPCH" << bbNum << ":\n";
|
||||
O << "\tcall\t.LLGETPC" << bbNum << '\n' ;
|
||||
|
||||
O << "\t sethi\t"
|
||||
<< "%hi(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << bbNum << ")), "
|
||||
<< operand << '\n' ;
|
||||
|
||||
O << ".LLGETPC" << bbNum << ":\n" ;
|
||||
O << "\tor\t" << operand
|
||||
<< ", %lo(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << bbNum << ")), "
|
||||
<< operand << '\n';
|
||||
O << "\tadd\t" << operand << ", %o7, " << operand << '\n';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
|
||||
int CC = (int)MI->getOperand(opNum).getImm();
|
||||
O << SPARCCondCodeToString((SPCC::CondCodes)CC);
|
||||
|
||||
@@ -34,10 +34,13 @@ class SparcDAGToDAGISel : public SelectionDAGISel {
|
||||
/// Subtarget - Keep a pointer to the Sparc Subtarget around so that we can
|
||||
/// make the right decision when generating code for different targets.
|
||||
const SparcSubtarget &Subtarget;
|
||||
SparcTargetMachine& TM;
|
||||
MachineBasicBlock *CurBB;
|
||||
public:
|
||||
explicit SparcDAGToDAGISel(SparcTargetMachine &TM)
|
||||
: SelectionDAGISel(TM),
|
||||
Subtarget(TM.getSubtarget<SparcSubtarget>()) {
|
||||
explicit SparcDAGToDAGISel(SparcTargetMachine &tm)
|
||||
: SelectionDAGISel(tm),
|
||||
Subtarget(tm.getSubtarget<SparcSubtarget>()),
|
||||
TM(tm) {
|
||||
}
|
||||
|
||||
SDNode *Select(SDValue Op);
|
||||
@@ -63,6 +66,9 @@ public:
|
||||
|
||||
// Include the pieces autogenerated from the target description.
|
||||
#include "SparcGenDAGISel.inc"
|
||||
|
||||
private:
|
||||
SDNode* getGlobalBaseReg();
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
@@ -70,12 +76,18 @@ public:
|
||||
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
|
||||
void SparcDAGToDAGISel::InstructionSelect() {
|
||||
DEBUG(BB->dump());
|
||||
|
||||
CurBB = BB;
|
||||
// Select target instructions for the DAG.
|
||||
SelectRoot(*CurDAG);
|
||||
CurDAG->RemoveDeadNodes();
|
||||
}
|
||||
|
||||
SDNode* SparcDAGToDAGISel::getGlobalBaseReg() {
|
||||
MachineFunction *MF = CurBB->getParent();
|
||||
unsigned GlobalBaseReg = TM.getInstrInfo()->getGlobalBaseReg(MF);
|
||||
return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode();
|
||||
}
|
||||
|
||||
bool SparcDAGToDAGISel::SelectADDRri(SDValue Op, SDValue Addr,
|
||||
SDValue &Base, SDValue &Offset) {
|
||||
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
|
||||
@@ -149,6 +161,9 @@ SDNode *SparcDAGToDAGISel::Select(SDValue Op) {
|
||||
|
||||
switch (N->getOpcode()) {
|
||||
default: break;
|
||||
case SPISD::GLOBAL_BASE_REG:
|
||||
return getGlobalBaseReg();
|
||||
|
||||
case ISD::SDIV:
|
||||
case ISD::UDIV: {
|
||||
// FIXME: should use a custom expander to expose the SRA to the dag.
|
||||
|
||||
@@ -740,17 +740,29 @@ static void LookThroughSetCC(SDValue &LHS, SDValue &RHS,
|
||||
}
|
||||
}
|
||||
|
||||
static SDValue LowerGLOBALADDRESS(SDValue Op, SelectionDAG &DAG) {
|
||||
SDValue SparcTargetLowering::LowerGlobalAddress(SDValue Op,
|
||||
SelectionDAG &DAG) {
|
||||
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
||||
// FIXME there isn't really any debug info here
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
|
||||
SDValue Hi = DAG.getNode(SPISD::Hi, dl, MVT::i32, GA);
|
||||
SDValue Lo = DAG.getNode(SPISD::Lo, dl, MVT::i32, GA);
|
||||
return DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
|
||||
|
||||
if (getTargetMachine().getRelocationModel() != Reloc::PIC_)
|
||||
return DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
|
||||
|
||||
SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, dl,
|
||||
getPointerTy());
|
||||
SDValue RelAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
|
||||
SDValue AbsAddr = DAG.getNode(ISD::ADD, dl, MVT::i32,
|
||||
GlobalBase, RelAddr);
|
||||
return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(),
|
||||
AbsAddr, NULL, 0);
|
||||
}
|
||||
|
||||
static SDValue LowerCONSTANTPOOL(SDValue Op, SelectionDAG &DAG) {
|
||||
SDValue SparcTargetLowering::LowerConstantPool(SDValue Op,
|
||||
SelectionDAG &DAG) {
|
||||
ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
|
||||
// FIXME there isn't really any debug info here
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
@@ -758,7 +770,16 @@ static SDValue LowerCONSTANTPOOL(SDValue Op, SelectionDAG &DAG) {
|
||||
SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment());
|
||||
SDValue Hi = DAG.getNode(SPISD::Hi, dl, MVT::i32, CP);
|
||||
SDValue Lo = DAG.getNode(SPISD::Lo, dl, MVT::i32, CP);
|
||||
return DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
|
||||
if (getTargetMachine().getRelocationModel() != Reloc::PIC_)
|
||||
return DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
|
||||
|
||||
SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, dl,
|
||||
getPointerTy());
|
||||
SDValue RelAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
|
||||
SDValue AbsAddr = DAG.getNode(ISD::ADD, dl, MVT::i32,
|
||||
GlobalBase, RelAddr);
|
||||
return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(),
|
||||
AbsAddr, NULL, 0);
|
||||
}
|
||||
|
||||
static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) {
|
||||
@@ -912,8 +933,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||
case ISD::FRAMEADDR: return SDValue();
|
||||
case ISD::GlobalTLSAddress:
|
||||
llvm_unreachable("TLS not implemented for Sparc.");
|
||||
case ISD::GlobalAddress: return LowerGLOBALADDRESS(Op, DAG);
|
||||
case ISD::ConstantPool: return LowerCONSTANTPOOL(Op, DAG);
|
||||
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
|
||||
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
|
||||
case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);
|
||||
case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG);
|
||||
case ISD::BR_CC: return LowerBR_CC(Op, DAG);
|
||||
@@ -1054,5 +1075,5 @@ SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
|
||||
|
||||
/// getFunctionAlignment - Return the Log2 alignment of this function.
|
||||
unsigned SparcTargetLowering::getFunctionAlignment(const Function *) const {
|
||||
return 4;
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,8 @@ namespace llvm {
|
||||
ITOF, // Int to FP within a FP register.
|
||||
|
||||
CALL, // A call instruction.
|
||||
RET_FLAG // Return with a flag operand.
|
||||
RET_FLAG, // Return with a flag operand.
|
||||
GLOBAL_BASE_REG // Global base reg for PIC
|
||||
};
|
||||
}
|
||||
|
||||
@@ -96,6 +97,9 @@ namespace llvm {
|
||||
CallingConv::ID CallConv, bool isVarArg,
|
||||
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||
DebugLoc dl, SelectionDAG &DAG);
|
||||
|
||||
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG);
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "SparcGenInstrInfo.inc"
|
||||
#include "SparcMachineFunctionInfo.h"
|
||||
using namespace llvm;
|
||||
|
||||
SparcInstrInfo::SparcInstrInfo(SparcSubtarget &ST)
|
||||
@@ -235,3 +237,25 @@ MachineInstr *SparcInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
|
||||
|
||||
return NewMI;
|
||||
}
|
||||
|
||||
unsigned SparcInstrInfo::getGlobalBaseReg(MachineFunction *MF) const
|
||||
{
|
||||
SparcMachineFunctionInfo *SparcFI = MF->getInfo<SparcMachineFunctionInfo>();
|
||||
unsigned GlobalBaseReg = SparcFI->getGlobalBaseReg();
|
||||
if (GlobalBaseReg != 0)
|
||||
return GlobalBaseReg;
|
||||
|
||||
// Insert the set of GlobalBaseReg into the first MBB of the function
|
||||
MachineBasicBlock &FirstMBB = MF->front();
|
||||
MachineBasicBlock::iterator MBBI = FirstMBB.begin();
|
||||
MachineRegisterInfo &RegInfo = MF->getRegInfo();
|
||||
|
||||
GlobalBaseReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
|
||||
|
||||
|
||||
DebugLoc dl = DebugLoc::getUnknownLoc();
|
||||
|
||||
BuildMI(FirstMBB, MBBI, dl, get(SP::GETPCX), GlobalBaseReg);
|
||||
SparcFI->setGlobalBaseReg(GlobalBaseReg);
|
||||
return GlobalBaseReg;
|
||||
}
|
||||
|
||||
@@ -97,6 +97,8 @@ public:
|
||||
MachineInstr* LoadMI) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned getGlobalBaseReg(MachineFunction *MF) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -134,6 +134,10 @@ def call : SDNode<"SPISD::CALL", SDT_SPCall,
|
||||
def retflag : SDNode<"SPISD::RET_FLAG", SDTNone,
|
||||
[SDNPHasChain, SDNPOptInFlag]>;
|
||||
|
||||
def getPCX : Operand<i32> {
|
||||
let PrintMethod = "printGetPCX";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SPARC Flag Conditions
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -207,6 +211,11 @@ multiclass F3_12np<string OpcStr, bits<6> Op3Val> {
|
||||
class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstSP<outs, ins, asmstr, pattern>;
|
||||
|
||||
// GETPCX for PIC
|
||||
let Defs = [O7], Uses = [O7] in {
|
||||
def GETPCX : Pseudo<(outs getPCX:$getpcseq), (ins), "$getpcseq", [] >;
|
||||
}
|
||||
|
||||
let Defs = [O6], Uses = [O6] in {
|
||||
def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt),
|
||||
"!ADJCALLSTACKDOWN $amt",
|
||||
@@ -431,18 +440,23 @@ def LEA_ADDri : F3_2<2, 0b000000,
|
||||
(outs IntRegs:$dst), (ins MEMri:$addr),
|
||||
"add ${addr:arith}, $dst",
|
||||
[(set IntRegs:$dst, ADDRri:$addr)]>;
|
||||
|
||||
defm ADDCC : F3_12<"addcc", 0b010000, addc>;
|
||||
|
||||
let Defs = [ICC] in
|
||||
defm ADDCC : F3_12<"addcc", 0b010000, addc>;
|
||||
|
||||
defm ADDX : F3_12<"addx", 0b001000, adde>;
|
||||
|
||||
// Section B.15 - Subtract Instructions, p. 110
|
||||
defm SUB : F3_12 <"sub" , 0b000100, sub>;
|
||||
defm SUBX : F3_12 <"subx" , 0b001100, sube>;
|
||||
defm SUBCC : F3_12 <"subcc", 0b010100, SPcmpicc>;
|
||||
|
||||
def SUBXCCrr: F3_1<2, 0b011100,
|
||||
(outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
|
||||
"subxcc $b, $c, $dst", []>;
|
||||
let Defs = [ICC] in {
|
||||
defm SUBCC : F3_12 <"subcc", 0b010100, SPcmpicc>;
|
||||
|
||||
def SUBXCCrr: F3_1<2, 0b011100,
|
||||
(outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
|
||||
"subxcc $b, $c, $dst", []>;
|
||||
}
|
||||
|
||||
// Section B.18 - Multiply Instructions, p. 113
|
||||
defm UMUL : F3_12np<"umul", 0b001010>;
|
||||
@@ -471,11 +485,12 @@ let isBarrier = 1 in
|
||||
def BA : BranchSP<0b1000, (ins brtarget:$dst),
|
||||
"ba $dst",
|
||||
[(br bb:$dst)]>;
|
||||
|
||||
|
||||
// FIXME: the encoding for the JIT should look at the condition field.
|
||||
def BCOND : BranchSP<0, (ins brtarget:$dst, CCOp:$cc),
|
||||
"b$cc $dst",
|
||||
[(SPbricc bb:$dst, imm:$cc)]>;
|
||||
let Uses = [ICC] in
|
||||
def BCOND : BranchSP<0, (ins brtarget:$dst, CCOp:$cc),
|
||||
"b$cc $dst",
|
||||
[(SPbricc bb:$dst, imm:$cc)]>;
|
||||
|
||||
|
||||
// Section B.22 - Branch on Floating-point Condition Codes Instructions, p. 121
|
||||
@@ -489,9 +504,10 @@ class FPBranchSP<bits<4> cc, dag ins, string asmstr, list<dag> pattern>
|
||||
}
|
||||
|
||||
// FIXME: the encoding for the JIT should look at the condition field.
|
||||
def FBCOND : FPBranchSP<0, (ins brtarget:$dst, CCOp:$cc),
|
||||
"fb$cc $dst",
|
||||
[(SPbrfcc bb:$dst, imm:$cc)]>;
|
||||
let Uses = [FCC] in
|
||||
def FBCOND : FPBranchSP<0, (ins brtarget:$dst, CCOp:$cc),
|
||||
"fb$cc $dst",
|
||||
[(SPbrfcc bb:$dst, imm:$cc)]>;
|
||||
|
||||
|
||||
// Section B.24 - Call and Link Instruction, p. 125
|
||||
@@ -633,15 +649,16 @@ def FDIVD : F3_3<2, 0b110100, 0b001001110,
|
||||
// Note 2: the result of a FCMP is not available until the 2nd cycle
|
||||
// after the instr is retired, but there is no interlock. This behavior
|
||||
// is modelled with a forced noop after the instruction.
|
||||
def FCMPS : F3_3<2, 0b110101, 0b001010001,
|
||||
(outs), (ins FPRegs:$src1, FPRegs:$src2),
|
||||
"fcmps $src1, $src2\n\tnop",
|
||||
[(SPcmpfcc FPRegs:$src1, FPRegs:$src2)]>;
|
||||
def FCMPD : F3_3<2, 0b110101, 0b001010010,
|
||||
(outs), (ins DFPRegs:$src1, DFPRegs:$src2),
|
||||
"fcmpd $src1, $src2\n\tnop",
|
||||
[(SPcmpfcc DFPRegs:$src1, DFPRegs:$src2)]>;
|
||||
|
||||
let Defs = [FCC] in {
|
||||
def FCMPS : F3_3<2, 0b110101, 0b001010001,
|
||||
(outs), (ins FPRegs:$src1, FPRegs:$src2),
|
||||
"fcmps $src1, $src2\n\tnop",
|
||||
[(SPcmpfcc FPRegs:$src1, FPRegs:$src2)]>;
|
||||
def FCMPD : F3_3<2, 0b110101, 0b001010010,
|
||||
(outs), (ins DFPRegs:$src1, DFPRegs:$src2),
|
||||
"fcmpd $src1, $src2\n\tnop",
|
||||
[(SPcmpfcc DFPRegs:$src1, DFPRegs:$src2)]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// V9 Instructions
|
||||
|
||||
@@ -16,6 +16,10 @@ class SparcReg<string n> : Register<n> {
|
||||
let Namespace = "SP";
|
||||
}
|
||||
|
||||
class SparcCtrlReg<string n>: Register<n> {
|
||||
let Namespace = "SP";
|
||||
}
|
||||
|
||||
// Registers are identified with 5-bit ID numbers.
|
||||
// Ri - 32-bit integer registers
|
||||
class Ri<bits<5> num, string n> : SparcReg<n> {
|
||||
@@ -31,6 +35,10 @@ class Rd<bits<5> num, string n, list<Register> subregs> : SparcReg<n> {
|
||||
let SubRegs = subregs;
|
||||
}
|
||||
|
||||
// Control Registers
|
||||
def ICC : SparcCtrlReg<"ICC">;
|
||||
def FCC : SparcCtrlReg<"FCC">;
|
||||
|
||||
// Integer registers
|
||||
def G0 : Ri< 0, "G0">, DwarfRegNum<[0]>;
|
||||
def G1 : Ri< 1, "G1">, DwarfRegNum<[1]>;
|
||||
@@ -46,7 +54,7 @@ def O2 : Ri<10, "O2">, DwarfRegNum<[10]>;
|
||||
def O3 : Ri<11, "O3">, DwarfRegNum<[11]>;
|
||||
def O4 : Ri<12, "O4">, DwarfRegNum<[12]>;
|
||||
def O5 : Ri<13, "O5">, DwarfRegNum<[13]>;
|
||||
def O6 : Ri<14, "O6">, DwarfRegNum<[14]>;
|
||||
def O6 : Ri<14, "SP">, DwarfRegNum<[14]>;
|
||||
def O7 : Ri<15, "O7">, DwarfRegNum<[15]>;
|
||||
def L0 : Ri<16, "L0">, DwarfRegNum<[16]>;
|
||||
def L1 : Ri<17, "L1">, DwarfRegNum<[17]>;
|
||||
@@ -62,7 +70,7 @@ def I2 : Ri<26, "I2">, DwarfRegNum<[26]>;
|
||||
def I3 : Ri<27, "I3">, DwarfRegNum<[27]>;
|
||||
def I4 : Ri<28, "I4">, DwarfRegNum<[28]>;
|
||||
def I5 : Ri<29, "I5">, DwarfRegNum<[29]>;
|
||||
def I6 : Ri<30, "I6">, DwarfRegNum<[30]>;
|
||||
def I6 : Ri<30, "FP">, DwarfRegNum<[30]>;
|
||||
def I7 : Ri<31, "I7">, DwarfRegNum<[31]>;
|
||||
|
||||
// Floating-point registers
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
; RUN: llvm-as < %s | llc -march=sparc --relocation-model=pic | grep _GLOBAL_OFFSET_TABLE_
|
||||
|
||||
@foo = global i32 0 ; <i32*> [#uses=1]
|
||||
|
||||
define i32 @func() nounwind readonly {
|
||||
entry:
|
||||
%0 = load i32* @foo, align 4 ; <i32> [#uses=1]
|
||||
ret i32 %0
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
; RUN: llvm-as < %s | llc -march=sparc | grep weak
|
||||
|
||||
define weak i32 @func() nounwind {
|
||||
entry:
|
||||
ret i32 0
|
||||
}
|
||||
Reference in New Issue
Block a user