blob: 92b5c7b253b0a2d5c0a8909df7cefec6691f9717 [file] [log] [blame]
Sanjiv Gupta0e687712008-05-13 09:02:57 +00001//
2// The LLVM Compiler Infrastructure
3//
4// This file is distributed under the University of Illinois Open Source
5// License. See LICENSE.TXT for details.
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the interfaces that PIC16 uses to lower LLVM code into a
10// selection DAG.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "pic16-lower"
Sanjiv Gupta753ec152009-10-15 19:26:25 +000015#include "PIC16ABINames.h"
Sanjiv Gupta0e687712008-05-13 09:02:57 +000016#include "PIC16ISelLowering.h"
Chris Lattnerf0144122009-07-28 03:13:23 +000017#include "PIC16TargetObjectFile.h"
Sanjiv Gupta0e687712008-05-13 09:02:57 +000018#include "PIC16TargetMachine.h"
19#include "llvm/DerivedTypes.h"
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +000020#include "llvm/GlobalValue.h"
Sanjiv Gupta0e687712008-05-13 09:02:57 +000021#include "llvm/Function.h"
Sanjiv Gupta1b046942009-01-13 19:18:47 +000022#include "llvm/CallingConv.h"
Sanjiv Gupta0e687712008-05-13 09:02:57 +000023#include "llvm/CodeGen/MachineFrameInfo.h"
24#include "llvm/CodeGen/MachineFunction.h"
Sanjiv Gupta1b046942009-01-13 19:18:47 +000025#include "llvm/CodeGen/MachineInstrBuilder.h"
26#include "llvm/CodeGen/MachineRegisterInfo.h"
Torok Edwin804e0fe2009-07-08 19:04:27 +000027#include "llvm/Support/ErrorHandling.h"
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +000028
29
Sanjiv Gupta0e687712008-05-13 09:02:57 +000030using namespace llvm;
31
Sanjiv Guptae0b4b0e2009-05-11 08:52:04 +000032static const char *getIntrinsicName(unsigned opcode) {
33 std::string Basename;
34 switch(opcode) {
Sanjiv Guptaaa939172009-07-31 07:35:57 +000035 default: llvm_unreachable("do not know intrinsic name");
Sanjiv Gupta003263b2009-06-16 16:17:35 +000036 // Arithmetic Right shift for integer types.
Sanjiv Guptae0b4b0e2009-05-11 08:52:04 +000037 case PIC16ISD::SRA_I8: Basename = "sra.i8"; break;
38 case RTLIB::SRA_I16: Basename = "sra.i16"; break;
39 case RTLIB::SRA_I32: Basename = "sra.i32"; break;
40
Sanjiv Gupta003263b2009-06-16 16:17:35 +000041 // Left shift for integer types.
Sanjiv Guptae0b4b0e2009-05-11 08:52:04 +000042 case PIC16ISD::SLL_I8: Basename = "sll.i8"; break;
43 case RTLIB::SHL_I16: Basename = "sll.i16"; break;
44 case RTLIB::SHL_I32: Basename = "sll.i32"; break;
45
Sanjiv Gupta003263b2009-06-16 16:17:35 +000046 // Logical Right Shift for integer types.
Sanjiv Guptae0b4b0e2009-05-11 08:52:04 +000047 case PIC16ISD::SRL_I8: Basename = "srl.i8"; break;
48 case RTLIB::SRL_I16: Basename = "srl.i16"; break;
49 case RTLIB::SRL_I32: Basename = "srl.i32"; break;
50
Sanjiv Gupta003263b2009-06-16 16:17:35 +000051 // Multiply for integer types.
Sanjiv Guptae0b4b0e2009-05-11 08:52:04 +000052 case PIC16ISD::MUL_I8: Basename = "mul.i8"; break;
53 case RTLIB::MUL_I16: Basename = "mul.i16"; break;
54 case RTLIB::MUL_I32: Basename = "mul.i32"; break;
Sanjiv Gupta46800772009-06-05 14:43:12 +000055
Sanjiv Gupta003263b2009-06-16 16:17:35 +000056 // Signed division for integers.
Sanjiv Gupta46800772009-06-05 14:43:12 +000057 case RTLIB::SDIV_I16: Basename = "sdiv.i16"; break;
58 case RTLIB::SDIV_I32: Basename = "sdiv.i32"; break;
Sanjiv Gupta003263b2009-06-16 16:17:35 +000059
60 // Unsigned division for integers.
Sanjiv Gupta46800772009-06-05 14:43:12 +000061 case RTLIB::UDIV_I16: Basename = "udiv.i16"; break;
62 case RTLIB::UDIV_I32: Basename = "udiv.i32"; break;
63
Sanjiv Gupta003263b2009-06-16 16:17:35 +000064 // Signed Modulas for integers.
Sanjiv Gupta46800772009-06-05 14:43:12 +000065 case RTLIB::SREM_I16: Basename = "srem.i16"; break;
66 case RTLIB::SREM_I32: Basename = "srem.i32"; break;
Sanjiv Gupta003263b2009-06-16 16:17:35 +000067
68 // Unsigned Modulas for integers.
Sanjiv Gupta46800772009-06-05 14:43:12 +000069 case RTLIB::UREM_I16: Basename = "urem.i16"; break;
70 case RTLIB::UREM_I32: Basename = "urem.i32"; break;
Sanjiv Gupta63963292009-06-11 16:50:48 +000071
Sanjiv Gupta003263b2009-06-16 16:17:35 +000072 //////////////////////
73 // LIBCALLS FOR FLOATS
74 //////////////////////
75
76 // Float to signed integrals
77 case RTLIB::FPTOSINT_F32_I8: Basename = "f32_to_si32"; break;
78 case RTLIB::FPTOSINT_F32_I16: Basename = "f32_to_si32"; break;
79 case RTLIB::FPTOSINT_F32_I32: Basename = "f32_to_si32"; break;
80
81 // Signed integrals to float. char and int are first sign extended to i32
82 // before being converted to float, so an I8_F32 or I16_F32 isn't required.
83 case RTLIB::SINTTOFP_I32_F32: Basename = "si32_to_f32"; break;
84
85 // Float to Unsigned conversions.
86 // Signed conversion can be used for unsigned conversion as well.
87 // In signed and unsigned versions only the interpretation of the
88 // MSB is different. Bit representation remains the same.
89 case RTLIB::FPTOUINT_F32_I8: Basename = "f32_to_si32"; break;
90 case RTLIB::FPTOUINT_F32_I16: Basename = "f32_to_si32"; break;
91 case RTLIB::FPTOUINT_F32_I32: Basename = "f32_to_si32"; break;
92
93 // Unsigned to Float conversions. char and int are first zero extended
94 // before being converted to float.
95 case RTLIB::UINTTOFP_I32_F32: Basename = "ui32_to_f32"; break;
Sanjiv Gupta63963292009-06-11 16:50:48 +000096
Sanjiv Gupta003263b2009-06-16 16:17:35 +000097 // Floating point add, sub, mul, div.
Sanjiv Gupta63963292009-06-11 16:50:48 +000098 case RTLIB::ADD_F32: Basename = "add.f32"; break;
99 case RTLIB::SUB_F32: Basename = "sub.f32"; break;
100 case RTLIB::MUL_F32: Basename = "mul.f32"; break;
101 case RTLIB::DIV_F32: Basename = "div.f32"; break;
Sanjiv Guptacbd5f0a2009-06-25 18:12:06 +0000102
103 // Floating point comparison
104 case RTLIB::O_F32: Basename = "unordered.f32"; break;
105 case RTLIB::UO_F32: Basename = "unordered.f32"; break;
106 case RTLIB::OLE_F32: Basename = "le.f32"; break;
107 case RTLIB::OGE_F32: Basename = "ge.f32"; break;
108 case RTLIB::OLT_F32: Basename = "lt.f32"; break;
109 case RTLIB::OGT_F32: Basename = "gt.f32"; break;
110 case RTLIB::OEQ_F32: Basename = "eq.f32"; break;
111 case RTLIB::UNE_F32: Basename = "neq.f32"; break;
Sanjiv Guptae0b4b0e2009-05-11 08:52:04 +0000112 }
113
114 std::string prefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
115 std::string tagname = PAN::getTagName(PAN::LIBCALL);
116 std::string Fullname = prefix + tagname + Basename;
117
118 // The name has to live through program life.
Sanjiv Guptaaa939172009-07-31 07:35:57 +0000119 return createESName(Fullname);
120}
121
122// getStdLibCallName - Get the name for the standard library function.
123static const char *getStdLibCallName(unsigned opcode) {
124 std::string BaseName;
125 switch(opcode) {
126 case RTLIB::COS_F32: BaseName = "cos";
127 break;
128 case RTLIB::SIN_F32: BaseName = "sin";
129 break;
130 case RTLIB::MEMCPY: BaseName = "memcpy";
131 break;
132 case RTLIB::MEMSET: BaseName = "memset";
133 break;
134 case RTLIB::MEMMOVE: BaseName = "memmove";
135 break;
136 default: llvm_unreachable("do not know std lib call name");
137 }
138 std::string prefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
139 std::string LibCallName = prefix + BaseName;
140
141 // The name has to live through program life.
142 return createESName(LibCallName);
Sanjiv Guptae0b4b0e2009-05-11 08:52:04 +0000143}
144
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000145// PIC16TargetLowering Constructor.
146PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
Chris Lattnera87dea42009-07-31 18:48:30 +0000147 : TargetLowering(TM, new PIC16TargetObjectFile()), TmpSize(0) {
Sanjiv Gupta003263b2009-06-16 16:17:35 +0000148
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000149 Subtarget = &TM.getSubtarget<PIC16Subtarget>();
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000150
Owen Anderson825b72b2009-08-11 20:47:22 +0000151 addRegisterClass(MVT::i8, PIC16::GPRRegisterClass);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000152
Owen Anderson825b72b2009-08-11 20:47:22 +0000153 setShiftAmountType(MVT::i8);
Sanjiv Guptaaa939172009-07-31 07:35:57 +0000154
155 // Std lib call names
156 setLibcallName(RTLIB::COS_F32, getStdLibCallName(RTLIB::COS_F32));
157 setLibcallName(RTLIB::SIN_F32, getStdLibCallName(RTLIB::SIN_F32));
158 setLibcallName(RTLIB::MEMCPY, getStdLibCallName(RTLIB::MEMCPY));
159 setLibcallName(RTLIB::MEMSET, getStdLibCallName(RTLIB::MEMSET));
160 setLibcallName(RTLIB::MEMMOVE, getStdLibCallName(RTLIB::MEMMOVE));
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000161
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000162 // SRA library call names
Sanjiv Guptae0b4b0e2009-05-11 08:52:04 +0000163 setPIC16LibcallName(PIC16ISD::SRA_I8, getIntrinsicName(PIC16ISD::SRA_I8));
164 setLibcallName(RTLIB::SRA_I16, getIntrinsicName(RTLIB::SRA_I16));
165 setLibcallName(RTLIB::SRA_I32, getIntrinsicName(RTLIB::SRA_I32));
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000166
Sanjiv Gupta08b9b052009-01-21 05:44:05 +0000167 // SHL library call names
Sanjiv Guptae0b4b0e2009-05-11 08:52:04 +0000168 setPIC16LibcallName(PIC16ISD::SLL_I8, getIntrinsicName(PIC16ISD::SLL_I8));
169 setLibcallName(RTLIB::SHL_I16, getIntrinsicName(RTLIB::SHL_I16));
170 setLibcallName(RTLIB::SHL_I32, getIntrinsicName(RTLIB::SHL_I32));
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000171
172 // SRL library call names
Sanjiv Guptae0b4b0e2009-05-11 08:52:04 +0000173 setPIC16LibcallName(PIC16ISD::SRL_I8, getIntrinsicName(PIC16ISD::SRL_I8));
174 setLibcallName(RTLIB::SRL_I16, getIntrinsicName(RTLIB::SRL_I16));
175 setLibcallName(RTLIB::SRL_I32, getIntrinsicName(RTLIB::SRL_I32));
Sanjiv Gupta08b9b052009-01-21 05:44:05 +0000176
177 // MUL Library call names
Sanjiv Guptae0b4b0e2009-05-11 08:52:04 +0000178 setPIC16LibcallName(PIC16ISD::MUL_I8, getIntrinsicName(PIC16ISD::MUL_I8));
179 setLibcallName(RTLIB::MUL_I16, getIntrinsicName(RTLIB::MUL_I16));
180 setLibcallName(RTLIB::MUL_I32, getIntrinsicName(RTLIB::MUL_I32));
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000181
Sanjiv Gupta46800772009-06-05 14:43:12 +0000182 // Signed division lib call names
183 setLibcallName(RTLIB::SDIV_I16, getIntrinsicName(RTLIB::SDIV_I16));
184 setLibcallName(RTLIB::SDIV_I32, getIntrinsicName(RTLIB::SDIV_I32));
Sanjiv Gupta003263b2009-06-16 16:17:35 +0000185
Sanjiv Gupta46800772009-06-05 14:43:12 +0000186 // Unsigned division lib call names
187 setLibcallName(RTLIB::UDIV_I16, getIntrinsicName(RTLIB::UDIV_I16));
188 setLibcallName(RTLIB::UDIV_I32, getIntrinsicName(RTLIB::UDIV_I32));
189
190 // Signed remainder lib call names
191 setLibcallName(RTLIB::SREM_I16, getIntrinsicName(RTLIB::SREM_I16));
192 setLibcallName(RTLIB::SREM_I32, getIntrinsicName(RTLIB::SREM_I32));
Sanjiv Gupta003263b2009-06-16 16:17:35 +0000193
Sanjiv Gupta46800772009-06-05 14:43:12 +0000194 // Unsigned remainder lib call names
195 setLibcallName(RTLIB::UREM_I16, getIntrinsicName(RTLIB::UREM_I16));
196 setLibcallName(RTLIB::UREM_I32, getIntrinsicName(RTLIB::UREM_I32));
Sanjiv Gupta63963292009-06-11 16:50:48 +0000197
Sanjiv Gupta003263b2009-06-16 16:17:35 +0000198 // Floating point to signed int conversions.
199 setLibcallName(RTLIB::FPTOSINT_F32_I8,
200 getIntrinsicName(RTLIB::FPTOSINT_F32_I8));
201 setLibcallName(RTLIB::FPTOSINT_F32_I16,
202 getIntrinsicName(RTLIB::FPTOSINT_F32_I16));
Sanjiv Gupta63963292009-06-11 16:50:48 +0000203 setLibcallName(RTLIB::FPTOSINT_F32_I32,
204 getIntrinsicName(RTLIB::FPTOSINT_F32_I32));
Sanjiv Gupta003263b2009-06-16 16:17:35 +0000205
206 // Signed int to floats.
Sanjiv Gupta63963292009-06-11 16:50:48 +0000207 setLibcallName(RTLIB::SINTTOFP_I32_F32,
208 getIntrinsicName(RTLIB::SINTTOFP_I32_F32));
Sanjiv Gupta003263b2009-06-16 16:17:35 +0000209
210 // Floating points to unsigned ints.
211 setLibcallName(RTLIB::FPTOUINT_F32_I8,
212 getIntrinsicName(RTLIB::FPTOUINT_F32_I8));
213 setLibcallName(RTLIB::FPTOUINT_F32_I16,
214 getIntrinsicName(RTLIB::FPTOUINT_F32_I16));
215 setLibcallName(RTLIB::FPTOUINT_F32_I32,
216 getIntrinsicName(RTLIB::FPTOUINT_F32_I32));
217
218 // Unsigned int to floats.
219 setLibcallName(RTLIB::UINTTOFP_I32_F32,
220 getIntrinsicName(RTLIB::UINTTOFP_I32_F32));
221
222 // Floating point add, sub, mul ,div.
Sanjiv Gupta63963292009-06-11 16:50:48 +0000223 setLibcallName(RTLIB::ADD_F32, getIntrinsicName(RTLIB::ADD_F32));
224 setLibcallName(RTLIB::SUB_F32, getIntrinsicName(RTLIB::SUB_F32));
225 setLibcallName(RTLIB::MUL_F32, getIntrinsicName(RTLIB::MUL_F32));
226 setLibcallName(RTLIB::DIV_F32, getIntrinsicName(RTLIB::DIV_F32));
227
Sanjiv Guptacbd5f0a2009-06-25 18:12:06 +0000228 // Floationg point comparison
Sanjiv Gupta223497e2009-12-29 03:24:34 +0000229 setLibcallName(RTLIB::O_F32, getIntrinsicName(RTLIB::O_F32));
Sanjiv Guptacbd5f0a2009-06-25 18:12:06 +0000230 setLibcallName(RTLIB::UO_F32, getIntrinsicName(RTLIB::UO_F32));
231 setLibcallName(RTLIB::OLE_F32, getIntrinsicName(RTLIB::OLE_F32));
232 setLibcallName(RTLIB::OGE_F32, getIntrinsicName(RTLIB::OGE_F32));
233 setLibcallName(RTLIB::OLT_F32, getIntrinsicName(RTLIB::OLT_F32));
234 setLibcallName(RTLIB::OGT_F32, getIntrinsicName(RTLIB::OGT_F32));
235 setLibcallName(RTLIB::OEQ_F32, getIntrinsicName(RTLIB::OEQ_F32));
236 setLibcallName(RTLIB::UNE_F32, getIntrinsicName(RTLIB::UNE_F32));
237
238 // Return value comparisons of floating point calls.
239 setCmpLibcallCC(RTLIB::OEQ_F32, ISD::SETNE);
240 setCmpLibcallCC(RTLIB::UNE_F32, ISD::SETNE);
241 setCmpLibcallCC(RTLIB::OLT_F32, ISD::SETNE);
242 setCmpLibcallCC(RTLIB::OLE_F32, ISD::SETNE);
243 setCmpLibcallCC(RTLIB::OGE_F32, ISD::SETNE);
244 setCmpLibcallCC(RTLIB::OGT_F32, ISD::SETNE);
245 setCmpLibcallCC(RTLIB::UO_F32, ISD::SETNE);
246 setCmpLibcallCC(RTLIB::O_F32, ISD::SETEQ);
247
Owen Anderson825b72b2009-08-11 20:47:22 +0000248 setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
249 setOperationAction(ISD::ExternalSymbol, MVT::i16, Custom);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000250
Owen Anderson825b72b2009-08-11 20:47:22 +0000251 setOperationAction(ISD::LOAD, MVT::i8, Legal);
252 setOperationAction(ISD::LOAD, MVT::i16, Custom);
253 setOperationAction(ISD::LOAD, MVT::i32, Custom);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000254
Owen Anderson825b72b2009-08-11 20:47:22 +0000255 setOperationAction(ISD::STORE, MVT::i8, Legal);
256 setOperationAction(ISD::STORE, MVT::i16, Custom);
257 setOperationAction(ISD::STORE, MVT::i32, Custom);
258 setOperationAction(ISD::STORE, MVT::i64, Custom);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000259
Owen Anderson825b72b2009-08-11 20:47:22 +0000260 setOperationAction(ISD::ADDE, MVT::i8, Custom);
261 setOperationAction(ISD::ADDC, MVT::i8, Custom);
262 setOperationAction(ISD::SUBE, MVT::i8, Custom);
263 setOperationAction(ISD::SUBC, MVT::i8, Custom);
264 setOperationAction(ISD::SUB, MVT::i8, Custom);
265 setOperationAction(ISD::ADD, MVT::i8, Custom);
266 setOperationAction(ISD::ADD, MVT::i16, Custom);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000267
Owen Anderson825b72b2009-08-11 20:47:22 +0000268 setOperationAction(ISD::OR, MVT::i8, Custom);
269 setOperationAction(ISD::AND, MVT::i8, Custom);
270 setOperationAction(ISD::XOR, MVT::i8, Custom);
Sanjiv Gupta8f78fa82008-11-26 10:53:50 +0000271
Owen Anderson825b72b2009-08-11 20:47:22 +0000272 setOperationAction(ISD::FrameIndex, MVT::i16, Custom);
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000273
Owen Anderson825b72b2009-08-11 20:47:22 +0000274 setOperationAction(ISD::MUL, MVT::i8, Custom);
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000275
Owen Anderson825b72b2009-08-11 20:47:22 +0000276 setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand);
277 setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand);
278 setOperationAction(ISD::MULHU, MVT::i8, Expand);
279 setOperationAction(ISD::MULHS, MVT::i8, Expand);
Sanjiv Gupta08b9b052009-01-21 05:44:05 +0000280
Owen Anderson825b72b2009-08-11 20:47:22 +0000281 setOperationAction(ISD::SRA, MVT::i8, Custom);
282 setOperationAction(ISD::SHL, MVT::i8, Custom);
283 setOperationAction(ISD::SRL, MVT::i8, Custom);
Eli Friedmane91bf2c2009-07-17 07:03:00 +0000284
Owen Anderson825b72b2009-08-11 20:47:22 +0000285 setOperationAction(ISD::ROTL, MVT::i8, Expand);
286 setOperationAction(ISD::ROTR, MVT::i8, Expand);
Eli Friedmane91bf2c2009-07-17 07:03:00 +0000287
Owen Anderson825b72b2009-08-11 20:47:22 +0000288 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Sanjiv Gupta08b9b052009-01-21 05:44:05 +0000289
290 // PIC16 does not support shift parts
Owen Anderson825b72b2009-08-11 20:47:22 +0000291 setOperationAction(ISD::SRA_PARTS, MVT::i8, Expand);
292 setOperationAction(ISD::SHL_PARTS, MVT::i8, Expand);
293 setOperationAction(ISD::SRL_PARTS, MVT::i8, Expand);
Sanjiv Gupta08b9b052009-01-21 05:44:05 +0000294
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000295
296 // PIC16 does not have a SETCC, expand it to SELECT_CC.
Owen Anderson825b72b2009-08-11 20:47:22 +0000297 setOperationAction(ISD::SETCC, MVT::i8, Expand);
298 setOperationAction(ISD::SELECT, MVT::i8, Expand);
299 setOperationAction(ISD::BRCOND, MVT::Other, Expand);
300 setOperationAction(ISD::BRIND, MVT::Other, Expand);
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000301
Owen Anderson825b72b2009-08-11 20:47:22 +0000302 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
303 setOperationAction(ISD::BR_CC, MVT::i8, Custom);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000304
Owen Anderson825b72b2009-08-11 20:47:22 +0000305 //setOperationAction(ISD::TRUNCATE, MVT::i16, Custom);
306 setTruncStoreAction(MVT::i16, MVT::i8, Custom);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000307
308 // Now deduce the information based on the above mentioned
309 // actions
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000310 computeRegisterProperties();
311}
312
Sanjiv Gupta6b830e62009-03-20 13:42:20 +0000313// getOutFlag - Extract the flag result if the Op has it.
314static SDValue getOutFlag(SDValue &Op) {
315 // Flag is the last value of the node.
316 SDValue Flag = Op.getValue(Op.getNode()->getNumValues() - 1);
317
Owen Anderson825b72b2009-08-11 20:47:22 +0000318 assert (Flag.getValueType() == MVT::Flag
Sanjiv Gupta6b830e62009-03-20 13:42:20 +0000319 && "Node does not have an out Flag");
320
321 return Flag;
322}
Sanjiv Guptacae1b622009-04-06 10:54:50 +0000323// Get the TmpOffset for FrameIndex
Sanjiv Guptaa3613be2009-04-10 15:10:14 +0000324unsigned PIC16TargetLowering::GetTmpOffsetForFI(unsigned FI, unsigned size) {
Sanjiv Guptacae1b622009-04-06 10:54:50 +0000325 std::map<unsigned, unsigned>::iterator
326 MapIt = FiTmpOffsetMap.find(FI);
327 if (MapIt != FiTmpOffsetMap.end())
328 return MapIt->second;
329
330 // This FI (FrameIndex) is not yet mapped, so map it
331 FiTmpOffsetMap[FI] = TmpSize;
Sanjiv Guptaa3613be2009-04-10 15:10:14 +0000332 TmpSize += size;
333 return FiTmpOffsetMap[FI];
Sanjiv Guptacae1b622009-04-06 10:54:50 +0000334}
Sanjiv Gupta6b830e62009-03-20 13:42:20 +0000335
336// To extract chain value from the SDValue Nodes
337// This function will help to maintain the chain extracting
338// code at one place. In case of any change in future it will
339// help maintain the code.
340static SDValue getChain(SDValue &Op) {
341 SDValue Chain = Op.getValue(Op.getNode()->getNumValues() - 1);
342
343 // If the last value returned in Flag then the chain is
344 // second last value returned.
Owen Anderson825b72b2009-08-11 20:47:22 +0000345 if (Chain.getValueType() == MVT::Flag)
Sanjiv Gupta6b830e62009-03-20 13:42:20 +0000346 Chain = Op.getValue(Op.getNode()->getNumValues() - 2);
347
348 // All nodes may not produce a chain. Therefore following assert
349 // verifies that the node is returning a chain only.
Owen Anderson825b72b2009-08-11 20:47:22 +0000350 assert (Chain.getValueType() == MVT::Other
Sanjiv Gupta6b830e62009-03-20 13:42:20 +0000351 && "Node does not have a chain");
352
353 return Chain;
354}
355
356/// PopulateResults - Helper function to LowerOperation.
357/// If a node wants to return multiple results after lowering,
358/// it stuffs them into an array of SDValue called Results.
359
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000360static void PopulateResults(SDValue N, SmallVectorImpl<SDValue>&Results) {
361 if (N.getOpcode() == ISD::MERGE_VALUES) {
362 int NumResults = N.getNumOperands();
363 for( int i = 0; i < NumResults; i++)
364 Results.push_back(N.getOperand(i));
365 }
366 else
367 Results.push_back(N);
368}
369
Owen Anderson825b72b2009-08-11 20:47:22 +0000370MVT::SimpleValueType
Owen Andersone50ed302009-08-10 22:56:29 +0000371PIC16TargetLowering::getSetCCResultType(EVT ValType) const {
Owen Anderson825b72b2009-08-11 20:47:22 +0000372 return MVT::i8;
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000373}
374
Sanjiv Gupta8f17a362009-12-28 02:40:33 +0000375MVT::SimpleValueType
376PIC16TargetLowering::getCmpLibcallReturnType() const {
377 return MVT::i8;
378}
379
Sanjiv Guptae9d81f02009-03-20 14:10:20 +0000380/// The type legalizer framework of generating legalizer can generate libcalls
381/// only when the operand/result types are illegal.
382/// PIC16 needs to generate libcalls even for the legal types (i8) for some ops.
383/// For example an arithmetic right shift. These functions are used to lower
384/// such operations that generate libcall for legal types.
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000385
386void
Sanjiv Gupta08b9b052009-01-21 05:44:05 +0000387PIC16TargetLowering::setPIC16LibcallName(PIC16ISD::PIC16Libcall Call,
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000388 const char *Name) {
Sanjiv Guptae9d81f02009-03-20 14:10:20 +0000389 PIC16LibcallNames[Call] = Name;
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000390}
391
392const char *
Sanjiv Gupta08b9b052009-01-21 05:44:05 +0000393PIC16TargetLowering::getPIC16LibcallName(PIC16ISD::PIC16Libcall Call) {
Sanjiv Guptae9d81f02009-03-20 14:10:20 +0000394 return PIC16LibcallNames[Call];
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000395}
396
397SDValue
Sanjiv Gupta08b9b052009-01-21 05:44:05 +0000398PIC16TargetLowering::MakePIC16Libcall(PIC16ISD::PIC16Libcall Call,
Owen Andersone50ed302009-08-10 22:56:29 +0000399 EVT RetVT, const SDValue *Ops,
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000400 unsigned NumOps, bool isSigned,
Dale Johannesen7d2ad622009-01-30 23:10:59 +0000401 SelectionDAG &DAG, DebugLoc dl) {
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000402
Sanjiv Guptae9d81f02009-03-20 14:10:20 +0000403 TargetLowering::ArgListTy Args;
404 Args.reserve(NumOps);
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000405
Sanjiv Guptae9d81f02009-03-20 14:10:20 +0000406 TargetLowering::ArgListEntry Entry;
407 for (unsigned i = 0; i != NumOps; ++i) {
408 Entry.Node = Ops[i];
Owen Anderson23b9b192009-08-12 00:36:31 +0000409 Entry.Ty = Entry.Node.getValueType().getTypeForEVT(*DAG.getContext());
Sanjiv Guptae9d81f02009-03-20 14:10:20 +0000410 Entry.isSExt = isSigned;
411 Entry.isZExt = !isSigned;
412 Args.push_back(Entry);
413 }
Sanjiv Guptaa4186282009-08-11 01:51:55 +0000414
Owen Anderson825b72b2009-08-11 20:47:22 +0000415 SDValue Callee = DAG.getExternalSymbol(getPIC16LibcallName(Call), MVT::i16);
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000416
Owen Anderson23b9b192009-08-12 00:36:31 +0000417 const Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext());
Sanjiv Guptae9d81f02009-03-20 14:10:20 +0000418 std::pair<SDValue,SDValue> CallInfo =
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000419 LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false,
Dan Gohman98ca4f22009-08-05 01:29:28 +0000420 false, 0, CallingConv::C, false,
421 /*isReturnValueUsed=*/true,
Bill Wendling3ea3c242009-12-22 02:10:19 +0000422 Callee, Args, DAG, dl,
423 DAG.GetOrdering(DAG.getEntryNode().getNode()));
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000424
425 return CallInfo.first;
426}
427
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000428const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const {
429 switch (Opcode) {
430 default: return NULL;
431 case PIC16ISD::Lo: return "PIC16ISD::Lo";
432 case PIC16ISD::Hi: return "PIC16ISD::Hi";
433 case PIC16ISD::MTLO: return "PIC16ISD::MTLO";
434 case PIC16ISD::MTHI: return "PIC16ISD::MTHI";
Sanjiv Gupta7836fc12009-04-08 05:38:48 +0000435 case PIC16ISD::MTPCLATH: return "PIC16ISD::MTPCLATH";
436 case PIC16ISD::PIC16Connect: return "PIC16ISD::PIC16Connect";
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000437 case PIC16ISD::Banksel: return "PIC16ISD::Banksel";
438 case PIC16ISD::PIC16Load: return "PIC16ISD::PIC16Load";
Sanjiv Guptab84d5a42009-04-02 17:42:00 +0000439 case PIC16ISD::PIC16LdArg: return "PIC16ISD::PIC16LdArg";
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000440 case PIC16ISD::PIC16LdWF: return "PIC16ISD::PIC16LdWF";
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000441 case PIC16ISD::PIC16Store: return "PIC16ISD::PIC16Store";
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000442 case PIC16ISD::PIC16StWF: return "PIC16ISD::PIC16StWF";
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000443 case PIC16ISD::BCF: return "PIC16ISD::BCF";
444 case PIC16ISD::LSLF: return "PIC16ISD::LSLF";
445 case PIC16ISD::LRLF: return "PIC16ISD::LRLF";
446 case PIC16ISD::RLF: return "PIC16ISD::RLF";
447 case PIC16ISD::RRF: return "PIC16ISD::RRF";
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000448 case PIC16ISD::CALL: return "PIC16ISD::CALL";
Sanjiv Gupta7836fc12009-04-08 05:38:48 +0000449 case PIC16ISD::CALLW: return "PIC16ISD::CALLW";
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000450 case PIC16ISD::SUBCC: return "PIC16ISD::SUBCC";
451 case PIC16ISD::SELECT_ICC: return "PIC16ISD::SELECT_ICC";
452 case PIC16ISD::BRCOND: return "PIC16ISD::BRCOND";
Dan Gohman98ca4f22009-08-05 01:29:28 +0000453 case PIC16ISD::RET: return "PIC16ISD::RET";
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000454 case PIC16ISD::Dummy: return "PIC16ISD::Dummy";
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000455 }
456}
457
Duncan Sands1607f052008-12-01 11:39:25 +0000458void PIC16TargetLowering::ReplaceNodeResults(SDNode *N,
459 SmallVectorImpl<SDValue>&Results,
460 SelectionDAG &DAG) {
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000461
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000462 switch (N->getOpcode()) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000463 case ISD::GlobalAddress:
Duncan Sands1607f052008-12-01 11:39:25 +0000464 Results.push_back(ExpandGlobalAddress(N, DAG));
465 return;
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000466 case ISD::ExternalSymbol:
467 Results.push_back(ExpandExternalSymbol(N, DAG));
468 return;
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000469 case ISD::STORE:
Duncan Sands1607f052008-12-01 11:39:25 +0000470 Results.push_back(ExpandStore(N, DAG));
471 return;
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000472 case ISD::LOAD:
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000473 PopulateResults(ExpandLoad(N, DAG), Results);
Duncan Sands1607f052008-12-01 11:39:25 +0000474 return;
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000475 case ISD::ADD:
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000476 // Results.push_back(ExpandAdd(N, DAG));
Duncan Sands1607f052008-12-01 11:39:25 +0000477 return;
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000478 case ISD::FrameIndex:
479 Results.push_back(ExpandFrameIndex(N, DAG));
480 return;
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000481 default:
482 assert (0 && "not implemented");
Duncan Sands1607f052008-12-01 11:39:25 +0000483 return;
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000484 }
485}
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000486
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000487SDValue PIC16TargetLowering::ExpandFrameIndex(SDNode *N, SelectionDAG &DAG) {
488
Owen Anderson825b72b2009-08-11 20:47:22 +0000489 // Currently handling FrameIndex of size MVT::i16 only
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000490 // One example of this scenario is when return value is written on
491 // FrameIndex#0
492
Owen Anderson825b72b2009-08-11 20:47:22 +0000493 if (N->getValueType(0) != MVT::i16)
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000494 return SDValue();
495
496 // Expand the FrameIndex into ExternalSymbol and a Constant node
497 // The constant will represent the frame index number
498 // Get the current function frame
499 MachineFunction &MF = DAG.getMachineFunction();
500 const Function *Func = MF.getFunction();
501 const std::string Name = Func->getName();
Dale Johannesende064702009-02-06 21:50:26 +0000502
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000503 FrameIndexSDNode *FR = dyn_cast<FrameIndexSDNode>(SDValue(N,0));
Dale Johannesende064702009-02-06 21:50:26 +0000504 // FIXME there isn't really debug info here
505 DebugLoc dl = FR->getDebugLoc();
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000506
Sanjiv Gupta85be4082009-04-14 02:49:52 +0000507 // Expand FrameIndex like GlobalAddress and ExternalSymbol
508 // Also use Offset field for lo and hi parts. The default
509 // offset is zero.
Sanjiv Gupta892c8ca2009-06-03 15:31:12 +0000510
Sanjiv Gupta892c8ca2009-06-03 15:31:12 +0000511 SDValue ES;
512 int FrameOffset;
513 SDValue FI = SDValue(N,0);
514 LegalizeFrameIndex(FI, DAG, ES, FrameOffset);
Owen Anderson825b72b2009-08-11 20:47:22 +0000515 SDValue Offset = DAG.getConstant(FrameOffset, MVT::i8);
516 SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, ES, Offset);
517 SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, ES, Offset);
Sanjiv Gupta892c8ca2009-06-03 15:31:12 +0000518 return DAG.getNode(ISD::BUILD_PAIR, dl, N->getValueType(0), Lo, Hi);
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000519}
520
521
522SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000523 StoreSDNode *St = cast<StoreSDNode>(N);
524 SDValue Chain = St->getChain();
525 SDValue Src = St->getValue();
526 SDValue Ptr = St->getBasePtr();
Owen Andersone50ed302009-08-10 22:56:29 +0000527 EVT ValueType = Src.getValueType();
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000528 unsigned StoreOffset = 0;
Dale Johannesende064702009-02-06 21:50:26 +0000529 DebugLoc dl = N->getDebugLoc();
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000530
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000531 SDValue PtrLo, PtrHi;
Dale Johannesenb300d2a2009-02-07 00:55:49 +0000532 LegalizeAddress(Ptr, DAG, PtrLo, PtrHi, StoreOffset, dl);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000533
Owen Anderson825b72b2009-08-11 20:47:22 +0000534 if (ValueType == MVT::i8) {
535 return DAG.getNode (PIC16ISD::PIC16Store, dl, MVT::Other, Chain, Src,
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000536 PtrLo, PtrHi,
Owen Anderson825b72b2009-08-11 20:47:22 +0000537 DAG.getConstant (0 + StoreOffset, MVT::i8));
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000538 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000539 else if (ValueType == MVT::i16) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000540 // Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR.
541 SDValue SrcLo, SrcHi;
542 GetExpandedParts(Src, DAG, SrcLo, SrcHi);
543 SDValue ChainLo = Chain, ChainHi = Chain;
Dan Gohman6ff5de42009-08-26 16:06:11 +0000544 // FIXME: This makes unsafe assumptions. The Chain may be a TokenFactor
545 // created for an unrelated purpose, in which case it may not have
546 // exactly two operands. Also, even if it does have two operands, they
547 // may not be the low and high parts of an aligned load that was split.
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000548 if (Chain.getOpcode() == ISD::TokenFactor) {
549 ChainLo = Chain.getOperand(0);
550 ChainHi = Chain.getOperand(1);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000551 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000552 SDValue Store1 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other,
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000553 ChainLo,
554 SrcLo, PtrLo, PtrHi,
Owen Anderson825b72b2009-08-11 20:47:22 +0000555 DAG.getConstant (0 + StoreOffset, MVT::i8));
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000556
Owen Anderson825b72b2009-08-11 20:47:22 +0000557 SDValue Store2 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, ChainHi,
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000558 SrcHi, PtrLo, PtrHi,
Owen Anderson825b72b2009-08-11 20:47:22 +0000559 DAG.getConstant (1 + StoreOffset, MVT::i8));
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000560
Owen Anderson825b72b2009-08-11 20:47:22 +0000561 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, getChain(Store1),
Duncan Sands1607f052008-12-01 11:39:25 +0000562 getChain(Store2));
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000563 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000564 else if (ValueType == MVT::i32) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000565 // Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR.
566 SDValue SrcLo, SrcHi;
567 GetExpandedParts(Src, DAG, SrcLo, SrcHi);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000568
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000569 // Get the expanded parts of each of SrcLo and SrcHi.
570 SDValue SrcLo1, SrcLo2, SrcHi1, SrcHi2;
571 GetExpandedParts(SrcLo, DAG, SrcLo1, SrcLo2);
572 GetExpandedParts(SrcHi, DAG, SrcHi1, SrcHi2);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000573
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000574 SDValue ChainLo = Chain, ChainHi = Chain;
Dan Gohman6ff5de42009-08-26 16:06:11 +0000575 // FIXME: This makes unsafe assumptions; see the FIXME above.
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000576 if (Chain.getOpcode() == ISD::TokenFactor) {
577 ChainLo = Chain.getOperand(0);
578 ChainHi = Chain.getOperand(1);
579 }
580 SDValue ChainLo1 = ChainLo, ChainLo2 = ChainLo, ChainHi1 = ChainHi,
581 ChainHi2 = ChainHi;
Dan Gohman6ff5de42009-08-26 16:06:11 +0000582 // FIXME: This makes unsafe assumptions; see the FIXME above.
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000583 if (ChainLo.getOpcode() == ISD::TokenFactor) {
584 ChainLo1 = ChainLo.getOperand(0);
585 ChainLo2 = ChainLo.getOperand(1);
586 }
Dan Gohman6ff5de42009-08-26 16:06:11 +0000587 // FIXME: This makes unsafe assumptions; see the FIXME above.
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000588 if (ChainHi.getOpcode() == ISD::TokenFactor) {
589 ChainHi1 = ChainHi.getOperand(0);
590 ChainHi2 = ChainHi.getOperand(1);
591 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000592 SDValue Store1 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other,
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000593 ChainLo1,
594 SrcLo1, PtrLo, PtrHi,
Owen Anderson825b72b2009-08-11 20:47:22 +0000595 DAG.getConstant (0 + StoreOffset, MVT::i8));
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000596
Owen Anderson825b72b2009-08-11 20:47:22 +0000597 SDValue Store2 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, ChainLo2,
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000598 SrcLo2, PtrLo, PtrHi,
Owen Anderson825b72b2009-08-11 20:47:22 +0000599 DAG.getConstant (1 + StoreOffset, MVT::i8));
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000600
Owen Anderson825b72b2009-08-11 20:47:22 +0000601 SDValue Store3 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, ChainHi1,
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000602 SrcHi1, PtrLo, PtrHi,
Owen Anderson825b72b2009-08-11 20:47:22 +0000603 DAG.getConstant (2 + StoreOffset, MVT::i8));
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000604
Owen Anderson825b72b2009-08-11 20:47:22 +0000605 SDValue Store4 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, ChainHi2,
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000606 SrcHi2, PtrLo, PtrHi,
Owen Anderson825b72b2009-08-11 20:47:22 +0000607 DAG.getConstant (3 + StoreOffset, MVT::i8));
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000608
Owen Anderson825b72b2009-08-11 20:47:22 +0000609 SDValue RetLo = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Dale Johannesende064702009-02-06 21:50:26 +0000610 getChain(Store1), getChain(Store2));
Owen Anderson825b72b2009-08-11 20:47:22 +0000611 SDValue RetHi = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Dale Johannesende064702009-02-06 21:50:26 +0000612 getChain(Store3), getChain(Store4));
Owen Anderson825b72b2009-08-11 20:47:22 +0000613 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, RetLo, RetHi);
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000614
Owen Anderson825b72b2009-08-11 20:47:22 +0000615 } else if (ValueType == MVT::i64) {
Sanjiv Guptaada097a2009-08-04 17:59:16 +0000616 SDValue SrcLo, SrcHi;
617 GetExpandedParts(Src, DAG, SrcLo, SrcHi);
618 SDValue ChainLo = Chain, ChainHi = Chain;
Dan Gohman6ff5de42009-08-26 16:06:11 +0000619 // FIXME: This makes unsafe assumptions; see the FIXME above.
Sanjiv Guptaada097a2009-08-04 17:59:16 +0000620 if (Chain.getOpcode() == ISD::TokenFactor) {
621 ChainLo = Chain.getOperand(0);
622 ChainHi = Chain.getOperand(1);
623 }
624 SDValue Store1 = DAG.getStore(ChainLo, dl, SrcLo, Ptr, NULL,
David Greene74a6a792010-02-15 16:56:34 +0000625 0 + StoreOffset, false, false, 0);
Sanjiv Guptaada097a2009-08-04 17:59:16 +0000626
627 Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr,
628 DAG.getConstant(4, Ptr.getValueType()));
629 SDValue Store2 = DAG.getStore(ChainHi, dl, SrcHi, Ptr, NULL,
David Greene74a6a792010-02-15 16:56:34 +0000630 1 + StoreOffset, false, false, 0);
Sanjiv Guptaada097a2009-08-04 17:59:16 +0000631
Owen Anderson825b72b2009-08-11 20:47:22 +0000632 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store1,
Sanjiv Guptaada097a2009-08-04 17:59:16 +0000633 Store2);
634 } else {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000635 assert (0 && "value type not supported");
Duncan Sands1607f052008-12-01 11:39:25 +0000636 return SDValue();
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000637 }
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000638}
639
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000640SDValue PIC16TargetLowering::ExpandExternalSymbol(SDNode *N, SelectionDAG &DAG)
641{
642 ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(SDValue(N, 0));
Dale Johannesende064702009-02-06 21:50:26 +0000643 // FIXME there isn't really debug info here
644 DebugLoc dl = ES->getDebugLoc();
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000645
Owen Anderson825b72b2009-08-11 20:47:22 +0000646 SDValue TES = DAG.getTargetExternalSymbol(ES->getSymbol(), MVT::i8);
647 SDValue Offset = DAG.getConstant(0, MVT::i8);
648 SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, TES, Offset);
649 SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, TES, Offset);
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000650
Owen Anderson825b72b2009-08-11 20:47:22 +0000651 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16, Lo, Hi);
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000652}
653
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000654// ExpandGlobalAddress -
Duncan Sands1607f052008-12-01 11:39:25 +0000655SDValue PIC16TargetLowering::ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000656 GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(SDValue(N, 0));
Dale Johannesende064702009-02-06 21:50:26 +0000657 // FIXME there isn't really debug info here
658 DebugLoc dl = G->getDebugLoc();
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000659
Owen Anderson825b72b2009-08-11 20:47:22 +0000660 SDValue TGA = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i8,
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000661 G->getOffset());
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000662
Owen Anderson825b72b2009-08-11 20:47:22 +0000663 SDValue Offset = DAG.getConstant(0, MVT::i8);
664 SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, TGA, Offset);
665 SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, TGA, Offset);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000666
Owen Anderson825b72b2009-08-11 20:47:22 +0000667 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16, Lo, Hi);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000668}
669
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000670bool PIC16TargetLowering::isDirectAddress(const SDValue &Op) {
671 assert (Op.getNode() != NULL && "Can't operate on NULL SDNode!!");
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000672
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000673 if (Op.getOpcode() == ISD::BUILD_PAIR) {
674 if (Op.getOperand(0).getOpcode() == PIC16ISD::Lo)
675 return true;
676 }
677 return false;
678}
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000679
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000680// Return true if DirectAddress is in ROM_SPACE
681bool PIC16TargetLowering::isRomAddress(const SDValue &Op) {
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000682
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000683 // RomAddress is a GlobalAddress in ROM_SPACE_
684 // If the Op is not a GlobalAddress return NULL without checking
685 // anything further.
686 if (!isDirectAddress(Op))
687 return false;
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000688
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000689 // Its a GlobalAddress.
690 // It is BUILD_PAIR((PIC16Lo TGA), (PIC16Hi TGA)) and Op is BUILD_PAIR
691 SDValue TGA = Op.getOperand(0).getOperand(0);
692 GlobalAddressSDNode *GSDN = dyn_cast<GlobalAddressSDNode>(TGA);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000693
Sanjiv Guptaa3518a12009-04-29 04:43:24 +0000694 if (GSDN->getAddressSpace() == PIC16ISD::ROM_SPACE)
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000695 return true;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000696
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000697 // Any other address space return it false
698 return false;
699}
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000700
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000701
Sanjiv Gupta6b830e62009-03-20 13:42:20 +0000702// GetExpandedParts - This function is on the similiar lines as
703// the GetExpandedInteger in type legalizer is. This returns expanded
704// parts of Op in Lo and Hi.
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000705
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000706void PIC16TargetLowering::GetExpandedParts(SDValue Op, SelectionDAG &DAG,
707 SDValue &Lo, SDValue &Hi) {
708 SDNode *N = Op.getNode();
Dale Johannesened2eee62009-02-06 01:31:28 +0000709 DebugLoc dl = N->getDebugLoc();
Owen Anderson23b9b192009-08-12 00:36:31 +0000710 EVT NewVT = getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000711
Sanjiv Gupta6b830e62009-03-20 13:42:20 +0000712 // Extract the lo component.
713 Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NewVT, Op,
Owen Anderson825b72b2009-08-11 20:47:22 +0000714 DAG.getConstant(0, MVT::i8));
Bill Wendling51b16f42009-05-30 01:09:53 +0000715
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000716 // extract the hi component
Sanjiv Gupta6b830e62009-03-20 13:42:20 +0000717 Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NewVT, Op,
Owen Anderson825b72b2009-08-11 20:47:22 +0000718 DAG.getConstant(1, MVT::i8));
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000719}
720
721// Legalize FrameIndex into ExternalSymbol and offset.
722void
723PIC16TargetLowering::LegalizeFrameIndex(SDValue Op, SelectionDAG &DAG,
724 SDValue &ES, int &Offset) {
725
726 MachineFunction &MF = DAG.getMachineFunction();
727 const Function *Func = MF.getFunction();
Sanjiv Guptab84d5a42009-04-02 17:42:00 +0000728 MachineFrameInfo *MFI = MF.getFrameInfo();
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000729 const std::string Name = Func->getName();
730
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000731 FrameIndexSDNode *FR = dyn_cast<FrameIndexSDNode>(Op);
Sanjiv Guptab84d5a42009-04-02 17:42:00 +0000732
733 // FrameIndices are not stack offsets. But they represent the request
734 // for space on stack. That space requested may be more than one byte.
735 // Therefore, to calculate the stack offset that a FrameIndex aligns
736 // with, we need to traverse all the FrameIndices available earlier in
737 // the list and add their requested size.
738 unsigned FIndex = FR->getIndex();
Sanjiv Gupta211f3622009-05-10 05:23:47 +0000739 const char *tmpName;
Sanjiv Guptae16178b2009-04-21 05:54:51 +0000740 if (FIndex < ReservedFrameCount) {
Sanjiv Gupta211f3622009-05-10 05:23:47 +0000741 tmpName = createESName(PAN::getFrameLabel(Name));
Owen Anderson825b72b2009-08-11 20:47:22 +0000742 ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
Sanjiv Guptae16178b2009-04-21 05:54:51 +0000743 Offset = 0;
744 for (unsigned i=0; i<FIndex ; ++i) {
745 Offset += MFI->getObjectSize(i);
746 }
747 } else {
748 // FrameIndex has been made for some temporary storage
Sanjiv Gupta211f3622009-05-10 05:23:47 +0000749 tmpName = createESName(PAN::getTempdataLabel(Name));
Owen Anderson825b72b2009-08-11 20:47:22 +0000750 ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
Sanjiv Guptae16178b2009-04-21 05:54:51 +0000751 Offset = GetTmpOffsetForFI(FIndex, MFI->getObjectSize(FIndex));
Sanjiv Guptab84d5a42009-04-02 17:42:00 +0000752 }
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000753
754 return;
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000755}
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000756
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000757// This function legalizes the PIC16 Addresses. If the Pointer is
758// -- Direct address variable residing
759// --> then a Banksel for that variable will be created.
760// -- Rom variable
761// --> then it will be treated as an indirect address.
762// -- Indirect address
763// --> then the address will be loaded into FSR
764// -- ADD with constant operand
765// --> then constant operand of ADD will be returned as Offset
766// and non-constant operand of ADD will be treated as pointer.
767// Returns the high and lo part of the address, and the offset(in case of ADD).
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000768
Sanjiv Guptacae1b622009-04-06 10:54:50 +0000769void PIC16TargetLowering::LegalizeAddress(SDValue Ptr, SelectionDAG &DAG,
770 SDValue &Lo, SDValue &Hi,
771 unsigned &Offset, DebugLoc dl) {
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000772
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000773 // Offset, by default, should be 0
774 Offset = 0;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000775
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000776 // If the pointer is ADD with constant,
777 // return the constant value as the offset
778 if (Ptr.getOpcode() == ISD::ADD) {
779 SDValue OperLeft = Ptr.getOperand(0);
780 SDValue OperRight = Ptr.getOperand(1);
Sanjiv Guptaae992272009-06-23 07:10:19 +0000781 if ((OperLeft.getOpcode() == ISD::Constant) &&
782 (dyn_cast<ConstantSDNode>(OperLeft)->getZExtValue() < 32 )) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000783 Offset = dyn_cast<ConstantSDNode>(OperLeft)->getZExtValue();
784 Ptr = OperRight;
Sanjiv Guptaae992272009-06-23 07:10:19 +0000785 } else if ((OperRight.getOpcode() == ISD::Constant) &&
786 (dyn_cast<ConstantSDNode>(OperRight)->getZExtValue() < 32 )){
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000787 Offset = dyn_cast<ConstantSDNode>(OperRight)->getZExtValue();
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000788 Ptr = OperLeft;
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000789 }
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000790 }
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000791
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000792 // If the pointer is Type i8 and an external symbol
793 // then treat it as direct address.
794 // One example for such case is storing and loading
795 // from function frame during a call
Owen Anderson825b72b2009-08-11 20:47:22 +0000796 if (Ptr.getValueType() == MVT::i8) {
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000797 switch (Ptr.getOpcode()) {
798 case ISD::TargetExternalSymbol:
799 Lo = Ptr;
Owen Anderson825b72b2009-08-11 20:47:22 +0000800 Hi = DAG.getConstant(1, MVT::i8);
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000801 return;
802 }
803 }
804
Sanjiv Gupta85be4082009-04-14 02:49:52 +0000805 // Expansion of FrameIndex has Lo/Hi parts
806 if (isDirectAddress(Ptr)) {
807 SDValue TFI = Ptr.getOperand(0).getOperand(0);
Sanjiv Gupta892c8ca2009-06-03 15:31:12 +0000808 int FrameOffset;
Sanjiv Gupta85be4082009-04-14 02:49:52 +0000809 if (TFI.getOpcode() == ISD::TargetFrameIndex) {
Sanjiv Gupta85be4082009-04-14 02:49:52 +0000810 LegalizeFrameIndex(TFI, DAG, Lo, FrameOffset);
Owen Anderson825b72b2009-08-11 20:47:22 +0000811 Hi = DAG.getConstant(1, MVT::i8);
Sanjiv Gupta85be4082009-04-14 02:49:52 +0000812 Offset += FrameOffset;
813 return;
Sanjiv Gupta892c8ca2009-06-03 15:31:12 +0000814 } else if (TFI.getOpcode() == ISD::TargetExternalSymbol) {
815 // FrameIndex has already been expanded.
816 // Now just make use of its expansion
817 Lo = TFI;
Owen Anderson825b72b2009-08-11 20:47:22 +0000818 Hi = DAG.getConstant(1, MVT::i8);
Sanjiv Gupta892c8ca2009-06-03 15:31:12 +0000819 SDValue FOffset = Ptr.getOperand(0).getOperand(1);
820 assert (FOffset.getOpcode() == ISD::Constant &&
821 "Invalid operand of PIC16ISD::Lo");
822 Offset += dyn_cast<ConstantSDNode>(FOffset)->getZExtValue();
823 return;
Sanjiv Gupta85be4082009-04-14 02:49:52 +0000824 }
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000825 }
826
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000827 if (isDirectAddress(Ptr) && !isRomAddress(Ptr)) {
828 // Direct addressing case for RAM variables. The Hi part is constant
829 // and the Lo part is the TGA itself.
830 Lo = Ptr.getOperand(0).getOperand(0);
831
832 // For direct addresses Hi is a constant. Value 1 for the constant
833 // signifies that banksel needs to generated for it. Value 0 for
834 // the constant signifies that banksel does not need to be generated
835 // for it. Mark it as 1 now and optimize later.
Owen Anderson825b72b2009-08-11 20:47:22 +0000836 Hi = DAG.getConstant(1, MVT::i8);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000837 return;
838 }
839
840 // Indirect addresses. Get the hi and lo parts of ptr.
841 GetExpandedParts(Ptr, DAG, Lo, Hi);
842
843 // Put the hi and lo parts into FSR.
Owen Anderson825b72b2009-08-11 20:47:22 +0000844 Lo = DAG.getNode(PIC16ISD::MTLO, dl, MVT::i8, Lo);
845 Hi = DAG.getNode(PIC16ISD::MTHI, dl, MVT::i8, Hi);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000846
847 return;
848}
849
Duncan Sands1607f052008-12-01 11:39:25 +0000850SDValue PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000851 LoadSDNode *LD = dyn_cast<LoadSDNode>(SDValue(N, 0));
852 SDValue Chain = LD->getChain();
853 SDValue Ptr = LD->getBasePtr();
Dale Johannesen2fabcb22009-02-05 01:01:16 +0000854 DebugLoc dl = LD->getDebugLoc();
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000855
856 SDValue Load, Offset;
857 SDVTList Tys;
Owen Andersone50ed302009-08-10 22:56:29 +0000858 EVT VT, NewVT;
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000859 SDValue PtrLo, PtrHi;
860 unsigned LoadOffset;
861
862 // Legalize direct/indirect addresses. This will give the lo and hi parts
863 // of the address and the offset.
Dale Johannesenb300d2a2009-02-07 00:55:49 +0000864 LegalizeAddress(Ptr, DAG, PtrLo, PtrHi, LoadOffset, dl);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000865
866 // Load from the pointer (direct address or FSR)
867 VT = N->getValueType(0);
868 unsigned NumLoads = VT.getSizeInBits() / 8;
869 std::vector<SDValue> PICLoads;
870 unsigned iter;
Owen Andersone50ed302009-08-10 22:56:29 +0000871 EVT MemVT = LD->getMemoryVT();
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000872 if(ISD::isNON_EXTLoad(N)) {
873 for (iter=0; iter<NumLoads ; ++iter) {
874 // Add the pointer offset if any
Owen Anderson825b72b2009-08-11 20:47:22 +0000875 Offset = DAG.getConstant(iter + LoadOffset, MVT::i8);
876 Tys = DAG.getVTList(MVT::i8, MVT::Other);
Dale Johannesen2fabcb22009-02-05 01:01:16 +0000877 Load = DAG.getNode(PIC16ISD::PIC16Load, dl, Tys, Chain, PtrLo, PtrHi,
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000878 Offset);
879 PICLoads.push_back(Load);
880 }
881 } else {
882 // If it is extended load then use PIC16Load for Memory Bytes
883 // and for all extended bytes perform action based on type of
884 // extention - i.e. SignExtendedLoad or ZeroExtendedLoad
885
886
887 // For extended loads this is the memory value type
888 // i.e. without any extension
Owen Andersone50ed302009-08-10 22:56:29 +0000889 EVT MemVT = LD->getMemoryVT();
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000890 unsigned MemBytes = MemVT.getSizeInBits() / 8;
Owen Anderson825b72b2009-08-11 20:47:22 +0000891 // if MVT::i1 is extended to MVT::i8 then MemBytes will be zero
Sanjiv Gupta1d2e6ed2009-07-03 07:58:59 +0000892 // So set it to one
893 if (MemBytes == 0) MemBytes = 1;
894
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000895 unsigned ExtdBytes = VT.getSizeInBits() / 8;
Owen Anderson825b72b2009-08-11 20:47:22 +0000896 Offset = DAG.getConstant(LoadOffset, MVT::i8);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000897
Owen Anderson825b72b2009-08-11 20:47:22 +0000898 Tys = DAG.getVTList(MVT::i8, MVT::Other);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000899 // For MemBytes generate PIC16Load with proper offset
Sanjiv Gupta1d2e6ed2009-07-03 07:58:59 +0000900 for (iter=0; iter < MemBytes; ++iter) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000901 // Add the pointer offset if any
Owen Anderson825b72b2009-08-11 20:47:22 +0000902 Offset = DAG.getConstant(iter + LoadOffset, MVT::i8);
Dale Johannesen2fabcb22009-02-05 01:01:16 +0000903 Load = DAG.getNode(PIC16ISD::PIC16Load, dl, Tys, Chain, PtrLo, PtrHi,
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000904 Offset);
905 PICLoads.push_back(Load);
906 }
907
908 // For SignExtendedLoad
909 if (ISD::isSEXTLoad(N)) {
910 // For all ExtdBytes use the Right Shifted(Arithmetic) Value of the
911 // highest MemByte
Owen Anderson825b72b2009-08-11 20:47:22 +0000912 SDValue SRA = DAG.getNode(ISD::SRA, dl, MVT::i8, Load,
913 DAG.getConstant(7, MVT::i8));
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000914 for (iter=MemBytes; iter<ExtdBytes; ++iter) {
915 PICLoads.push_back(SRA);
916 }
Sanjiv Gupta892c8ca2009-06-03 15:31:12 +0000917 } else if (ISD::isZEXTLoad(N) || ISD::isEXTLoad(N)) {
918 //} else if (ISD::isZEXTLoad(N)) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000919 // ZeroExtendedLoad -- For all ExtdBytes use constant 0
Owen Anderson825b72b2009-08-11 20:47:22 +0000920 SDValue ConstZero = DAG.getConstant(0, MVT::i8);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000921 for (iter=MemBytes; iter<ExtdBytes; ++iter) {
922 PICLoads.push_back(ConstZero);
923 }
924 }
925 }
926 SDValue BP;
927
Owen Anderson825b72b2009-08-11 20:47:22 +0000928 if (VT == MVT::i8) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000929 // Operand of Load is illegal -- Load itself is legal
Duncan Sands1607f052008-12-01 11:39:25 +0000930 return PICLoads[0];
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000931 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000932 else if (VT == MVT::i16) {
Dale Johannesen2fabcb22009-02-05 01:01:16 +0000933 BP = DAG.getNode(ISD::BUILD_PAIR, dl, VT, PICLoads[0], PICLoads[1]);
Sanjiv Gupta917283a2009-12-28 04:53:24 +0000934 if ((MemVT == MVT::i8) || (MemVT == MVT::i1))
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000935 Chain = getChain(PICLoads[0]);
936 else
Owen Anderson825b72b2009-08-11 20:47:22 +0000937 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Dale Johannesen2fabcb22009-02-05 01:01:16 +0000938 getChain(PICLoads[0]), getChain(PICLoads[1]));
Owen Anderson825b72b2009-08-11 20:47:22 +0000939 } else if (VT == MVT::i32) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000940 SDValue BPs[2];
Owen Anderson825b72b2009-08-11 20:47:22 +0000941 BPs[0] = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16,
Dale Johannesen2fabcb22009-02-05 01:01:16 +0000942 PICLoads[0], PICLoads[1]);
Owen Anderson825b72b2009-08-11 20:47:22 +0000943 BPs[1] = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16,
Dale Johannesen2fabcb22009-02-05 01:01:16 +0000944 PICLoads[2], PICLoads[3]);
945 BP = DAG.getNode(ISD::BUILD_PAIR, dl, VT, BPs[0], BPs[1]);
Sanjiv Gupta917283a2009-12-28 04:53:24 +0000946 if ((MemVT == MVT::i8) || (MemVT == MVT::i1))
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000947 Chain = getChain(PICLoads[0]);
Owen Anderson825b72b2009-08-11 20:47:22 +0000948 else if (MemVT == MVT::i16)
949 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Dale Johannesen2fabcb22009-02-05 01:01:16 +0000950 getChain(PICLoads[0]), getChain(PICLoads[1]));
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000951 else {
952 SDValue Chains[2];
Owen Anderson825b72b2009-08-11 20:47:22 +0000953 Chains[0] = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000954 getChain(PICLoads[0]), getChain(PICLoads[1]));
Owen Anderson825b72b2009-08-11 20:47:22 +0000955 Chains[1] = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000956 getChain(PICLoads[2]), getChain(PICLoads[3]));
Owen Anderson825b72b2009-08-11 20:47:22 +0000957 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Dale Johannesen2fabcb22009-02-05 01:01:16 +0000958 Chains[0], Chains[1]);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000959 }
960 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000961 Tys = DAG.getVTList(VT, MVT::Other);
Dale Johannesen2fabcb22009-02-05 01:01:16 +0000962 return DAG.getNode(ISD::MERGE_VALUES, dl, Tys, BP, Chain);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000963}
964
Sanjiv Gupta08b9b052009-01-21 05:44:05 +0000965SDValue PIC16TargetLowering::LowerShift(SDValue Op, SelectionDAG &DAG) {
966 // We should have handled larger operands in type legalizer itself.
Owen Anderson825b72b2009-08-11 20:47:22 +0000967 assert (Op.getValueType() == MVT::i8 && "illegal shift to lower");
Sanjiv Gupta08b9b052009-01-21 05:44:05 +0000968
969 SDNode *N = Op.getNode();
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000970 SDValue Value = N->getOperand(0);
971 SDValue Amt = N->getOperand(1);
Sanjiv Gupta08b9b052009-01-21 05:44:05 +0000972 PIC16ISD::PIC16Libcall CallCode;
973 switch (N->getOpcode()) {
974 case ISD::SRA:
975 CallCode = PIC16ISD::SRA_I8;
976 break;
977 case ISD::SHL:
978 CallCode = PIC16ISD::SLL_I8;
979 break;
980 case ISD::SRL:
981 CallCode = PIC16ISD::SRL_I8;
982 break;
983 default:
984 assert ( 0 && "This shift is not implemented yet.");
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000985 return SDValue();
986 }
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000987 SmallVector<SDValue, 2> Ops(2);
988 Ops[0] = Value;
989 Ops[1] = Amt;
Dale Johannesen7d2ad622009-01-30 23:10:59 +0000990 SDValue Call = MakePIC16Libcall(CallCode, N->getValueType(0), &Ops[0], 2,
991 true, DAG, N->getDebugLoc());
Sanjiv Gupta1b046942009-01-13 19:18:47 +0000992 return Call;
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000993}
994
Sanjiv Gupta8e14eab2009-07-27 02:44:46 +0000995SDValue PIC16TargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) {
996 // We should have handled larger operands in type legalizer itself.
Owen Anderson825b72b2009-08-11 20:47:22 +0000997 assert (Op.getValueType() == MVT::i8 && "illegal multiply to lower");
Sanjiv Gupta8e14eab2009-07-27 02:44:46 +0000998
999 SDNode *N = Op.getNode();
1000 SmallVector<SDValue, 2> Ops(2);
1001 Ops[0] = N->getOperand(0);
1002 Ops[1] = N->getOperand(1);
1003 SDValue Call = MakePIC16Libcall(PIC16ISD::MUL_I8, N->getValueType(0),
1004 &Ops[0], 2, true, DAG, N->getDebugLoc());
1005 return Call;
1006}
1007
Duncan Sands9fbc7e22009-01-21 09:00:29 +00001008void
1009PIC16TargetLowering::LowerOperationWrapper(SDNode *N,
1010 SmallVectorImpl<SDValue>&Results,
1011 SelectionDAG &DAG) {
1012 SDValue Op = SDValue(N, 0);
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001013 SDValue Res;
1014 unsigned i;
1015 switch (Op.getOpcode()) {
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001016 case ISD::LOAD:
1017 Res = ExpandLoad(Op.getNode(), DAG); break;
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001018 default: {
1019 // All other operations are handled in LowerOperation.
1020 Res = LowerOperation(Op, DAG);
1021 if (Res.getNode())
1022 Results.push_back(Res);
1023
1024 return;
1025 }
1026 }
Duncan Sands9fbc7e22009-01-21 09:00:29 +00001027
1028 N = Res.getNode();
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001029 unsigned NumValues = N->getNumValues();
Duncan Sands9fbc7e22009-01-21 09:00:29 +00001030 for (i = 0; i < NumValues ; i++) {
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001031 Results.push_back(SDValue(N, i));
1032 }
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001033}
1034
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001035SDValue PIC16TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
1036 switch (Op.getOpcode()) {
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001037 case ISD::ADD:
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001038 case ISD::ADDC:
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001039 case ISD::ADDE:
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001040 return LowerADD(Op, DAG);
1041 case ISD::SUB:
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001042 case ISD::SUBC:
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001043 case ISD::SUBE:
1044 return LowerSUB(Op, DAG);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001045 case ISD::LOAD:
Duncan Sands1607f052008-12-01 11:39:25 +00001046 return ExpandLoad(Op.getNode(), DAG);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001047 case ISD::STORE:
Duncan Sands1607f052008-12-01 11:39:25 +00001048 return ExpandStore(Op.getNode(), DAG);
Sanjiv Gupta8e14eab2009-07-27 02:44:46 +00001049 case ISD::MUL:
1050 return LowerMUL(Op, DAG);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001051 case ISD::SHL:
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001052 case ISD::SRA:
1053 case ISD::SRL:
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001054 return LowerShift(Op, DAG);
Sanjiv Gupta8f78fa82008-11-26 10:53:50 +00001055 case ISD::OR:
1056 case ISD::AND:
1057 case ISD::XOR:
1058 return LowerBinOp(Op, DAG);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001059 case ISD::BR_CC:
1060 return LowerBR_CC(Op, DAG);
1061 case ISD::SELECT_CC:
1062 return LowerSELECT_CC(Op, DAG);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001063 }
Dan Gohman475871a2008-07-27 21:46:04 +00001064 return SDValue();
Sanjiv Gupta0e687712008-05-13 09:02:57 +00001065}
1066
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001067SDValue PIC16TargetLowering::ConvertToMemOperand(SDValue Op,
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001068 SelectionDAG &DAG,
1069 DebugLoc dl) {
Owen Anderson825b72b2009-08-11 20:47:22 +00001070 assert (Op.getValueType() == MVT::i8
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001071 && "illegal value type to store on stack.");
1072
1073 MachineFunction &MF = DAG.getMachineFunction();
1074 const Function *Func = MF.getFunction();
1075 const std::string FuncName = Func->getName();
1076
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001077
1078 // Put the value on stack.
1079 // Get a stack slot index and convert to es.
David Greene3f2bf852009-11-12 20:49:22 +00001080 int FI = MF.getFrameInfo()->CreateStackObject(1, 1, false);
Sanjiv Gupta211f3622009-05-10 05:23:47 +00001081 const char *tmpName = createESName(PAN::getTempdataLabel(FuncName));
Owen Anderson825b72b2009-08-11 20:47:22 +00001082 SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001083
1084 // Store the value to ES.
Owen Anderson825b72b2009-08-11 20:47:22 +00001085 SDValue Store = DAG.getNode (PIC16ISD::PIC16Store, dl, MVT::Other,
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001086 DAG.getEntryNode(),
1087 Op, ES,
Owen Anderson825b72b2009-08-11 20:47:22 +00001088 DAG.getConstant (1, MVT::i8), // Banksel.
Sanjiv Guptaa3613be2009-04-10 15:10:14 +00001089 DAG.getConstant (GetTmpOffsetForFI(FI, 1),
Owen Anderson825b72b2009-08-11 20:47:22 +00001090 MVT::i8));
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001091
1092 // Load the value from ES.
Owen Anderson825b72b2009-08-11 20:47:22 +00001093 SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other);
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001094 SDValue Load = DAG.getNode(PIC16ISD::PIC16Load, dl, Tys, Store,
Owen Anderson825b72b2009-08-11 20:47:22 +00001095 ES, DAG.getConstant (1, MVT::i8),
Sanjiv Guptaa3613be2009-04-10 15:10:14 +00001096 DAG.getConstant (GetTmpOffsetForFI(FI, 1),
Owen Anderson825b72b2009-08-11 20:47:22 +00001097 MVT::i8));
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001098
1099 return Load.getValue(0);
1100}
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001101
1102SDValue PIC16TargetLowering::
Dan Gohman98ca4f22009-08-05 01:29:28 +00001103LowerIndirectCallArguments(SDValue Chain, SDValue InFlag,
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001104 SDValue DataAddr_Lo, SDValue DataAddr_Hi,
Dan Gohman98ca4f22009-08-05 01:29:28 +00001105 const SmallVectorImpl<ISD::OutputArg> &Outs,
Sanjiv Guptaa4186282009-08-11 01:51:55 +00001106 const SmallVectorImpl<ISD::InputArg> &Ins,
Dan Gohman98ca4f22009-08-05 01:29:28 +00001107 DebugLoc dl, SelectionDAG &DAG) {
1108 unsigned NumOps = Outs.size();
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001109
1110 // If call has no arguments then do nothing and return.
1111 if (NumOps == 0)
1112 return Chain;
1113
1114 std::vector<SDValue> Ops;
Owen Anderson825b72b2009-08-11 20:47:22 +00001115 SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001116 SDValue Arg, StoreRet;
Sanjiv Guptae206b1d2009-04-09 10:29:32 +00001117
1118 // For PIC16 ABI the arguments come after the return value.
Sanjiv Guptaa4186282009-08-11 01:51:55 +00001119 unsigned RetVals = Ins.size();
Sanjiv Guptae206b1d2009-04-09 10:29:32 +00001120 for (unsigned i = 0, ArgOffset = RetVals; i < NumOps; i++) {
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001121 // Get the arguments
Dan Gohman98ca4f22009-08-05 01:29:28 +00001122 Arg = Outs[i].Val;
Sanjiv Guptae16178b2009-04-21 05:54:51 +00001123
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001124 Ops.clear();
1125 Ops.push_back(Chain);
1126 Ops.push_back(Arg);
1127 Ops.push_back(DataAddr_Lo);
1128 Ops.push_back(DataAddr_Hi);
Owen Anderson825b72b2009-08-11 20:47:22 +00001129 Ops.push_back(DAG.getConstant(ArgOffset, MVT::i8));
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001130 Ops.push_back(InFlag);
1131
1132 StoreRet = DAG.getNode (PIC16ISD::PIC16StWF, dl, Tys, &Ops[0], Ops.size());
1133
1134 Chain = getChain(StoreRet);
1135 InFlag = getOutFlag(StoreRet);
Sanjiv Guptae206b1d2009-04-09 10:29:32 +00001136 ArgOffset++;
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001137 }
1138 return Chain;
1139}
Sanjiv Gupta85be4082009-04-14 02:49:52 +00001140
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001141SDValue PIC16TargetLowering::
Dan Gohman98ca4f22009-08-05 01:29:28 +00001142LowerDirectCallArguments(SDValue ArgLabel, SDValue Chain, SDValue InFlag,
1143 const SmallVectorImpl<ISD::OutputArg> &Outs,
1144 DebugLoc dl, SelectionDAG &DAG) {
1145 unsigned NumOps = Outs.size();
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001146 std::string Name;
1147 SDValue Arg, StoreAt;
Owen Andersone50ed302009-08-10 22:56:29 +00001148 EVT ArgVT;
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001149 unsigned Size=0;
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001150
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001151 // If call has no arguments then do nothing and return.
1152 if (NumOps == 0)
1153 return Chain;
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001154
1155 // FIXME: This portion of code currently assumes only
1156 // primitive types being passed as arguments.
1157
1158 // Legalize the address before use
1159 SDValue PtrLo, PtrHi;
1160 unsigned AddressOffset;
1161 int StoreOffset = 0;
Sanjiv Gupta85be4082009-04-14 02:49:52 +00001162 LegalizeAddress(ArgLabel, DAG, PtrLo, PtrHi, AddressOffset, dl);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001163 SDValue StoreRet;
1164
1165 std::vector<SDValue> Ops;
Owen Anderson825b72b2009-08-11 20:47:22 +00001166 SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
Dan Gohman98ca4f22009-08-05 01:29:28 +00001167 for (unsigned i=0, Offset = 0; i<NumOps; i++) {
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001168 // Get the argument
Dan Gohman98ca4f22009-08-05 01:29:28 +00001169 Arg = Outs[i].Val;
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001170 StoreOffset = (Offset + AddressOffset);
1171
1172 // Store the argument on frame
1173
1174 Ops.clear();
1175 Ops.push_back(Chain);
Sanjiv Gupta12f23a82009-04-13 09:38:38 +00001176 Ops.push_back(Arg);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001177 Ops.push_back(PtrLo);
1178 Ops.push_back(PtrHi);
Owen Anderson825b72b2009-08-11 20:47:22 +00001179 Ops.push_back(DAG.getConstant(StoreOffset, MVT::i8));
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001180 Ops.push_back(InFlag);
1181
Dale Johannesene8d72302009-02-06 23:05:02 +00001182 StoreRet = DAG.getNode (PIC16ISD::PIC16StWF, dl, Tys, &Ops[0], Ops.size());
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001183
1184 Chain = getChain(StoreRet);
1185 InFlag = getOutFlag(StoreRet);
1186
1187 // Update the frame offset to be used for next argument
1188 ArgVT = Arg.getValueType();
1189 Size = ArgVT.getSizeInBits();
1190 Size = Size/8; // Calculate size in bytes
1191 Offset += Size; // Increase the frame offset
1192 }
1193 return Chain;
1194}
1195
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001196SDValue PIC16TargetLowering::
Dan Gohman98ca4f22009-08-05 01:29:28 +00001197LowerIndirectCallReturn(SDValue Chain, SDValue InFlag,
1198 SDValue DataAddr_Lo, SDValue DataAddr_Hi,
1199 const SmallVectorImpl<ISD::InputArg> &Ins,
1200 DebugLoc dl, SelectionDAG &DAG,
1201 SmallVectorImpl<SDValue> &InVals) {
1202 unsigned RetVals = Ins.size();
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001203
1204 // If call does not have anything to return
1205 // then do nothing and go back.
1206 if (RetVals == 0)
1207 return Chain;
1208
1209 // Call has something to return
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001210 SDValue LoadRet;
1211
Owen Anderson825b72b2009-08-11 20:47:22 +00001212 SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001213 for(unsigned i=0;i<RetVals;i++) {
1214 LoadRet = DAG.getNode(PIC16ISD::PIC16LdWF, dl, Tys, Chain, DataAddr_Lo,
Owen Anderson825b72b2009-08-11 20:47:22 +00001215 DataAddr_Hi, DAG.getConstant(i, MVT::i8),
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001216 InFlag);
1217 InFlag = getOutFlag(LoadRet);
1218 Chain = getChain(LoadRet);
Dan Gohman98ca4f22009-08-05 01:29:28 +00001219 InVals.push_back(LoadRet);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001220 }
Dan Gohman98ca4f22009-08-05 01:29:28 +00001221 return Chain;
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001222}
1223
1224SDValue PIC16TargetLowering::
Dan Gohman98ca4f22009-08-05 01:29:28 +00001225LowerDirectCallReturn(SDValue RetLabel, SDValue Chain, SDValue InFlag,
1226 const SmallVectorImpl<ISD::InputArg> &Ins,
1227 DebugLoc dl, SelectionDAG &DAG,
1228 SmallVectorImpl<SDValue> &InVals) {
1229
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001230 // Currently handling primitive types only. They will come in
1231 // i8 parts
Dan Gohman98ca4f22009-08-05 01:29:28 +00001232 unsigned RetVals = Ins.size();
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001233
1234 // Return immediately if the return type is void
1235 if (RetVals == 0)
1236 return Chain;
1237
1238 // Call has something to return
1239
1240 // Legalize the address before use
1241 SDValue LdLo, LdHi;
1242 unsigned LdOffset;
Sanjiv Gupta85be4082009-04-14 02:49:52 +00001243 LegalizeAddress(RetLabel, DAG, LdLo, LdHi, LdOffset, dl);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001244
Owen Anderson825b72b2009-08-11 20:47:22 +00001245 SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001246 SDValue LoadRet;
1247
1248 for(unsigned i=0, Offset=0;i<RetVals;i++) {
1249
Dale Johannesen4be0bdf2009-02-05 00:20:09 +00001250 LoadRet = DAG.getNode(PIC16ISD::PIC16LdWF, dl, Tys, Chain, LdLo, LdHi,
Owen Anderson825b72b2009-08-11 20:47:22 +00001251 DAG.getConstant(LdOffset + Offset, MVT::i8),
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001252 InFlag);
1253
1254 InFlag = getOutFlag(LoadRet);
1255
1256 Chain = getChain(LoadRet);
1257 Offset++;
Dan Gohman98ca4f22009-08-05 01:29:28 +00001258 InVals.push_back(LoadRet);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001259 }
1260
Dan Gohman98ca4f22009-08-05 01:29:28 +00001261 return Chain;
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001262}
1263
Dan Gohman98ca4f22009-08-05 01:29:28 +00001264SDValue
1265PIC16TargetLowering::LowerReturn(SDValue Chain,
Sandeep Patel65c3c8f2009-09-02 08:44:58 +00001266 CallingConv::ID CallConv, bool isVarArg,
Dan Gohman98ca4f22009-08-05 01:29:28 +00001267 const SmallVectorImpl<ISD::OutputArg> &Outs,
1268 DebugLoc dl, SelectionDAG &DAG) {
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001269
Sanjiv Guptab84d5a42009-04-02 17:42:00 +00001270 // Number of values to return
Dan Gohman98ca4f22009-08-05 01:29:28 +00001271 unsigned NumRet = Outs.size();
Sanjiv Guptab84d5a42009-04-02 17:42:00 +00001272
1273 // Function returns value always on stack with the offset starting
1274 // from 0
1275 MachineFunction &MF = DAG.getMachineFunction();
1276 const Function *F = MF.getFunction();
1277 std::string FuncName = F->getName();
1278
Sanjiv Gupta211f3622009-05-10 05:23:47 +00001279 const char *tmpName = createESName(PAN::getFrameLabel(FuncName));
Owen Anderson825b72b2009-08-11 20:47:22 +00001280 SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
1281 SDValue BS = DAG.getConstant(1, MVT::i8);
Sanjiv Guptab84d5a42009-04-02 17:42:00 +00001282 SDValue RetVal;
1283 for(unsigned i=0;i<NumRet; ++i) {
Dan Gohman98ca4f22009-08-05 01:29:28 +00001284 RetVal = Outs[i].Val;
Owen Anderson825b72b2009-08-11 20:47:22 +00001285 Chain = DAG.getNode (PIC16ISD::PIC16Store, dl, MVT::Other, Chain, RetVal,
Sanjiv Guptab84d5a42009-04-02 17:42:00 +00001286 ES, BS,
Owen Anderson825b72b2009-08-11 20:47:22 +00001287 DAG.getConstant (i, MVT::i8));
Sanjiv Guptab84d5a42009-04-02 17:42:00 +00001288
1289 }
Chris Lattner35a27c82009-08-21 23:12:15 +00001290 return DAG.getNode(PIC16ISD::RET, dl, MVT::Other, Chain);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001291}
1292
1293void PIC16TargetLowering::
1294GetDataAddress(DebugLoc dl, SDValue Callee, SDValue &Chain,
1295 SDValue &DataAddr_Lo, SDValue &DataAddr_Hi,
1296 SelectionDAG &DAG) {
1297 assert (Callee.getOpcode() == PIC16ISD::PIC16Connect
1298 && "Don't know what to do of such callee!!");
Owen Anderson825b72b2009-08-11 20:47:22 +00001299 SDValue ZeroOperand = DAG.getConstant(0, MVT::i8);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001300 SDValue SeqStart = DAG.getCALLSEQ_START(Chain, ZeroOperand);
1301 Chain = getChain(SeqStart);
1302 SDValue OperFlag = getOutFlag(SeqStart); // To manage the data dependency
1303
1304 // Get the Lo and Hi part of code address
1305 SDValue Lo = Callee.getOperand(0);
1306 SDValue Hi = Callee.getOperand(1);
1307
Sanjiv Guptadd92dba2009-04-22 12:02:36 +00001308 SDValue Data_Lo, Data_Hi;
Owen Anderson825b72b2009-08-11 20:47:22 +00001309 SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag);
Sanjiv Gupta09560f82009-05-09 05:11:19 +00001310 // Subtract 2 from Address to get the Lower part of DataAddress.
Owen Anderson825b72b2009-08-11 20:47:22 +00001311 SDVTList VTList = DAG.getVTList(MVT::i8, MVT::Flag);
Sanjiv Gupta09560f82009-05-09 05:11:19 +00001312 Data_Lo = DAG.getNode(ISD::SUBC, dl, VTList, Lo,
Owen Anderson825b72b2009-08-11 20:47:22 +00001313 DAG.getConstant(2, MVT::i8));
1314 SDValue Ops[3] = { Hi, DAG.getConstant(0, MVT::i8), Data_Lo.getValue(1)};
Sanjiv Gupta09560f82009-05-09 05:11:19 +00001315 Data_Hi = DAG.getNode(ISD::SUBE, dl, VTList, Ops, 3);
Owen Anderson825b72b2009-08-11 20:47:22 +00001316 SDValue PCLATH = DAG.getNode(PIC16ISD::MTPCLATH, dl, MVT::i8, Data_Hi);
1317 Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Data_Lo, PCLATH);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001318 SDValue Call = DAG.getNode(PIC16ISD::CALLW, dl, Tys, Chain, Callee,
1319 OperFlag);
1320 Chain = getChain(Call);
1321 OperFlag = getOutFlag(Call);
1322 SDValue SeqEnd = DAG.getCALLSEQ_END(Chain, ZeroOperand, ZeroOperand,
1323 OperFlag);
1324 Chain = getChain(SeqEnd);
1325 OperFlag = getOutFlag(SeqEnd);
1326
1327 // Low part of Data Address
Owen Anderson825b72b2009-08-11 20:47:22 +00001328 DataAddr_Lo = DAG.getNode(PIC16ISD::MTLO, dl, MVT::i8, Call, OperFlag);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001329
1330 // Make the second call.
1331 SeqStart = DAG.getCALLSEQ_START(Chain, ZeroOperand);
1332 Chain = getChain(SeqStart);
1333 OperFlag = getOutFlag(SeqStart); // To manage the data dependency
1334
Sanjiv Gupta09560f82009-05-09 05:11:19 +00001335 // Subtract 1 from Address to get high part of data address.
1336 Data_Lo = DAG.getNode(ISD::SUBC, dl, VTList, Lo,
Owen Anderson825b72b2009-08-11 20:47:22 +00001337 DAG.getConstant(1, MVT::i8));
1338 SDValue HiOps[3] = { Hi, DAG.getConstant(0, MVT::i8), Data_Lo.getValue(1)};
Sanjiv Gupta09560f82009-05-09 05:11:19 +00001339 Data_Hi = DAG.getNode(ISD::SUBE, dl, VTList, HiOps, 3);
Owen Anderson825b72b2009-08-11 20:47:22 +00001340 PCLATH = DAG.getNode(PIC16ISD::MTPCLATH, dl, MVT::i8, Data_Hi);
Sanjiv Gupta09560f82009-05-09 05:11:19 +00001341
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001342 // Use new Lo to make another CALLW
Owen Anderson825b72b2009-08-11 20:47:22 +00001343 Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Data_Lo, PCLATH);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001344 Call = DAG.getNode(PIC16ISD::CALLW, dl, Tys, Chain, Callee, OperFlag);
1345 Chain = getChain(Call);
1346 OperFlag = getOutFlag(Call);
1347 SeqEnd = DAG.getCALLSEQ_END(Chain, ZeroOperand, ZeroOperand,
1348 OperFlag);
1349 Chain = getChain(SeqEnd);
1350 OperFlag = getOutFlag(SeqEnd);
1351 // Hi part of Data Address
Owen Anderson825b72b2009-08-11 20:47:22 +00001352 DataAddr_Hi = DAG.getNode(PIC16ISD::MTHI, dl, MVT::i8, Call, OperFlag);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001353}
1354
Dan Gohman98ca4f22009-08-05 01:29:28 +00001355SDValue
Evan Cheng022d9e12010-02-02 23:55:14 +00001356PIC16TargetLowering::LowerCall(SDValue Chain, SDValue Callee,
Sandeep Patel65c3c8f2009-09-02 08:44:58 +00001357 CallingConv::ID CallConv, bool isVarArg,
Evan Cheng0c439eb2010-01-27 00:07:07 +00001358 bool &isTailCall,
Dan Gohman98ca4f22009-08-05 01:29:28 +00001359 const SmallVectorImpl<ISD::OutputArg> &Outs,
1360 const SmallVectorImpl<ISD::InputArg> &Ins,
1361 DebugLoc dl, SelectionDAG &DAG,
1362 SmallVectorImpl<SDValue> &InVals) {
Evan Cheng0c439eb2010-01-27 00:07:07 +00001363 // PIC16 target does not yet support tail call optimization.
1364 isTailCall = false;
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001365
Owen Anderson825b72b2009-08-11 20:47:22 +00001366 assert(Callee.getValueType() == MVT::i16 &&
Dan Gohman98ca4f22009-08-05 01:29:28 +00001367 "Don't know how to legalize this call node!!!");
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001368
1369 // The flag to track if this is a direct or indirect call.
1370 bool IsDirectCall = true;
Dan Gohman98ca4f22009-08-05 01:29:28 +00001371 unsigned RetVals = Ins.size();
1372 unsigned NumArgs = Outs.size();
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001373
1374 SDValue DataAddr_Lo, DataAddr_Hi;
Dan Gohman98ca4f22009-08-05 01:29:28 +00001375 if (!isa<GlobalAddressSDNode>(Callee) &&
1376 !isa<ExternalSymbolSDNode>(Callee)) {
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001377 IsDirectCall = false; // This is indirect call
Dan Gohman98ca4f22009-08-05 01:29:28 +00001378
1379 // If this is an indirect call then to pass the arguments
1380 // and read the return value back, we need the data address
1381 // of the function being called.
1382 // To get the data address two more calls need to be made.
1383
1384 // Come here for indirect calls
1385 SDValue Lo, Hi;
1386 // Indirect addresses. Get the hi and lo parts of ptr.
1387 GetExpandedParts(Callee, DAG, Lo, Hi);
1388 // Connect Lo and Hi parts of the callee with the PIC16Connect
Owen Anderson825b72b2009-08-11 20:47:22 +00001389 Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Lo, Hi);
Dan Gohman98ca4f22009-08-05 01:29:28 +00001390
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001391 // Read DataAddress only if we have to pass arguments or
1392 // read return value.
1393 if ((RetVals > 0) || (NumArgs > 0))
1394 GetDataAddress(dl, Callee, Chain, DataAddr_Lo, DataAddr_Hi, DAG);
1395 }
1396
Owen Anderson825b72b2009-08-11 20:47:22 +00001397 SDValue ZeroOperand = DAG.getConstant(0, MVT::i8);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001398
1399 // Start the call sequence.
1400 // Carring the Constant 0 along the CALLSEQSTART
1401 // because there is nothing else to carry.
1402 SDValue SeqStart = DAG.getCALLSEQ_START(Chain, ZeroOperand);
1403 Chain = getChain(SeqStart);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001404 SDValue OperFlag = getOutFlag(SeqStart); // To manage the data dependency
1405 std::string Name;
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001406
1407 // For any direct call - callee will be GlobalAddressNode or
1408 // ExternalSymbol
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001409 SDValue ArgLabel, RetLabel;
1410 if (IsDirectCall) {
1411 // Considering the GlobalAddressNode case here.
1412 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
1413 GlobalValue *GV = G->getGlobal();
Owen Anderson825b72b2009-08-11 20:47:22 +00001414 Callee = DAG.getTargetGlobalAddress(GV, MVT::i8);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001415 Name = G->getGlobal()->getName();
1416 } else {// Considering the ExternalSymbol case here
1417 ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Callee);
Owen Anderson825b72b2009-08-11 20:47:22 +00001418 Callee = DAG.getTargetExternalSymbol(ES->getSymbol(), MVT::i8);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001419 Name = ES->getSymbol();
1420 }
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001421
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001422 // Label for argument passing
Sanjiv Gupta211f3622009-05-10 05:23:47 +00001423 const char *argFrame = createESName(PAN::getArgsLabel(Name));
Owen Anderson825b72b2009-08-11 20:47:22 +00001424 ArgLabel = DAG.getTargetExternalSymbol(argFrame, MVT::i8);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001425
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001426 // Label for reading return value
Sanjiv Gupta211f3622009-05-10 05:23:47 +00001427 const char *retName = createESName(PAN::getRetvalLabel(Name));
Owen Anderson825b72b2009-08-11 20:47:22 +00001428 RetLabel = DAG.getTargetExternalSymbol(retName, MVT::i8);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001429 } else {
1430 // if indirect call
1431 SDValue CodeAddr_Lo = Callee.getOperand(0);
1432 SDValue CodeAddr_Hi = Callee.getOperand(1);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001433
Owen Anderson825b72b2009-08-11 20:47:22 +00001434 /*CodeAddr_Lo = DAG.getNode(ISD::ADD, dl, MVT::i8, CodeAddr_Lo,
1435 DAG.getConstant(2, MVT::i8));*/
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001436
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001437 // move Hi part in PCLATH
Owen Anderson825b72b2009-08-11 20:47:22 +00001438 CodeAddr_Hi = DAG.getNode(PIC16ISD::MTPCLATH, dl, MVT::i8, CodeAddr_Hi);
1439 Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, CodeAddr_Lo,
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001440 CodeAddr_Hi);
1441 }
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001442
1443 // Pass the argument to function before making the call.
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001444 SDValue CallArgs;
1445 if (IsDirectCall) {
Dan Gohman98ca4f22009-08-05 01:29:28 +00001446 CallArgs = LowerDirectCallArguments(ArgLabel, Chain, OperFlag,
1447 Outs, dl, DAG);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001448 Chain = getChain(CallArgs);
1449 OperFlag = getOutFlag(CallArgs);
1450 } else {
Dan Gohman98ca4f22009-08-05 01:29:28 +00001451 CallArgs = LowerIndirectCallArguments(Chain, OperFlag, DataAddr_Lo,
Sanjiv Guptaa4186282009-08-11 01:51:55 +00001452 DataAddr_Hi, Outs, Ins, dl, DAG);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001453 Chain = getChain(CallArgs);
1454 OperFlag = getOutFlag(CallArgs);
1455 }
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001456
Owen Anderson825b72b2009-08-11 20:47:22 +00001457 SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001458 SDValue PICCall = DAG.getNode(PIC16ISD::CALL, dl, Tys, Chain, Callee,
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001459 OperFlag);
1460 Chain = getChain(PICCall);
1461 OperFlag = getOutFlag(PICCall);
1462
1463
1464 // Carrying the Constant 0 along the CALLSEQSTART
1465 // because there is nothing else to carry.
1466 SDValue SeqEnd = DAG.getCALLSEQ_END(Chain, ZeroOperand, ZeroOperand,
1467 OperFlag);
1468 Chain = getChain(SeqEnd);
1469 OperFlag = getOutFlag(SeqEnd);
1470
1471 // Lower the return value reading after the call.
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001472 if (IsDirectCall)
Dan Gohman98ca4f22009-08-05 01:29:28 +00001473 return LowerDirectCallReturn(RetLabel, Chain, OperFlag,
1474 Ins, dl, DAG, InVals);
Sanjiv Gupta7836fc12009-04-08 05:38:48 +00001475 else
Dan Gohman98ca4f22009-08-05 01:29:28 +00001476 return LowerIndirectCallReturn(Chain, OperFlag, DataAddr_Lo,
1477 DataAddr_Hi, Ins, dl, DAG, InVals);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001478}
1479
1480bool PIC16TargetLowering::isDirectLoad(const SDValue Op) {
1481 if (Op.getOpcode() == PIC16ISD::PIC16Load)
1482 if (Op.getOperand(1).getOpcode() == ISD::TargetGlobalAddress
1483 || Op.getOperand(1).getOpcode() == ISD::TargetExternalSymbol)
1484 return true;
1485 return false;
1486}
1487
Sanjiv Gupta6b830e62009-03-20 13:42:20 +00001488// NeedToConvertToMemOp - Returns true if one of the operands of the
1489// operation 'Op' needs to be put into memory. Also returns the
1490// operand no. of the operand to be converted in 'MemOp'. Remember, PIC16 has
1491// no instruction that can operation on two registers. Most insns take
1492// one register and one memory operand (addwf) / Constant (addlw).
Sanjiv Gupta76d2f9a2009-12-23 11:19:09 +00001493bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp,
1494 SelectionDAG &DAG) {
Sanjiv Gupta6b830e62009-03-20 13:42:20 +00001495 // If one of the operand is a constant, return false.
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001496 if (Op.getOperand(0).getOpcode() == ISD::Constant ||
1497 Op.getOperand(1).getOpcode() == ISD::Constant)
1498 return false;
Sanjiv Gupta6b830e62009-03-20 13:42:20 +00001499
1500 // Return false if one of the operands is already a direct
1501 // load and that operand has only one use.
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001502 if (isDirectLoad(Op.getOperand(0))) {
Sanjiv Gupta76d2f9a2009-12-23 11:19:09 +00001503 if (Op.getOperand(0).hasOneUse()) {
1504 // Legal and profitable folding check uses the NodeId of DAG nodes.
1505 // This NodeId is assigned by topological order. Therefore first
1506 // assign topological order then perform legal and profitable check.
1507 // Note:- Though this ordering is done before begining with legalization,
1508 // newly added node during legalization process have NodeId=-1 (NewNode)
1509 // therefore before performing any check proper ordering of the node is
1510 // required.
1511 DAG.AssignTopologicalOrder();
1512
1513 // Direct load operands are folded in binary operations. But before folding
1514 // verify if this folding is legal. Fold only if it is legal otherwise
1515 // convert this direct load to a separate memory operation.
1516 if(ISel->IsLegalAndProfitableToFold(Op.getOperand(0).getNode(),
1517 Op.getNode(), Op.getNode()))
1518 return false;
1519 else
1520 MemOp = 0;
1521 }
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001522 }
Sanjiv Gupta76d2f9a2009-12-23 11:19:09 +00001523
1524 // For operations that are non-cummutative there is no need to check
1525 // for right operand because folding right operand may result in
1526 // incorrect operation.
1527 if (! SelectionDAG::isCommutativeBinOp(Op.getOpcode()))
1528 return true;
1529
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001530 if (isDirectLoad(Op.getOperand(1))) {
1531 if (Op.getOperand(1).hasOneUse())
1532 return false;
1533 else
1534 MemOp = 1;
1535 }
1536 return true;
1537}
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001538
Sanjiv Gupta6b830e62009-03-20 13:42:20 +00001539// LowerBinOp - Lower a commutative binary operation that does not
1540// affect status flag carry.
1541SDValue PIC16TargetLowering::LowerBinOp(SDValue Op, SelectionDAG &DAG) {
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001542 DebugLoc dl = Op.getDebugLoc();
Sanjiv Gupta6b830e62009-03-20 13:42:20 +00001543
Sanjiv Gupta8f78fa82008-11-26 10:53:50 +00001544 // We should have handled larger operands in type legalizer itself.
Owen Anderson825b72b2009-08-11 20:47:22 +00001545 assert (Op.getValueType() == MVT::i8 && "illegal Op to lower");
Sanjiv Gupta6b830e62009-03-20 13:42:20 +00001546
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001547 unsigned MemOp = 1;
Sanjiv Gupta76d2f9a2009-12-23 11:19:09 +00001548 if (NeedToConvertToMemOp(Op, MemOp, DAG)) {
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001549 // Put one value on stack.
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001550 SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG, dl);
Sanjiv Gupta8f78fa82008-11-26 10:53:50 +00001551
Owen Anderson825b72b2009-08-11 20:47:22 +00001552 return DAG.getNode(Op.getOpcode(), dl, MVT::i8, Op.getOperand(MemOp ^ 1),
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001553 NewVal);
1554 }
1555 else {
Sanjiv Gupta8f78fa82008-11-26 10:53:50 +00001556 return Op;
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001557 }
Sanjiv Gupta8f78fa82008-11-26 10:53:50 +00001558}
1559
Sanjiv Gupta6b830e62009-03-20 13:42:20 +00001560// LowerADD - Lower all types of ADD operations including the ones
1561// that affects carry.
1562SDValue PIC16TargetLowering::LowerADD(SDValue Op, SelectionDAG &DAG) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001563 // We should have handled larger operands in type legalizer itself.
Owen Anderson825b72b2009-08-11 20:47:22 +00001564 assert (Op.getValueType() == MVT::i8 && "illegal add to lower");
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001565 DebugLoc dl = Op.getDebugLoc();
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001566 unsigned MemOp = 1;
Sanjiv Gupta76d2f9a2009-12-23 11:19:09 +00001567 if (NeedToConvertToMemOp(Op, MemOp, DAG)) {
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001568 // Put one value on stack.
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001569 SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG, dl);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001570
Dale Johannesen83138992009-06-01 23:13:42 +00001571 // ADDC and ADDE produce two results.
Owen Anderson825b72b2009-08-11 20:47:22 +00001572 SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001573
Dale Johannesen83138992009-06-01 23:13:42 +00001574 // ADDE has three operands, the last one is the carry bit.
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001575 if (Op.getOpcode() == ISD::ADDE)
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001576 return DAG.getNode(Op.getOpcode(), dl, Tys, Op.getOperand(MemOp ^ 1),
1577 NewVal, Op.getOperand(2));
Sanjiv Gupta6e2a46a2009-04-09 04:03:43 +00001578 // ADDC has two operands.
1579 else if (Op.getOpcode() == ISD::ADDC)
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001580 return DAG.getNode(Op.getOpcode(), dl, Tys, Op.getOperand(MemOp ^ 1),
1581 NewVal);
Sanjiv Gupta6e2a46a2009-04-09 04:03:43 +00001582 // ADD it is. It produces only one result.
1583 else
Owen Anderson825b72b2009-08-11 20:47:22 +00001584 return DAG.getNode(Op.getOpcode(), dl, MVT::i8, Op.getOperand(MemOp ^ 1),
Sanjiv Gupta6e2a46a2009-04-09 04:03:43 +00001585 NewVal);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001586 }
Sanjiv Gupta6e2a46a2009-04-09 04:03:43 +00001587 else
Sanjiv Guptadf75a272009-05-28 06:59:57 +00001588 return Op;
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001589}
1590
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001591SDValue PIC16TargetLowering::LowerSUB(SDValue Op, SelectionDAG &DAG) {
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001592 DebugLoc dl = Op.getDebugLoc();
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001593 // We should have handled larger operands in type legalizer itself.
Owen Anderson825b72b2009-08-11 20:47:22 +00001594 assert (Op.getValueType() == MVT::i8 && "illegal sub to lower");
Sanjiv Gupta7fb0ead2009-12-23 10:56:02 +00001595 unsigned MemOp = 1;
Owen Anderson825b72b2009-08-11 20:47:22 +00001596 SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
Sanjiv Gupta7fb0ead2009-12-23 10:56:02 +00001597
1598 // Since we don't have an instruction for X - c ,
1599 // we can change it to X + (-c)
1600 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
1601 if (C && (Op.getOpcode() == ISD::SUB))
1602 {
1603 return DAG.getNode(ISD::ADD,
1604 dl, MVT::i8, Op.getOperand(0),
1605 DAG.getConstant(0-(C->getZExtValue()), MVT::i8));
1606 }
1607
Sanjiv Gupta76d2f9a2009-12-23 11:19:09 +00001608 if (NeedToConvertToMemOp(Op, MemOp, DAG) ||
Sanjiv Gupta7fb0ead2009-12-23 10:56:02 +00001609 (isDirectLoad(Op.getOperand(1)) &&
1610 (!isDirectLoad(Op.getOperand(0))) &&
1611 (Op.getOperand(0).getOpcode() != ISD::Constant)))
1612 {
1613 // Put first operand on stack.
1614 SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG, dl);
1615
1616 switch (Op.getOpcode()) {
1617 default:
1618 assert (0 && "Opcode unknown.");
1619 case ISD::SUBE:
1620 return DAG.getNode(Op.getOpcode(),
1621 dl, Tys, NewVal, Op.getOperand(1),
1622 Op.getOperand(2));
1623 break;
1624 case ISD::SUBC:
1625 return DAG.getNode(Op.getOpcode(),
1626 dl, Tys, NewVal, Op.getOperand(1));
1627 break;
1628 case ISD::SUB:
1629 return DAG.getNode(Op.getOpcode(),
1630 dl, MVT::i8, NewVal, Op.getOperand(1));
1631 break;
1632 }
1633 }
1634 else
1635 return Op;
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001636}
1637
Sanjiv Guptae16178b2009-04-21 05:54:51 +00001638void PIC16TargetLowering::InitReservedFrameCount(const Function *F) {
1639 unsigned NumArgs = F->arg_size();
1640
1641 bool isVoidFunc = (F->getReturnType()->getTypeID() == Type::VoidTyID);
1642
1643 if (isVoidFunc)
1644 ReservedFrameCount = NumArgs;
1645 else
1646 ReservedFrameCount = NumArgs + 1;
1647}
1648
Dan Gohman98ca4f22009-08-05 01:29:28 +00001649// LowerFormalArguments - Argument values are loaded from the
Sanjiv Guptacae1b622009-04-06 10:54:50 +00001650// <fname>.args + offset. All arguments are already broken to leaglized
1651// types, so the offset just runs from 0 to NumArgVals - 1.
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001652
Dan Gohman98ca4f22009-08-05 01:29:28 +00001653SDValue
1654PIC16TargetLowering::LowerFormalArguments(SDValue Chain,
Sandeep Patel65c3c8f2009-09-02 08:44:58 +00001655 CallingConv::ID CallConv,
Dan Gohman98ca4f22009-08-05 01:29:28 +00001656 bool isVarArg,
1657 const SmallVectorImpl<ISD::InputArg> &Ins,
1658 DebugLoc dl,
1659 SelectionDAG &DAG,
1660 SmallVectorImpl<SDValue> &InVals) {
1661 unsigned NumArgVals = Ins.size();
Sanjiv Guptacae1b622009-04-06 10:54:50 +00001662
Sanjiv Guptacae1b622009-04-06 10:54:50 +00001663 // Get the callee's name to create the <fname>.args label to pass args.
Sanjiv Guptab84d5a42009-04-02 17:42:00 +00001664 MachineFunction &MF = DAG.getMachineFunction();
Sanjiv Guptab84d5a42009-04-02 17:42:00 +00001665 const Function *F = MF.getFunction();
1666 std::string FuncName = F->getName();
1667
Sanjiv Guptae16178b2009-04-21 05:54:51 +00001668 // Reset the map of FI and TmpOffset
1669 ResetTmpOffsetMap();
1670 // Initialize the ReserveFrameCount
1671 InitReservedFrameCount(F);
1672
Sanjiv Guptacae1b622009-04-06 10:54:50 +00001673 // Create the <fname>.args external symbol.
Sanjiv Gupta211f3622009-05-10 05:23:47 +00001674 const char *tmpName = createESName(PAN::getArgsLabel(FuncName));
Owen Anderson825b72b2009-08-11 20:47:22 +00001675 SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
Sanjiv Guptacae1b622009-04-06 10:54:50 +00001676
1677 // Load arg values from the label + offset.
Owen Anderson825b72b2009-08-11 20:47:22 +00001678 SDVTList VTs = DAG.getVTList (MVT::i8, MVT::Other);
1679 SDValue BS = DAG.getConstant(1, MVT::i8);
Sanjiv Guptacae1b622009-04-06 10:54:50 +00001680 for (unsigned i = 0; i < NumArgVals ; ++i) {
Owen Anderson825b72b2009-08-11 20:47:22 +00001681 SDValue Offset = DAG.getConstant(i, MVT::i8);
Sanjiv Guptab84d5a42009-04-02 17:42:00 +00001682 SDValue PICLoad = DAG.getNode(PIC16ISD::PIC16LdArg, dl, VTs, Chain, ES, BS,
Sanjiv Guptacae1b622009-04-06 10:54:50 +00001683 Offset);
Sanjiv Guptab84d5a42009-04-02 17:42:00 +00001684 Chain = getChain(PICLoad);
Dan Gohman98ca4f22009-08-05 01:29:28 +00001685 InVals.push_back(PICLoad);
Sanjiv Gupta0e687712008-05-13 09:02:57 +00001686 }
1687
Dan Gohman98ca4f22009-08-05 01:29:28 +00001688 return Chain;
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001689}
1690
Sanjiv Gupta6b830e62009-03-20 13:42:20 +00001691// Perform DAGCombine of PIC16Load.
1692// FIXME - Need a more elaborate comment here.
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001693SDValue PIC16TargetLowering::
1694PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const {
1695 SelectionDAG &DAG = DCI.DAG;
1696 SDValue Chain = N->getOperand(0);
1697 if (N->hasNUsesOfValue(0, 0)) {
1698 DAG.ReplaceAllUsesOfValueWith(SDValue(N,1), Chain);
1699 }
1700 return SDValue();
1701}
1702
Sanjiv Guptab84d5a42009-04-02 17:42:00 +00001703// For all the functions with arguments some STORE nodes are generated
1704// that store the argument on the frameindex. However in PIC16 the arguments
1705// are passed on stack only. Therefore these STORE nodes are redundant.
1706// To remove these STORE nodes will be removed in PerformStoreCombine
1707//
1708// Currently this function is doint nothing and will be updated for removing
1709// unwanted store operations
1710SDValue PIC16TargetLowering::
1711PerformStoreCombine(SDNode *N, DAGCombinerInfo &DCI) const {
Sanjiv Guptab84d5a42009-04-02 17:42:00 +00001712 return SDValue(N, 0);
1713 /*
1714 // Storing an undef value is of no use, so remove it
1715 if (isStoringUndef(N, Chain, DAG)) {
1716 return Chain; // remove the store and return the chain
1717 }
1718 //else everything is ok.
1719 return SDValue(N, 0);
1720 */
1721}
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001722
1723SDValue PIC16TargetLowering::PerformDAGCombine(SDNode *N,
1724 DAGCombinerInfo &DCI) const {
1725 switch (N->getOpcode()) {
Sanjiv Guptab84d5a42009-04-02 17:42:00 +00001726 case ISD::STORE:
1727 return PerformStoreCombine(N, DCI);
1728 case PIC16ISD::PIC16Load:
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +00001729 return PerformPIC16LoadCombine(N, DCI);
1730 }
1731 return SDValue();
Sanjiv Gupta0e687712008-05-13 09:02:57 +00001732}
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001733
1734static PIC16CC::CondCodes IntCCToPIC16CC(ISD::CondCode CC) {
1735 switch (CC) {
Torok Edwinc23197a2009-07-14 16:55:14 +00001736 default: llvm_unreachable("Unknown condition code!");
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001737 case ISD::SETNE: return PIC16CC::NE;
1738 case ISD::SETEQ: return PIC16CC::EQ;
1739 case ISD::SETGT: return PIC16CC::GT;
1740 case ISD::SETGE: return PIC16CC::GE;
1741 case ISD::SETLT: return PIC16CC::LT;
1742 case ISD::SETLE: return PIC16CC::LE;
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001743 case ISD::SETULT: return PIC16CC::ULT;
Sanjiv Gupta703e2352009-06-03 13:36:44 +00001744 case ISD::SETULE: return PIC16CC::ULE;
1745 case ISD::SETUGE: return PIC16CC::UGE;
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001746 case ISD::SETUGT: return PIC16CC::UGT;
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001747 }
1748}
1749
1750// Look at LHS/RHS/CC and see if they are a lowered setcc instruction. If so
1751// set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition.
1752static void LookThroughSetCC(SDValue &LHS, SDValue &RHS,
1753 ISD::CondCode CC, unsigned &SPCC) {
1754 if (isa<ConstantSDNode>(RHS) &&
1755 cast<ConstantSDNode>(RHS)->getZExtValue() == 0 &&
1756 CC == ISD::SETNE &&
1757 (LHS.getOpcode() == PIC16ISD::SELECT_ICC &&
1758 LHS.getOperand(3).getOpcode() == PIC16ISD::SUBCC) &&
1759 isa<ConstantSDNode>(LHS.getOperand(0)) &&
1760 isa<ConstantSDNode>(LHS.getOperand(1)) &&
1761 cast<ConstantSDNode>(LHS.getOperand(0))->getZExtValue() == 1 &&
1762 cast<ConstantSDNode>(LHS.getOperand(1))->getZExtValue() == 0) {
1763 SDValue CMPCC = LHS.getOperand(3);
1764 SPCC = cast<ConstantSDNode>(LHS.getOperand(2))->getZExtValue();
1765 LHS = CMPCC.getOperand(0);
1766 RHS = CMPCC.getOperand(1);
1767 }
1768}
1769
1770// Returns appropriate CMP insn and corresponding condition code in PIC16CC
1771SDValue PIC16TargetLowering::getPIC16Cmp(SDValue LHS, SDValue RHS,
1772 unsigned CC, SDValue &PIC16CC,
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001773 SelectionDAG &DAG, DebugLoc dl) {
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001774 PIC16CC::CondCodes CondCode = (PIC16CC::CondCodes) CC;
1775
1776 // PIC16 sub is literal - W. So Swap the operands and condition if needed.
1777 // i.e. a < 12 can be rewritten as 12 > a.
1778 if (RHS.getOpcode() == ISD::Constant) {
1779
1780 SDValue Tmp = LHS;
1781 LHS = RHS;
1782 RHS = Tmp;
1783
1784 switch (CondCode) {
1785 default: break;
1786 case PIC16CC::LT:
1787 CondCode = PIC16CC::GT;
1788 break;
1789 case PIC16CC::GT:
1790 CondCode = PIC16CC::LT;
1791 break;
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001792 case PIC16CC::ULT:
1793 CondCode = PIC16CC::UGT;
1794 break;
1795 case PIC16CC::UGT:
1796 CondCode = PIC16CC::ULT;
1797 break;
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001798 case PIC16CC::GE:
1799 CondCode = PIC16CC::LE;
1800 break;
1801 case PIC16CC::LE:
1802 CondCode = PIC16CC::GE;
1803 break;
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001804 case PIC16CC::ULE:
1805 CondCode = PIC16CC::UGE;
1806 break;
1807 case PIC16CC::UGE:
1808 CondCode = PIC16CC::ULE;
1809 break;
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001810 }
1811 }
1812
Owen Anderson825b72b2009-08-11 20:47:22 +00001813 PIC16CC = DAG.getConstant(CondCode, MVT::i8);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001814
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001815 // These are signed comparisons.
Owen Anderson825b72b2009-08-11 20:47:22 +00001816 SDValue Mask = DAG.getConstant(128, MVT::i8);
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001817 if (isSignedComparison(CondCode)) {
Owen Anderson825b72b2009-08-11 20:47:22 +00001818 LHS = DAG.getNode (ISD::XOR, dl, MVT::i8, LHS, Mask);
1819 RHS = DAG.getNode (ISD::XOR, dl, MVT::i8, RHS, Mask);
Sanjiv Gupta08b9b052009-01-21 05:44:05 +00001820 }
Sanjiv Guptae0ffc922009-01-30 07:55:25 +00001821
Owen Anderson825b72b2009-08-11 20:47:22 +00001822 SDVTList VTs = DAG.getVTList (MVT::i8, MVT::Flag);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001823 // We can use a subtract operation to set the condition codes. But
1824 // we need to put one operand in memory if required.
Sanjiv Guptae0ffc922009-01-30 07:55:25 +00001825 // Nothing to do if the first operand is already a valid type (direct load
1826 // for subwf and literal for sublw) and it is used by this operation only.
1827 if ((LHS.getOpcode() == ISD::Constant || isDirectLoad(LHS))
1828 && LHS.hasOneUse())
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001829 return DAG.getNode(PIC16ISD::SUBCC, dl, VTs, LHS, RHS);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001830
Sanjiv Guptae0ffc922009-01-30 07:55:25 +00001831 // else convert the first operand to mem.
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001832 LHS = ConvertToMemOperand (LHS, DAG, dl);
1833 return DAG.getNode(PIC16ISD::SUBCC, dl, VTs, LHS, RHS);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001834}
1835
1836
1837SDValue PIC16TargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
1838 SDValue LHS = Op.getOperand(0);
1839 SDValue RHS = Op.getOperand(1);
1840 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
1841 SDValue TrueVal = Op.getOperand(2);
1842 SDValue FalseVal = Op.getOperand(3);
1843 unsigned ORIGCC = ~0;
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001844 DebugLoc dl = Op.getDebugLoc();
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001845
1846 // If this is a select_cc of a "setcc", and if the setcc got lowered into
1847 // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
1848 // i.e.
1849 // A setcc: lhs, rhs, cc is expanded by llvm to
1850 // select_cc: result of setcc, 0, 1, 0, setne
1851 // We can think of it as:
1852 // select_cc: lhs, rhs, 1, 0, cc
1853 LookThroughSetCC(LHS, RHS, CC, ORIGCC);
1854 if (ORIGCC == ~0U) ORIGCC = IntCCToPIC16CC (CC);
1855
1856 SDValue PIC16CC;
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001857 SDValue Cmp = getPIC16Cmp(LHS, RHS, ORIGCC, PIC16CC, DAG, dl);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001858
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001859 return DAG.getNode (PIC16ISD::SELECT_ICC, dl, TrueVal.getValueType(), TrueVal,
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001860 FalseVal, PIC16CC, Cmp.getValue(1));
1861}
1862
1863MachineBasicBlock *
1864PIC16TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
Evan Chengfb2e7522009-09-18 21:02:19 +00001865 MachineBasicBlock *BB,
1866 DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const {
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001867 const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
1868 unsigned CC = (PIC16CC::CondCodes)MI->getOperand(3).getImm();
Dale Johannesenbd9ef182009-02-13 02:29:03 +00001869 DebugLoc dl = MI->getDebugLoc();
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001870
1871 // To "insert" a SELECT_CC instruction, we actually have to insert the diamond
1872 // control-flow pattern. The incoming instruction knows the destination vreg
1873 // to set, the condition code register to branch on, the true/false values to
1874 // select between, and a branch opcode to use.
1875 const BasicBlock *LLVM_BB = BB->getBasicBlock();
1876 MachineFunction::iterator It = BB;
1877 ++It;
1878
1879 // thisMBB:
1880 // ...
1881 // TrueVal = ...
1882 // [f]bCC copy1MBB
1883 // fallthrough --> copy0MBB
1884 MachineBasicBlock *thisMBB = BB;
1885 MachineFunction *F = BB->getParent();
1886 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
1887 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
Dale Johannesenbd9ef182009-02-13 02:29:03 +00001888 BuildMI(BB, dl, TII.get(PIC16::pic16brcond)).addMBB(sinkMBB).addImm(CC);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001889 F->insert(It, copy0MBB);
1890 F->insert(It, sinkMBB);
1891
Evan Chengce319102009-09-19 09:51:03 +00001892 // Update machine-CFG edges by first adding all successors of the current
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001893 // block to the new block which will contain the Phi node for the select.
Evan Chengce319102009-09-19 09:51:03 +00001894 // Also inform sdisel of the edge changes.
1895 for (MachineBasicBlock::succ_iterator I = BB->succ_begin(),
1896 E = BB->succ_end(); I != E; ++I) {
1897 EM->insert(std::make_pair(*I, sinkMBB));
1898 sinkMBB->addSuccessor(*I);
1899 }
1900 // Next, remove all successors of the current block, and add the true
1901 // and fallthrough blocks as its successors.
1902 while (!BB->succ_empty())
1903 BB->removeSuccessor(BB->succ_begin());
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001904 // Next, add the true and fallthrough blocks as its successors.
1905 BB->addSuccessor(copy0MBB);
1906 BB->addSuccessor(sinkMBB);
1907
1908 // copy0MBB:
1909 // %FalseValue = ...
1910 // # fallthrough to sinkMBB
1911 BB = copy0MBB;
1912
1913 // Update machine-CFG edges
1914 BB->addSuccessor(sinkMBB);
1915
1916 // sinkMBB:
1917 // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
1918 // ...
1919 BB = sinkMBB;
Dale Johannesenbd9ef182009-02-13 02:29:03 +00001920 BuildMI(BB, dl, TII.get(PIC16::PHI), MI->getOperand(0).getReg())
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001921 .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB)
1922 .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB);
1923
1924 F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.
1925 return BB;
1926}
1927
1928
1929SDValue PIC16TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) {
1930 SDValue Chain = Op.getOperand(0);
1931 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
1932 SDValue LHS = Op.getOperand(2); // LHS of the condition.
1933 SDValue RHS = Op.getOperand(3); // RHS of the condition.
1934 SDValue Dest = Op.getOperand(4); // BB to jump to
1935 unsigned ORIGCC = ~0;
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001936 DebugLoc dl = Op.getDebugLoc();
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001937
1938 // If this is a br_cc of a "setcc", and if the setcc got lowered into
1939 // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
1940 LookThroughSetCC(LHS, RHS, CC, ORIGCC);
1941 if (ORIGCC == ~0U) ORIGCC = IntCCToPIC16CC (CC);
1942
1943 // Get the Compare insn and condition code.
1944 SDValue PIC16CC;
Dale Johannesen2fabcb22009-02-05 01:01:16 +00001945 SDValue Cmp = getPIC16Cmp(LHS, RHS, ORIGCC, PIC16CC, DAG, dl);
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001946
Owen Anderson825b72b2009-08-11 20:47:22 +00001947 return DAG.getNode(PIC16ISD::BRCOND, dl, MVT::Other, Chain, Dest, PIC16CC,
Sanjiv Gupta1b046942009-01-13 19:18:47 +00001948 Cmp.getValue(1));
1949}
1950