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