blob: 04538d18993ae86ec4a5aae77c993dfc9fbf5166 [file] [log] [blame]
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +00001//===-- MSP430ISelDAGToDAG.cpp - A dag to dag inst selector for MSP430 ----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an instruction selector for the MSP430 target.
11//
12//===----------------------------------------------------------------------===//
13
14#include "MSP430.h"
15#include "MSP430ISelLowering.h"
16#include "MSP430TargetMachine.h"
17#include "llvm/DerivedTypes.h"
18#include "llvm/Function.h"
19#include "llvm/Intrinsics.h"
20#include "llvm/CallingConv.h"
21#include "llvm/Constants.h"
22#include "llvm/CodeGen/MachineFrameInfo.h"
23#include "llvm/CodeGen/MachineFunction.h"
24#include "llvm/CodeGen/MachineInstrBuilder.h"
25#include "llvm/CodeGen/MachineRegisterInfo.h"
26#include "llvm/CodeGen/SelectionDAG.h"
27#include "llvm/CodeGen/SelectionDAGISel.h"
28#include "llvm/Target/TargetLowering.h"
29#include "llvm/Support/Compiler.h"
30#include "llvm/Support/Debug.h"
Torok Edwindac237e2009-07-08 20:53:28 +000031#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/raw_ostream.h"
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +000033using namespace llvm;
34
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +000035namespace {
36 struct MSP430ISelAddressMode {
37 enum {
38 RegBase,
39 FrameIndexBase
40 } BaseType;
41
42 struct { // This is really a union, discriminated by BaseType!
43 SDValue Reg;
44 int FrameIndex;
45 } Base;
46
47 int16_t Disp;
Dan Gohman46510a72010-04-15 01:51:59 +000048 const GlobalValue *GV;
49 const Constant *CP;
50 const BlockAddress *BlockAddr;
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +000051 const char *ES;
52 int JT;
53 unsigned Align; // CP alignment.
54
55 MSP430ISelAddressMode()
56 : BaseType(RegBase), Disp(0), GV(0), CP(0), BlockAddr(0),
57 ES(0), JT(-1), Align(0) {
58 }
59
60 bool hasSymbolicDisplacement() const {
61 return GV != 0 || CP != 0 || ES != 0 || JT != -1;
62 }
63
64 bool hasBaseReg() const {
65 return Base.Reg.getNode() != 0;
66 }
67
68 void setBaseReg(SDValue Reg) {
69 BaseType = RegBase;
70 Base.Reg = Reg;
71 }
72
73 void dump() {
74 errs() << "MSP430ISelAddressMode " << this << '\n';
Anton Korobeynikovcdcad112009-12-13 01:00:32 +000075 if (BaseType == RegBase && Base.Reg.getNode() != 0) {
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +000076 errs() << "Base.Reg ";
77 Base.Reg.getNode()->dump();
Anton Korobeynikovcdcad112009-12-13 01:00:32 +000078 } else if (BaseType == FrameIndexBase) {
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +000079 errs() << " Base.FrameIndex " << Base.FrameIndex << '\n';
80 }
81 errs() << " Disp " << Disp << '\n';
82 if (GV) {
83 errs() << "GV ";
84 GV->dump();
85 } else if (CP) {
86 errs() << " CP ";
87 CP->dump();
88 errs() << " Align" << Align << '\n';
89 } else if (ES) {
90 errs() << "ES ";
91 errs() << ES << '\n';
92 } else if (JT != -1)
93 errs() << " JT" << JT << " Align" << Align << '\n';
94 }
95 };
96}
97
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +000098/// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
99/// instructions for SelectionDAG operations.
100///
101namespace {
102 class MSP430DAGToDAGISel : public SelectionDAGISel {
103 MSP430TargetLowering &Lowering;
104 const MSP430Subtarget &Subtarget;
105
106 public:
Anton Korobeynikov60871cb2009-05-03 13:19:42 +0000107 MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel)
108 : SelectionDAGISel(TM, OptLevel),
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000109 Lowering(*TM.getTargetLowering()),
110 Subtarget(*TM.getSubtargetImpl()) { }
111
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000112 virtual const char *getPassName() const {
113 return "MSP430 DAG->DAG Pattern Instruction Selection";
114 }
115
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000116 bool MatchAddress(SDValue N, MSP430ISelAddressMode &AM);
117 bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
118 bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
119
Anton Korobeynikov95eb4702009-10-11 19:14:21 +0000120 virtual bool
121 SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
122 std::vector<SDValue> &OutOps);
123
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000124 // Include the pieces autogenerated from the target description.
125 #include "MSP430GenDAGISel.inc"
126
127 private:
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000128 SDNode *Select(SDNode *N);
129 SDNode *SelectIndexedLoad(SDNode *Op);
130 SDNode *SelectIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2,
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000131 unsigned Opc8, unsigned Opc16);
132
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000133 bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Disp);
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000134 };
135} // end anonymous namespace
136
137/// createMSP430ISelDag - This pass converts a legalized DAG into a
138/// MSP430-specific DAG, ready for instruction scheduling.
139///
Anton Korobeynikov60871cb2009-05-03 13:19:42 +0000140FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM,
141 CodeGenOpt::Level OptLevel) {
142 return new MSP430DAGToDAGISel(TM, OptLevel);
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000143}
144
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000145
146/// MatchWrapper - Try to match MSP430ISD::Wrapper node into an addressing mode.
147/// These wrap things that will resolve down into a symbol reference. If no
148/// match is possible, this returns true, otherwise it returns false.
149bool MSP430DAGToDAGISel::MatchWrapper(SDValue N, MSP430ISelAddressMode &AM) {
150 // If the addressing mode already has a symbol as the displacement, we can
151 // never match another symbol.
152 if (AM.hasSymbolicDisplacement())
153 return true;
154
155 SDValue N0 = N.getOperand(0);
156
157 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
158 AM.GV = G->getGlobal();
159 AM.Disp += G->getOffset();
160 //AM.SymbolFlags = G->getTargetFlags();
161 } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
162 AM.CP = CP->getConstVal();
163 AM.Align = CP->getAlignment();
164 AM.Disp += CP->getOffset();
165 //AM.SymbolFlags = CP->getTargetFlags();
166 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
167 AM.ES = S->getSymbol();
168 //AM.SymbolFlags = S->getTargetFlags();
169 } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
170 AM.JT = J->getIndex();
171 //AM.SymbolFlags = J->getTargetFlags();
172 } else {
173 AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress();
174 //AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags();
175 }
176 return false;
177}
178
179/// MatchAddressBase - Helper for MatchAddress. Add the specified node to the
180/// specified addressing mode without any further recursion.
181bool MSP430DAGToDAGISel::MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM) {
182 // Is the base register already occupied?
183 if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) {
184 // If so, we cannot select it.
Anton Korobeynikov82e46c22009-05-03 13:10:11 +0000185 return true;
186 }
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000187
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000188 // Default, generate it as a register.
189 AM.BaseType = MSP430ISelAddressMode::RegBase;
190 AM.Base.Reg = N;
191 return false;
192}
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000193
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000194bool MSP430DAGToDAGISel::MatchAddress(SDValue N, MSP430ISelAddressMode &AM) {
Chris Lattner6b7f39c2010-03-02 22:30:08 +0000195 DEBUG(errs() << "MatchAddress: "; AM.dump());
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000196
197 switch (N.getOpcode()) {
198 default: break;
199 case ISD::Constant: {
200 uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
201 AM.Disp += Val;
202 return false;
203 }
204
Anton Korobeynikov0eb6af42009-05-03 13:08:51 +0000205 case MSP430ISD::Wrapper:
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000206 if (!MatchWrapper(N, AM))
207 return false;
208 break;
209
210 case ISD::FrameIndex:
211 if (AM.BaseType == MSP430ISelAddressMode::RegBase
212 && AM.Base.Reg.getNode() == 0) {
213 AM.BaseType = MSP430ISelAddressMode::FrameIndexBase;
214 AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
215 return false;
Anton Korobeynikov0eb6af42009-05-03 13:08:51 +0000216 }
217 break;
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000218
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000219 case ISD::ADD: {
220 MSP430ISelAddressMode Backup = AM;
221 if (!MatchAddress(N.getNode()->getOperand(0), AM) &&
222 !MatchAddress(N.getNode()->getOperand(1), AM))
223 return false;
224 AM = Backup;
225 if (!MatchAddress(N.getNode()->getOperand(1), AM) &&
226 !MatchAddress(N.getNode()->getOperand(0), AM))
227 return false;
228 AM = Backup;
229
230 break;
231 }
232
233 case ISD::OR:
234 // Handle "X | C" as "X + C" iff X is known to have C bits clear.
235 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
236 MSP430ISelAddressMode Backup = AM;
237 uint64_t Offset = CN->getSExtValue();
238 // Start with the LHS as an addr mode.
239 if (!MatchAddress(N.getOperand(0), AM) &&
240 // Address could not have picked a GV address for the displacement.
241 AM.GV == NULL &&
242 // Check to see if the LHS & C is zero.
243 CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
244 AM.Disp += Offset;
245 return false;
246 }
247 AM = Backup;
248 }
249 break;
250 }
251
252 return MatchAddressBase(N, AM);
253}
254
255/// SelectAddr - returns true if it is able pattern match an addressing mode.
256/// It returns the operands which make up the maximal addressing mode it can
257/// match by reference.
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000258bool MSP430DAGToDAGISel::SelectAddr(SDNode *Op, SDValue N,
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000259 SDValue &Base, SDValue &Disp) {
260 MSP430ISelAddressMode AM;
261
262 if (MatchAddress(N, AM))
263 return false;
264
265 EVT VT = N.getValueType();
266 if (AM.BaseType == MSP430ISelAddressMode::RegBase) {
267 if (!AM.Base.Reg.getNode())
268 AM.Base.Reg = CurDAG->getRegister(0, VT);
269 }
270
271 Base = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase) ?
272 CurDAG->getTargetFrameIndex(AM.Base.FrameIndex, TLI.getPointerTy()) :
273 AM.Base.Reg;
274
275 if (AM.GV)
276 Disp = CurDAG->getTargetGlobalAddress(AM.GV, MVT::i16, AM.Disp,
277 0/*AM.SymbolFlags*/);
278 else if (AM.CP)
279 Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16,
280 AM.Align, AM.Disp, 0/*AM.SymbolFlags*/);
281 else if (AM.ES)
282 Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0/*AM.SymbolFlags*/);
283 else if (AM.JT != -1)
284 Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/);
285 else if (AM.BlockAddr)
Dan Gohman71a41962009-11-20 23:21:00 +0000286 Disp = CurDAG->getBlockAddress(AM.BlockAddr, MVT::i32,
287 true, 0/*AM.SymbolFlags*/);
Anton Korobeynikov123ed8f2009-11-07 17:13:35 +0000288 else
289 Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i16);
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000290
291 return true;
292}
293
Anton Korobeynikov95eb4702009-10-11 19:14:21 +0000294bool MSP430DAGToDAGISel::
295SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
296 std::vector<SDValue> &OutOps) {
297 SDValue Op0, Op1;
298 switch (ConstraintCode) {
299 default: return true;
300 case 'm': // memory
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000301 if (!SelectAddr(Op.getNode(), Op, Op0, Op1))
Anton Korobeynikov95eb4702009-10-11 19:14:21 +0000302 return true;
303 break;
304 }
305
306 OutOps.push_back(Op0);
307 OutOps.push_back(Op1);
308 return false;
309}
Anton Korobeynikov36b6e532009-05-03 13:06:03 +0000310
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000311static bool isValidIndexedLoad(const LoadSDNode *LD) {
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000312 ISD::MemIndexedMode AM = LD->getAddressingMode();
313 if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD)
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000314 return false;
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000315
316 EVT VT = LD->getMemoryVT();
317
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000318 switch (VT.getSimpleVT().SimpleTy) {
319 case MVT::i8:
320 // Sanity check
321 if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 1)
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000322 return false;
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000323
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000324 break;
325 case MVT::i16:
326 // Sanity check
327 if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 2)
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000328 return false;
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000329
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000330 break;
331 default:
332 return false;
333 }
334
335 return true;
336}
337
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000338SDNode *MSP430DAGToDAGISel::SelectIndexedLoad(SDNode *N) {
339 LoadSDNode *LD = cast<LoadSDNode>(N);
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000340 if (!isValidIndexedLoad(LD))
341 return NULL;
342
343 MVT VT = LD->getMemoryVT().getSimpleVT();
344
345 unsigned Opcode = 0;
346 switch (VT.SimpleTy) {
347 case MVT::i8:
348 Opcode = MSP430::MOV8rm_POST;
349 break;
350 case MVT::i16:
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000351 Opcode = MSP430::MOV16rm_POST;
352 break;
353 default:
354 return NULL;
355 }
356
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000357 return CurDAG->getMachineNode(Opcode, N->getDebugLoc(),
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000358 VT, MVT::i16, MVT::Other,
359 LD->getBasePtr(), LD->getChain());
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000360}
361
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000362SDNode *MSP430DAGToDAGISel::SelectIndexedBinOp(SDNode *Op,
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000363 SDValue N1, SDValue N2,
364 unsigned Opc8, unsigned Opc16) {
365 if (N1.getOpcode() == ISD::LOAD &&
366 N1.hasOneUse() &&
Evan Cheng014bf212010-02-15 19:41:07 +0000367 IsLegalToFold(N1, Op, Op)) {
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000368 LoadSDNode *LD = cast<LoadSDNode>(N1);
369 if (!isValidIndexedLoad(LD))
370 return NULL;
371
372 MVT VT = LD->getMemoryVT().getSimpleVT();
373 unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8);
374 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
375 MemRefs0[0] = cast<MemSDNode>(N1)->getMemOperand();
376 SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() };
377 SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000378 CurDAG->SelectNodeTo(Op, Opc,
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000379 VT, MVT::i16, MVT::Other,
380 Ops0, 3);
381 cast<MachineSDNode>(ResNode)->setMemRefs(MemRefs0, MemRefs0 + 1);
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000382 // Transfer chain.
383 ReplaceUses(SDValue(N1.getNode(), 2), SDValue(ResNode, 2));
384 // Transfer writeback.
385 ReplaceUses(SDValue(N1.getNode(), 1), SDValue(ResNode, 1));
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000386 return ResNode;
387 }
388
389 return NULL;
390}
391
392
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000393SDNode *MSP430DAGToDAGISel::Select(SDNode *Node) {
394 DebugLoc dl = Node->getDebugLoc();
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000395
396 // Dump information about the Node being selected
Chris Lattner7c306da2010-03-02 06:34:30 +0000397 DEBUG(errs() << "Selecting: ");
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000398 DEBUG(Node->dump(CurDAG));
Chris Lattner893e1c92009-08-23 06:49:22 +0000399 DEBUG(errs() << "\n");
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000400
401 // If we have a custom node, we already have selected!
402 if (Node->isMachineOpcode()) {
Chris Lattner7c306da2010-03-02 06:34:30 +0000403 DEBUG(errs() << "== ";
Chris Lattner893e1c92009-08-23 06:49:22 +0000404 Node->dump(CurDAG);
405 errs() << "\n");
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000406 return NULL;
407 }
408
Anton Korobeynikov40477312009-05-03 13:10:26 +0000409 // Few custom selection stuff.
410 switch (Node->getOpcode()) {
411 default: break;
412 case ISD::FrameIndex: {
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000413 assert(Node->getValueType(0) == MVT::i16);
Anton Korobeynikov40477312009-05-03 13:10:26 +0000414 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
Owen Anderson825b72b2009-08-11 20:47:22 +0000415 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16);
Anton Korobeynikov40477312009-05-03 13:10:26 +0000416 if (Node->hasOneUse())
Owen Anderson825b72b2009-08-11 20:47:22 +0000417 return CurDAG->SelectNodeTo(Node, MSP430::ADD16ri, MVT::i16,
418 TFI, CurDAG->getTargetConstant(0, MVT::i16));
Dan Gohman602b0c82009-09-25 18:54:59 +0000419 return CurDAG->getMachineNode(MSP430::ADD16ri, dl, MVT::i16,
420 TFI, CurDAG->getTargetConstant(0, MVT::i16));
Anton Korobeynikov40477312009-05-03 13:10:26 +0000421 }
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000422 case ISD::LOAD:
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000423 if (SDNode *ResNode = SelectIndexedLoad(Node))
Anton Korobeynikov6534f832009-11-07 17:15:06 +0000424 return ResNode;
425 // Other cases are autogenerated.
426 break;
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000427 case ISD::ADD:
428 if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000429 SelectIndexedBinOp(Node,
430 Node->getOperand(0), Node->getOperand(1),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000431 MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
432 return ResNode;
433 else if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000434 SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000435 MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
436 return ResNode;
437
438 // Other cases are autogenerated.
439 break;
440 case ISD::SUB:
441 if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000442 SelectIndexedBinOp(Node,
443 Node->getOperand(0), Node->getOperand(1),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000444 MSP430::SUB8rm_POST, MSP430::SUB16rm_POST))
445 return ResNode;
446
447 // Other cases are autogenerated.
448 break;
449 case ISD::AND:
450 if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000451 SelectIndexedBinOp(Node,
452 Node->getOperand(0), Node->getOperand(1),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000453 MSP430::AND8rm_POST, MSP430::AND16rm_POST))
454 return ResNode;
455 else if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000456 SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000457 MSP430::AND8rm_POST, MSP430::AND16rm_POST))
458 return ResNode;
459
460 // Other cases are autogenerated.
461 break;
462 case ISD::OR:
463 if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000464 SelectIndexedBinOp(Node,
465 Node->getOperand(0), Node->getOperand(1),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000466 MSP430::OR8rm_POST, MSP430::OR16rm_POST))
467 return ResNode;
468 else if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000469 SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000470 MSP430::OR8rm_POST, MSP430::OR16rm_POST))
471 return ResNode;
472
473 // Other cases are autogenerated.
474 break;
475 case ISD::XOR:
476 if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000477 SelectIndexedBinOp(Node,
478 Node->getOperand(0), Node->getOperand(1),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000479 MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
480 return ResNode;
481 else if (SDNode *ResNode =
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000482 SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
Anton Korobeynikov52f28e92009-11-08 14:27:38 +0000483 MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
484 return ResNode;
Anton Korobeynikov06ac0822009-11-07 17:15:25 +0000485
486 // Other cases are autogenerated.
487 break;
Anton Korobeynikov40477312009-05-03 13:10:26 +0000488 }
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000489
490 // Select the default instruction
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000491 SDNode *ResNode = SelectCode(Node);
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000492
Chris Lattner7c306da2010-03-02 06:34:30 +0000493 DEBUG(errs() << "=> ");
Dan Gohmaneeb3a002010-01-05 01:24:18 +0000494 if (ResNode == NULL || ResNode == Node)
495 DEBUG(Node->dump(CurDAG));
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000496 else
497 DEBUG(ResNode->dump(CurDAG));
Chris Lattner893e1c92009-08-23 06:49:22 +0000498 DEBUG(errs() << "\n");
Anton Korobeynikov43ed64a2009-05-03 12:58:58 +0000499
500 return ResNode;
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000501}