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