Rename ISD::LOCATION to ISD::DBG_STOPPOINT to better reflect its
[oota-llvm.git] / lib / Target / PIC16 / PIC16ISelLowering.cpp
1 //===-- PIC16ISelLowering.cpp - PIC16 DAG Lowering Implementation ---------===//
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 the interfaces that PIC16 uses to lower LLVM code into a
11 // selection DAG.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "pic16-lower"
16
17 #include "PIC16ISelLowering.h"
18 #include "PIC16TargetMachine.h"
19 #include "llvm/DerivedTypes.h"
20 #include "llvm/Function.h"
21 #include "llvm/Intrinsics.h"
22 #include "llvm/CallingConv.h"
23 #include "llvm/CodeGen/CallingConvLower.h"
24 #include "llvm/CodeGen/MachineFrameInfo.h"
25 #include "llvm/CodeGen/MachineFunction.h"
26 #include "llvm/CodeGen/MachineInstrBuilder.h"
27 #include "llvm/CodeGen/MachineRegisterInfo.h"
28 #include "llvm/CodeGen/SelectionDAGISel.h"
29 #include "llvm/CodeGen/ValueTypes.h"
30 #include "llvm/Support/Debug.h"
31 #include <queue>
32 #include <set>
33
34 using namespace llvm;
35
36 const char *PIC16TargetLowering:: getTargetNodeName(unsigned Opcode) const 
37 {
38   switch (Opcode) {
39     case PIC16ISD::Hi        : return "PIC16ISD::Hi";
40     case PIC16ISD::Lo        : return "PIC16ISD::Lo";
41     case PIC16ISD::Package   : return "PIC16ISD::Package";
42     case PIC16ISD::Wrapper   : return "PIC16ISD::Wrapper";
43     case PIC16ISD::SetBank   : return "PIC16ISD::SetBank";
44     case PIC16ISD::SetPage   : return "PIC16ISD::SetPage";
45     case PIC16ISD::Branch    : return "PIC16ISD::Branch";
46     case PIC16ISD::Cmp       : return "PIC16ISD::Cmp";
47     case PIC16ISD::BTFSS     : return "PIC16ISD::BTFSS";
48     case PIC16ISD::BTFSC     : return "PIC16ISD::BTFSC";
49     case PIC16ISD::XORCC     : return "PIC16ISD::XORCC";
50     case PIC16ISD::SUBCC     : return "PIC16ISD::SUBCC";
51     default                  : return NULL;
52   }
53 }
54
55 PIC16TargetLowering::
56 PIC16TargetLowering(PIC16TargetMachine &TM): TargetLowering(TM) 
57 {
58   // Set up the register classes.
59   addRegisterClass(MVT::i8, PIC16::CPURegsRegisterClass);
60   addRegisterClass(MVT::i16, PIC16::PTRRegsRegisterClass);
61
62   // Load extented operations for i1 types must be promoted .
63   setLoadXAction(ISD::EXTLOAD, MVT::i1,  Promote);
64   setLoadXAction(ISD::ZEXTLOAD, MVT::i1,  Promote);
65   setLoadXAction(ISD::SEXTLOAD, MVT::i1,  Promote);
66
67   setOperationAction(ISD::ADD, MVT::i1, Promote);
68   setOperationAction(ISD::ADD, MVT::i8, Legal);
69   setOperationAction(ISD::ADD, MVT::i16, Custom);
70   setOperationAction(ISD::ADD, MVT::i32, Expand);
71   setOperationAction(ISD::ADD, MVT::i64, Expand);
72
73   setOperationAction(ISD::SUB, MVT::i1, Promote);
74   setOperationAction(ISD::SUB, MVT::i8, Legal);
75   setOperationAction(ISD::SUB, MVT::i16, Custom);
76   setOperationAction(ISD::SUB, MVT::i32, Expand);
77   setOperationAction(ISD::SUB, MVT::i64, Expand);
78
79   setOperationAction(ISD::ADDC, MVT::i1, Promote);
80   setOperationAction(ISD::ADDC, MVT::i8, Legal);
81   setOperationAction(ISD::ADDC, MVT::i16, Custom);
82   setOperationAction(ISD::ADDC, MVT::i32, Expand);
83   setOperationAction(ISD::ADDC, MVT::i64, Expand);
84
85   setOperationAction(ISD::ADDE, MVT::i1, Promote);
86   setOperationAction(ISD::ADDE, MVT::i8, Legal);
87   setOperationAction(ISD::ADDE, MVT::i16, Custom);
88   setOperationAction(ISD::ADDE, MVT::i32, Expand);
89   setOperationAction(ISD::ADDE, MVT::i64, Expand);
90
91   setOperationAction(ISD::SUBC, MVT::i1, Promote);
92   setOperationAction(ISD::SUBC, MVT::i8, Legal);
93   setOperationAction(ISD::SUBC, MVT::i16, Custom);
94   setOperationAction(ISD::SUBC, MVT::i32, Expand);
95   setOperationAction(ISD::SUBC, MVT::i64, Expand);
96
97   setOperationAction(ISD::SUBE, MVT::i1, Promote);
98   setOperationAction(ISD::SUBE, MVT::i8, Legal);
99   setOperationAction(ISD::SUBE, MVT::i16, Custom);
100   setOperationAction(ISD::SUBE, MVT::i32, Expand);
101   setOperationAction(ISD::SUBE, MVT::i64, Expand);
102
103   // PIC16 does not have these NodeTypes below.
104   setOperationAction(ISD::SETCC, MVT::i1, Expand);
105   setOperationAction(ISD::SETCC, MVT::i8, Expand);
106   setOperationAction(ISD::SETCC, MVT::Other, Expand);
107   setOperationAction(ISD::SELECT_CC, MVT::i1, Custom);
108   setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
109
110   setOperationAction(ISD::BRCOND, MVT::i1, Expand);
111   setOperationAction(ISD::BRCOND, MVT::i8, Expand);
112   setOperationAction(ISD::BRCOND, MVT::Other, Expand);
113
114   setOperationAction(ISD::BR_CC, MVT::i1, Custom);
115   setOperationAction(ISD::BR_CC, MVT::i8, Custom);
116
117   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
118
119   
120   // FIXME: Do we really need to Custom lower the GA ??
121   setOperationAction(ISD::GlobalAddress, MVT::i8, Custom);
122   setOperationAction(ISD::RET, MVT::Other, Custom);
123
124   setOperationAction(ISD::CTPOP, MVT::i32, Expand);
125   setOperationAction(ISD::CTTZ, MVT::i32, Expand);
126   setOperationAction(ISD::CTLZ, MVT::i32, Expand);
127   setOperationAction(ISD::ROTL, MVT::i32, Expand);
128   setOperationAction(ISD::ROTR, MVT::i32, Expand);
129   setOperationAction(ISD::BSWAP, MVT::i32, Expand);
130
131   setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
132   setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
133   setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
134
135   // We don't have line number support yet.
136   setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
137   setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
138   setOperationAction(ISD::LABEL, MVT::Other, Expand);
139
140   // Use the default for now.
141   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
142   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
143
144   setOperationAction(ISD::LOAD, MVT::i1, Promote);
145   setOperationAction(ISD::LOAD, MVT::i8, Legal);
146
147   setTargetDAGCombine(ISD::LOAD);
148   setTargetDAGCombine(ISD::STORE);
149   setTargetDAGCombine(ISD::ADDE);
150   setTargetDAGCombine(ISD::ADDC);
151   setTargetDAGCombine(ISD::ADD);
152   setTargetDAGCombine(ISD::SUBE);
153   setTargetDAGCombine(ISD::SUBC);
154   setTargetDAGCombine(ISD::SUB);
155
156   setStackPointerRegisterToSaveRestore(PIC16::STKPTR);
157   computeRegisterProperties();
158 }
159
160
161 SDOperand PIC16TargetLowering:: LowerOperation(SDOperand Op, SelectionDAG &DAG) 
162 {
163   SDVTList VTList16 = DAG.getVTList(MVT::i16, MVT::i16, MVT::Other);
164   switch (Op.getOpcode()) {
165     case ISD::STORE: 
166       DOUT << "reduce store\n"; 
167       break;
168
169     case ISD::FORMAL_ARGUMENTS:   
170       DOUT << "==== lowering formal args\n";
171       return LowerFORMAL_ARGUMENTS(Op, DAG);
172
173     case ISD::GlobalAddress:      
174       DOUT << "==== lowering GA\n";
175       return LowerGlobalAddress(Op, DAG);
176
177     case ISD::RET:                
178       DOUT << "==== lowering ret\n";
179       return LowerRET(Op, DAG);
180
181     case ISD::FrameIndex:                
182       DOUT << "==== lowering frame index\n";
183       return LowerFrameIndex(Op, DAG);
184
185     case ISD::ADDE: 
186       DOUT << "==== lowering adde\n"; 
187       break;
188
189     case ISD::LOAD:
190     case ISD::ADD: 
191       break;
192
193     case ISD::BR_CC:                
194       DOUT << "==== lowering BR_CC\n"; 
195       return LowerBR_CC(Op, DAG); 
196   } // end switch.
197   return SDOperand();
198 }
199
200
201 //===----------------------------------------------------------------------===//
202 //  Lower helper functions
203 //===----------------------------------------------------------------------===//
204
205 SDOperand PIC16TargetLowering::LowerBR_CC(SDOperand Op, SelectionDAG &DAG) 
206 {
207   MVT VT = Op.getValueType();
208   SDOperand Chain = Op.getOperand(0);
209   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
210   SDOperand LHS = Op.getOperand(2);
211   SDOperand RHS = Op.getOperand(3);
212   SDOperand JumpVal = Op.getOperand(4);
213   SDOperand Result;
214   unsigned  cmpOpcode;
215   unsigned  branchOpcode;
216   SDOperand branchOperand;
217
218   SDOperand StatusReg = DAG.getRegister(PIC16::STATUSREG, MVT::i8);
219   SDOperand CPUReg = DAG.getRegister(PIC16::WREG, MVT::i8);
220   switch(CC) {
221     default:
222       assert(0 && "This condition code is not handled yet!!");
223       abort();
224
225     case ISD::SETNE:
226       DOUT << "setne\n";
227       cmpOpcode = PIC16ISD::XORCC;
228       branchOpcode = PIC16ISD::BTFSS;
229       branchOperand = DAG.getConstant(2, MVT::i8);
230       break;
231
232     case ISD::SETEQ:
233       DOUT << "seteq\n";
234       cmpOpcode = PIC16ISD::XORCC;
235       branchOpcode = PIC16ISD::BTFSC;
236       branchOperand = DAG.getConstant(2, MVT::i8);
237       break;
238
239     case ISD::SETGT:
240       assert(0 && "Greater Than condition code is not handled yet!!");
241       abort();
242       break;
243
244     case ISD::SETGE:
245       DOUT << "setge\n";
246       cmpOpcode = PIC16ISD::SUBCC;
247       branchOpcode = PIC16ISD::BTFSS;
248       branchOperand = DAG.getConstant(1, MVT::i8);
249       break;
250
251     case ISD::SETLT:
252       DOUT << "setlt\n";
253       cmpOpcode = PIC16ISD::SUBCC;
254       branchOpcode = PIC16ISD::BTFSC;
255       branchOperand = DAG.getConstant(1,MVT::i8);
256       break;
257
258     case ISD::SETLE:
259       assert(0 && "Less Than Equal condition code is not handled yet!!");
260       abort();
261       break;
262   }  // End of Switch
263
264    SDVTList VTList = DAG.getVTList(MVT::i8, MVT::Flag);
265    SDOperand CmpValue = DAG.getNode(cmpOpcode, VTList, LHS, RHS).getValue(1);
266    Result = DAG.getNode(branchOpcode, VT, Chain, JumpVal, branchOperand, 
267                         StatusReg, CmpValue);
268    return Result;
269 }
270
271
272 //===----------------------------------------------------------------------===//
273 //  Misc Lower Operation implementation
274 //===----------------------------------------------------------------------===//
275
276 // LowerGlobalAddress - Create a constant pool entry for global value 
277 // and wrap it in a wrapper node.
278 SDOperand
279 PIC16TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) 
280 {
281   MVT PtrVT = getPointerTy();
282   GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
283   GlobalValue *GV = GSDN->getGlobal();
284
285   // FIXME: for now only do the ram.
286   SDOperand CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 2);
287   SDOperand CPBank = DAG.getNode(PIC16ISD::SetBank, MVT::i8, CPAddr);
288   CPAddr = DAG.getNode(PIC16ISD::Wrapper, MVT::i8, CPAddr,CPBank);
289
290   return CPAddr;
291 }
292
293 SDOperand
294 PIC16TargetLowering::LowerRET(SDOperand Op, SelectionDAG &DAG) 
295 {
296   switch(Op.getNumOperands()) {
297     default:
298       assert(0 && "Do not know how to return this many arguments!");
299       abort();
300
301     case 1:
302       return SDOperand(); // ret void is legal
303   }
304 }
305
306 SDOperand
307 PIC16TargetLowering::LowerFrameIndex(SDOperand N, SelectionDAG &DAG) 
308 {
309   if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
310     return DAG.getTargetFrameIndex(FIN->getIndex(), MVT::i32);
311   }
312
313   return N;
314 }
315
316 SDOperand
317 PIC16TargetLowering::LowerLOAD(SDNode *N,
318                                SelectionDAG &DAG,
319                                DAGCombinerInfo &DCI) const
320 {
321   SDOperand Outs[2];
322   SDOperand TF; //TokenFactor
323   SDOperand OutChains[2];
324   SDOperand Chain = N->getOperand(0);  
325   SDOperand Src   = N->getOperand(1);
326   SDOperand retVal;
327   SDVTList VTList;
328
329   // If this load is directly stored, replace the load value with the stored
330   // value.
331   // FIXME: Handle store large -> read small portion.
332   // FIXME: Handle TRUNCSTORE/LOADEXT
333   LoadSDNode *LD  = cast<LoadSDNode>(N);
334   SDOperand Ptr   = LD->getBasePtr();
335   if (LD->getExtensionType() == ISD::NON_EXTLOAD) {
336     if (ISD::isNON_TRUNCStore(Chain.Val)) {
337       StoreSDNode *PrevST = cast<StoreSDNode>(Chain);
338       if (PrevST->getBasePtr() == Ptr &&
339           PrevST->getValue().getValueType() == N->getValueType(0))
340         return DCI.CombineTo(N, Chain.getOperand(1), Chain);
341     }
342   }
343
344   if (N->getValueType(0) != MVT::i16)
345     return SDOperand();
346
347   SDOperand toWorklist;
348   Outs[0] = DAG.getLoad(MVT::i8, Chain, Src, NULL, 0);
349   toWorklist = DAG.getNode(ISD::ADD, MVT::i16, Src,
350                            DAG.getConstant(1, MVT::i16));
351   Outs[1] = DAG.getLoad(MVT::i8, Chain, toWorklist, NULL, 0);
352   // FIXME: Add to worklist may not be needed. 
353   // It is meant to merge sequences of add with constant into one. 
354   DCI.AddToWorklist(toWorklist.Val);   
355   
356   // Create the tokenfactors and carry it on to the build_pair node
357   OutChains[0] = Outs[0].getValue(1);
358   OutChains[1] = Outs[1].getValue(1);
359   TF = DAG.getNode(ISD::TokenFactor, MVT::Other, &OutChains[0], 2);
360   
361   VTList = DAG.getVTList(MVT::i16, MVT::Flag);
362   retVal = DAG.getNode (PIC16ISD::Package, VTList, &Outs[0], 2);
363
364   DCI.CombineTo (N, retVal, TF);
365
366   return retVal;
367 }
368
369 SDOperand
370 PIC16TargetLowering::LowerADDSUB(SDNode *N, SelectionDAG &DAG,
371                                  DAGCombinerInfo &DCI) const
372 {
373   bool changed = false;
374   int i;
375   SDOperand LoOps[3], HiOps[3];
376   SDOperand OutOps[3]; // [0]:left, [1]:right, [2]:carry
377   SDOperand InOp[2];
378   SDOperand retVal;
379   SDOperand as1,as2;
380   SDVTList VTList;
381   unsigned AS = 0, ASE = 0, ASC=0;
382
383   InOp[0] = N->getOperand(0);
384   InOp[1] = N->getOperand(1);  
385
386   switch (N->getOpcode()) {
387     case ISD::ADD:
388       if (InOp[0].getOpcode() == ISD::Constant &&
389           InOp[1].getOpcode() == ISD::Constant) {
390         ConstantSDNode *CST0 = dyn_cast<ConstantSDNode>(InOp[0]);
391         ConstantSDNode *CST1 = dyn_cast<ConstantSDNode>(InOp[1]);
392         return DAG.getConstant(CST0->getValue() + CST1->getValue(), MVT::i16);
393       }
394       break;
395
396     case ISD::ADDE:
397     case ISD::ADDC:
398       AS  = ISD::ADD;
399       ASE = ISD::ADDE;
400       ASC = ISD::ADDC;
401       break;
402
403     case ISD::SUB:
404       if (InOp[0].getOpcode() == ISD::Constant &&
405           InOp[1].getOpcode() == ISD::Constant) {
406         ConstantSDNode *CST0 = dyn_cast<ConstantSDNode>(InOp[0]);
407         ConstantSDNode *CST1 = dyn_cast<ConstantSDNode>(InOp[1]);
408         return DAG.getConstant(CST0->getValue() - CST1->getValue(), MVT::i16);
409       }
410       break;
411
412     case ISD::SUBE:
413     case ISD::SUBC:
414       AS  = ISD::SUB;
415       ASE = ISD::SUBE;
416       ASC = ISD::SUBC;
417       break;
418   } // end switch.
419
420   assert ((N->getValueType(0) == MVT::i16) 
421            && "expecting an MVT::i16 node for lowering");
422   assert ((N->getOperand(0).getValueType() == MVT::i16) 
423            && (N->getOperand(1).getValueType() == MVT::i16) 
424             && "both inputs to addx/subx:i16 must be i16");
425
426   for (i = 0; i < 2; i++) {
427     if (InOp[i].getOpcode() == ISD::GlobalAddress) {
428       // We don't want to lower subs/adds with global address yet.
429       return SDOperand();
430     }
431     else if (InOp[i].getOpcode() == ISD::Constant) {
432       changed = true;
433       ConstantSDNode *CST = dyn_cast<ConstantSDNode>(InOp[i]);
434       LoOps[i] = DAG.getConstant(CST->getValue() & 0xFF, MVT::i8);
435       HiOps[i] = DAG.getConstant(CST->getValue() >> 8, MVT::i8);
436     }
437     else if (InOp[i].getOpcode() == PIC16ISD::Package) {
438       LoOps[i] = InOp[i].getOperand(0);
439       HiOps[i] = InOp[i].getOperand(1);
440     }
441     else if (InOp[i].getOpcode() == ISD::LOAD) {
442       changed = true;
443       // LowerLOAD returns a Package node or it may combine and return 
444       // anything else.
445       SDOperand lowered = LowerLOAD(InOp[i].Val, DAG, DCI);
446
447       // So If LowerLOAD returns something other than Package, 
448       // then just call ADD again.
449       if (lowered.getOpcode() != PIC16ISD::Package)
450         return LowerADDSUB(N, DAG, DCI);
451           
452       LoOps[i] = lowered.getOperand(0);
453       HiOps[i] = lowered.getOperand(1);
454     }
455     else if ((InOp[i].getOpcode() == ISD::ADD) || 
456              (InOp[i].getOpcode() == ISD::ADDE) ||
457              (InOp[i].getOpcode() == ISD::ADDC) ||
458              (InOp[i].getOpcode() == ISD::SUB) ||
459              (InOp[i].getOpcode() == ISD::SUBE) ||
460              (InOp[i].getOpcode() == ISD::SUBC)) {
461       changed = true;
462       // Must call LowerADDSUB recursively here,
463       // LowerADDSUB returns a Package node.
464       SDOperand lowered = LowerADDSUB(InOp[i].Val, DAG, DCI);
465
466       LoOps[i] = lowered.getOperand(0);
467       HiOps[i] = lowered.getOperand(1);
468     }
469     else if (InOp[i].getOpcode() == ISD::SIGN_EXTEND) {
470       // FIXME: I am just zero extending. for now.
471       changed = true;
472       LoOps[i] = InOp[i].getOperand(0);
473       HiOps[i] = DAG.getConstant(0, MVT::i8);
474     }
475     else {
476       DAG.setGraphColor(N, "blue");
477       DAG.viewGraph();
478       assert (0 && "not implemented yet");
479     }
480   } // end for.
481
482   assert (changed && "nothing changed while lowering SUBx/ADDx");
483
484   VTList = DAG.getVTList(MVT::i8, MVT::Flag);
485   if (N->getOpcode() == ASE) { 
486     // We must take in the existing carry
487     // if this node is part of an existing subx/addx sequence.
488     LoOps[2] = N->getOperand(2).getValue(1);
489     as1 = DAG.getNode (ASE, VTList, LoOps, 3);
490   }
491   else {
492     as1 = DAG.getNode (ASC, VTList, LoOps, 2);
493   }
494   HiOps[2] = as1.getValue(1);
495   as2 = DAG.getNode (ASE, VTList, HiOps, 3);
496   // We must build a pair that also provides the carry from sube/adde.
497   OutOps[0] = as1;
498   OutOps[1] = as2;
499   OutOps[2] = as2.getValue(1);
500   // Breaking an original i16, so lets make the Package also an i16.
501   if (N->getOpcode() == ASE) {
502     VTList = DAG.getVTList(MVT::i16, MVT::Flag);
503     retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 3);
504     DCI.CombineTo (N, retVal, OutOps[2]);
505   }
506   else if (N->getOpcode() == ASC) {
507     VTList = DAG.getVTList(MVT::i16, MVT::Flag);
508     retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 2);
509     DCI.CombineTo (N, retVal, OutOps[2]);
510   }
511   else if (N->getOpcode() == AS) {
512     VTList = DAG.getVTList(MVT::i16);
513     retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 2);
514     DCI.CombineTo (N, retVal);
515   }
516
517   return retVal;
518 }
519
520
521 //===----------------------------------------------------------------------===//
522 //                      Calling Convention Implementation
523 //===----------------------------------------------------------------------===//
524
525 #include "PIC16GenCallingConv.inc"
526
527 //===----------------------------------------------------------------------===//
528 //                  CALL Calling Convention Implementation
529 //===----------------------------------------------------------------------===//
530
531
532 //===----------------------------------------------------------------------===//
533 //             FORMAL_ARGUMENTS Calling Convention Implementation
534 //===----------------------------------------------------------------------===//
535 SDOperand PIC16TargetLowering::
536 LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG)
537 {
538   SmallVector<SDOperand, 8> ArgValues;
539   SDOperand Root = Op.getOperand(0);
540
541   // Return the new list of results.
542   // FIXME: Just copy right now.
543   ArgValues.push_back(Root);
544
545   return DAG.getMergeValues(Op.Val->getVTList(), &ArgValues[0],
546                             ArgValues.size()).getValue(Op.ResNo);
547 }
548
549
550 //===----------------------------------------------------------------------===//
551 //               Return Value Calling Convention Implementation
552 //===----------------------------------------------------------------------===//
553
554 //===----------------------------------------------------------------------===//
555 //                           PIC16 Inline Assembly Support
556 //===----------------------------------------------------------------------===//
557
558 //===----------------------------------------------------------------------===//
559 // Target Optimization Hooks
560 //===----------------------------------------------------------------------===//
561
562 SDOperand PIC16TargetLowering::PerformDAGCombine(SDNode *N, 
563                                                  DAGCombinerInfo &DCI) const 
564 {
565   int i;
566   ConstantSDNode *CST;
567   SelectionDAG &DAG = DCI.DAG;
568
569   switch (N->getOpcode()) {
570     default: 
571       break;
572
573     case PIC16ISD::Package:
574       DOUT << "==== combining PIC16ISD::Package\n";
575       return SDOperand();
576
577     case ISD::ADD:
578     case ISD::SUB:
579       if ((N->getOperand(0).getOpcode() == ISD::GlobalAddress) ||
580           (N->getOperand(0).getOpcode() == ISD::FrameIndex)) {
581         // Do not touch pointer adds.
582         return SDOperand ();
583       }
584       break;
585
586     case ISD::ADDE :
587     case ISD::ADDC :
588     case ISD::SUBE :
589     case ISD::SUBC :
590       if (N->getValueType(0) == MVT::i16) {
591         SDOperand retVal = LowerADDSUB(N, DAG,DCI); 
592         // LowerADDSUB has already combined the result, 
593         // so we just return nothing to avoid assertion failure from llvm 
594         // if N has been deleted already.
595         return SDOperand();
596       }
597       else if (N->getValueType(0) == MVT::i8) { 
598         // Sanity check ....
599         for (int i=0; i<2; i++) {
600           if (N->getOperand (i).getOpcode() == PIC16ISD::Package) {
601             assert (0 && 
602                     "don't want to have PIC16ISD::Package as intput to add:i8");
603           }
604         }
605       }
606       break;
607
608     // FIXME: split this large chunk of code.
609     case ISD::STORE :
610     {
611       SDOperand Chain = N->getOperand(0);  
612       SDOperand Src = N->getOperand(1);
613       SDOperand Dest = N->getOperand(2);
614       unsigned int DstOff = 0;
615       int NUM_STORES = 0;
616       SDOperand Stores[6];
617
618       // if source operand is expected to be extended to 
619       // some higher type then - remove this extension 
620       // SDNode and do the extension manually
621       if ((Src.getOpcode() == ISD::ANY_EXTEND) ||
622           (Src.getOpcode() == ISD::SIGN_EXTEND) || 
623           (Src.getOpcode() == ISD::ZERO_EXTEND)) {
624         Src = Src.Val->getOperand(0);
625         Stores[0] = DAG.getStore(Chain, Src, Dest, NULL,0);
626         return Stores[0];
627       }
628
629       switch(Src.getValueType().getSimpleVT()) {
630         default:
631           assert(false && "Invalid value type!");
632
633         case MVT::i8:  
634           break;
635
636         case MVT::i16: 
637           NUM_STORES = 2;
638           break;
639
640         case MVT::i32: 
641           NUM_STORES = 4;
642           break;
643
644         case MVT::i64: 
645           NUM_STORES = 8; 
646           break;
647       }
648
649       if (isa<GlobalAddressSDNode>(Dest) && isa<LoadSDNode>(Src) && 
650           (Src.getValueType() != MVT::i8)) {
651         //create direct addressing a = b
652         Chain = Src.getOperand(0);
653         for (i=0; i<NUM_STORES; i++) {
654           SDOperand ADN = DAG.getNode(ISD::ADD, MVT::i16, Src.getOperand(1),
655                                       DAG.getConstant(DstOff, MVT::i16));
656           SDOperand LDN = DAG.getLoad(MVT::i8, Chain, ADN, NULL, 0);
657           SDOperand DSTADDR = DAG.getNode(ISD::ADD, MVT::i16, Dest,
658                                           DAG.getConstant(DstOff, MVT::i16));
659           Stores[i] = DAG.getStore(Chain, LDN, DSTADDR, NULL, 0);
660           Chain = Stores[i];
661           DstOff += 1;
662         } 
663         
664         Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i);
665         return Chain;
666       }
667       else if (isa<GlobalAddressSDNode>(Dest) && isa<ConstantSDNode>(Src) 
668                && (Src.getValueType() != MVT::i8)) {
669         //create direct addressing a = CONST
670         CST = dyn_cast<ConstantSDNode>(Src);
671         for (i = 0; i < NUM_STORES; i++) {
672           SDOperand CNST = DAG.getConstant(CST->getValue() >> i*8, MVT::i8);
673           SDOperand ADN = DAG.getNode(ISD::ADD, MVT::i16, Dest,
674                                       DAG.getConstant(DstOff, MVT::i16));
675           Stores[i] = DAG.getStore(Chain, CNST, ADN, NULL, 0);
676           Chain = Stores[i];
677           DstOff += 1;
678         } 
679           
680         Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i);
681         return Chain;
682       }
683       else if (isa<LoadSDNode>(Dest) && isa<ConstantSDNode>(Src) 
684               && (Src.getValueType() != MVT::i8)) {
685         // Create indirect addressing.
686         CST = dyn_cast<ConstantSDNode>(Src);
687         Chain = Dest.getOperand(0);  
688         SDOperand Load;
689         Load = DAG.getLoad(MVT::i16, Chain,Dest.getOperand(1), NULL, 0);
690         Chain = Load.getValue(1);
691         for (i=0; i<NUM_STORES; i++) {
692           SDOperand CNST = DAG.getConstant(CST->getValue() >> i*8, MVT::i8);
693           Stores[i] = DAG.getStore(Chain, CNST, Load, NULL, 0);
694           Chain = Stores[i];
695           DstOff += 1;
696         } 
697           
698         Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i);
699         return Chain;
700       }
701       else if (isa<LoadSDNode>(Dest) && isa<GlobalAddressSDNode>(Src)) {
702         // GlobalAddressSDNode *GAD = dyn_cast<GlobalAddressSDNode>(Src);
703         return SDOperand();
704       }
705       else if (Src.getOpcode() == PIC16ISD::Package) {
706         StoreSDNode *st = dyn_cast<StoreSDNode>(N);
707         SDOperand toWorkList, retVal;
708         Chain = N->getOperand(0);
709
710         if (st->isTruncatingStore()) {
711           retVal = DAG.getStore(Chain, Src.getOperand(0), Dest, NULL, 0);
712         }
713         else {
714           toWorkList = DAG.getNode(ISD::ADD, MVT::i16, Dest,
715                                    DAG.getConstant(1, MVT::i16));
716           Stores[1] = DAG.getStore(Chain, Src.getOperand(0), Dest, NULL, 0);
717           Stores[0] = DAG.getStore(Chain, Src.getOperand(1), toWorkList, NULL, 
718                                    0);
719
720           // We want to merge sequence of add with constant to one add and a 
721           // constant, so add the ADD node to worklist to have llvm do that 
722           // automatically.
723           DCI.AddToWorklist(toWorkList.Val); 
724
725           // We don't need the Package so add to worklist so llvm deletes it
726           DCI.AddToWorklist(Src.Val);
727           retVal = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], 2);
728         }
729
730         return retVal;
731       }
732       else if (Src.getOpcode() == ISD::TRUNCATE) {
733       }
734       else {
735       }
736     } // end ISD::STORE.
737     break;
738
739     case ISD::LOAD :
740     {
741       SDOperand Ptr = N->getOperand(1);
742       if (Ptr.getOpcode() == PIC16ISD::Package) {
743         assert (0 && "not implemented yet");
744        }
745     }
746     break;
747   } // end switch.
748
749   return SDOperand();
750 }
751
752 //===----------------------------------------------------------------------===//
753 //               Utility functions
754 //===----------------------------------------------------------------------===//
755 const SDOperand *PIC16TargetLowering::
756 findLoadi8(const SDOperand &Src, SelectionDAG &DAG) const
757 {
758   unsigned int i;
759   if ((Src.getOpcode() == ISD::LOAD) && (Src.getValueType() == MVT::i8))
760     return &Src;
761   for (i=0; i<Src.getNumOperands(); i++) {
762     const SDOperand *retVal = findLoadi8(Src.getOperand(i),DAG);
763     if (retVal) return retVal;
764   }
765
766   return NULL;
767 }