simplifications, fix typo
[oota-llvm.git] / lib / Target / Sparc / SparcISelDAGToDAG.cpp
1 //===-- SparcV8ISelDAGToDAG.cpp - A dag to dag inst selector for SparcV8 --===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Chris Lattner and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines an instruction selector for the V8 target
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "SparcV8.h"
15 #include "SparcV8TargetMachine.h"
16 #include "llvm/Function.h"
17 #include "llvm/CodeGen/MachineFrameInfo.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/SelectionDAG.h"
20 #include "llvm/CodeGen/SelectionDAGISel.h"
21 #include "llvm/CodeGen/SSARegMap.h"
22 #include "llvm/Target/TargetLowering.h"
23 #include "llvm/Support/Debug.h"
24 #include <iostream>
25 using namespace llvm;
26
27 //===----------------------------------------------------------------------===//
28 // TargetLowering Implementation
29 //===----------------------------------------------------------------------===//
30
31 namespace V8ISD {
32   enum {
33     FIRST_NUMBER = ISD::BUILTIN_OP_END+V8::INSTRUCTION_LIST_END,
34     CMPICC,   // Compare two GPR operands, set icc.
35     CMPFCC,   // Compare two FP operands, set fcc.
36     BRICC,    // Branch to dest on icc condition
37     BRFCC,    // Branch to dest on fcc condition
38     
39     Hi, Lo,   // Hi/Lo operations, typically on a global address.
40     
41     FTOI,     // FP to Int within a FP register.
42     ITOF,     // Int to FP within a FP register.
43   };
44 }
45
46 namespace {
47   class SparcV8TargetLowering : public TargetLowering {
48   public:
49     SparcV8TargetLowering(TargetMachine &TM);
50     virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
51     virtual std::vector<SDOperand>
52       LowerArguments(Function &F, SelectionDAG &DAG);
53     virtual std::pair<SDOperand, SDOperand>
54       LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
55                   unsigned CC,
56                   bool isTailCall, SDOperand Callee, ArgListTy &Args,
57                   SelectionDAG &DAG);
58     
59     virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
60                                     SelectionDAG &DAG);
61     virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP,
62                                    Value *VAListV, SelectionDAG &DAG);
63     virtual std::pair<SDOperand,SDOperand>
64       LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
65                  const Type *ArgTy, SelectionDAG &DAG);
66     virtual std::pair<SDOperand, SDOperand>
67       LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
68                               SelectionDAG &DAG);
69   };
70 }
71
72 SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM)
73   : TargetLowering(TM) {
74   
75   // Set up the register classes.
76   addRegisterClass(MVT::i32, V8::IntRegsRegisterClass);
77   addRegisterClass(MVT::f32, V8::FPRegsRegisterClass);
78   addRegisterClass(MVT::f64, V8::DFPRegsRegisterClass);
79
80   // Custom legalize GlobalAddress nodes into LO/HI parts.
81   setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
82   setOperationAction(ISD::ConstantPool , MVT::i32, Custom);
83   
84   // Sparc doesn't have sext_inreg, replace them with shl/sra
85   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16  , Expand);
86   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8   , Expand);
87   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1   , Expand);
88
89   // Sparc has no REM operation.
90   setOperationAction(ISD::UREM, MVT::i32, Expand);
91   setOperationAction(ISD::SREM, MVT::i32, Expand);
92
93   // Custom expand fp<->sint
94   setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
95   setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
96
97   // Expand fp<->uint
98   setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
99   setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand);
100   
101   // Sparc has no select or setcc: expand to SELECT_CC.
102   setOperationAction(ISD::SELECT, MVT::i32, Expand);
103   setOperationAction(ISD::SELECT, MVT::f32, Expand);
104   setOperationAction(ISD::SELECT, MVT::f64, Expand);
105   setOperationAction(ISD::SETCC, MVT::i32, Expand);
106   setOperationAction(ISD::SETCC, MVT::f32, Expand);
107   setOperationAction(ISD::SETCC, MVT::f64, Expand);
108   
109   // Sparc doesn't have BRCOND either, it has BR_CC.
110   setOperationAction(ISD::BRCOND, MVT::Other, Expand);
111   setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
112   setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand);
113   setOperationAction(ISD::BR_CC, MVT::i32, Custom);
114   setOperationAction(ISD::BR_CC, MVT::f32, Custom);
115   setOperationAction(ISD::BR_CC, MVT::f64, Custom);
116   
117   computeRegisterProperties();
118 }
119
120 std::vector<SDOperand>
121 SparcV8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
122   MachineFunction &MF = DAG.getMachineFunction();
123   SSARegMap *RegMap = MF.getSSARegMap();
124   std::vector<SDOperand> ArgValues;
125   
126   static const unsigned GPR[] = {
127     V8::I0, V8::I1, V8::I2, V8::I3, V8::I4, V8::I5
128   };
129   unsigned ArgNo = 0;
130   for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
131     MVT::ValueType ObjectVT = getValueType(I->getType());
132     assert(ArgNo < 6 && "Only args in regs for now");
133     
134     switch (ObjectVT) {
135     default: assert(0 && "Unhandled argument type!");
136     // TODO: MVT::i64 & FP
137     case MVT::i1:
138     case MVT::i8:
139     case MVT::i16:
140     case MVT::i32: {
141       unsigned VReg = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
142       MF.addLiveIn(GPR[ArgNo++], VReg);
143       SDOperand Arg = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
144       DAG.setRoot(Arg.getValue(1));
145       if (ObjectVT != MVT::i32) {
146         unsigned AssertOp = I->getType()->isSigned() ? ISD::AssertSext 
147                                                      : ISD::AssertZext;
148         Arg = DAG.getNode(AssertOp, MVT::i32, Arg, 
149                           DAG.getValueType(ObjectVT));
150         Arg = DAG.getNode(ISD::TRUNCATE, ObjectVT, Arg);
151       }
152       ArgValues.push_back(Arg);
153       break;
154     }
155     case MVT::i64: {
156       unsigned VRegHi = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
157       MF.addLiveIn(GPR[ArgNo++], VRegHi);
158       unsigned VRegLo = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
159       MF.addLiveIn(GPR[ArgNo++], VRegLo);
160       SDOperand ArgLo = DAG.getCopyFromReg(DAG.getRoot(), VRegLo, MVT::i32);
161       SDOperand ArgHi = DAG.getCopyFromReg(ArgLo.getValue(1), VRegHi, MVT::i32);
162       DAG.setRoot(ArgHi.getValue(1));
163       ArgValues.push_back(DAG.getNode(ISD::BUILD_PAIR, MVT::i64, ArgLo, ArgHi));
164       break;
165     }
166     }
167   }
168   
169   assert(!F.isVarArg() && "Unimp");
170   
171   // Finally, inform the code generator which regs we return values in.
172   switch (getValueType(F.getReturnType())) {
173   default: assert(0 && "Unknown type!");
174   case MVT::isVoid: break;
175   case MVT::i1:
176   case MVT::i8:
177   case MVT::i16:
178   case MVT::i32:
179     MF.addLiveOut(V8::I0);
180     break;
181   case MVT::i64:
182     MF.addLiveOut(V8::I0);
183     MF.addLiveOut(V8::I1);
184     break;
185   case MVT::f32:
186     MF.addLiveOut(V8::F0);
187     break;
188   case MVT::f64:
189     MF.addLiveOut(V8::D0);
190     break;
191   }
192   
193   return ArgValues;
194 }
195
196 std::pair<SDOperand, SDOperand>
197 SparcV8TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
198                                    bool isVarArg, unsigned CC,
199                                    bool isTailCall, SDOperand Callee, 
200                                    ArgListTy &Args, SelectionDAG &DAG) {
201   assert(0 && "Unimp");
202   abort();
203 }
204
205 SDOperand SparcV8TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
206                                                SelectionDAG &DAG) {
207   if (Op.getValueType() == MVT::i64) {
208     SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op, 
209                                DAG.getConstant(1, MVT::i32));
210     SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
211                                DAG.getConstant(0, MVT::i32));
212     return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Hi);
213   } else {
214     return DAG.getNode(ISD::RET, MVT::Other, Chain, Op);
215   }
216 }
217
218 SDOperand SparcV8TargetLowering::
219 LowerVAStart(SDOperand Chain, SDOperand VAListP, Value *VAListV, 
220              SelectionDAG &DAG) {
221              
222   assert(0 && "Unimp");
223   abort();
224 }
225
226 std::pair<SDOperand,SDOperand> SparcV8TargetLowering::
227 LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
228            const Type *ArgTy, SelectionDAG &DAG) {
229   assert(0 && "Unimp");
230   abort();
231 }
232
233 std::pair<SDOperand, SDOperand> SparcV8TargetLowering::
234 LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
235                         SelectionDAG &DAG) {
236   assert(0 && "Unimp");
237   abort();
238 }
239
240 SDOperand SparcV8TargetLowering::
241 LowerOperation(SDOperand Op, SelectionDAG &DAG) {
242   switch (Op.getOpcode()) {
243   default: assert(0 && "Should not custom lower this!");
244   case ISD::BR_CC: {
245     SDOperand Chain = Op.getOperand(0);
246     SDOperand CC = Op.getOperand(1);
247     SDOperand LHS = Op.getOperand(2);
248     SDOperand RHS = Op.getOperand(3);
249     SDOperand Dest = Op.getOperand(4);
250     
251     // Get the condition flag.
252     if (LHS.getValueType() == MVT::i32) {
253       SDOperand Cond = DAG.getNode(V8ISD::CMPICC, MVT::Flag, LHS, RHS);
254       return DAG.getNode(V8ISD::BRICC, MVT::Other, Chain, Dest, CC, Cond);
255     } else {
256       SDOperand Cond = DAG.getNode(V8ISD::CMPFCC, MVT::Flag, LHS, RHS);
257       return DAG.getNode(V8ISD::BRFCC, MVT::Other, Chain, Dest, CC, Cond);
258     }
259   }
260   case ISD::GlobalAddress: {
261     GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
262     SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
263     SDOperand Hi = DAG.getNode(V8ISD::Hi, MVT::i32, GA);
264     SDOperand Lo = DAG.getNode(V8ISD::Lo, MVT::i32, GA);
265     return DAG.getNode(ISD::ADD, MVT::i32, Lo, Hi);
266   }
267   case ISD::ConstantPool: {
268     Constant *C = cast<ConstantPoolSDNode>(Op)->get();
269     SDOperand CP = DAG.getTargetConstantPool(C, MVT::i32);
270     SDOperand Hi = DAG.getNode(V8ISD::Hi, MVT::i32, CP);
271     SDOperand Lo = DAG.getNode(V8ISD::Lo, MVT::i32, CP);
272     return DAG.getNode(ISD::ADD, MVT::i32, Lo, Hi);
273   }
274   case ISD::FP_TO_SINT: {
275     // Convert the fp value to integer in an FP register.
276     Op = DAG.getNode(V8ISD::FTOI, Op.getOperand(0).getValueType(),
277                      Op.getOperand(0));
278     int Size = Op.getOperand(0).getValueType() == MVT::f32 ? 4 : 8;
279     int FrameIdx =
280       DAG.getMachineFunction().getFrameInfo()->CreateStackObject(Size, Size);
281     SDOperand FI = DAG.getFrameIndex(FrameIdx, MVT::i32);
282     SDOperand ST = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
283                                Op, FI, DAG.getSrcValue(0));
284     return DAG.getLoad(MVT::i32, ST, FI, DAG.getSrcValue(0));
285   }
286   case ISD::SINT_TO_FP: {
287     int Size = Op.getOperand(0).getValueType() == MVT::f32 ? 4 : 8;
288     int FrameIdx =
289       DAG.getMachineFunction().getFrameInfo()->CreateStackObject(Size, Size);
290     SDOperand FI = DAG.getFrameIndex(FrameIdx, MVT::i32);
291     SDOperand ST = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
292                                Op.getOperand(0), FI, DAG.getSrcValue(0));
293     
294     Op = DAG.getLoad(Op.getValueType(), ST, FI, DAG.getSrcValue(0));
295     
296     // Convert the int value to FP in an FP register.
297     return DAG.getNode(V8ISD::ITOF, Op.getValueType(), Op);
298   }
299   }  
300 }
301
302
303 //===----------------------------------------------------------------------===//
304 // Instruction Selector Implementation
305 //===----------------------------------------------------------------------===//
306
307 //===--------------------------------------------------------------------===//
308 /// SparcV8DAGToDAGISel - PPC specific code to select Sparc V8 machine
309 /// instructions for SelectionDAG operations.
310 ///
311 namespace {
312 class SparcV8DAGToDAGISel : public SelectionDAGISel {
313   SparcV8TargetLowering V8Lowering;
314 public:
315   SparcV8DAGToDAGISel(TargetMachine &TM)
316     : SelectionDAGISel(V8Lowering), V8Lowering(TM) {}
317
318   SDOperand Select(SDOperand Op);
319
320   // Complex Pattern Selectors.
321   bool SelectADDRrr(SDOperand N, SDOperand &R1, SDOperand &R2);
322   bool SelectADDRri(SDOperand N, SDOperand &Base, SDOperand &Offset);
323   
324   /// InstructionSelectBasicBlock - This callback is invoked by
325   /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
326   virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
327   
328   virtual const char *getPassName() const {
329     return "PowerPC DAG->DAG Pattern Instruction Selection";
330   } 
331   
332   // Include the pieces autogenerated from the target description.
333 #include "SparcV8GenDAGISel.inc"
334 };
335 }  // end anonymous namespace
336
337 /// InstructionSelectBasicBlock - This callback is invoked by
338 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
339 void SparcV8DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
340   DEBUG(BB->dump());
341   
342   // Select target instructions for the DAG.
343   DAG.setRoot(Select(DAG.getRoot()));
344   CodeGenMap.clear();
345   DAG.RemoveDeadNodes();
346   
347   // Emit machine code to BB. 
348   ScheduleAndEmitDAG(DAG);
349 }
350
351 bool SparcV8DAGToDAGISel::SelectADDRri(SDOperand Addr, SDOperand &Base,
352                                        SDOperand &Offset) {
353   if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
354     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
355     Offset = CurDAG->getTargetConstant(0, MVT::i32);
356     return true;
357   }
358   
359   if (Addr.getOpcode() == ISD::ADD) {
360     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
361       if (Predicate_simm13(CN)) {
362         if (FrameIndexSDNode *FIN = 
363                 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
364           // Constant offset from frame ref.
365           Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
366         } else {
367           Base = Select(Addr.getOperand(0));
368         }
369         Offset = CurDAG->getTargetConstant(CN->getValue(), MVT::i32);
370         return true;
371       }
372     }
373     if (Addr.getOperand(0).getOpcode() == V8ISD::Lo) {
374       Base = Select(Addr.getOperand(1));
375       Offset = Addr.getOperand(0).getOperand(0);
376       return true;
377     }
378     if (Addr.getOperand(1).getOpcode() == V8ISD::Lo) {
379       Base = Select(Addr.getOperand(0));
380       Offset = Addr.getOperand(1).getOperand(0);
381       return true;
382     }
383   }
384   Base = Select(Addr);
385   Offset = CurDAG->getTargetConstant(0, MVT::i32);
386   return true;
387 }
388
389 bool SparcV8DAGToDAGISel::SelectADDRrr(SDOperand Addr, SDOperand &R1, 
390                                        SDOperand &R2) {
391   if (Addr.getOpcode() == ISD::FrameIndex) return false; 
392   if (Addr.getOpcode() == ISD::ADD) {
393     if (isa<ConstantSDNode>(Addr.getOperand(1)) &&
394         Predicate_simm13(Addr.getOperand(1).Val))
395       return false;  // Let the reg+imm pattern catch this!
396     if (Addr.getOperand(0).getOpcode() == V8ISD::Lo ||
397         Addr.getOperand(1).getOpcode() == V8ISD::Lo)
398       return false;  // Let the reg+imm pattern catch this!
399     R1 = Select(Addr.getOperand(0));
400     R2 = Select(Addr.getOperand(1));
401     return true;
402   }
403
404   R1 = Select(Addr);
405   R2 = CurDAG->getRegister(V8::G0, MVT::i32);
406   return true;
407 }
408
409 SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) {
410   SDNode *N = Op.Val;
411   if (N->getOpcode() >= ISD::BUILTIN_OP_END &&
412       N->getOpcode() < V8ISD::FIRST_NUMBER)
413     return Op;   // Already selected.
414                  // If this has already been converted, use it.
415   std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(Op);
416   if (CGMI != CodeGenMap.end()) return CGMI->second;
417   
418   switch (N->getOpcode()) {
419   default: break;
420   case ISD::BasicBlock:         return CodeGenMap[Op] = Op;
421   case ISD::FrameIndex: {
422     int FI = cast<FrameIndexSDNode>(N)->getIndex();
423     if (N->hasOneUse())
424       return CurDAG->SelectNodeTo(N, V8::ADDri, MVT::i32,
425                                   CurDAG->getTargetFrameIndex(FI, MVT::i32),
426                                   CurDAG->getTargetConstant(0, MVT::i32));
427     return CodeGenMap[Op] = 
428       CurDAG->getTargetNode(V8::ADDri, MVT::i32,
429                             CurDAG->getTargetFrameIndex(FI, MVT::i32),
430                             CurDAG->getTargetConstant(0, MVT::i32));
431   }
432   case V8ISD::CMPICC: {
433     // FIXME: Handle compare with immediate.
434     SDOperand LHS = Select(N->getOperand(0));
435     SDOperand RHS = Select(N->getOperand(1));
436     SDOperand Result = CurDAG->getTargetNode(V8::SUBCCrr, MVT::i32, MVT::Flag,
437                                              LHS, RHS);
438     return CodeGenMap[Op] = Result.getValue(1);
439   }
440   case ISD::ADD_PARTS: {
441     SDOperand LHSL = Select(N->getOperand(0));
442     SDOperand LHSH = Select(N->getOperand(1));
443     SDOperand RHSL = Select(N->getOperand(2));
444     SDOperand RHSH = Select(N->getOperand(3));
445     // FIXME, handle immediate RHS.
446     SDOperand Low = CurDAG->getTargetNode(V8::ADDCCrr, MVT::i32, MVT::Flag,
447                                           LHSL, RHSL);
448     SDOperand Hi  = CurDAG->getTargetNode(V8::ADDXrr, MVT::i32, LHSH, RHSH, 
449                                           Low.getValue(1));
450     CodeGenMap[SDOperand(N, 0)] = Low;
451     CodeGenMap[SDOperand(N, 1)] = Hi;
452     return Op.ResNo ? Hi : Low;
453   }
454   case ISD::SUB_PARTS: {
455     SDOperand LHSL = Select(N->getOperand(0));
456     SDOperand LHSH = Select(N->getOperand(1));
457     SDOperand RHSL = Select(N->getOperand(2));
458     SDOperand RHSH = Select(N->getOperand(3));
459     // FIXME, handle immediate RHS.
460     SDOperand Low = CurDAG->getTargetNode(V8::SUBCCrr, MVT::i32, MVT::Flag,
461                                           LHSL, RHSL);
462     SDOperand Hi  = CurDAG->getTargetNode(V8::SUBXrr, MVT::i32, LHSH, RHSH, 
463                                           Low.getValue(1));
464     CodeGenMap[SDOperand(N, 0)] = Low;
465     CodeGenMap[SDOperand(N, 1)] = Hi;
466     return Op.ResNo ? Hi : Low;
467   }
468   case ISD::SDIV:
469   case ISD::UDIV: {
470     // FIXME: should use a custom expander to expose the SRA to the dag.
471     SDOperand DivLHS = Select(N->getOperand(0));
472     SDOperand DivRHS = Select(N->getOperand(1));
473     
474     // Set the Y register to the high-part.
475     SDOperand TopPart;
476     if (N->getOpcode() == ISD::SDIV) {
477       TopPart = CurDAG->getTargetNode(V8::SRAri, MVT::i32, DivLHS,
478                                       CurDAG->getTargetConstant(31, MVT::i32));
479     } else {
480       TopPart = CurDAG->getRegister(V8::G0, MVT::i32);
481     }
482     TopPart = CurDAG->getTargetNode(V8::WRYrr, MVT::Flag, TopPart,
483                                     CurDAG->getRegister(V8::G0, MVT::i32));
484
485     // FIXME: Handle div by immediate.
486     unsigned Opcode = N->getOpcode() == ISD::SDIV ? V8::SDIVrr : V8::UDIVrr;
487     return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart);
488   }    
489   case ISD::MULHU:
490   case ISD::MULHS: {
491     // FIXME: Handle mul by immediate.
492     SDOperand MulLHS = Select(N->getOperand(0));
493     SDOperand MulRHS = Select(N->getOperand(1));
494     unsigned Opcode = N->getOpcode() == ISD::MULHU ? V8::UMULrr : V8::SMULrr;
495     SDOperand Mul = CurDAG->getTargetNode(Opcode, MVT::i32, MVT::Flag,
496                                           MulLHS, MulRHS);
497     // The high part is in the Y register.
498     return CurDAG->SelectNodeTo(N, V8::RDY, MVT::i32, Mul.getValue(1));
499   }
500     
501   case ISD::RET: {
502     if (N->getNumOperands() == 2) {
503       SDOperand Chain = Select(N->getOperand(0));     // Token chain.
504       SDOperand Val = Select(N->getOperand(1));
505       if (N->getOperand(1).getValueType() == MVT::i32) {
506         Chain = CurDAG->getCopyToReg(Chain, V8::I0, Val);
507       } else if (N->getOperand(1).getValueType() == MVT::f32) {
508         Chain = CurDAG->getCopyToReg(Chain, V8::F0, Val);
509       } else {
510         assert(N->getOperand(1).getValueType() == MVT::f64);
511         Chain = CurDAG->getCopyToReg(Chain, V8::D0, Val);
512       }
513       return CurDAG->SelectNodeTo(N, V8::RETL, MVT::Other, Chain);
514     } else if (N->getNumOperands() > 1) {
515       SDOperand Chain = Select(N->getOperand(0));     // Token chain.
516       assert(N->getOperand(1).getValueType() == MVT::i32 &&
517              N->getOperand(2).getValueType() == MVT::i32 &&
518              N->getNumOperands() == 3 && "Unknown two-register ret value!");
519       Chain = CurDAG->getCopyToReg(Chain, V8::I1, Select(N->getOperand(1)));
520       Chain = CurDAG->getCopyToReg(Chain, V8::I0, Select(N->getOperand(2)));
521       return CurDAG->SelectNodeTo(N, V8::RETL, MVT::Other, Chain);
522     }
523     break;  // Generated code handles the void case.
524   }
525   }
526   
527   return SelectCode(Op);
528 }
529
530
531 /// createPPCISelDag - This pass converts a legalized DAG into a 
532 /// PowerPC-specific DAG, ready for instruction scheduling.
533 ///
534 FunctionPass *llvm::createSparcV8ISelDag(TargetMachine &TM) {
535   return new SparcV8DAGToDAGISel(TM);
536 }