1a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck//===-- MBlazeISelDAGToDAG.cpp - A dag to dag inst selector for MBlaze ----===//
2a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck//
3a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck//                     The LLVM Compiler Infrastructure
4a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck//
5a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck// This file is distributed under the University of Illinois Open Source
6a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck// License. See LICENSE.TXT for details.
7a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck//
8a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck//===----------------------------------------------------------------------===//
9a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck//
10a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck// This file defines an instruction selector for the MBlaze target.
11a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck//
12a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck//===----------------------------------------------------------------------===//
13a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
14a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#define DEBUG_TYPE "mblaze-isel"
15a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "MBlaze.h"
16a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "MBlazeMachineFunction.h"
17a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "MBlazeRegisterInfo.h"
18a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "MBlazeSubtarget.h"
19a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "MBlazeTargetMachine.h"
20a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/GlobalValue.h"
21a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/Instructions.h"
22a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/Intrinsics.h"
23a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/Support/CFG.h"
24a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/Type.h"
25a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/CodeGen/MachineConstantPool.h"
26a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/CodeGen/MachineFunction.h"
27a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/CodeGen/MachineFrameInfo.h"
28a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/CodeGen/MachineInstrBuilder.h"
29a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/CodeGen/MachineRegisterInfo.h"
30a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/CodeGen/SelectionDAGISel.h"
31a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/Target/TargetMachine.h"
32a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/Support/Debug.h"
33a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/Support/ErrorHandling.h"
34a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck#include "llvm/Support/raw_ostream.h"
35a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peckusing namespace llvm;
36a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
37a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck//===----------------------------------------------------------------------===//
38a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck// Instruction Selector Implementation
39a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck//===----------------------------------------------------------------------===//
40a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
41a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck//===----------------------------------------------------------------------===//
42a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck// MBlazeDAGToDAGISel - MBlaze specific code to select MBlaze machine
43a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck// instructions for SelectionDAG operations.
44a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck//===----------------------------------------------------------------------===//
45a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Pecknamespace {
46a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
47a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peckclass MBlazeDAGToDAGISel : public SelectionDAGISel {
48a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
49a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  /// TM - Keep a reference to MBlazeTargetMachine.
50a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  MBlazeTargetMachine &TM;
51a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
52a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  /// Subtarget - Keep a pointer to the MBlazeSubtarget around so that we can
53a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  /// make the right decision when generating code for different targets.
54a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  const MBlazeSubtarget &Subtarget;
55a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
56a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peckpublic:
57a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  explicit MBlazeDAGToDAGISel(MBlazeTargetMachine &tm) :
58a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  SelectionDAGISel(tm),
59a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  TM(tm), Subtarget(tm.getSubtarget<MBlazeSubtarget>()) {}
60a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
61a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  // Pass Name
62a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  virtual const char *getPassName() const {
63a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    return "MBlaze DAG->DAG Pattern Instruction Selection";
64a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  }
65a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peckprivate:
66a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  // Include the pieces autogenerated from the target description.
67a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  #include "MBlazeGenDAGISel.inc"
68a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
69a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  /// getTargetMachine - Return a reference to the TargetMachine, casted
70a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  /// to the target-specific type.
71a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  const MBlazeTargetMachine &getTargetMachine() {
72a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    return static_cast<const MBlazeTargetMachine &>(TM);
73a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  }
74a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
75a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  /// getInstrInfo - Return a reference to the TargetInstrInfo, casted
76a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  /// to the target-specific type.
77a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  const MBlazeInstrInfo *getInstrInfo() {
78a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    return getTargetMachine().getInstrInfo();
79a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  }
80a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
81a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  SDNode *getGlobalBaseReg();
82a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  SDNode *Select(SDNode *N);
83a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
84a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  // Address Selection
8552a261b3c1391c5fec399ddeb3fc6ee9541e8790Chris Lattner  bool SelectAddrRegReg(SDValue N, SDValue &Base, SDValue &Index);
8652a261b3c1391c5fec399ddeb3fc6ee9541e8790Chris Lattner  bool SelectAddrRegImm(SDValue N, SDValue &Disp, SDValue &Base);
87a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
88a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  // getI32Imm - Return a target constant with the specified value, of type i32.
89a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  inline SDValue getI32Imm(unsigned Imm) {
90a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    return CurDAG->getTargetConstant(Imm, MVT::i32);
91a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  }
92a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck};
93a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
94a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck}
95a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
96a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// isIntS32Immediate - This method tests to see if the node is either a 32-bit
97a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// or 64-bit immediate, and if the value can be accurately represented as a
98a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// sign extension from a 32-bit value.  If so, this returns true and the
99a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// immediate.
100a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peckstatic bool isIntS32Immediate(SDNode *N, int32_t &Imm) {
101a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  unsigned Opc = N->getOpcode();
102a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  if (Opc != ISD::Constant)
103a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    return false;
104a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
105a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  Imm = (int32_t)cast<ConstantSDNode>(N)->getZExtValue();
106a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  if (N->getValueType(0) == MVT::i32)
107a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    return Imm == (int32_t)cast<ConstantSDNode>(N)->getZExtValue();
108a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  else
109a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    return Imm == (int64_t)cast<ConstantSDNode>(N)->getZExtValue();
110a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck}
111a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
112a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peckstatic bool isIntS32Immediate(SDValue Op, int32_t &Imm) {
113a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  return isIntS32Immediate(Op.getNode(), Imm);
114a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck}
115a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
116a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
117a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// SelectAddressRegReg - Given the specified addressed, check to see if it
118a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// can be represented as an indexed [r+r] operation.  Returns false if it
119a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// can be more efficiently represented with [r+imm].
120a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peckbool MBlazeDAGToDAGISel::
12152a261b3c1391c5fec399ddeb3fc6ee9541e8790Chris LattnerSelectAddrRegReg(SDValue N, SDValue &Base, SDValue &Index) {
122a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  if (N.getOpcode() == ISD::FrameIndex) return false;
123a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  if (N.getOpcode() == ISD::TargetExternalSymbol ||
124a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck      N.getOpcode() == ISD::TargetGlobalAddress)
125a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    return false;  // direct calls.
126a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
127a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  int32_t imm = 0;
128a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
129a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    if (isIntS32Immediate(N.getOperand(1), imm))
130a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck      return false;    // r+i
131a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
132c2bf2bbe93c7ce44bedc8485cc24927423404835Wesley Peck    if (N.getOperand(0).getOpcode() == ISD::TargetJumpTable ||
133c2bf2bbe93c7ce44bedc8485cc24927423404835Wesley Peck        N.getOperand(1).getOpcode() == ISD::TargetJumpTable)
134c2bf2bbe93c7ce44bedc8485cc24927423404835Wesley Peck      return false; // jump tables.
135c2bf2bbe93c7ce44bedc8485cc24927423404835Wesley Peck
13641400da31ead2f61d171381c0945dceddd8fc786Wesley Peck    Base = N.getOperand(0);
13741400da31ead2f61d171381c0945dceddd8fc786Wesley Peck    Index = N.getOperand(1);
138a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    return true;
139a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  }
140a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
141a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  return false;
142a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck}
143a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
144a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// Returns true if the address N can be represented by a base register plus
145a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// a signed 32-bit displacement [r+imm], and if it is not better
146a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// represented as reg+reg.
147a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peckbool MBlazeDAGToDAGISel::
14841400da31ead2f61d171381c0945dceddd8fc786Wesley PeckSelectAddrRegImm(SDValue N, SDValue &Base, SDValue &Disp) {
149a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  // If this can be more profitably realized as r+r, fail.
15041400da31ead2f61d171381c0945dceddd8fc786Wesley Peck  if (SelectAddrRegReg(N, Base, Disp))
151a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    return false;
152a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
153a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
154a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    int32_t imm = 0;
155a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    if (isIntS32Immediate(N.getOperand(1), imm)) {
156a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck      Disp = CurDAG->getTargetConstant(imm, MVT::i32);
157a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck      if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) {
158a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType());
159a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck      } else {
160a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        Base = N.getOperand(0);
161a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck      }
162a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck      return true; // [r+i]
163a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    }
164a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) {
165a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    // Loading from a constant address.
166a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    uint32_t Imm = CN->getZExtValue();
167a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    Disp = CurDAG->getTargetConstant(Imm, CN->getValueType(0));
168a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    Base = CurDAG->getRegister(MBlaze::R0, CN->getValueType(0));
169a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    return true;
170a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  }
171a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
172a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  Disp = CurDAG->getTargetConstant(0, TM.getTargetLowering()->getPointerTy());
173a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N))
174a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType());
175a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  else
176a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    Base = N;
177a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  return true;      // [r+0]
178a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck}
179a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
180a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// getGlobalBaseReg - Output the instructions required to put the
181a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// GOT address into a register.
182a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley PeckSDNode *MBlazeDAGToDAGISel::getGlobalBaseReg() {
183a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF);
184a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode();
185a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck}
186a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
187a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// Select instructions not customized! Used for
188a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// expanded, promoted and normal instructions
189a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley PeckSDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) {
190a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  unsigned Opcode = Node->getOpcode();
191a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  DebugLoc dl = Node->getDebugLoc();
192a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
193a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  // If we have a custom node, we already have selected!
1940a67d92938d77b6a8cde6e1676750264b274cebcWesley Peck  if (Node->isMachineOpcode())
195a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    return NULL;
196a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
197a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  ///
198a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  // Instruction Selection not handled by the auto-generated
199a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  // tablegen selection should be handled here.
200a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  ///
2010a67d92938d77b6a8cde6e1676750264b274cebcWesley Peck  switch (Opcode) {
202a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    default: break;
203a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
204a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    // Get target GOT address.
205a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    case ISD::GLOBAL_OFFSET_TABLE:
206a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck      return getGlobalBaseReg();
207a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
208a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    case ISD::FrameIndex: {
209a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        SDValue imm = CurDAG->getTargetConstant(0, MVT::i32);
210a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex();
211a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        EVT VT = Node->getValueType(0);
212a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
213a7c7b9dccba2c14a93f0f9a29490f1df4f9b4080Wesley Peck        unsigned Opc = MBlaze::ADDIK;
214a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        if (Node->hasOneUse())
215a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck          return CurDAG->SelectNodeTo(Node, Opc, VT, TFI, imm);
216a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        return CurDAG->getMachineNode(Opc, dl, VT, TFI, imm);
217a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    }
218a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
219a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
220a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    /// Handle direct and indirect calls when using PIC. On PIC, when
221a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    /// GOT is smaller than about 64k (small code) the GA target is
222a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    /// loaded with only one instruction. Otherwise GA's target must
223a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    /// be loaded with 3 instructions.
224a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    case MBlazeISD::JmpLink: {
225a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck      if (TM.getRelocationModel() == Reloc::PIC_) {
226a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        SDValue Chain  = Node->getOperand(0);
227a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        SDValue Callee = Node->getOperand(1);
228a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        SDValue R20Reg = CurDAG->getRegister(MBlaze::R20, MVT::i32);
229a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        SDValue InFlag(0, 0);
230a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
2310a67d92938d77b6a8cde6e1676750264b274cebcWesley Peck        if ((isa<GlobalAddressSDNode>(Callee)) ||
2320a67d92938d77b6a8cde6e1676750264b274cebcWesley Peck            (isa<ExternalSymbolSDNode>(Callee)))
233a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        {
234a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck          /// Direct call for global addresses and external symbols
235a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck          SDValue GPReg = CurDAG->getRegister(MBlaze::R15, MVT::i32);
236a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
237a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck          // Use load to get GOT target
238a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck          SDValue Ops[] = { Callee, GPReg, Chain };
239a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck          SDValue Load = SDValue(CurDAG->getMachineNode(MBlaze::LW, dl,
240a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck                                 MVT::i32, MVT::Other, Ops, 3), 0);
241a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck          Chain = Load.getValue(1);
242a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
243a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck          // Call target must be on T9
244a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck          Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Load, InFlag);
245a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        } else
246a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck          /// Indirect call
247a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck          Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Callee, InFlag);
248a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
249a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        // Emit Jump and Link Register
250a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        SDNode *ResNode = CurDAG->getMachineNode(MBlaze::BRLID, dl, MVT::Other,
251f1b4eafbfec976f939ec0ea3e8acf91cef5363e3Chris Lattner                                                 MVT::Glue, R20Reg, Chain);
252a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        Chain  = SDValue(ResNode, 0);
253a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        InFlag = SDValue(ResNode, 1);
254a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        ReplaceUses(SDValue(Node, 0), Chain);
255a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        ReplaceUses(SDValue(Node, 1), InFlag);
256a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck        return ResNode;
257a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck      }
258a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    }
259a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  }
260a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
261a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  // Select the default instruction
262a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  SDNode *ResNode = SelectCode(Node);
263a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
2647c306da505e2d7f64e160890b274a47fa0740962Chris Lattner  DEBUG(errs() << "=> ");
265a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  if (ResNode == NULL || ResNode == Node)
266a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    DEBUG(Node->dump(CurDAG));
267a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  else
268a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck    DEBUG(ResNode->dump(CurDAG));
269a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  DEBUG(errs() << "\n");
270a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  return ResNode;
271a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck}
272a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck
273a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// createMBlazeISelDag - This pass converts a legalized DAG into a
274a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck/// MBlaze-specific DAG, ready for instruction scheduling.
275a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley PeckFunctionPass *llvm::createMBlazeISelDag(MBlazeTargetMachine &TM) {
276a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck  return new MBlazeDAGToDAGISel(TM);
277a70f28ce7dc85d0075a7d86da5d7987b6e306bc6Wesley Peck}
278