blob: bb31fc7f5c8caf2d5b545dab4dec9b332a9e4bc6 [file] [log] [blame]
Duraid Madina9b9d45f2005-03-17 18:17:03 +00001//===-- IA64ISelPattern.cpp - A pattern matching inst selector for IA64 ---===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Duraid Madina and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a pattern matching instruction selector for IA64.
11//
12//===----------------------------------------------------------------------===//
13
14#include "IA64.h"
15#include "IA64InstrBuilder.h"
16#include "IA64RegisterInfo.h"
17#include "IA64MachineFunctionInfo.h"
18#include "llvm/Constants.h" // FIXME: REMOVE
19#include "llvm/Function.h"
20#include "llvm/CodeGen/MachineConstantPool.h" // FIXME: REMOVE
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineFrameInfo.h"
23#include "llvm/CodeGen/SelectionDAG.h"
24#include "llvm/CodeGen/SelectionDAGISel.h"
25#include "llvm/CodeGen/SSARegMap.h"
26#include "llvm/Target/TargetData.h"
27#include "llvm/Target/TargetLowering.h"
28#include "llvm/Support/MathExtras.h"
29#include "llvm/ADT/Statistic.h"
30#include <set>
31#include <algorithm>
32using namespace llvm;
33
34//===----------------------------------------------------------------------===//
35// IA64TargetLowering - IA64 Implementation of the TargetLowering interface
36namespace {
37 class IA64TargetLowering : public TargetLowering {
38 int VarArgsFrameIndex; // FrameIndex for start of varargs area.
39
40 //int ReturnAddrIndex; // FrameIndex for return slot.
41 unsigned GP, SP, RP; // FIXME - clean this mess up
42 public:
43
44 unsigned VirtGPR; // this is public so it can be accessed in the selector
45 // for ISD::RET down below. add an accessor instead? FIXME
46
47 IA64TargetLowering(TargetMachine &TM) : TargetLowering(TM) {
48
49 // register class for general registers
50 addRegisterClass(MVT::i64, IA64::GRRegisterClass);
51
52 // register class for FP registers
53 addRegisterClass(MVT::f64, IA64::FPRegisterClass);
54
55 // register class for predicate registers
56 addRegisterClass(MVT::i1, IA64::PRRegisterClass);
57
58 setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand);
59
60 setSetCCResultType(MVT::i1);
61 setShiftAmountType(MVT::i64);
62
63 setOperationAction(ISD::EXTLOAD , MVT::i1 , Promote);
64 setOperationAction(ISD::EXTLOAD , MVT::f32 , Promote);
65
66 setOperationAction(ISD::ZEXTLOAD , MVT::i1 , Expand);
67 setOperationAction(ISD::ZEXTLOAD , MVT::i32 , Expand);
68
69 setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand);
70 setOperationAction(ISD::SEXTLOAD , MVT::i8 , Expand);
71 setOperationAction(ISD::SEXTLOAD , MVT::i16 , Expand);
72
73 setOperationAction(ISD::SREM , MVT::f32 , Expand);
74 setOperationAction(ISD::SREM , MVT::f64 , Expand);
75
76 setOperationAction(ISD::UREM , MVT::f32 , Expand);
77 setOperationAction(ISD::UREM , MVT::f64 , Expand);
78
79 setOperationAction(ISD::MEMMOVE , MVT::Other, Expand);
80 setOperationAction(ISD::MEMSET , MVT::Other, Expand);
81 setOperationAction(ISD::MEMCPY , MVT::Other, Expand);
82
Chris Lattner43fdea02005-04-02 05:03:24 +000083 // We don't support these yet.
84 setOperationAction(ISD::FNEG , MVT::f64 , Expand);
85 setOperationAction(ISD::FABS , MVT::f64 , Expand);
Duraid Madina9b9d45f2005-03-17 18:17:03 +000086
87 computeRegisterProperties();
88
89 addLegalFPImmediate(+0.0);
90 addLegalFPImmediate(+1.0);
91 addLegalFPImmediate(-0.0);
92 addLegalFPImmediate(-1.0);
93 }
94
95 /// LowerArguments - This hook must be implemented to indicate how we should
96 /// lower the arguments for the specified function, into the specified DAG.
97 virtual std::vector<SDOperand>
98 LowerArguments(Function &F, SelectionDAG &DAG);
99
100 /// LowerCallTo - This hook lowers an abstract call to a function into an
101 /// actual call.
102 virtual std::pair<SDOperand, SDOperand>
Nate Begeman8e21e712005-03-26 01:29:23 +0000103 LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
104 SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG);
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000105
106 virtual std::pair<SDOperand, SDOperand>
107 LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
108
109 virtual std::pair<SDOperand,SDOperand>
110 LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
111 const Type *ArgTy, SelectionDAG &DAG);
112
113 virtual std::pair<SDOperand, SDOperand>
114 LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
115 SelectionDAG &DAG);
116
117 void restoreGP_SP_RP(MachineBasicBlock* BB)
118 {
119 BuildMI(BB, IA64::MOV, 1, IA64::r1).addReg(GP);
120 BuildMI(BB, IA64::MOV, 1, IA64::r12).addReg(SP);
121 BuildMI(BB, IA64::MOV, 1, IA64::rp).addReg(RP);
122 }
123
Duraid Madinabeeaab22005-03-31 12:31:11 +0000124 void restoreSP_RP(MachineBasicBlock* BB)
125 {
126 BuildMI(BB, IA64::MOV, 1, IA64::r12).addReg(SP);
127 BuildMI(BB, IA64::MOV, 1, IA64::rp).addReg(RP);
128 }
129
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000130 void restoreRP(MachineBasicBlock* BB)
131 {
132 BuildMI(BB, IA64::MOV, 1, IA64::rp).addReg(RP);
133 }
134
135 void restoreGP(MachineBasicBlock* BB)
136 {
137 BuildMI(BB, IA64::MOV, 1, IA64::r1).addReg(GP);
138 }
139
140 };
141}
142
143
144std::vector<SDOperand>
145IA64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
146 std::vector<SDOperand> ArgValues;
147
148 //
149 // add beautiful description of IA64 stack frame format
150 // here (from intel 24535803.pdf most likely)
151 //
152 MachineFunction &MF = DAG.getMachineFunction();
153 MachineFrameInfo *MFI = MF.getFrameInfo();
154
155 GP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
156 SP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
157 RP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
158
159 MachineBasicBlock& BB = MF.front();
160
161 unsigned args_int[] = {IA64::r32, IA64::r33, IA64::r34, IA64::r35,
162 IA64::r36, IA64::r37, IA64::r38, IA64::r39};
163
164 unsigned args_FP[] = {IA64::F8, IA64::F9, IA64::F10, IA64::F11,
165 IA64::F12,IA64::F13,IA64::F14, IA64::F15};
166
167 unsigned argVreg[8];
168 unsigned argPreg[8];
169 unsigned argOpc[8];
170
Duraid Madinabeeaab22005-03-31 12:31:11 +0000171 unsigned used_FPArgs = 0; // how many FP args have been used so far?
172
173 unsigned ArgOffset = 0;
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000174 int count = 0;
Duraid Madinabeeaab22005-03-31 12:31:11 +0000175
Alkis Evlogimenos12cf3852005-03-19 09:22:17 +0000176 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000177 {
178 SDOperand newroot, argt;
179 if(count < 8) { // need to fix this logic? maybe.
180
181 switch (getValueType(I->getType())) {
182 default:
183 std::cerr << "ERROR in LowerArgs: unknown type "
184 << getValueType(I->getType()) << "\n";
185 abort();
186 case MVT::f32:
187 // fixme? (well, will need to for weird FP structy stuff,
188 // see intel ABI docs)
189 case MVT::f64:
190 BuildMI(&BB, IA64::IDEF, 0, args_FP[used_FPArgs]);
191 // floating point args go into f8..f15 as-needed, the increment
192 argVreg[count] = // is below..:
193 MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::f64));
194 // FP args go into f8..f15 as needed: (hence the ++)
195 argPreg[count] = args_FP[used_FPArgs++];
196 argOpc[count] = IA64::FMOV;
197 argt = newroot = DAG.getCopyFromReg(argVreg[count],
198 getValueType(I->getType()), DAG.getRoot());
199 break;
200 case MVT::i1: // NOTE: as far as C abi stuff goes,
201 // bools are just boring old ints
202 case MVT::i8:
203 case MVT::i16:
204 case MVT::i32:
205 case MVT::i64:
206 BuildMI(&BB, IA64::IDEF, 0, args_int[count]);
207 argVreg[count] =
208 MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
209 argPreg[count] = args_int[count];
210 argOpc[count] = IA64::MOV;
211 argt = newroot =
212 DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot());
213 if ( getValueType(I->getType()) != MVT::i64)
214 argt = DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()),
215 newroot);
216 break;
217 }
218 } else { // more than 8 args go into the frame
219 // Create the frame index object for this incoming parameter...
Duraid Madinabeeaab22005-03-31 12:31:11 +0000220 ArgOffset = 16 + 8 * (count - 8);
221 int FI = MFI->CreateFixedObject(8, ArgOffset);
222
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000223 // Create the SelectionDAG nodes corresponding to a load
224 //from this parameter
225 SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
226 argt = newroot = DAG.getLoad(getValueType(I->getType()),
227 DAG.getEntryNode(), FIN);
228 }
229 ++count;
230 DAG.setRoot(newroot.getValue(1));
231 ArgValues.push_back(argt);
232 }
Duraid Madinabeeaab22005-03-31 12:31:11 +0000233
234
235 // Create a vreg to hold the output of (what will become)
236 // the "alloc" instruction
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000237 VirtGPR = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
238 BuildMI(&BB, IA64::PSEUDO_ALLOC, 0, VirtGPR);
239 // we create a PSEUDO_ALLOC (pseudo)instruction for now
240
241 BuildMI(&BB, IA64::IDEF, 0, IA64::r1);
242
243 // hmm:
244 BuildMI(&BB, IA64::IDEF, 0, IA64::r12);
245 BuildMI(&BB, IA64::IDEF, 0, IA64::rp);
246 // ..hmm.
247
248 BuildMI(&BB, IA64::MOV, 1, GP).addReg(IA64::r1);
249
250 // hmm:
251 BuildMI(&BB, IA64::MOV, 1, SP).addReg(IA64::r12);
252 BuildMI(&BB, IA64::MOV, 1, RP).addReg(IA64::rp);
253 // ..hmm.
254
Duraid Madinabeeaab22005-03-31 12:31:11 +0000255 unsigned tempOffset=0;
256
257 // if this is a varargs function, we simply lower llvm.va_start by
258 // pointing to the first entry
259 if(F.isVarArg()) {
260 tempOffset=0;
261 VarArgsFrameIndex = MFI->CreateFixedObject(8, tempOffset);
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000262 }
263
Duraid Madinabeeaab22005-03-31 12:31:11 +0000264 // here we actually do the moving of args, and store them to the stack
265 // too if this is a varargs function:
266 for (int i = 0; i < count && i < 8; ++i) {
267 BuildMI(&BB, argOpc[i], 1, argVreg[i]).addReg(argPreg[i]);
268 if(F.isVarArg()) {
269 // if this is a varargs function, we copy the input registers to the stack
270 int FI = MFI->CreateFixedObject(8, tempOffset);
271 tempOffset+=8; //XXX: is it safe to use r22 like this?
272 BuildMI(&BB, IA64::MOV, 1, IA64::r22).addFrameIndex(FI);
273 // FIXME: we should use st8.spill here, one day
274 BuildMI(&BB, IA64::ST8, 1, IA64::r22).addReg(argPreg[i]);
275 }
276 }
277
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000278 return ArgValues;
279}
280
281std::pair<SDOperand, SDOperand>
282IA64TargetLowering::LowerCallTo(SDOperand Chain,
Nate Begeman8e21e712005-03-26 01:29:23 +0000283 const Type *RetTy, bool isVarArg,
284 SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG) {
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000285
286 MachineFunction &MF = DAG.getMachineFunction();
287
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000288 unsigned NumBytes = 16;
Duraid Madinabeeaab22005-03-31 12:31:11 +0000289 unsigned outRegsUsed = 0;
290
291 if (Args.size() > 8) {
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000292 NumBytes += (Args.size() - 8) * 8;
Duraid Madinabeeaab22005-03-31 12:31:11 +0000293 outRegsUsed = 8;
294 } else {
295 outRegsUsed = Args.size();
296 }
297
298 // FIXME? this WILL fail if we ever try to pass around an arg that
299 // consumes more than a single output slot (a 'real' double, int128
300 // some sort of aggregate etc.), as we'll underestimate how many 'outX'
301 // registers we use. Hopefully, the assembler will notice.
302 MF.getInfo<IA64FunctionInfo>()->outRegsUsed=
303 std::max(outRegsUsed, MF.getInfo<IA64FunctionInfo>()->outRegsUsed);
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000304
305 Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
306 DAG.getConstant(NumBytes, getPointerTy()));
Duraid Madinabeeaab22005-03-31 12:31:11 +0000307
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000308 std::vector<SDOperand> args_to_use;
309 for (unsigned i = 0, e = Args.size(); i != e; ++i)
310 {
311 switch (getValueType(Args[i].second)) {
312 default: assert(0 && "unexpected argument type!");
313 case MVT::i1:
314 case MVT::i8:
315 case MVT::i16:
316 case MVT::i32:
317 //promote to 64-bits, sign/zero extending based on type
318 //of the argument
319 if(Args[i].second->isSigned())
320 Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64,
321 Args[i].first);
322 else
323 Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64,
324 Args[i].first);
325 break;
326 case MVT::f32:
327 //promote to 64-bits
328 Args[i].first = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Args[i].first);
329 case MVT::f64:
330 case MVT::i64:
331 break;
332 }
333 args_to_use.push_back(Args[i].first);
334 }
335
336 std::vector<MVT::ValueType> RetVals;
337 MVT::ValueType RetTyVT = getValueType(RetTy);
338 if (RetTyVT != MVT::isVoid)
339 RetVals.push_back(RetTyVT);
340 RetVals.push_back(MVT::Other);
341
342 SDOperand TheCall = SDOperand(DAG.getCall(RetVals, Chain,
343 Callee, args_to_use), 0);
344 Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
345 Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
346 DAG.getConstant(NumBytes, getPointerTy()));
347 return std::make_pair(TheCall, Chain);
348}
349
350std::pair<SDOperand, SDOperand>
351IA64TargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
352 // vastart just returns the address of the VarArgsFrameIndex slot.
353 return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain);
354}
355
356std::pair<SDOperand,SDOperand> IA64TargetLowering::
357LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
358 const Type *ArgTy, SelectionDAG &DAG) {
Duraid Madinabeeaab22005-03-31 12:31:11 +0000359
360 MVT::ValueType ArgVT = getValueType(ArgTy);
361 SDOperand Result;
362 if (!isVANext) {
363 Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), VAList);
364 } else {
365 unsigned Amt;
366 if (ArgVT == MVT::i32 || ArgVT == MVT::f32)
367 Amt = 8;
368 else {
369 assert((ArgVT == MVT::i64 || ArgVT == MVT::f64) &&
370 "Other types should have been promoted for varargs!");
371 Amt = 8;
372 }
373 Result = DAG.getNode(ISD::ADD, VAList.getValueType(), VAList,
374 DAG.getConstant(Amt, VAList.getValueType()));
375 }
376 return std::make_pair(Result, Chain);
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000377}
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000378
379std::pair<SDOperand, SDOperand> IA64TargetLowering::
380LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
381 SelectionDAG &DAG) {
382
383 assert(0 && "LowerFrameReturnAddress not done yet\n");
Duraid Madina817aed42005-03-17 19:00:40 +0000384 abort();
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000385}
386
387
388namespace {
389
390 //===--------------------------------------------------------------------===//
391 /// ISel - IA64 specific code to select IA64 machine instructions for
392 /// SelectionDAG operations.
393 ///
394 class ISel : public SelectionDAGISel {
395 /// IA64Lowering - This object fully describes how to lower LLVM code to an
396 /// IA64-specific SelectionDAG.
397 IA64TargetLowering IA64Lowering;
398
399 /// ExprMap - As shared expressions are codegen'd, we keep track of which
400 /// vreg the value is produced in, so we only emit one copy of each compiled
401 /// tree.
402 std::map<SDOperand, unsigned> ExprMap;
403 std::set<SDOperand> LoweredTokens;
404
405 public:
406 ISel(TargetMachine &TM) : SelectionDAGISel(IA64Lowering), IA64Lowering(TM) {
407 }
408
409 /// InstructionSelectBasicBlock - This callback is invoked by
410 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
411 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
412
413// bool isFoldableLoad(SDOperand Op);
414// void EmitFoldedLoad(SDOperand Op, IA64AddressMode &AM);
415
416 unsigned SelectExpr(SDOperand N);
417 void Select(SDOperand N);
418 };
419}
420
421/// InstructionSelectBasicBlock - This callback is invoked by SelectionDAGISel
422/// when it has created a SelectionDAG for us to codegen.
423void ISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
424
425 // Codegen the basic block.
426 Select(DAG.getRoot());
427
428 // Clear state used for selection.
429 ExprMap.clear();
430 LoweredTokens.clear();
431}
432
433unsigned ISel::SelectExpr(SDOperand N) {
434 unsigned Result;
435 unsigned Tmp1, Tmp2, Tmp3;
436 unsigned Opc = 0;
437 MVT::ValueType DestType = N.getValueType();
438
439 unsigned opcode = N.getOpcode();
440
441 SDNode *Node = N.Val;
442 SDOperand Op0, Op1;
443
444 if (Node->getOpcode() == ISD::CopyFromReg)
445 // Just use the specified register as our input.
446 return dyn_cast<RegSDNode>(Node)->getReg();
447
448 unsigned &Reg = ExprMap[N];
449 if (Reg) return Reg;
450
451 if (N.getOpcode() != ISD::CALL)
452 Reg = Result = (N.getValueType() != MVT::Other) ?
453 MakeReg(N.getValueType()) : 1;
454 else {
455 // If this is a call instruction, make sure to prepare ALL of the result
456 // values as well as the chain.
457 if (Node->getNumValues() == 1)
458 Reg = Result = 1; // Void call, just a chain.
459 else {
460 Result = MakeReg(Node->getValueType(0));
461 ExprMap[N.getValue(0)] = Result;
462 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
463 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
464 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1;
465 }
466 }
467
468 switch (N.getOpcode()) {
469 default:
470 Node->dump();
471 assert(0 && "Node not handled!\n");
472
473 case ISD::FrameIndex: {
474 Tmp1 = cast<FrameIndexSDNode>(N)->getIndex();
475 BuildMI(BB, IA64::MOV, 1, Result).addFrameIndex(Tmp1);
476 return Result;
477 }
478
479 case ISD::ConstantPool: {
480 Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
481 IA64Lowering.restoreGP(BB); // FIXME: do i really need this?
482 BuildMI(BB, IA64::ADD, 2, Result).addConstantPoolIndex(Tmp1)
483 .addReg(IA64::r1);
484 return Result;
485 }
486
487 case ISD::ConstantFP: {
488 Tmp1 = Result; // Intermediate Register
489 if (cast<ConstantFPSDNode>(N)->getValue() < 0.0 ||
490 cast<ConstantFPSDNode>(N)->isExactlyValue(-0.0))
491 Tmp1 = MakeReg(MVT::f64);
492
493 if (cast<ConstantFPSDNode>(N)->isExactlyValue(+0.0) ||
494 cast<ConstantFPSDNode>(N)->isExactlyValue(-0.0))
495 BuildMI(BB, IA64::FMOV, 1, Tmp1).addReg(IA64::F0); // load 0.0
496 else if (cast<ConstantFPSDNode>(N)->isExactlyValue(+1.0) ||
497 cast<ConstantFPSDNode>(N)->isExactlyValue(-1.0))
498 BuildMI(BB, IA64::FMOV, 1, Tmp1).addReg(IA64::F1); // load 1.0
499 else
500 assert(0 && "Unexpected FP constant!");
501 if (Tmp1 != Result)
502 // we multiply by +1.0, negate (this is FNMA), and then add 0.0
503 BuildMI(BB, IA64::FNMA, 3, Result).addReg(Tmp1).addReg(IA64::F1)
504 .addReg(IA64::F0);
505 return Result;
506 }
507
508 case ISD::DYNAMIC_STACKALLOC: {
509 // Generate both result values.
510 if (Result != 1)
511 ExprMap[N.getValue(1)] = 1; // Generate the token
512 else
513 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
514
515 // FIXME: We are currently ignoring the requested alignment for handling
516 // greater than the stack alignment. This will need to be revisited at some
517 // point. Align = N.getOperand(2);
518
519 if (!isa<ConstantSDNode>(N.getOperand(2)) ||
520 cast<ConstantSDNode>(N.getOperand(2))->getValue() != 0) {
521 std::cerr << "Cannot allocate stack object with greater alignment than"
522 << " the stack alignment yet!";
523 abort();
524 }
Duraid Madinabeeaab22005-03-31 12:31:11 +0000525
526/*
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000527 Select(N.getOperand(0));
528 if (ConstantSDNode* CN = dyn_cast<ConstantSDNode>(N.getOperand(1)))
529 {
530 if (CN->getValue() < 32000)
531 {
532 BuildMI(BB, IA64::ADDIMM22, 2, IA64::r12).addReg(IA64::r12)
533 .addImm(-CN->getValue());
534 } else {
535 Tmp1 = SelectExpr(N.getOperand(1));
536 // Subtract size from stack pointer, thereby allocating some space.
537 BuildMI(BB, IA64::SUB, 2, IA64::r12).addReg(IA64::r12).addReg(Tmp1);
538 }
539 } else {
540 Tmp1 = SelectExpr(N.getOperand(1));
541 // Subtract size from stack pointer, thereby allocating some space.
542 BuildMI(BB, IA64::SUB, 2, IA64::r12).addReg(IA64::r12).addReg(Tmp1);
543 }
Duraid Madinabeeaab22005-03-31 12:31:11 +0000544*/
545 Select(N.getOperand(0));
546 Tmp1 = SelectExpr(N.getOperand(1));
547 // Subtract size from stack pointer, thereby allocating some space.
548 BuildMI(BB, IA64::SUB, 2, IA64::r12).addReg(IA64::r12).addReg(Tmp1);
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000549 // Put a pointer to the space into the result register, by copying the
550 // stack pointer.
551 BuildMI(BB, IA64::MOV, 1, Result).addReg(IA64::r12);
552 return Result;
553 }
554
555 case ISD::SELECT: {
556 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
557 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
558 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
559
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000560 unsigned bogoResult;
561
562 switch (N.getOperand(1).getValueType()) {
563 default: assert(0 &&
564 "ISD::SELECT: 'select'ing something other than i64 or f64!\n");
565 case MVT::i64:
566 bogoResult=MakeReg(MVT::i64);
567 break;
568 case MVT::f64:
569 bogoResult=MakeReg(MVT::f64);
570 break;
571 }
Duraid Madina69c8e202005-04-01 10:35:00 +0000572
573 BuildMI(BB, IA64::MOV, 1, bogoResult).addReg(Tmp3);
574 BuildMI(BB, IA64::CMOV, 2, Result).addReg(bogoResult).addReg(Tmp2)
575 .addReg(Tmp1); // FIXME: should be FMOV/FCMOV sometimes,
576 // though this will work for now (no JIT)
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000577 return Result;
578 }
579
580 case ISD::Constant: {
581 unsigned depositPos=0;
582 unsigned depositLen=0;
583 switch (N.getValueType()) {
584 default: assert(0 && "Cannot use constants of this type!");
585 case MVT::i1: { // if a bool, we don't 'load' so much as generate
586 // the constant:
587 if(cast<ConstantSDNode>(N)->getValue()) // true:
588 BuildMI(BB, IA64::CMPEQ, 2, Result)
589 .addReg(IA64::r0).addReg(IA64::r0);
590 else // false:
591 BuildMI(BB, IA64::CMPNE, 2, Result)
592 .addReg(IA64::r0).addReg(IA64::r0);
593 return Result;
594 }
595 case MVT::i64: Opc = IA64::MOVLI32; break;
596 }
597
598 int64_t immediate = cast<ConstantSDNode>(N)->getValue();
599 if(immediate>>32) { // if our immediate really is big:
600 int highPart = immediate>>32;
601 int lowPart = immediate&0xFFFFFFFF;
602 unsigned dummy = MakeReg(MVT::i64);
603 unsigned dummy2 = MakeReg(MVT::i64);
604 unsigned dummy3 = MakeReg(MVT::i64);
605
606 BuildMI(BB, IA64::MOVLI32, 1, dummy).addImm(highPart);
607 BuildMI(BB, IA64::SHLI, 2, dummy2).addReg(dummy).addImm(32);
608 BuildMI(BB, IA64::MOVLI32, 1, dummy3).addImm(lowPart);
609 BuildMI(BB, IA64::ADD, 2, Result).addReg(dummy2).addReg(dummy3);
610 } else {
611 BuildMI(BB, IA64::MOVLI32, 1, Result).addImm(immediate);
612 }
613
614 return Result;
615 }
616
617 case ISD::GlobalAddress: {
618 GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
619 unsigned Tmp1 = MakeReg(MVT::i64);
Duraid Madinabeeaab22005-03-31 12:31:11 +0000620
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000621 BuildMI(BB, IA64::ADD, 2, Tmp1).addGlobalAddress(GV).addReg(IA64::r1);
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000622 BuildMI(BB, IA64::LD8, 1, Result).addReg(Tmp1);
Duraid Madinabeeaab22005-03-31 12:31:11 +0000623
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000624 return Result;
625 }
626
627 case ISD::ExternalSymbol: {
628 const char *Sym = cast<ExternalSymbolSDNode>(N)->getSymbol();
Duraid Madinabeeaab22005-03-31 12:31:11 +0000629// assert(0 && "sorry, but what did you want an ExternalSymbol for again?");
630 BuildMI(BB, IA64::MOV, 1, Result).addExternalSymbol(Sym); // XXX
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000631 return Result;
632 }
633
634 case ISD::FP_EXTEND: {
635 Tmp1 = SelectExpr(N.getOperand(0));
636 BuildMI(BB, IA64::FMOV, 1, Result).addReg(Tmp1);
637 return Result;
638 }
639
640 case ISD::ZERO_EXTEND: {
641 Tmp1 = SelectExpr(N.getOperand(0)); // value
642
643 switch (N.getOperand(0).getValueType()) {
644 default: assert(0 && "Cannot zero-extend this type!");
645 case MVT::i8: Opc = IA64::ZXT1; break;
646 case MVT::i16: Opc = IA64::ZXT2; break;
647 case MVT::i32: Opc = IA64::ZXT4; break;
648
649 // we handle bools differently! :
650 case MVT::i1: { // if the predicate reg has 1, we want a '1' in our GR.
651 unsigned dummy = MakeReg(MVT::i64);
652 // first load zero:
653 BuildMI(BB, IA64::MOV, 1, dummy).addReg(IA64::r0);
654 // ...then conditionally (PR:Tmp1) add 1:
655 BuildMI(BB, IA64::CADDIMM22, 3, Result).addReg(dummy)
656 .addImm(1).addReg(Tmp1);
657 return Result; // XXX early exit!
658 }
659 }
660
661 BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
662 return Result;
663 }
664
665 case ISD::SIGN_EXTEND: { // we should only have to handle i1 -> i64 here!!!
666
667assert(0 && "hmm, ISD::SIGN_EXTEND: shouldn't ever be reached. bad luck!\n");
668
669 Tmp1 = SelectExpr(N.getOperand(0)); // value
670
671 switch (N.getOperand(0).getValueType()) {
672 default: assert(0 && "Cannot sign-extend this type!");
673 case MVT::i1: assert(0 && "trying to sign extend a bool? ow.\n");
674 Opc = IA64::SXT1; break;
675 // FIXME: for now, we treat bools the same as i8s
676 case MVT::i8: Opc = IA64::SXT1; break;
677 case MVT::i16: Opc = IA64::SXT2; break;
678 case MVT::i32: Opc = IA64::SXT4; break;
679 }
680
681 BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
682 return Result;
683 }
684
685 case ISD::TRUNCATE: {
686 // we use the funky dep.z (deposit (zero)) instruction to deposit bits
687 // of R0 appropriately.
688 switch (N.getOperand(0).getValueType()) {
689 default: assert(0 && "Unknown truncate!");
690 case MVT::i64: break;
691 }
692 Tmp1 = SelectExpr(N.getOperand(0));
693 unsigned depositPos, depositLen;
694
695 switch (N.getValueType()) {
696 default: assert(0 && "Unknown truncate!");
697 case MVT::i1: {
698 // if input (normal reg) is 0, 0!=0 -> false (0), if 1, 1!=0 ->true (1):
699 BuildMI(BB, IA64::CMPNE, 2, Result).addReg(Tmp1)
700 .addReg(IA64::r0);
701 return Result; // XXX early exit!
702 }
703 case MVT::i8: depositPos=0; depositLen=8; break;
704 case MVT::i16: depositPos=0; depositLen=16; break;
705 case MVT::i32: depositPos=0; depositLen=32; break;
706 }
707 BuildMI(BB, IA64::DEPZ, 1, Result).addReg(Tmp1)
708 .addImm(depositPos).addImm(depositLen);
709 return Result;
710 }
711
712/*
713 case ISD::FP_ROUND: {
714 assert (DestType == MVT::f32 && N.getOperand(0).getValueType() == MVT::f64 &&
715 "error: trying to FP_ROUND something other than f64 -> f32!\n");
716 Tmp1 = SelectExpr(N.getOperand(0));
717 BuildMI(BB, IA64::FADDS, 2, Result).addReg(Tmp1).addReg(IA64::F0);
718 // we add 0.0 using a single precision add to do rounding
719 return Result;
720 }
721*/
722
723// FIXME: the following 4 cases need cleaning
724 case ISD::SINT_TO_FP: {
725 Tmp1 = SelectExpr(N.getOperand(0));
726 Tmp2 = MakeReg(MVT::f64);
727 unsigned dummy = MakeReg(MVT::f64);
728 BuildMI(BB, IA64::SETFSIG, 1, Tmp2).addReg(Tmp1);
729 BuildMI(BB, IA64::FCVTXF, 1, dummy).addReg(Tmp2);
730 BuildMI(BB, IA64::FNORMD, 1, Result).addReg(dummy);
731 return Result;
732 }
733
734 case ISD::UINT_TO_FP: {
735 Tmp1 = SelectExpr(N.getOperand(0));
736 Tmp2 = MakeReg(MVT::f64);
737 unsigned dummy = MakeReg(MVT::f64);
738 BuildMI(BB, IA64::SETFSIG, 1, Tmp2).addReg(Tmp1);
739 BuildMI(BB, IA64::FCVTXUF, 1, dummy).addReg(Tmp2);
740 BuildMI(BB, IA64::FNORMD, 1, Result).addReg(dummy);
741 return Result;
742 }
743
744 case ISD::FP_TO_SINT: {
745 Tmp1 = SelectExpr(N.getOperand(0));
746 Tmp2 = MakeReg(MVT::f64);
747 BuildMI(BB, IA64::FCVTFXTRUNC, 1, Tmp2).addReg(Tmp1);
748 BuildMI(BB, IA64::GETFSIG, 1, Result).addReg(Tmp2);
749 return Result;
750 }
751
752 case ISD::FP_TO_UINT: {
753 Tmp1 = SelectExpr(N.getOperand(0));
754 Tmp2 = MakeReg(MVT::f64);
755 BuildMI(BB, IA64::FCVTFXUTRUNC, 1, Tmp2).addReg(Tmp1);
756 BuildMI(BB, IA64::GETFSIG, 1, Result).addReg(Tmp2);
757 return Result;
758 }
759
760 case ISD::ADD: {
761 Tmp1 = SelectExpr(N.getOperand(0));
762 Tmp2 = SelectExpr(N.getOperand(1));
763 if(DestType != MVT::f64)
764 BuildMI(BB, IA64::ADD, 2, Result).addReg(Tmp1).addReg(Tmp2); // int
765 else
766 BuildMI(BB, IA64::FADD, 2, Result).addReg(Tmp1).addReg(Tmp2); // FP
767 return Result;
768 }
769
770 case ISD::MUL: {
771 Tmp1 = SelectExpr(N.getOperand(0));
772 Tmp2 = SelectExpr(N.getOperand(1));
773 if(DestType != MVT::f64) { // integer multiply, emit some code (FIXME)
774 unsigned TempFR1=MakeReg(MVT::f64);
775 unsigned TempFR2=MakeReg(MVT::f64);
776 unsigned TempFR3=MakeReg(MVT::f64);
777 BuildMI(BB, IA64::SETFSIG, 1, TempFR1).addReg(Tmp1);
778 BuildMI(BB, IA64::SETFSIG, 1, TempFR2).addReg(Tmp2);
779 BuildMI(BB, IA64::XMAL, 1, TempFR3).addReg(TempFR1).addReg(TempFR2)
780 .addReg(IA64::F0);
781 BuildMI(BB, IA64::GETFSIG, 1, Result).addReg(TempFR3);
782 }
783 else // floating point multiply
784 BuildMI(BB, IA64::FMPY, 2, Result).addReg(Tmp1).addReg(Tmp2);
785 return Result;
786 }
787
788 case ISD::SUB: {
789 Tmp1 = SelectExpr(N.getOperand(0));
790 Tmp2 = SelectExpr(N.getOperand(1));
791 if(DestType != MVT::f64)
792 BuildMI(BB, IA64::SUB, 2, Result).addReg(Tmp1).addReg(Tmp2);
793 else
794 BuildMI(BB, IA64::FSUB, 2, Result).addReg(Tmp1).addReg(Tmp2);
795 return Result;
796 }
797
798 case ISD::AND: {
799 switch (N.getValueType()) {
800 default: assert(0 && "Cannot AND this type!");
801 case MVT::i1: { // if a bool, we emit a pseudocode AND
802 unsigned pA = SelectExpr(N.getOperand(0));
803 unsigned pB = SelectExpr(N.getOperand(1));
804
805/* our pseudocode for AND is:
806 *
807(pA) cmp.eq.unc pC,p0 = r0,r0 // pC = pA
808 cmp.eq pTemp,p0 = r0,r0 // pTemp = NOT pB
809 ;;
810(pB) cmp.ne pTemp,p0 = r0,r0
811 ;;
812(pTemp)cmp.ne pC,p0 = r0,r0 // if (NOT pB) pC = 0
813
814*/
815 unsigned pTemp = MakeReg(MVT::i1);
816
817 unsigned bogusTemp1 = MakeReg(MVT::i1);
818 unsigned bogusTemp2 = MakeReg(MVT::i1);
819 unsigned bogusTemp3 = MakeReg(MVT::i1);
820 unsigned bogusTemp4 = MakeReg(MVT::i1);
821
822 BuildMI(BB, IA64::PCMPEQUNC, 3, bogusTemp1)
823 .addReg(IA64::r0).addReg(IA64::r0).addReg(pA);
824 BuildMI(BB, IA64::CMPEQ, 2, bogusTemp2)
825 .addReg(IA64::r0).addReg(IA64::r0);
826 BuildMI(BB, IA64::TPCMPNE, 3, pTemp)
827 .addReg(bogusTemp2).addReg(IA64::r0).addReg(IA64::r0).addReg(pB);
828 BuildMI(BB, IA64::TPCMPNE, 3, Result)
829 .addReg(bogusTemp1).addReg(IA64::r0).addReg(IA64::r0).addReg(pTemp);
830 break;
831 }
832 // if not a bool, we just AND away:
833 case MVT::i8:
834 case MVT::i16:
835 case MVT::i32:
836 case MVT::i64: {
837 Tmp1 = SelectExpr(N.getOperand(0));
838 Tmp2 = SelectExpr(N.getOperand(1));
839 BuildMI(BB, IA64::AND, 2, Result).addReg(Tmp1).addReg(Tmp2);
840 break;
841 }
842 }
843 return Result;
844 }
845
846 case ISD::OR: {
847 switch (N.getValueType()) {
848 default: assert(0 && "Cannot OR this type!");
849 case MVT::i1: { // if a bool, we emit a pseudocode OR
850 unsigned pA = SelectExpr(N.getOperand(0));
851 unsigned pB = SelectExpr(N.getOperand(1));
852
853 unsigned pTemp1 = MakeReg(MVT::i1);
854
855/* our pseudocode for OR is:
856 *
857
858pC = pA OR pB
859-------------
860
861(pA) cmp.eq.unc pC,p0 = r0,r0 // pC = pA
862 ;;
863(pB) cmp.eq pC,p0 = r0,r0 // if (pB) pC = 1
864
865*/
866 BuildMI(BB, IA64::PCMPEQUNC, 3, pTemp1)
867 .addReg(IA64::r0).addReg(IA64::r0).addReg(pA);
868 BuildMI(BB, IA64::TPCMPEQ, 3, Result)
869 .addReg(pTemp1).addReg(IA64::r0).addReg(IA64::r0).addReg(pB);
870 break;
871 }
872 // if not a bool, we just OR away:
873 case MVT::i8:
874 case MVT::i16:
875 case MVT::i32:
876 case MVT::i64: {
877 Tmp1 = SelectExpr(N.getOperand(0));
878 Tmp2 = SelectExpr(N.getOperand(1));
879 BuildMI(BB, IA64::OR, 2, Result).addReg(Tmp1).addReg(Tmp2);
880 break;
881 }
882 }
883 return Result;
884 }
885
886 case ISD::XOR: {
887 switch (N.getValueType()) {
888 default: assert(0 && "Cannot XOR this type!");
889 case MVT::i1: { // if a bool, we emit a pseudocode XOR
890 unsigned pY = SelectExpr(N.getOperand(0));
891 unsigned pZ = SelectExpr(N.getOperand(1));
892
893/* one possible routine for XOR is:
894
895 // Compute px = py ^ pz
896 // using sum of products: px = (py & !pz) | (pz & !py)
897 // Uses 5 instructions in 3 cycles.
898 // cycle 1
899(pz) cmp.eq.unc px = r0, r0 // px = pz
900(py) cmp.eq.unc pt = r0, r0 // pt = py
901 ;;
902 // cycle 2
903(pt) cmp.ne.and px = r0, r0 // px = px & !pt (px = pz & !pt)
904(pz) cmp.ne.and pt = r0, r0 // pt = pt & !pz
905 ;;
906 } { .mmi
907 // cycle 3
908(pt) cmp.eq.or px = r0, r0 // px = px | pt
909
910*** Another, which we use here, requires one scratch GR. it is:
911
912 mov rt = 0 // initialize rt off critical path
913 ;;
914
915 // cycle 1
916(pz) cmp.eq.unc px = r0, r0 // px = pz
917(pz) mov rt = 1 // rt = pz
918 ;;
919 // cycle 2
920(py) cmp.ne px = 1, rt // if (py) px = !pz
921
922.. these routines kindly provided by Jim Hull
923*/
924 unsigned rt = MakeReg(MVT::i64);
925
926 // these two temporaries will never actually appear,
927 // due to the two-address form of some of the instructions below
928 unsigned bogoPR = MakeReg(MVT::i1); // becomes Result
929 unsigned bogoGR = MakeReg(MVT::i64); // becomes rt
930
931 BuildMI(BB, IA64::MOV, 1, bogoGR).addReg(IA64::r0);
932 BuildMI(BB, IA64::PCMPEQUNC, 3, bogoPR)
933 .addReg(IA64::r0).addReg(IA64::r0).addReg(pZ);
934 BuildMI(BB, IA64::TPCADDIMM22, 2, rt)
935 .addReg(bogoGR).addImm(1).addReg(pZ);
936 BuildMI(BB, IA64::TPCMPIMM8NE, 3, Result)
937 .addReg(bogoPR).addImm(1).addReg(rt).addReg(pY);
938 break;
939 }
940 // if not a bool, we just XOR away:
941 case MVT::i8:
942 case MVT::i16:
943 case MVT::i32:
944 case MVT::i64: {
945 Tmp1 = SelectExpr(N.getOperand(0));
946 Tmp2 = SelectExpr(N.getOperand(1));
947 BuildMI(BB, IA64::XOR, 2, Result).addReg(Tmp1).addReg(Tmp2);
948 break;
949 }
950 }
951 return Result;
952 }
953
954 case ISD::SHL: {
955 Tmp1 = SelectExpr(N.getOperand(0));
956 Tmp2 = SelectExpr(N.getOperand(1));
957 BuildMI(BB, IA64::SHL, 2, Result).addReg(Tmp1).addReg(Tmp2);
958 return Result;
959 }
960 case ISD::SRL: {
961 Tmp1 = SelectExpr(N.getOperand(0));
962 Tmp2 = SelectExpr(N.getOperand(1));
963 BuildMI(BB, IA64::SHRU, 2, Result).addReg(Tmp1).addReg(Tmp2);
964 return Result;
965 }
966 case ISD::SRA: {
967 Tmp1 = SelectExpr(N.getOperand(0));
968 Tmp2 = SelectExpr(N.getOperand(1));
969 BuildMI(BB, IA64::SHRS, 2, Result).addReg(Tmp1).addReg(Tmp2);
970 return Result;
971 }
972
973 case ISD::SDIV:
974 case ISD::UDIV:
975 case ISD::SREM:
976 case ISD::UREM: {
977
978 Tmp1 = SelectExpr(N.getOperand(0));
979 Tmp2 = SelectExpr(N.getOperand(1));
980
981 bool isFP=false;
982
983 if(DestType == MVT::f64) // XXX: we're not gonna be fed MVT::f32, are we?
984 isFP=true;
985
986 bool isModulus=false; // is it a division or a modulus?
987 bool isSigned=false;
988
989 switch(N.getOpcode()) {
990 case ISD::SDIV: isModulus=false; isSigned=true; break;
991 case ISD::UDIV: isModulus=false; isSigned=false; break;
992 case ISD::SREM: isModulus=true; isSigned=true; break;
993 case ISD::UREM: isModulus=true; isSigned=false; break;
994 }
995
Duraid Madinabeeaab22005-03-31 12:31:11 +0000996 unsigned TmpPR=MakeReg(MVT::i1); // we need two scratch
997 unsigned TmpPR2=MakeReg(MVT::i1); // predicate registers,
Duraid Madina9b9d45f2005-03-17 18:17:03 +0000998 unsigned TmpF1=MakeReg(MVT::f64); // and one metric truckload of FP regs.
999 unsigned TmpF2=MakeReg(MVT::f64); // lucky we have IA64?
1000 unsigned TmpF3=MakeReg(MVT::f64); // well, the real FIXME is to have
1001 unsigned TmpF4=MakeReg(MVT::f64); // isTwoAddress forms of these
1002 unsigned TmpF5=MakeReg(MVT::f64); // FP instructions so we can end up with
1003 unsigned TmpF6=MakeReg(MVT::f64); // stuff like setf.sig f10=f10 etc.
1004 unsigned TmpF7=MakeReg(MVT::f64);
1005 unsigned TmpF8=MakeReg(MVT::f64);
1006 unsigned TmpF9=MakeReg(MVT::f64);
1007 unsigned TmpF10=MakeReg(MVT::f64);
1008 unsigned TmpF11=MakeReg(MVT::f64);
1009 unsigned TmpF12=MakeReg(MVT::f64);
1010 unsigned TmpF13=MakeReg(MVT::f64);
1011 unsigned TmpF14=MakeReg(MVT::f64);
1012 unsigned TmpF15=MakeReg(MVT::f64);
Duraid Madinabeeaab22005-03-31 12:31:11 +00001013
Duraid Madina9b9d45f2005-03-17 18:17:03 +00001014 // OK, emit some code:
1015
1016 if(!isFP) {
1017 // first, load the inputs into FP regs.
1018 BuildMI(BB, IA64::SETFSIG, 1, TmpF1).addReg(Tmp1);
1019 BuildMI(BB, IA64::SETFSIG, 1, TmpF2).addReg(Tmp2);
1020
1021 // next, convert the inputs to FP
1022 if(isSigned) {
1023 BuildMI(BB, IA64::FCVTXF, 1, TmpF3).addReg(TmpF1);
1024 BuildMI(BB, IA64::FCVTXF, 1, TmpF4).addReg(TmpF2);
1025 } else {
1026 BuildMI(BB, IA64::FCVTXUFS1, 1, TmpF3).addReg(TmpF1);
1027 BuildMI(BB, IA64::FCVTXUFS1, 1, TmpF4).addReg(TmpF2);
1028 }
1029
1030 } else { // this is an FP divide/remainder, so we 'leak' some temp
1031 // regs and assign TmpF3=Tmp1, TmpF4=Tmp2
1032 TmpF3=Tmp1;
1033 TmpF4=Tmp2;
1034 }
1035
1036 // we start by computing an approximate reciprocal (good to 9 bits?)
1037 // note, this instruction writes _both_ TmpF5 (answer) and tmpPR (predicate)
1038 // FIXME: or at least, it should!!
1039 BuildMI(BB, IA64::FRCPAS1FLOAT, 2, TmpF5).addReg(TmpF3).addReg(TmpF4);
1040 BuildMI(BB, IA64::FRCPAS1PREDICATE, 2, TmpPR).addReg(TmpF3).addReg(TmpF4);
1041
Duraid Madinabeeaab22005-03-31 12:31:11 +00001042 if(!isModulus) { // if this is a divide, we worry about div-by-zero
1043 unsigned bogusPR=MakeReg(MVT::i1); // won't appear, due to twoAddress
1044 // TPCMPNE below
1045 BuildMI(BB, IA64::CMPEQ, 2, bogusPR).addReg(IA64::r0).addReg(IA64::r0);
1046 BuildMI(BB, IA64::TPCMPNE, 3, TmpPR2).addReg(bogusPR)
1047 .addReg(IA64::r0).addReg(IA64::r0).addReg(TmpPR);
1048 }
1049
Duraid Madina9b9d45f2005-03-17 18:17:03 +00001050 // now we apply newton's method, thrice! (FIXME: this is ~72 bits of
1051 // precision, don't need this much for f32/i32)
1052 BuildMI(BB, IA64::CFNMAS1, 4, TmpF6)
1053 .addReg(TmpF4).addReg(TmpF5).addReg(IA64::F1).addReg(TmpPR);
1054 BuildMI(BB, IA64::CFMAS1, 4, TmpF7)
1055 .addReg(TmpF3).addReg(TmpF5).addReg(IA64::F0).addReg(TmpPR);
1056 BuildMI(BB, IA64::CFMAS1, 4, TmpF8)
1057 .addReg(TmpF6).addReg(TmpF6).addReg(IA64::F0).addReg(TmpPR);
1058 BuildMI(BB, IA64::CFMAS1, 4, TmpF9)
1059 .addReg(TmpF6).addReg(TmpF7).addReg(TmpF7).addReg(TmpPR);
1060 BuildMI(BB, IA64::CFMAS1, 4,TmpF10)
1061 .addReg(TmpF6).addReg(TmpF5).addReg(TmpF5).addReg(TmpPR);
1062 BuildMI(BB, IA64::CFMAS1, 4,TmpF11)
1063 .addReg(TmpF8).addReg(TmpF9).addReg(TmpF9).addReg(TmpPR);
1064 BuildMI(BB, IA64::CFMAS1, 4,TmpF12)
1065 .addReg(TmpF8).addReg(TmpF10).addReg(TmpF10).addReg(TmpPR);
1066 BuildMI(BB, IA64::CFNMAS1, 4,TmpF13)
1067 .addReg(TmpF4).addReg(TmpF11).addReg(TmpF3).addReg(TmpPR);
1068 BuildMI(BB, IA64::CFMAS1, 4,TmpF14)
1069 .addReg(TmpF13).addReg(TmpF12).addReg(TmpF11).addReg(TmpPR);
1070
1071 if(!isFP) {
1072 // round to an integer
1073 if(isSigned)
1074 BuildMI(BB, IA64::FCVTFXTRUNCS1, 1, TmpF15).addReg(TmpF14);
1075 else
1076 BuildMI(BB, IA64::FCVTFXUTRUNCS1, 1, TmpF15).addReg(TmpF14);
1077 } else {
1078 BuildMI(BB, IA64::FMOV, 1, TmpF15).addReg(TmpF14);
1079 // EXERCISE: can you see why TmpF15=TmpF14 does not work here, and
1080 // we really do need the above FMOV? ;)
1081 }
1082
1083 if(!isModulus) {
Duraid Madinabeeaab22005-03-31 12:31:11 +00001084 if(isFP) { // extra worrying about div-by-zero
1085 unsigned bogoResult=MakeReg(MVT::f64);
1086
1087 // we do a 'conditional fmov' (of the correct result, depending
1088 // on how the frcpa predicate turned out)
1089 BuildMI(BB, IA64::PFMOV, 2, bogoResult)
1090 .addReg(TmpF12).addReg(TmpPR2);
1091 BuildMI(BB, IA64::CFMOV, 2, Result)
1092 .addReg(bogoResult).addReg(TmpF15).addReg(TmpPR);
1093 }
Duraid Madina9b9d45f2005-03-17 18:17:03 +00001094 else
1095 BuildMI(BB, IA64::GETFSIG, 1, Result).addReg(TmpF15);
1096 } else { // this is a modulus
1097 if(!isFP) {
1098 // answer = q * (-b) + a
1099 unsigned ModulusResult = MakeReg(MVT::f64);
1100 unsigned TmpF = MakeReg(MVT::f64);
1101 unsigned TmpI = MakeReg(MVT::i64);
1102 BuildMI(BB, IA64::SUB, 2, TmpI).addReg(IA64::r0).addReg(Tmp2);
1103 BuildMI(BB, IA64::SETFSIG, 1, TmpF).addReg(TmpI);
1104 BuildMI(BB, IA64::XMAL, 3, ModulusResult)
1105 .addReg(TmpF15).addReg(TmpF).addReg(TmpF1);
1106 BuildMI(BB, IA64::GETFSIG, 1, Result).addReg(ModulusResult);
1107 } else { // FP modulus! The horror... the horror....
1108 assert(0 && "sorry, no FP modulus just yet!\n!\n");
1109 }
1110 }
1111
1112 return Result;
1113 }
1114
1115 case ISD::ZERO_EXTEND_INREG: {
1116 Tmp1 = SelectExpr(N.getOperand(0));
1117 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
1118 switch(MVN->getExtraValueType())
1119 {
1120 default:
1121 Node->dump();
1122 assert(0 && "don't know how to zero extend this type");
1123 break;
1124 case MVT::i8: Opc = IA64::ZXT1; break;
1125 case MVT::i16: Opc = IA64::ZXT2; break;
1126 case MVT::i32: Opc = IA64::ZXT4; break;
1127 }
1128 BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
1129 return Result;
1130 }
1131
1132 case ISD::SIGN_EXTEND_INREG: {
1133 Tmp1 = SelectExpr(N.getOperand(0));
1134 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
1135 switch(MVN->getExtraValueType())
1136 {
1137 default:
1138 Node->dump();
1139 assert(0 && "don't know how to sign extend this type");
1140 break;
1141 case MVT::i8: Opc = IA64::SXT1; break;
1142 case MVT::i16: Opc = IA64::SXT2; break;
1143 case MVT::i32: Opc = IA64::SXT4; break;
1144 }
1145 BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
1146 return Result;
1147 }
1148
1149 case ISD::SETCC: {
1150 Tmp1 = SelectExpr(N.getOperand(0));
1151 Tmp2 = SelectExpr(N.getOperand(1));
1152 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
1153 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
1154 switch (SetCC->getCondition()) {
1155 default: assert(0 && "Unknown integer comparison!");
1156 case ISD::SETEQ:
1157 BuildMI(BB, IA64::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
1158 break;
1159 case ISD::SETGT:
1160 BuildMI(BB, IA64::CMPGT, 2, Result).addReg(Tmp1).addReg(Tmp2);
1161 break;
1162 case ISD::SETGE:
1163 BuildMI(BB, IA64::CMPGE, 2, Result).addReg(Tmp1).addReg(Tmp2);
1164 break;
1165 case ISD::SETLT:
1166 BuildMI(BB, IA64::CMPLT, 2, Result).addReg(Tmp1).addReg(Tmp2);
1167 break;
1168 case ISD::SETLE:
1169 BuildMI(BB, IA64::CMPLE, 2, Result).addReg(Tmp1).addReg(Tmp2);
1170 break;
1171 case ISD::SETNE:
1172 BuildMI(BB, IA64::CMPNE, 2, Result).addReg(Tmp1).addReg(Tmp2);
1173 break;
1174 case ISD::SETULT:
1175 BuildMI(BB, IA64::CMPLTU, 2, Result).addReg(Tmp1).addReg(Tmp2);
1176 break;
1177 case ISD::SETUGT:
1178 BuildMI(BB, IA64::CMPGTU, 2, Result).addReg(Tmp1).addReg(Tmp2);
1179 break;
1180 case ISD::SETULE:
1181 BuildMI(BB, IA64::CMPLEU, 2, Result).addReg(Tmp1).addReg(Tmp2);
1182 break;
1183 case ISD::SETUGE:
1184 BuildMI(BB, IA64::CMPGEU, 2, Result).addReg(Tmp1).addReg(Tmp2);
1185 break;
1186 }
1187 }
1188 else { // if not integer, should be FP. FIXME: what about bools? ;)
1189 assert(SetCC->getOperand(0).getValueType() != MVT::f32 &&
1190 "error: SETCC should have had incoming f32 promoted to f64!\n");
1191 switch (SetCC->getCondition()) {
1192 default: assert(0 && "Unknown FP comparison!");
1193 case ISD::SETEQ:
1194 BuildMI(BB, IA64::FCMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
1195 break;
1196 case ISD::SETGT:
1197 BuildMI(BB, IA64::FCMPGT, 2, Result).addReg(Tmp1).addReg(Tmp2);
1198 break;
1199 case ISD::SETGE:
1200 BuildMI(BB, IA64::FCMPGE, 2, Result).addReg(Tmp1).addReg(Tmp2);
1201 break;
1202 case ISD::SETLT:
1203 BuildMI(BB, IA64::FCMPLT, 2, Result).addReg(Tmp1).addReg(Tmp2);
1204 break;
1205 case ISD::SETLE:
1206 BuildMI(BB, IA64::FCMPLE, 2, Result).addReg(Tmp1).addReg(Tmp2);
1207 break;
1208 case ISD::SETNE:
1209 BuildMI(BB, IA64::FCMPNE, 2, Result).addReg(Tmp1).addReg(Tmp2);
1210 break;
1211 case ISD::SETULT:
1212 BuildMI(BB, IA64::FCMPLTU, 2, Result).addReg(Tmp1).addReg(Tmp2);
1213 break;
1214 case ISD::SETUGT:
1215 BuildMI(BB, IA64::FCMPGTU, 2, Result).addReg(Tmp1).addReg(Tmp2);
1216 break;
1217 case ISD::SETULE:
1218 BuildMI(BB, IA64::FCMPLEU, 2, Result).addReg(Tmp1).addReg(Tmp2);
1219 break;
1220 case ISD::SETUGE:
1221 BuildMI(BB, IA64::FCMPGEU, 2, Result).addReg(Tmp1).addReg(Tmp2);
1222 break;
1223 }
1224 }
1225 }
1226 else
1227 assert(0 && "this setcc not implemented yet");
1228
1229 return Result;
1230 }
1231
1232 case ISD::EXTLOAD:
1233 case ISD::ZEXTLOAD:
1234 case ISD::LOAD: {
1235 // Make sure we generate both values.
1236 if (Result != 1)
1237 ExprMap[N.getValue(1)] = 1; // Generate the token
1238 else
1239 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
1240
1241 bool isBool=false;
1242
1243 if(opcode == ISD::LOAD) { // this is a LOAD
1244 switch (Node->getValueType(0)) {
1245 default: assert(0 && "Cannot load this type!");
1246 case MVT::i1: Opc = IA64::LD1; isBool=true; break;
1247 // FIXME: for now, we treat bool loads the same as i8 loads */
1248 case MVT::i8: Opc = IA64::LD1; break;
1249 case MVT::i16: Opc = IA64::LD2; break;
1250 case MVT::i32: Opc = IA64::LD4; break;
1251 case MVT::i64: Opc = IA64::LD8; break;
1252
1253 case MVT::f32: Opc = IA64::LDF4; break;
1254 case MVT::f64: Opc = IA64::LDF8; break;
1255 }
1256 } else { // this is an EXTLOAD or ZEXTLOAD
1257 MVT::ValueType TypeBeingLoaded = cast<MVTSDNode>(Node)->getExtraValueType();
1258 switch (TypeBeingLoaded) {
1259 default: assert(0 && "Cannot extload/zextload this type!");
1260 // FIXME: bools?
1261 case MVT::i8: Opc = IA64::LD1; break;
1262 case MVT::i16: Opc = IA64::LD2; break;
1263 case MVT::i32: Opc = IA64::LD4; break;
1264 case MVT::f32: Opc = IA64::LDF4; break;
1265 }
1266 }
1267
1268 SDOperand Chain = N.getOperand(0);
1269 SDOperand Address = N.getOperand(1);
1270
1271 if(Address.getOpcode() == ISD::GlobalAddress) {
1272 Select(Chain);
1273 unsigned dummy = MakeReg(MVT::i64);
1274 unsigned dummy2 = MakeReg(MVT::i64);
1275 BuildMI(BB, IA64::ADD, 2, dummy)
1276 .addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal())
1277 .addReg(IA64::r1);
1278 BuildMI(BB, IA64::LD8, 1, dummy2).addReg(dummy);
1279 if(!isBool)
1280 BuildMI(BB, Opc, 1, Result).addReg(dummy2);
1281 else { // emit a little pseudocode to load a bool (stored in one byte)
1282 // into a predicate register
1283 assert(Opc==IA64::LD1 && "problem loading a bool");
1284 unsigned dummy3 = MakeReg(MVT::i64);
1285 BuildMI(BB, Opc, 1, dummy3).addReg(dummy2);
1286 // we compare to 0. true? 0. false? 1.
1287 BuildMI(BB, IA64::CMPNE, 2, Result).addReg(dummy3).addReg(IA64::r0);
1288 }
1289 } else if(ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
1290 Select(Chain);
1291 IA64Lowering.restoreGP(BB);
1292 unsigned dummy = MakeReg(MVT::i64);
1293 BuildMI(BB, IA64::ADD, 2, dummy).addConstantPoolIndex(CP->getIndex())
1294 .addReg(IA64::r1); // CPI+GP
1295 if(!isBool)
1296 BuildMI(BB, Opc, 1, Result).addReg(dummy);
1297 else { // emit a little pseudocode to load a bool (stored in one byte)
1298 // into a predicate register
1299 assert(Opc==IA64::LD1 && "problem loading a bool");
1300 unsigned dummy3 = MakeReg(MVT::i64);
1301 BuildMI(BB, Opc, 1, dummy3).addReg(dummy);
1302 // we compare to 0. true? 0. false? 1.
1303 BuildMI(BB, IA64::CMPNE, 2, Result).addReg(dummy3).addReg(IA64::r0);
1304 }
1305 } else if(Address.getOpcode() == ISD::FrameIndex) {
1306 Select(Chain); // FIXME ? what about bools?
1307 unsigned dummy = MakeReg(MVT::i64);
1308 BuildMI(BB, IA64::MOV, 1, dummy)
1309 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex());
1310 if(!isBool)
1311 BuildMI(BB, Opc, 1, Result).addReg(dummy);
1312 else { // emit a little pseudocode to load a bool (stored in one byte)
1313 // into a predicate register
1314 assert(Opc==IA64::LD1 && "problem loading a bool");
1315 unsigned dummy3 = MakeReg(MVT::i64);
1316 BuildMI(BB, Opc, 1, dummy3).addReg(dummy);
1317 // we compare to 0. true? 0. false? 1.
1318 BuildMI(BB, IA64::CMPNE, 2, Result).addReg(dummy3).addReg(IA64::r0);
1319 }
1320 } else { // none of the above...
1321 Select(Chain);
1322 Tmp2 = SelectExpr(Address);
1323 if(!isBool)
1324 BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
1325 else { // emit a little pseudocode to load a bool (stored in one byte)
1326 // into a predicate register
1327 assert(Opc==IA64::LD1 && "problem loading a bool");
1328 unsigned dummy = MakeReg(MVT::i64);
1329 BuildMI(BB, Opc, 1, dummy).addReg(Tmp2);
1330 // we compare to 0. true? 0. false? 1.
1331 BuildMI(BB, IA64::CMPNE, 2, Result).addReg(dummy).addReg(IA64::r0);
1332 }
1333 }
1334
1335 return Result;
1336 }
1337
1338 case ISD::CopyFromReg: {
1339 if (Result == 1)
1340 Result = ExprMap[N.getValue(0)] =
1341 MakeReg(N.getValue(0).getValueType());
1342
1343 SDOperand Chain = N.getOperand(0);
1344
1345 Select(Chain);
1346 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
1347
1348 if(N.getValueType() == MVT::i1) // if a bool, we use pseudocode
1349 BuildMI(BB, IA64::PCMPEQUNC, 3, Result)
1350 .addReg(IA64::r0).addReg(IA64::r0).addReg(r);
1351 // (r) Result =cmp.eq.unc(r0,r0)
1352 else
1353 BuildMI(BB, IA64::MOV, 1, Result).addReg(r); // otherwise MOV
1354 return Result;
1355 }
1356
1357 case ISD::CALL: {
1358 Select(N.getOperand(0));
1359
1360 // The chain for this call is now lowered.
1361 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), 1));
1362
1363 //grab the arguments
1364 std::vector<unsigned> argvregs;
1365
1366 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
1367 argvregs.push_back(SelectExpr(N.getOperand(i)));
1368
1369 // see section 8.5.8 of "Itanium Software Conventions and
1370 // Runtime Architecture Guide to see some examples of what's going
1371 // on here. (in short: int args get mapped 1:1 'slot-wise' to out0->out7,
1372 // while FP args get mapped to F8->F15 as needed)
1373
1374 unsigned used_FPArgs=0; // how many FP Args have been used so far?
1375
1376 // in reg args
1377 for(int i = 0, e = std::min(8, (int)argvregs.size()); i < e; ++i)
1378 {
1379 unsigned intArgs[] = {IA64::out0, IA64::out1, IA64::out2, IA64::out3,
1380 IA64::out4, IA64::out5, IA64::out6, IA64::out7 };
1381 unsigned FPArgs[] = {IA64::F8, IA64::F9, IA64::F10, IA64::F11,
1382 IA64::F12, IA64::F13, IA64::F14, IA64::F15 };
1383
1384 switch(N.getOperand(i+2).getValueType())
1385 {
1386 default: // XXX do we need to support MVT::i1 here?
1387 Node->dump();
1388 N.getOperand(i).Val->dump();
1389 std::cerr << "Type for " << i << " is: " <<
1390 N.getOperand(i+2).getValueType() << std::endl;
1391 assert(0 && "Unknown value type for call");
1392 case MVT::i64:
1393 BuildMI(BB, IA64::MOV, 1, intArgs[i]).addReg(argvregs[i]);
1394 break;
1395 case MVT::f64:
1396 BuildMI(BB, IA64::FMOV, 1, FPArgs[used_FPArgs++])
1397 .addReg(argvregs[i]);
Duraid Madinabeeaab22005-03-31 12:31:11 +00001398 // FIXME: we don't need to do this _all_ the time:
Duraid Madina9b9d45f2005-03-17 18:17:03 +00001399 BuildMI(BB, IA64::GETFD, 1, intArgs[i]).addReg(argvregs[i]);
1400 break;
1401 }
1402 }
1403
1404 //in mem args
1405 for (int i = 8, e = argvregs.size(); i < e; ++i)
1406 {
1407 unsigned tempAddr = MakeReg(MVT::i64);
1408
1409 switch(N.getOperand(i+2).getValueType()) {
1410 default:
1411 Node->dump();
1412 N.getOperand(i).Val->dump();
1413 std::cerr << "Type for " << i << " is: " <<
1414 N.getOperand(i+2).getValueType() << "\n";
1415 assert(0 && "Unknown value type for call");
1416 case MVT::i1: // FIXME?
1417 case MVT::i8:
1418 case MVT::i16:
1419 case MVT::i32:
1420 case MVT::i64:
1421 BuildMI(BB, IA64::ADDIMM22, 2, tempAddr)
1422 .addReg(IA64::r12).addImm(16 + (i - 8) * 8); // r12 is SP
1423 BuildMI(BB, IA64::ST8, 2).addReg(tempAddr).addReg(argvregs[i]);
1424 break;
1425 case MVT::f32:
1426 case MVT::f64:
1427 BuildMI(BB, IA64::ADDIMM22, 2, tempAddr)
1428 .addReg(IA64::r12).addImm(16 + (i - 8) * 8); // r12 is SP
1429 BuildMI(BB, IA64::STF8, 2).addReg(tempAddr).addReg(argvregs[i]);
1430 break;
1431 }
1432 }
Duraid Madinabeeaab22005-03-31 12:31:11 +00001433
1434 /* XXX we want to re-enable direct branches! crippling them now
1435 * to stress-test indirect branches.:
Duraid Madina9b9d45f2005-03-17 18:17:03 +00001436 //build the right kind of call
1437 if (GlobalAddressSDNode *GASD =
1438 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
1439 {
1440 BuildMI(BB, IA64::BRCALL, 1).addGlobalAddress(GASD->getGlobal(),true);
1441 IA64Lowering.restoreGP_SP_RP(BB);
1442 }
Duraid Madinabeeaab22005-03-31 12:31:11 +00001443 ^^^^^^^^^^^^^ we want this code one day XXX */
1444 if (ExternalSymbolSDNode *ESSDN =
Duraid Madina9b9d45f2005-03-17 18:17:03 +00001445 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
Duraid Madinabeeaab22005-03-31 12:31:11 +00001446 { // FIXME : currently need this case for correctness, to avoid
1447 // "non-pic code with imm relocation against dynamic symbol" errors
1448 BuildMI(BB, IA64::BRCALL, 1)
Duraid Madina9b9d45f2005-03-17 18:17:03 +00001449 .addExternalSymbol(ESSDN->getSymbol(), true);
1450 IA64Lowering.restoreGP_SP_RP(BB);
1451 }
1452 else {
Duraid Madina9b9d45f2005-03-17 18:17:03 +00001453 Tmp1 = SelectExpr(N.getOperand(1));
Duraid Madinabeeaab22005-03-31 12:31:11 +00001454
1455 unsigned targetEntryPoint=MakeReg(MVT::i64);
1456 unsigned targetGPAddr=MakeReg(MVT::i64);
1457 unsigned currentGP=MakeReg(MVT::i64);
1458
1459 // b6 is a scratch branch register, we load the target entry point
1460 // from the base of the function descriptor
1461 BuildMI(BB, IA64::LD8, 1, targetEntryPoint).addReg(Tmp1);
1462 BuildMI(BB, IA64::MOV, 1, IA64::B6).addReg(targetEntryPoint);
1463
1464 // save the current GP:
1465 BuildMI(BB, IA64::MOV, 1, currentGP).addReg(IA64::r1);
1466
1467 /* TODO: we need to make sure doing this never, ever loads a
1468 * bogus value into r1 (GP). */
1469 // load the target GP (which is at mem[functiondescriptor+8])
1470 BuildMI(BB, IA64::ADDIMM22, 2, targetGPAddr)
1471 .addReg(Tmp1).addImm(8); // FIXME: addimm22? why not postincrement ld
1472 BuildMI(BB, IA64::LD8, 1, IA64::r1).addReg(targetGPAddr);
1473
Duraid Madina9b9d45f2005-03-17 18:17:03 +00001474 // and then jump: (well, call)
1475 BuildMI(BB, IA64::BRCALL, 1).addReg(IA64::B6);
Duraid Madinabeeaab22005-03-31 12:31:11 +00001476 // and finally restore the old GP
1477 BuildMI(BB, IA64::MOV, 1, IA64::r1).addReg(currentGP);
1478 IA64Lowering.restoreSP_RP(BB);
1479 }
Duraid Madina9b9d45f2005-03-17 18:17:03 +00001480
1481 switch (Node->getValueType(0)) {
1482 default: assert(0 && "Unknown value type for call result!");
1483 case MVT::Other: return 1;
1484 case MVT::i1:
1485 BuildMI(BB, IA64::CMPNE, 2, Result)
1486 .addReg(IA64::r8).addReg(IA64::r0);
1487 break;
1488 case MVT::i8:
1489 case MVT::i16:
1490 case MVT::i32:
1491 case MVT::i64:
1492 BuildMI(BB, IA64::MOV, 1, Result).addReg(IA64::r8);
1493 break;
1494 case MVT::f64:
1495 BuildMI(BB, IA64::FMOV, 1, Result).addReg(IA64::F8);
1496 break;
1497 }
1498 return Result+N.ResNo;
1499 }
1500
1501 } // <- uhhh XXX
1502 return 0;
1503}
1504
1505void ISel::Select(SDOperand N) {
1506 unsigned Tmp1, Tmp2, Opc;
1507 unsigned opcode = N.getOpcode();
1508
Nate Begeman85fdeb22005-03-24 04:39:54 +00001509 if (!LoweredTokens.insert(N).second)
Duraid Madina9b9d45f2005-03-17 18:17:03 +00001510 return; // Already selected.
1511
1512 SDNode *Node = N.Val;
1513
1514 switch (Node->getOpcode()) {
1515 default:
1516 Node->dump(); std::cerr << "\n";
1517 assert(0 && "Node not handled yet!");
1518
1519 case ISD::EntryToken: return; // Noop
1520
1521 case ISD::TokenFactor: {
1522 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
1523 Select(Node->getOperand(i));
1524 return;
1525 }
1526
1527 case ISD::CopyToReg: {
1528 Select(N.getOperand(0));
1529 Tmp1 = SelectExpr(N.getOperand(1));
1530 Tmp2 = cast<RegSDNode>(N)->getReg();
1531
1532 if (Tmp1 != Tmp2) {
1533 if(N.getValueType() == MVT::i1) // if a bool, we use pseudocode
1534 BuildMI(BB, IA64::PCMPEQUNC, 3, Tmp2)
1535 .addReg(IA64::r0).addReg(IA64::r0).addReg(Tmp1);
1536 // (Tmp1) Tmp2 = cmp.eq.unc(r0,r0)
1537 else
1538 BuildMI(BB, IA64::MOV, 1, Tmp2).addReg(Tmp1);
1539 // XXX is this the right way 'round? ;)
1540 }
1541 return;
1542 }
1543
1544 case ISD::RET: {
1545
1546 /* what the heck is going on here:
1547
1548<_sabre_> ret with two operands is obvious: chain and value
1549<camel_> yep
1550<_sabre_> ret with 3 values happens when 'expansion' occurs
1551<_sabre_> e.g. i64 gets split into 2x i32
1552<camel_> oh right
1553<_sabre_> you don't have this case on ia64
1554<camel_> yep
1555<_sabre_> so the two returned values go into EAX/EDX on ia32
1556<camel_> ahhh *memories*
1557<_sabre_> :)
1558<camel_> ok, thanks :)
1559<_sabre_> so yeah, everything that has a side effect takes a 'token chain'
1560<_sabre_> this is the first operand always
1561<_sabre_> these operand often define chains, they are the last operand
1562<_sabre_> they are printed as 'ch' if you do DAG.dump()
1563 */
1564
1565 switch (N.getNumOperands()) {
1566 default:
1567 assert(0 && "Unknown return instruction!");
1568 case 2:
1569 Select(N.getOperand(0));
1570 Tmp1 = SelectExpr(N.getOperand(1));
1571 switch (N.getOperand(1).getValueType()) {
1572 default: assert(0 && "All other types should have been promoted!!");
1573 // FIXME: do I need to add support for bools here?
1574 // (return '0' or '1' r8, basically...)
1575 case MVT::i64:
1576 BuildMI(BB, IA64::MOV, 1, IA64::r8).addReg(Tmp1);
1577 break;
1578 case MVT::f64:
1579 BuildMI(BB, IA64::FMOV, 1, IA64::F8).addReg(Tmp1);
1580 }
1581 break;
1582 case 1:
1583 Select(N.getOperand(0));
1584 break;
1585 }
1586 // before returning, restore the ar.pfs register (set by the 'alloc' up top)
1587 BuildMI(BB, IA64::MOV, 1).addReg(IA64::AR_PFS).addReg(IA64Lowering.VirtGPR);
1588 BuildMI(BB, IA64::RET, 0); // and then just emit a 'ret' instruction
1589 return;
1590 }
1591
1592 case ISD::BR: {
1593 Select(N.getOperand(0));
1594 MachineBasicBlock *Dest =
1595 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
1596 BuildMI(BB, IA64::BRLCOND_NOTCALL, 1).addReg(IA64::p0).addMBB(Dest);
1597 // XXX HACK! we do _not_ need long branches all the time
1598 return;
1599 }
1600
1601 case ISD::ImplicitDef: {
1602 Select(N.getOperand(0));
1603 BuildMI(BB, IA64::IDEF, 0, cast<RegSDNode>(N)->getReg());
1604 return;
1605 }
1606
1607 case ISD::BRCOND: {
1608 MachineBasicBlock *Dest =
1609 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
1610
1611 Select(N.getOperand(0));
1612 Tmp1 = SelectExpr(N.getOperand(1));
1613 BuildMI(BB, IA64::BRLCOND_NOTCALL, 1).addReg(Tmp1).addMBB(Dest);
1614 // XXX HACK! we do _not_ need long branches all the time
1615 return;
1616 }
1617
1618 case ISD::EXTLOAD:
1619 case ISD::ZEXTLOAD:
1620 case ISD::SEXTLOAD:
1621 case ISD::LOAD:
1622 case ISD::CALL:
1623 case ISD::CopyFromReg:
1624 case ISD::DYNAMIC_STACKALLOC:
1625 SelectExpr(N);
1626 return;
1627
1628 case ISD::TRUNCSTORE:
1629 case ISD::STORE: {
1630 Select(N.getOperand(0));
1631 Tmp1 = SelectExpr(N.getOperand(1)); // value
1632
1633 bool isBool=false;
1634
1635 if(opcode == ISD::STORE) {
1636 switch (N.getOperand(1).getValueType()) {
1637 default: assert(0 && "Cannot store this type!");
1638 case MVT::i1: Opc = IA64::ST1; isBool=true; break;
1639 // FIXME?: for now, we treat bool loads the same as i8 stores */
1640 case MVT::i8: Opc = IA64::ST1; break;
1641 case MVT::i16: Opc = IA64::ST2; break;
1642 case MVT::i32: Opc = IA64::ST4; break;
1643 case MVT::i64: Opc = IA64::ST8; break;
1644
1645 case MVT::f32: Opc = IA64::STF4; break;
1646 case MVT::f64: Opc = IA64::STF8; break;
1647 }
1648 } else { // truncstore
1649 switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
1650 default: assert(0 && "unknown type in truncstore");
1651 case MVT::i1: Opc = IA64::ST1; isBool=true; break;
1652 //FIXME: DAG does not promote this load?
1653 case MVT::i8: Opc = IA64::ST1; break;
1654 case MVT::i16: Opc = IA64::ST2; break;
1655 case MVT::i32: Opc = IA64::ST4; break;
1656 case MVT::f32: Opc = IA64::STF4; break;
1657 }
1658 }
1659
1660 if(N.getOperand(2).getOpcode() == ISD::GlobalAddress) {
1661 unsigned dummy = MakeReg(MVT::i64);
1662 unsigned dummy2 = MakeReg(MVT::i64);
1663 BuildMI(BB, IA64::ADD, 2, dummy)
1664 .addGlobalAddress(cast<GlobalAddressSDNode>
1665 (N.getOperand(2))->getGlobal()).addReg(IA64::r1);
1666 BuildMI(BB, IA64::LD8, 1, dummy2).addReg(dummy);
1667
1668 if(!isBool)
1669 BuildMI(BB, Opc, 2).addReg(dummy2).addReg(Tmp1);
1670 else { // we are storing a bool, so emit a little pseudocode
1671 // to store a predicate register as one byte
1672 assert(Opc==IA64::ST1);
1673 unsigned dummy3 = MakeReg(MVT::i64);
1674 unsigned dummy4 = MakeReg(MVT::i64);
1675 BuildMI(BB, IA64::MOV, 1, dummy3).addReg(IA64::r0);
1676 BuildMI(BB, IA64::CADDIMM22, 3, dummy4)
1677 .addReg(dummy3).addImm(1).addReg(Tmp1); // if(Tmp1) dummy=0+1;
1678 BuildMI(BB, Opc, 2).addReg(dummy2).addReg(dummy4);
1679 }
1680 } else if(N.getOperand(2).getOpcode() == ISD::FrameIndex) {
1681
1682 // FIXME? (what about bools?)
1683
1684 unsigned dummy = MakeReg(MVT::i64);
1685 BuildMI(BB, IA64::MOV, 1, dummy)
1686 .addFrameIndex(cast<FrameIndexSDNode>(N.getOperand(2))->getIndex());
1687 BuildMI(BB, Opc, 2).addReg(dummy).addReg(Tmp1);
1688 } else { // otherwise
1689 Tmp2 = SelectExpr(N.getOperand(2)); //address
1690 if(!isBool)
1691 BuildMI(BB, Opc, 2).addReg(Tmp2).addReg(Tmp1);
1692 else { // we are storing a bool, so emit a little pseudocode
1693 // to store a predicate register as one byte
1694 assert(Opc==IA64::ST1);
1695 unsigned dummy3 = MakeReg(MVT::i64);
1696 unsigned dummy4 = MakeReg(MVT::i64);
1697 BuildMI(BB, IA64::MOV, 1, dummy3).addReg(IA64::r0);
1698 BuildMI(BB, IA64::CADDIMM22, 3, dummy4)
1699 .addReg(dummy3).addImm(1).addReg(Tmp1); // if(Tmp1) dummy=0+1;
1700 BuildMI(BB, Opc, 2).addReg(Tmp2).addReg(dummy4);
1701 }
1702 }
1703 return;
1704 }
1705
1706 case ISD::ADJCALLSTACKDOWN:
1707 case ISD::ADJCALLSTACKUP: {
1708 Select(N.getOperand(0));
1709 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1710
1711 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? IA64::ADJUSTCALLSTACKDOWN :
1712 IA64::ADJUSTCALLSTACKUP;
1713 BuildMI(BB, Opc, 1).addImm(Tmp1);
1714 return;
1715 }
1716
1717 return;
1718 }
1719 assert(0 && "GAME OVER. INSERT COIN?");
1720}
1721
1722
1723/// createIA64PatternInstructionSelector - This pass converts an LLVM function
1724/// into a machine code representation using pattern matching and a machine
1725/// description file.
1726///
1727FunctionPass *llvm::createIA64PatternInstructionSelector(TargetMachine &TM) {
1728 return new ISel(TM);
1729}
1730
1731