1193323Sed//===-- MSP430ISelDAGToDAG.cpp - A dag to dag inst selector for MSP430 ----===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file defines an instruction selector for the MSP430 target.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed#include "MSP430.h"
15193323Sed#include "MSP430TargetMachine.h"
16193323Sed#include "llvm/CodeGen/MachineFrameInfo.h"
17193323Sed#include "llvm/CodeGen/MachineFunction.h"
18193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h"
19193323Sed#include "llvm/CodeGen/MachineRegisterInfo.h"
20193323Sed#include "llvm/CodeGen/SelectionDAG.h"
21193323Sed#include "llvm/CodeGen/SelectionDAGISel.h"
22249423Sdim#include "llvm/IR/CallingConv.h"
23249423Sdim#include "llvm/IR/Constants.h"
24249423Sdim#include "llvm/IR/DerivedTypes.h"
25249423Sdim#include "llvm/IR/Function.h"
26249423Sdim#include "llvm/IR/Intrinsics.h"
27193323Sed#include "llvm/Support/Compiler.h"
28193323Sed#include "llvm/Support/Debug.h"
29198090Srdivacky#include "llvm/Support/ErrorHandling.h"
30198090Srdivacky#include "llvm/Support/raw_ostream.h"
31249423Sdim#include "llvm/Target/TargetLowering.h"
32193323Sedusing namespace llvm;
33193323Sed
34199481Srdivackynamespace {
35199481Srdivacky  struct MSP430ISelAddressMode {
36199481Srdivacky    enum {
37199481Srdivacky      RegBase,
38199481Srdivacky      FrameIndexBase
39199481Srdivacky    } BaseType;
40199481Srdivacky
41199481Srdivacky    struct {            // This is really a union, discriminated by BaseType!
42199481Srdivacky      SDValue Reg;
43199481Srdivacky      int FrameIndex;
44199481Srdivacky    } Base;
45199481Srdivacky
46199481Srdivacky    int16_t Disp;
47207618Srdivacky    const GlobalValue *GV;
48207618Srdivacky    const Constant *CP;
49207618Srdivacky    const BlockAddress *BlockAddr;
50199481Srdivacky    const char *ES;
51199481Srdivacky    int JT;
52199481Srdivacky    unsigned Align;    // CP alignment.
53199481Srdivacky
54199481Srdivacky    MSP430ISelAddressMode()
55199481Srdivacky      : BaseType(RegBase), Disp(0), GV(0), CP(0), BlockAddr(0),
56199481Srdivacky        ES(0), JT(-1), Align(0) {
57199481Srdivacky    }
58199481Srdivacky
59199481Srdivacky    bool hasSymbolicDisplacement() const {
60199481Srdivacky      return GV != 0 || CP != 0 || ES != 0 || JT != -1;
61199481Srdivacky    }
62199481Srdivacky
63199481Srdivacky    void dump() {
64199481Srdivacky      errs() << "MSP430ISelAddressMode " << this << '\n';
65200581Srdivacky      if (BaseType == RegBase && Base.Reg.getNode() != 0) {
66199481Srdivacky        errs() << "Base.Reg ";
67199481Srdivacky        Base.Reg.getNode()->dump();
68200581Srdivacky      } else if (BaseType == FrameIndexBase) {
69199481Srdivacky        errs() << " Base.FrameIndex " << Base.FrameIndex << '\n';
70199481Srdivacky      }
71199481Srdivacky      errs() << " Disp " << Disp << '\n';
72199481Srdivacky      if (GV) {
73199481Srdivacky        errs() << "GV ";
74199481Srdivacky        GV->dump();
75199481Srdivacky      } else if (CP) {
76199481Srdivacky        errs() << " CP ";
77199481Srdivacky        CP->dump();
78199481Srdivacky        errs() << " Align" << Align << '\n';
79199481Srdivacky      } else if (ES) {
80199481Srdivacky        errs() << "ES ";
81199481Srdivacky        errs() << ES << '\n';
82199481Srdivacky      } else if (JT != -1)
83199481Srdivacky        errs() << " JT" << JT << " Align" << Align << '\n';
84199481Srdivacky    }
85199481Srdivacky  };
86199481Srdivacky}
87199481Srdivacky
88193323Sed/// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
89193323Sed/// instructions for SelectionDAG operations.
90193323Sed///
91193323Sednamespace {
92193323Sed  class MSP430DAGToDAGISel : public SelectionDAGISel {
93207618Srdivacky    const MSP430TargetLowering &Lowering;
94193323Sed    const MSP430Subtarget &Subtarget;
95193323Sed
96193323Sed  public:
97193323Sed    MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel)
98193323Sed      : SelectionDAGISel(TM, OptLevel),
99193323Sed        Lowering(*TM.getTargetLowering()),
100193323Sed        Subtarget(*TM.getSubtargetImpl()) { }
101193323Sed
102193323Sed    virtual const char *getPassName() const {
103193323Sed      return "MSP430 DAG->DAG Pattern Instruction Selection";
104193323Sed    }
105193323Sed
106199481Srdivacky    bool MatchAddress(SDValue N, MSP430ISelAddressMode &AM);
107199481Srdivacky    bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
108199481Srdivacky    bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
109199481Srdivacky
110198090Srdivacky    virtual bool
111198090Srdivacky    SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
112198090Srdivacky                                 std::vector<SDValue> &OutOps);
113198090Srdivacky
114193323Sed    // Include the pieces autogenerated from the target description.
115193323Sed  #include "MSP430GenDAGISel.inc"
116193323Sed
117193323Sed  private:
118202375Srdivacky    SDNode *Select(SDNode *N);
119202375Srdivacky    SDNode *SelectIndexedLoad(SDNode *Op);
120202375Srdivacky    SDNode *SelectIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2,
121199481Srdivacky                               unsigned Opc8, unsigned Opc16);
122199481Srdivacky
123218893Sdim    bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Disp);
124193323Sed  };
125193323Sed}  // end anonymous namespace
126193323Sed
127193323Sed/// createMSP430ISelDag - This pass converts a legalized DAG into a
128193323Sed/// MSP430-specific DAG, ready for instruction scheduling.
129193323Sed///
130193323SedFunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM,
131193323Sed                                        CodeGenOpt::Level OptLevel) {
132193323Sed  return new MSP430DAGToDAGISel(TM, OptLevel);
133193323Sed}
134193323Sed
135199481Srdivacky
136199481Srdivacky/// MatchWrapper - Try to match MSP430ISD::Wrapper node into an addressing mode.
137199481Srdivacky/// These wrap things that will resolve down into a symbol reference.  If no
138199481Srdivacky/// match is possible, this returns true, otherwise it returns false.
139199481Srdivackybool MSP430DAGToDAGISel::MatchWrapper(SDValue N, MSP430ISelAddressMode &AM) {
140199481Srdivacky  // If the addressing mode already has a symbol as the displacement, we can
141199481Srdivacky  // never match another symbol.
142199481Srdivacky  if (AM.hasSymbolicDisplacement())
143193323Sed    return true;
144199481Srdivacky
145199481Srdivacky  SDValue N0 = N.getOperand(0);
146199481Srdivacky
147199481Srdivacky  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
148199481Srdivacky    AM.GV = G->getGlobal();
149199481Srdivacky    AM.Disp += G->getOffset();
150199481Srdivacky    //AM.SymbolFlags = G->getTargetFlags();
151199481Srdivacky  } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
152199481Srdivacky    AM.CP = CP->getConstVal();
153199481Srdivacky    AM.Align = CP->getAlignment();
154199481Srdivacky    AM.Disp += CP->getOffset();
155199481Srdivacky    //AM.SymbolFlags = CP->getTargetFlags();
156199481Srdivacky  } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
157199481Srdivacky    AM.ES = S->getSymbol();
158199481Srdivacky    //AM.SymbolFlags = S->getTargetFlags();
159199481Srdivacky  } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
160199481Srdivacky    AM.JT = J->getIndex();
161199481Srdivacky    //AM.SymbolFlags = J->getTargetFlags();
162199481Srdivacky  } else {
163199481Srdivacky    AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress();
164199481Srdivacky    //AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags();
165193323Sed  }
166199481Srdivacky  return false;
167199481Srdivacky}
168193323Sed
169199481Srdivacky/// MatchAddressBase - Helper for MatchAddress. Add the specified node to the
170199481Srdivacky/// specified addressing mode without any further recursion.
171199481Srdivackybool MSP430DAGToDAGISel::MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM) {
172199481Srdivacky  // Is the base register already occupied?
173199481Srdivacky  if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) {
174199481Srdivacky    // If so, we cannot select it.
175199481Srdivacky    return true;
176199481Srdivacky  }
177193323Sed
178199481Srdivacky  // Default, generate it as a register.
179199481Srdivacky  AM.BaseType = MSP430ISelAddressMode::RegBase;
180199481Srdivacky  AM.Base.Reg = N;
181199481Srdivacky  return false;
182199481Srdivacky}
183199481Srdivacky
184199481Srdivackybool MSP430DAGToDAGISel::MatchAddress(SDValue N, MSP430ISelAddressMode &AM) {
185204642Srdivacky  DEBUG(errs() << "MatchAddress: "; AM.dump());
186199481Srdivacky
187199481Srdivacky  switch (N.getOpcode()) {
188199481Srdivacky  default: break;
189199481Srdivacky  case ISD::Constant: {
190199481Srdivacky    uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
191199481Srdivacky    AM.Disp += Val;
192199481Srdivacky    return false;
193199481Srdivacky  }
194199481Srdivacky
195199481Srdivacky  case MSP430ISD::Wrapper:
196199481Srdivacky    if (!MatchWrapper(N, AM))
197199481Srdivacky      return false;
198199481Srdivacky    break;
199199481Srdivacky
200199481Srdivacky  case ISD::FrameIndex:
201199481Srdivacky    if (AM.BaseType == MSP430ISelAddressMode::RegBase
202199481Srdivacky        && AM.Base.Reg.getNode() == 0) {
203199481Srdivacky      AM.BaseType = MSP430ISelAddressMode::FrameIndexBase;
204199481Srdivacky      AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
205199481Srdivacky      return false;
206193323Sed    }
207193323Sed    break;
208199481Srdivacky
209199481Srdivacky  case ISD::ADD: {
210199481Srdivacky    MSP430ISelAddressMode Backup = AM;
211199481Srdivacky    if (!MatchAddress(N.getNode()->getOperand(0), AM) &&
212199481Srdivacky        !MatchAddress(N.getNode()->getOperand(1), AM))
213199481Srdivacky      return false;
214199481Srdivacky    AM = Backup;
215199481Srdivacky    if (!MatchAddress(N.getNode()->getOperand(1), AM) &&
216199481Srdivacky        !MatchAddress(N.getNode()->getOperand(0), AM))
217199481Srdivacky      return false;
218199481Srdivacky    AM = Backup;
219199481Srdivacky
220199481Srdivacky    break;
221199481Srdivacky  }
222199481Srdivacky
223199481Srdivacky  case ISD::OR:
224199481Srdivacky    // Handle "X | C" as "X + C" iff X is known to have C bits clear.
225199481Srdivacky    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
226199481Srdivacky      MSP430ISelAddressMode Backup = AM;
227199481Srdivacky      uint64_t Offset = CN->getSExtValue();
228199481Srdivacky      // Start with the LHS as an addr mode.
229199481Srdivacky      if (!MatchAddress(N.getOperand(0), AM) &&
230199481Srdivacky          // Address could not have picked a GV address for the displacement.
231199481Srdivacky          AM.GV == NULL &&
232199481Srdivacky          // Check to see if the LHS & C is zero.
233199481Srdivacky          CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
234199481Srdivacky        AM.Disp += Offset;
235199481Srdivacky        return false;
236199481Srdivacky      }
237199481Srdivacky      AM = Backup;
238193323Sed    }
239193323Sed    break;
240199481Srdivacky  }
241193323Sed
242199481Srdivacky  return MatchAddressBase(N, AM);
243199481Srdivacky}
244193323Sed
245199481Srdivacky/// SelectAddr - returns true if it is able pattern match an addressing mode.
246199481Srdivacky/// It returns the operands which make up the maximal addressing mode it can
247199481Srdivacky/// match by reference.
248218893Sdimbool MSP430DAGToDAGISel::SelectAddr(SDValue N,
249199481Srdivacky                                    SDValue &Base, SDValue &Disp) {
250199481Srdivacky  MSP430ISelAddressMode AM;
251199481Srdivacky
252199481Srdivacky  if (MatchAddress(N, AM))
253199481Srdivacky    return false;
254199481Srdivacky
255199481Srdivacky  EVT VT = N.getValueType();
256199481Srdivacky  if (AM.BaseType == MSP430ISelAddressMode::RegBase) {
257199481Srdivacky    if (!AM.Base.Reg.getNode())
258199481Srdivacky      AM.Base.Reg = CurDAG->getRegister(0, VT);
259199481Srdivacky  }
260199481Srdivacky
261199481Srdivacky  Base  = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase) ?
262263508Sdim    CurDAG->getTargetFrameIndex(AM.Base.FrameIndex,
263263508Sdim                                getTargetLowering()->getPointerTy()) :
264199481Srdivacky    AM.Base.Reg;
265199481Srdivacky
266199481Srdivacky  if (AM.GV)
267263508Sdim    Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(N),
268210299Sed                                          MVT::i16, AM.Disp,
269199481Srdivacky                                          0/*AM.SymbolFlags*/);
270199481Srdivacky  else if (AM.CP)
271199481Srdivacky    Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16,
272199481Srdivacky                                         AM.Align, AM.Disp, 0/*AM.SymbolFlags*/);
273199481Srdivacky  else if (AM.ES)
274199481Srdivacky    Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0/*AM.SymbolFlags*/);
275199481Srdivacky  else if (AM.JT != -1)
276199481Srdivacky    Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/);
277199481Srdivacky  else if (AM.BlockAddr)
278243830Sdim    Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, 0,
279243830Sdim                                         0/*AM.SymbolFlags*/);
280199481Srdivacky  else
281199481Srdivacky    Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i16);
282199481Srdivacky
283193323Sed  return true;
284193323Sed}
285193323Sed
286198090Srdivackybool MSP430DAGToDAGISel::
287198090SrdivackySelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
288198090Srdivacky                             std::vector<SDValue> &OutOps) {
289198090Srdivacky  SDValue Op0, Op1;
290198090Srdivacky  switch (ConstraintCode) {
291198090Srdivacky  default: return true;
292198090Srdivacky  case 'm':   // memory
293218893Sdim    if (!SelectAddr(Op, Op0, Op1))
294198090Srdivacky      return true;
295198090Srdivacky    break;
296198090Srdivacky  }
297193323Sed
298198090Srdivacky  OutOps.push_back(Op0);
299198090Srdivacky  OutOps.push_back(Op1);
300198090Srdivacky  return false;
301198090Srdivacky}
302198090Srdivacky
303199481Srdivackystatic bool isValidIndexedLoad(const LoadSDNode *LD) {
304199481Srdivacky  ISD::MemIndexedMode AM = LD->getAddressingMode();
305199481Srdivacky  if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD)
306199481Srdivacky    return false;
307199481Srdivacky
308199481Srdivacky  EVT VT = LD->getMemoryVT();
309199481Srdivacky
310199481Srdivacky  switch (VT.getSimpleVT().SimpleTy) {
311199481Srdivacky  case MVT::i8:
312199481Srdivacky    // Sanity check
313199481Srdivacky    if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 1)
314199481Srdivacky      return false;
315199481Srdivacky
316199481Srdivacky    break;
317199481Srdivacky  case MVT::i16:
318199481Srdivacky    // Sanity check
319199481Srdivacky    if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 2)
320199481Srdivacky      return false;
321199481Srdivacky
322199481Srdivacky    break;
323199481Srdivacky  default:
324199481Srdivacky    return false;
325199481Srdivacky  }
326199481Srdivacky
327199481Srdivacky  return true;
328199481Srdivacky}
329199481Srdivacky
330202375SrdivackySDNode *MSP430DAGToDAGISel::SelectIndexedLoad(SDNode *N) {
331202375Srdivacky  LoadSDNode *LD = cast<LoadSDNode>(N);
332199481Srdivacky  if (!isValidIndexedLoad(LD))
333199481Srdivacky    return NULL;
334199481Srdivacky
335199481Srdivacky  MVT VT = LD->getMemoryVT().getSimpleVT();
336199481Srdivacky
337199481Srdivacky  unsigned Opcode = 0;
338199481Srdivacky  switch (VT.SimpleTy) {
339199481Srdivacky  case MVT::i8:
340199481Srdivacky    Opcode = MSP430::MOV8rm_POST;
341199481Srdivacky    break;
342199481Srdivacky  case MVT::i16:
343199481Srdivacky    Opcode = MSP430::MOV16rm_POST;
344199481Srdivacky    break;
345199481Srdivacky  default:
346199481Srdivacky    return NULL;
347199481Srdivacky  }
348199481Srdivacky
349263508Sdim   return CurDAG->getMachineNode(Opcode, SDLoc(N),
350199481Srdivacky                                 VT, MVT::i16, MVT::Other,
351199481Srdivacky                                 LD->getBasePtr(), LD->getChain());
352199481Srdivacky}
353199481Srdivacky
354202375SrdivackySDNode *MSP430DAGToDAGISel::SelectIndexedBinOp(SDNode *Op,
355199481Srdivacky                                               SDValue N1, SDValue N2,
356199481Srdivacky                                               unsigned Opc8, unsigned Opc16) {
357199481Srdivacky  if (N1.getOpcode() == ISD::LOAD &&
358199481Srdivacky      N1.hasOneUse() &&
359207618Srdivacky      IsLegalToFold(N1, Op, Op, OptLevel)) {
360199481Srdivacky    LoadSDNode *LD = cast<LoadSDNode>(N1);
361199481Srdivacky    if (!isValidIndexedLoad(LD))
362199481Srdivacky      return NULL;
363199481Srdivacky
364199481Srdivacky    MVT VT = LD->getMemoryVT().getSimpleVT();
365199481Srdivacky    unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8);
366199481Srdivacky    MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
367199481Srdivacky    MemRefs0[0] = cast<MemSDNode>(N1)->getMemOperand();
368199481Srdivacky    SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() };
369199481Srdivacky    SDNode *ResNode =
370202375Srdivacky      CurDAG->SelectNodeTo(Op, Opc,
371199481Srdivacky                           VT, MVT::i16, MVT::Other,
372199481Srdivacky                           Ops0, 3);
373199481Srdivacky    cast<MachineSDNode>(ResNode)->setMemRefs(MemRefs0, MemRefs0 + 1);
374199481Srdivacky    // Transfer chain.
375199481Srdivacky    ReplaceUses(SDValue(N1.getNode(), 2), SDValue(ResNode, 2));
376199481Srdivacky    // Transfer writeback.
377199481Srdivacky    ReplaceUses(SDValue(N1.getNode(), 1), SDValue(ResNode, 1));
378199481Srdivacky    return ResNode;
379199481Srdivacky  }
380199481Srdivacky
381199481Srdivacky  return NULL;
382199481Srdivacky}
383199481Srdivacky
384199481Srdivacky
385202375SrdivackySDNode *MSP430DAGToDAGISel::Select(SDNode *Node) {
386263508Sdim  SDLoc dl(Node);
387193323Sed
388193323Sed  // Dump information about the Node being selected
389204642Srdivacky  DEBUG(errs() << "Selecting: ");
390193323Sed  DEBUG(Node->dump(CurDAG));
391198090Srdivacky  DEBUG(errs() << "\n");
392193323Sed
393193323Sed  // If we have a custom node, we already have selected!
394193323Sed  if (Node->isMachineOpcode()) {
395204642Srdivacky    DEBUG(errs() << "== ";
396198090Srdivacky          Node->dump(CurDAG);
397198090Srdivacky          errs() << "\n");
398255804Sdim    Node->setNodeId(-1);
399193323Sed    return NULL;
400193323Sed  }
401193323Sed
402193323Sed  // Few custom selection stuff.
403193323Sed  switch (Node->getOpcode()) {
404193323Sed  default: break;
405193323Sed  case ISD::FrameIndex: {
406202375Srdivacky    assert(Node->getValueType(0) == MVT::i16);
407193323Sed    int FI = cast<FrameIndexSDNode>(Node)->getIndex();
408193323Sed    SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16);
409193323Sed    if (Node->hasOneUse())
410193323Sed      return CurDAG->SelectNodeTo(Node, MSP430::ADD16ri, MVT::i16,
411193323Sed                                  TFI, CurDAG->getTargetConstant(0, MVT::i16));
412198090Srdivacky    return CurDAG->getMachineNode(MSP430::ADD16ri, dl, MVT::i16,
413198090Srdivacky                                  TFI, CurDAG->getTargetConstant(0, MVT::i16));
414193323Sed  }
415199481Srdivacky  case ISD::LOAD:
416202375Srdivacky    if (SDNode *ResNode = SelectIndexedLoad(Node))
417199481Srdivacky      return ResNode;
418199481Srdivacky    // Other cases are autogenerated.
419199481Srdivacky    break;
420199481Srdivacky  case ISD::ADD:
421199481Srdivacky    if (SDNode *ResNode =
422202375Srdivacky        SelectIndexedBinOp(Node,
423202375Srdivacky                           Node->getOperand(0), Node->getOperand(1),
424199481Srdivacky                           MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
425199481Srdivacky      return ResNode;
426199481Srdivacky    else if (SDNode *ResNode =
427202375Srdivacky             SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
428199481Srdivacky                                MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
429199481Srdivacky      return ResNode;
430199481Srdivacky
431199481Srdivacky    // Other cases are autogenerated.
432199481Srdivacky    break;
433199481Srdivacky  case ISD::SUB:
434199481Srdivacky    if (SDNode *ResNode =
435202375Srdivacky        SelectIndexedBinOp(Node,
436202375Srdivacky                           Node->getOperand(0), Node->getOperand(1),
437199481Srdivacky                           MSP430::SUB8rm_POST, MSP430::SUB16rm_POST))
438199481Srdivacky      return ResNode;
439199481Srdivacky
440199481Srdivacky    // Other cases are autogenerated.
441199481Srdivacky    break;
442199481Srdivacky  case ISD::AND:
443199481Srdivacky    if (SDNode *ResNode =
444202375Srdivacky        SelectIndexedBinOp(Node,
445202375Srdivacky                           Node->getOperand(0), Node->getOperand(1),
446199481Srdivacky                           MSP430::AND8rm_POST, MSP430::AND16rm_POST))
447199481Srdivacky      return ResNode;
448199481Srdivacky    else if (SDNode *ResNode =
449202375Srdivacky             SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
450199481Srdivacky                                MSP430::AND8rm_POST, MSP430::AND16rm_POST))
451199481Srdivacky      return ResNode;
452199481Srdivacky
453199481Srdivacky    // Other cases are autogenerated.
454199481Srdivacky    break;
455199481Srdivacky  case ISD::OR:
456199481Srdivacky    if (SDNode *ResNode =
457202375Srdivacky        SelectIndexedBinOp(Node,
458202375Srdivacky                           Node->getOperand(0), Node->getOperand(1),
459199481Srdivacky                           MSP430::OR8rm_POST, MSP430::OR16rm_POST))
460199481Srdivacky      return ResNode;
461199481Srdivacky    else if (SDNode *ResNode =
462202375Srdivacky             SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
463199481Srdivacky                                MSP430::OR8rm_POST, MSP430::OR16rm_POST))
464199481Srdivacky      return ResNode;
465199481Srdivacky
466199481Srdivacky    // Other cases are autogenerated.
467199481Srdivacky    break;
468199481Srdivacky  case ISD::XOR:
469199481Srdivacky    if (SDNode *ResNode =
470202375Srdivacky        SelectIndexedBinOp(Node,
471202375Srdivacky                           Node->getOperand(0), Node->getOperand(1),
472199481Srdivacky                           MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
473199481Srdivacky      return ResNode;
474199481Srdivacky    else if (SDNode *ResNode =
475202375Srdivacky             SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
476199481Srdivacky                                MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
477199481Srdivacky      return ResNode;
478199481Srdivacky
479199481Srdivacky    // Other cases are autogenerated.
480199481Srdivacky    break;
481193323Sed  }
482193323Sed
483193323Sed  // Select the default instruction
484202375Srdivacky  SDNode *ResNode = SelectCode(Node);
485193323Sed
486204642Srdivacky  DEBUG(errs() << "=> ");
487202375Srdivacky  if (ResNode == NULL || ResNode == Node)
488202375Srdivacky    DEBUG(Node->dump(CurDAG));
489193323Sed  else
490193323Sed    DEBUG(ResNode->dump(CurDAG));
491198090Srdivacky  DEBUG(errs() << "\n");
492193323Sed
493193323Sed  return ResNode;
494193323Sed}
495