blob: deab5d5675436d85e41b50bd74535fc0f0f7bc08 [file] [log] [blame]
Sanjiv Gupta0e687712008-05-13 09:02:57 +00001//===-- 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
34using namespace llvm;
35
36const char *PIC16TargetLowering:: getTargetNodeName(unsigned Opcode) const
37{
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +000038 switch (Opcode) {
Sanjiv Gupta0e687712008-05-13 09:02:57 +000039 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";
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +000046 case PIC16ISD::Cmp : return "PIC16ISD::Cmp";
Sanjiv Gupta0e687712008-05-13 09:02:57 +000047 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
55PIC16TargetLowering::
56PIC16TargetLowering(PIC16TargetMachine &TM): TargetLowering(TM)
57{
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +000058 // Set up the register classes.
59 addRegisterClass(MVT::i8, PIC16::CPURegsRegisterClass);
Sanjiv Gupta0e687712008-05-13 09:02:57 +000060 addRegisterClass(MVT::i16, PIC16::PTRRegsRegisterClass);
Sanjiv Gupta0e687712008-05-13 09:02:57 +000061
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +000062 // Load extented operations for i1 types must be promoted .
63 setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote);
Sanjiv Gupta0e687712008-05-13 09:02:57 +000064 setLoadXAction(ISD::ZEXTLOAD, MVT::i1, Promote);
65 setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote);
66
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +000067 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);
Sanjiv Gupta0e687712008-05-13 09:02:57 +000072
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +000073 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);
Sanjiv Gupta0e687712008-05-13 09:02:57 +000078
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +000079 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);
Sanjiv Gupta0e687712008-05-13 09:02:57 +000084
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +000085 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);
Sanjiv Gupta0e687712008-05-13 09:02:57 +000090
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +000091 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);
Sanjiv Gupta0e687712008-05-13 09:02:57 +000096
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +000097 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);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000102
103 // PIC16 does not have these NodeTypes below.
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000104 setOperationAction(ISD::SETCC, MVT::i1, Expand);
105 setOperationAction(ISD::SETCC, MVT::i8, Expand);
106 setOperationAction(ISD::SETCC, MVT::Other, Expand);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000107 setOperationAction(ISD::SELECT_CC, MVT::i1, Custom);
108 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
109
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000110 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);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000116
117 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
118
119
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000120 // FIXME: Do we really need to Custom lower the GA ??
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000121 setOperationAction(ISD::GlobalAddress, MVT::i8, Custom);
122 setOperationAction(ISD::RET, MVT::Other, Custom);
123
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000124 setOperationAction(ISD::CTPOP, MVT::i32, Expand);
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000125 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);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000129 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::LOCATION, MVT::Other, Expand);
137 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
138 setOperationAction(ISD::LABEL, MVT::Other, Expand);
139
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000140 // Use the default for now.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000141 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);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000146
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
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000156 setStackPointerRegisterToSaveRestore(PIC16::STKPTR);
157 computeRegisterProperties();
158}
159
160
161SDOperand PIC16TargetLowering:: LowerOperation(SDOperand Op, SelectionDAG &DAG)
162{
163 SDVTList VTList16 = DAG.getVTList(MVT::i16, MVT::i16, MVT::Other);
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000164 switch (Op.getOpcode()) {
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000165 case ISD::STORE:
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000166 DOUT << "reduce store\n";
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000167 break;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000168
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
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000189 case ISD::LOAD:
190 case ISD::ADD:
191 break;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000192
193 case ISD::BR_CC:
194 DOUT << "==== lowering BR_CC\n";
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000195 return LowerBR_CC(Op, DAG);
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000196 } // end switch.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000197 return SDOperand();
198}
199
200
201//===----------------------------------------------------------------------===//
202// Lower helper functions
203//===----------------------------------------------------------------------===//
204
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000205SDOperand PIC16TargetLowering::LowerBR_CC(SDOperand Op, SelectionDAG &DAG)
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000206{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000207 MVT VT = Op.getValueType();
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000208 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
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000218 SDOperand StatusReg = DAG.getRegister(PIC16::STATUSREG, MVT::i8);
219 SDOperand CPUReg = DAG.getRegister(PIC16::WREG, MVT::i8);
220 switch(CC) {
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000221 default:
222 assert(0 && "This condition code is not handled yet!!");
223 abort();
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000224
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000225 case ISD::SETNE:
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000226 DOUT << "setne\n";
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000227 cmpOpcode = PIC16ISD::XORCC;
228 branchOpcode = PIC16ISD::BTFSS;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000229 branchOperand = DAG.getConstant(2, MVT::i8);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000230 break;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000231
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000232 case ISD::SETEQ:
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000233 DOUT << "seteq\n";
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000234 cmpOpcode = PIC16ISD::XORCC;
235 branchOpcode = PIC16ISD::BTFSC;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000236 branchOperand = DAG.getConstant(2, MVT::i8);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000237 break;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000238
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000239 case ISD::SETGT:
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000240 assert(0 && "Greater Than condition code is not handled yet!!");
241 abort();
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000242 break;
243
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000244 case ISD::SETGE:
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000245 DOUT << "setge\n";
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000246 cmpOpcode = PIC16ISD::SUBCC;
247 branchOpcode = PIC16ISD::BTFSS;
248 branchOperand = DAG.getConstant(1, MVT::i8);
249 break;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000250
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000251 case ISD::SETLT:
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000252 DOUT << "setlt\n";
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000253 cmpOpcode = PIC16ISD::SUBCC;
254 branchOpcode = PIC16ISD::BTFSC;
255 branchOperand = DAG.getConstant(1,MVT::i8);
256 break;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000257
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000258 case ISD::SETLE:
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000259 assert(0 && "Less Than Equal condition code is not handled yet!!");
260 abort();
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000261 break;
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000262 } // End of Switch
263
264 SDVTList VTList = DAG.getVTList(MVT::i8, MVT::Flag);
265 SDOperand CmpValue = DAG.getNode(cmpOpcode, VTList, LHS, RHS).getValue(1);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000266 Result = DAG.getNode(branchOpcode, VT, Chain, JumpVal, branchOperand,
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000267 StatusReg, CmpValue);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000268 return Result;
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000269}
270
271
272//===----------------------------------------------------------------------===//
273// Misc Lower Operation implementation
274//===----------------------------------------------------------------------===//
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000275
276// LowerGlobalAddress - Create a constant pool entry for global value
277// and wrap it in a wrapper node.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000278SDOperand
279PIC16TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG)
280{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000281 MVT PtrVT = getPointerTy();
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000282 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
283 GlobalValue *GV = GSDN->getGlobal();
284
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000285 // FIXME: for now only do the ram.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000286 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
293SDOperand
294PIC16TargetLowering::LowerRET(SDOperand Op, SelectionDAG &DAG)
295{
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000296 switch(Op.getNumOperands()) {
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000297 default:
298 assert(0 && "Do not know how to return this many arguments!");
299 abort();
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000300
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000301 case 1:
302 return SDOperand(); // ret void is legal
303 }
304}
305
306SDOperand
307PIC16TargetLowering::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
316SDOperand
317PIC16TargetLowering::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.
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000331 // FIXME: Handle store large -> read small portion.
332 // FIXME: Handle TRUNCSTORE/LOADEXT
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000333 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);
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000352 // FIXME: Add to worklist may not be needed.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000353 // 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
369SDOperand
370PIC16TargetLowering::LowerADDSUB(SDNode *N, SelectionDAG &DAG,
371 DAGCombinerInfo &DCI) const
372{
373 bool changed = false;
374 int i;
375 SDOperand LoOps[3], HiOps[3];
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000376 SDOperand OutOps[3]; // [0]:left, [1]:right, [2]:carry
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000377 SDOperand InOp[2];
378 SDOperand retVal;
379 SDOperand as1,as2;
380 SDVTList VTList;
Evan Chengbb606742008-05-14 20:33:21 +0000381 unsigned AS = 0, ASE = 0, ASC=0;
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000382
383 InOp[0] = N->getOperand(0);
384 InOp[1] = N->getOperand(1);
385
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000386 switch (N->getOpcode()) {
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000387 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 }
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000394 break;
395
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000396 case ISD::ADDE:
397 case ISD::ADDC:
398 AS = ISD::ADD;
399 ASE = ISD::ADDE;
400 ASC = ISD::ADDC;
401 break;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000402
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000403 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 }
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000410 break;
411
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000412 case ISD::SUBE:
413 case ISD::SUBC:
414 AS = ISD::SUB;
415 ASE = ISD::SUBE;
416 ASC = ISD::SUBC;
417 break;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000418 } // end switch.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000419
420 assert ((N->getValueType(0) == MVT::i16)
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000421 && "expecting an MVT::i16 node for lowering");
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000422 assert ((N->getOperand(0).getValueType() == MVT::i16)
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000423 && (N->getOperand(1).getValueType() == MVT::i16)
424 && "both inputs to addx/subx:i16 must be i16");
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000425
426 for (i = 0; i < 2; i++) {
427 if (InOp[i].getOpcode() == ISD::GlobalAddress) {
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000428 // We don't want to lower subs/adds with global address yet.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000429 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
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000444 // anything else.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000445 SDOperand lowered = LowerLOAD(InOp[i].Val, DAG, DCI);
446
447 // So If LowerLOAD returns something other than Package,
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000448 // then just call ADD again.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000449 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;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000462 // Must call LowerADDSUB recursively here,
463 // LowerADDSUB returns a Package node.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000464 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) {
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000470 // FIXME: I am just zero extending. for now.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000471 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 }
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000480 } // end for.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000481
482 assert (changed && "nothing changed while lowering SUBx/ADDx");
483
484 VTList = DAG.getVTList(MVT::i8, MVT::Flag);
485 if (N->getOpcode() == ASE) {
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000486 // We must take in the existing carry
487 // if this node is part of an existing subx/addx sequence.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000488 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);
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000496 // We must build a pair that also provides the carry from sube/adde.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000497 OutOps[0] = as1;
498 OutOps[1] = as2;
499 OutOps[2] = as2.getValue(1);
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000500 // Breaking an original i16, so lets make the Package also an i16.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000501 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
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000523//===----------------------------------------------------------------------===//
524
525#include "PIC16GenCallingConv.inc"
526
527//===----------------------------------------------------------------------===//
528// CALL Calling Convention Implementation
529//===----------------------------------------------------------------------===//
530
531
532//===----------------------------------------------------------------------===//
533// FORMAL_ARGUMENTS Calling Convention Implementation
534//===----------------------------------------------------------------------===//
535SDOperand PIC16TargetLowering::
536LowerFORMAL_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.
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000542 // FIXME: Just copy right now.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000543 ArgValues.push_back(Root);
544
545 return DAG.getNode(ISD::MERGE_VALUES, 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
562SDOperand PIC16TargetLowering::PerformDAGCombine(SDNode *N,
563 DAGCombinerInfo &DCI) const
564{
565 int i;
566 ConstantSDNode *CST;
567 SelectionDAG &DAG = DCI.DAG;
568
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000569 switch (N->getOpcode()) {
570 default:
571 break;
572
573 case PIC16ISD::Package:
574 DOUT << "==== combining PIC16ISD::Package\n";
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000575 return SDOperand();
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000576
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 }
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000604 }
605 }
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000606 break;
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000607
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000608 // FIXME: split this large chunk of code.
609 case ISD::STORE :
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000610 {
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000611 SDOperand Chain = N->getOperand(0);
612 SDOperand Src = N->getOperand(1);
613 SDOperand Dest = N->getOperand(2);
614 unsigned int DstOff = 0;
Evan Chengbb606742008-05-14 20:33:21 +0000615 int NUM_STORES = 0;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000616 SDOperand Stores[6];
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000617
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000618 // 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
Duncan Sands83ec4b62008-06-06 12:08:01 +0000629 switch(Src.getValueType().getSimpleVT()) {
630 default:
631 assert(false && "Invalid value type!");
632
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000633 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 }
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000663
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000664 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 }
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000679
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000680 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 }
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000697
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000698 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);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000709
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000710 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) {
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000733 }
734 else {
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000735 }
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000736 } // end ISD::STORE.
737 break;
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000738
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000739 case ISD::LOAD :
740 {
741 SDOperand Ptr = N->getOperand(1);
742 if (Ptr.getOpcode() == PIC16ISD::Package) {
743 assert (0 && "not implemented yet");
744 }
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000745 }
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000746 break;
747 } // end switch.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000748
749 return SDOperand();
750}
751
752//===----------------------------------------------------------------------===//
753// Utility functions
754//===----------------------------------------------------------------------===//
755const SDOperand *PIC16TargetLowering::
756findLoadi8(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++) {
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000762 const SDOperand *retVal = findLoadi8(Src.getOperand(i),DAG);
763 if (retVal) return retVal;
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000764 }
765
766 return NULL;
767}