- /// Handle direct and indirect calls when using PIC. On PIC, when
- /// GOT is smaller than about 64k (small code) the GA target is
- /// loaded with only one instruction. Otherwise GA's target must
- /// be loaded with 3 instructions.
- case MipsISD::JmpLink: {
- if (TM.getRelocationModel() == Reloc::PIC_) {
- //bool isCodeLarge = (TM.getCodeModel() == CodeModel::Large);
- SDValue Chain = Node->getOperand(0);
- SDValue Callee = Node->getOperand(1);
- SDValue T9Reg = CurDAG->getRegister(Mips::T9, MVT::i32);
- SDValue InFlag(0, 0);
-
- if ( (isa<GlobalAddressSDNode>(Callee)) ||
- (isa<ExternalSymbolSDNode>(Callee)) )
- {
- /// Direct call for global addresses and external symbols
- SDValue GPReg = CurDAG->getRegister(Mips::GP, MVT::i32);
-
- // Use load to get GOT target
- SDValue Ops[] = { Callee, GPReg, Chain };
- SDValue Load = SDValue(CurDAG->getTargetNode(Mips::LW, dl, MVT::i32,
- MVT::Other, Ops, 3), 0);
- Chain = Load.getValue(1);
-
- // Call target must be on T9
- Chain = CurDAG->getCopyToReg(Chain, dl, T9Reg, Load, InFlag);
- } else
- /// Indirect call
- Chain = CurDAG->getCopyToReg(Chain, dl, T9Reg, Callee, InFlag);
-
- // Emit Jump and Link Register
- SDNode *ResNode = CurDAG->getTargetNode(Mips::JALR, dl, MVT::Other,
- MVT::Flag, T9Reg, Chain);
- Chain = SDValue(ResNode, 0);
- InFlag = SDValue(ResNode, 1);
- ReplaceUses(SDValue(Node, 0), Chain);
- ReplaceUses(SDValue(Node, 1), InFlag);
- return ResNode;
- }
+ if (PtrVT == MVT::i32) {
+ RdhwrOpc = Mips::RDHWR;
+ SrcReg = Mips::HWR29;
+ DestReg = Mips::V1;
+ } else {
+ RdhwrOpc = Mips::RDHWR64;
+ SrcReg = Mips::HWR29_64;
+ DestReg = Mips::V1_64;
+ }
+
+ SDNode *Rdhwr = CurDAG->getMachineNode(RdhwrOpc, Node->getDebugLoc(),
+ Node->getValueType(0), CurDAG->getRegister(SrcReg, PtrVT));
+ SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, DestReg,
+ SDValue(Rdhwr, 0));
+ SDValue ResNode = CurDAG->getCopyFromReg(Chain, dl, DestReg, PtrVT);
+ ReplaceUses(SDValue(Node, 0), ResNode);
+ return ResNode.getNode();