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