add isTerminatortto b and bcond
[oota-llvm.git] / lib / Target / ARM / ARMISelDAGToDAG.cpp
index ffcdbc1180b7ac6fca651c066ec9c807e709316b..283d0f18c796fea04341ba4189eff44cf21066fb 100644 (file)
@@ -47,15 +47,38 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
   addRegisterClass(MVT::f32, ARM::FPRegsRegisterClass);
   addRegisterClass(MVT::f64, ARM::DFPRegsRegisterClass);
 
+  setLoadXAction(ISD::EXTLOAD, MVT::f32, Expand);
+
+  setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
   setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
 
+  setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
+  setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
+
   setOperationAction(ISD::RET,           MVT::Other, Custom);
   setOperationAction(ISD::GlobalAddress, MVT::i32,   Custom);
   setOperationAction(ISD::ConstantPool,  MVT::i32,   Custom);
 
+  setOperationAction(ISD::SELECT, MVT::i32, Expand);
+
   setOperationAction(ISD::SETCC, MVT::i32, Expand);
+  setOperationAction(ISD::SETCC, MVT::f32, Expand);
+  setOperationAction(ISD::SETCC, MVT::f64, Expand);
+
   setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
   setOperationAction(ISD::BR_CC, MVT::i32, Custom);
+  setOperationAction(ISD::BR_CC, MVT::f32, Custom);
+  setOperationAction(ISD::BR_CC, MVT::f64, Custom);
+
+  setOperationAction(ISD::BRCOND,        MVT::Other, Expand);
+
+  setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
+  setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
+  setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
+  setOperationAction(ISD::SDIV,      MVT::i32, Expand);
+  setOperationAction(ISD::UDIV,      MVT::i32, Expand);
+  setOperationAction(ISD::SREM,      MVT::i32, Expand);
+  setOperationAction(ISD::UREM,      MVT::i32, Expand);
 
   setOperationAction(ISD::VASTART,       MVT::Other, Custom);
   setOperationAction(ISD::VAEND,         MVT::Other, Expand);
@@ -85,32 +108,82 @@ namespace llvm {
       BR,
 
       FSITOS,
+      FTOSIS,
 
       FSITOD,
+      FTOSID,
+
+      FUITOS,
+      FTOUIS,
+
+      FUITOD,
+      FTOUID,
 
       FMRRD,
 
-      FMDRR
+      FMDRR,
+
+      FMSTAT
     };
   }
 }
 
-/// DAGCCToARMCC - Convert a DAG integer condition code to an ARM CC
-static ARMCC::CondCodes DAGCCToARMCC(ISD::CondCode CC) {
+/// DAGFPCCToARMCC - Convert a DAG fp condition code to an ARM CC
+// Unordered = !N & !Z & C & V = V
+// Ordered   =  N | Z | !C | !V = N | Z | !V
+static ARMCC::CondCodes DAGFPCCToARMCC(ISD::CondCode CC) {
   switch (CC) {
   default:
-    std::cerr << "CC = " << CC << "\n";
-    assert(0 && "Unknown condition code!");
+    assert(0 && "Unknown fp condition code!");
+// SETOEQ = (N | Z | !V) & Z = Z                               = EQ
+  case ISD::SETEQ:
+  case ISD::SETOEQ: return ARMCC::EQ;
+// SETOGT = (N | Z | !V) & !N & !Z = !V &!N &!Z = (N = V) & !Z = GT
+  case ISD::SETGT:
+  case ISD::SETOGT: return ARMCC::GT;
+// SETOGE = (N | Z | !V) & !N = (Z | !V) & !N = !V & !N        = GE
+  case ISD::SETGE:
+  case ISD::SETOGE: return ARMCC::GE;
+// SETOLT = (N | Z | !V) & N = N                               = MI
+  case ISD::SETLT:
+  case ISD::SETOLT: return ARMCC::MI;
+// SETOLE = (N | Z | !V) & (N | Z) = N | Z = !C | Z            = LS
+  case ISD::SETLE:
+  case ISD::SETOLE: return ARMCC::LS;
+// SETONE = (N | Z | !V) & !Z = (N | !V) & Z = !V & Z = Z      = NE
+  case ISD::SETNE:
+  case ISD::SETONE: return ARMCC::NE;
+// SETO   = N | Z | !V = Z | !V = !V                           = VC
+  case ISD::SETO:   return ARMCC::VC;
+// SETUO  = V                                                  = VS
+  case ISD::SETUO:  return ARMCC::VS;
+// SETUEQ = V | Z                                              = ??
+// SETUGT = V | (!Z & !N) = !Z & !N = !Z & C                   = HI
   case ISD::SETUGT: return ARMCC::HI;
-  case ISD::SETULE: return ARMCC::LS;
-  case ISD::SETLE:  return ARMCC::LE;
+// SETUGE = V | !N = !N                                        = PL
+  case ISD::SETUGE: return ARMCC::PL;
+// SETULT = V | N                                              = ??
+// SETULE = V | Z | N                                          = ??
+// SETUNE = V | !Z = !Z                                        = NE
+  case ISD::SETUNE: return ARMCC::NE;
+  }
+}
+
+/// DAGIntCCToARMCC - Convert a DAG integer condition code to an ARM CC
+static ARMCC::CondCodes DAGIntCCToARMCC(ISD::CondCode CC) {
+  switch (CC) {
+  default:
+    assert(0 && "Unknown integer condition code!");
+  case ISD::SETEQ:  return ARMCC::EQ;
+  case ISD::SETNE:  return ARMCC::NE;
   case ISD::SETLT:  return ARMCC::LT;
+  case ISD::SETLE:  return ARMCC::LE;
   case ISD::SETGT:  return ARMCC::GT;
-  case ISD::SETNE:  return ARMCC::NE;
-  case ISD::SETEQ:  return ARMCC::EQ;
   case ISD::SETGE:  return ARMCC::GE;
-  case ISD::SETUGE: return ARMCC::CS;
   case ISD::SETULT: return ARMCC::CC;
+  case ISD::SETULE: return ARMCC::LS;
+  case ISD::SETUGT: return ARMCC::HI;
+  case ISD::SETUGE: return ARMCC::CS;
   }
 }
 
@@ -123,9 +196,16 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
   case ARMISD::CMP:           return "ARMISD::CMP";
   case ARMISD::BR:            return "ARMISD::BR";
   case ARMISD::FSITOS:        return "ARMISD::FSITOS";
+  case ARMISD::FTOSIS:        return "ARMISD::FTOSIS";
   case ARMISD::FSITOD:        return "ARMISD::FSITOD";
+  case ARMISD::FTOSID:        return "ARMISD::FTOSID";
+  case ARMISD::FUITOS:        return "ARMISD::FUITOS";
+  case ARMISD::FTOUIS:        return "ARMISD::FTOUIS";
+  case ARMISD::FUITOD:        return "ARMISD::FUITOD";
+  case ARMISD::FTOUID:        return "ARMISD::FTOUID";
   case ARMISD::FMRRD:         return "ARMISD::FMRRD";
   case ARMISD::FMDRR:         return "ARMISD::FMDRR";
+  case ARMISD::FMSTAT:        return "ARMISD::FMSTAT";
   }
 }
 
@@ -134,12 +214,12 @@ class ArgumentLayout {
   std::vector<unsigned>       pos;
   std::vector<MVT::ValueType> types;
 public:
-  ArgumentLayout(std::vector<MVT::ValueType> Types) {
+  ArgumentLayout(const std::vector<MVT::ValueType> &Types) {
     types = Types;
 
     unsigned      RegNum = 0;
     unsigned StackOffset = 0;
-    for(std::vector<MVT::ValueType>::iterator I = Types.begin();
+    for(std::vector<MVT::ValueType>::const_iterator I = Types.begin();
         I != Types.end();
         ++I) {
       MVT::ValueType VT = *I;
@@ -181,6 +261,8 @@ public:
   }
   unsigned getStackSize(void) {
     int last = is_reg.size() - 1;
+    if (last < 0)
+      return 0;
     if (isRegister(last))
       return 0;
     return getOffset(last) + MVT::getSizeInBits(getType(last))/8;
@@ -193,7 +275,7 @@ public:
     last--;
     return last;
   }
-  unsigned lastRegNum(void) {
+  int lastRegNum(void) {
     int            l = lastRegArg();
     if (l < 0)
       return -1;
@@ -212,10 +294,11 @@ public:
 static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
   SDOperand Chain    = Op.getOperand(0);
   unsigned CallConv  = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
-  assert(CallConv == CallingConv::C && "unknown calling convention");
+  assert((CallConv == CallingConv::C ||
+          CallConv == CallingConv::Fast)
+         && "unknown calling convention");
   bool isVarArg      = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
   bool isTailCall    = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0;
-  assert(isTailCall == false && "tail call not supported");
   SDOperand Callee   = Op.getOperand(4);
   unsigned NumOps    = (Op.getNumOperands() - 5) / 2;
   SDOperand StackPtr = DAG.getRegister(ARM::R13, MVT::i32);
@@ -242,18 +325,20 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
     unsigned ArgOffset = Layout.getOffset(i);
     SDOperand   PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
     PtrOff             = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
-    MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                      Arg, PtrOff, DAG.getSrcValue(NULL)));
+    MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
   }
   if (!MemOpChains.empty())
     Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
                         &MemOpChains[0], MemOpChains.size());
 
-  // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
-  // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
-  // node so that legalize doesn't hack it.
+  // If the callee is a GlobalAddress node (quite common, every direct call is)
+  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
+  // Likewise ExternalSymbol -> TargetExternalSymbol.
+  assert(Callee.getValueType() == MVT::i32);
   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
-    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType());
+    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32);
+  else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
+    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
 
   // If this is a direct call, pass the chain and the callee.
   assert (Callee.Val);
@@ -264,17 +349,32 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
   // Build a sequence of copy-to-reg nodes chained together with token chain
   // and flag operands which copy the outgoing args into the appropriate regs.
   SDOperand InFlag;
-  for (unsigned i = 0, e = Layout.lastRegArg(); i <= e; ++i) {
-    SDOperand Arg = Op.getOperand(5+2*i);
-    unsigned  Reg = regs[Layout.getRegisterNum(i)];
-    assert(Layout.getType(i) == Arg.getValueType());
-    assert(Layout.getType(i) == MVT::i32);
-    Chain         = DAG.getCopyToReg(Chain, Reg, Arg, InFlag);
-    InFlag        = Chain.getValue(1);
+  for (int i = 0, e = Layout.lastRegArg(); i <= e; ++i) {
+    SDOperand     Arg = Op.getOperand(5+2*i);
+    unsigned   RegNum = Layout.getRegisterNum(i);
+    unsigned     Reg1 = regs[RegNum];
+    MVT::ValueType VT = Layout.getType(i);
+    assert(VT == Arg.getValueType());
+    assert(VT == MVT::i32 || VT == MVT::f32 || VT == MVT::f64);
 
     // Add argument register to the end of the list so that it is known live
     // into the call.
-    Ops.push_back(DAG.getRegister(Reg, Arg.getValueType()));
+    Ops.push_back(DAG.getRegister(Reg1, MVT::i32));
+    if (VT == MVT::f64) {
+      unsigned    Reg2 = regs[RegNum + 1];
+      SDOperand SDReg1 = DAG.getRegister(Reg1, MVT::i32);
+      SDOperand SDReg2 = DAG.getRegister(Reg2, MVT::i32);
+
+      Ops.push_back(DAG.getRegister(Reg2, MVT::i32));
+      SDVTList    VTs = DAG.getVTList(MVT::Other, MVT::Flag);
+      SDOperand Ops[] = {Chain, SDReg1, SDReg2, Arg, InFlag};
+      Chain = DAG.getNode(ARMISD::FMRRD, VTs, Ops, InFlag.Val ? 5 : 4);
+    } else {
+      if (VT == MVT::f32)
+        Arg = DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Arg);
+      Chain = DAG.getCopyToReg(Chain, Reg1, Arg, InFlag);
+    }
+    InFlag = Chain.getValue(1);
   }
 
   std::vector<MVT::ValueType> NodeTys;
@@ -291,14 +391,33 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
   NodeTys.clear();
 
   // If the call has results, copy the values out of the ret val registers.
-  switch (Op.Val->getValueType(0)) {
-  default: assert(0 && "Unexpected ret value!");
-  case MVT::Other:
-    break;
-  case MVT::i32:
-    Chain = DAG.getCopyFromReg(Chain, ARM::R0, MVT::i32, InFlag).getValue(1);
-    ResultVals.push_back(Chain.getValue(0));
-    NodeTys.push_back(MVT::i32);
+  MVT::ValueType VT = Op.Val->getValueType(0);
+  if (VT != MVT::Other) {
+    assert(VT == MVT::i32 || VT == MVT::f32 || VT == MVT::f64);
+
+    SDOperand Value1 = DAG.getCopyFromReg(Chain, ARM::R0, MVT::i32, InFlag);
+    Chain            = Value1.getValue(1);
+    InFlag           = Value1.getValue(2);
+    NodeTys.push_back(VT);
+    if (VT == MVT::i32) {
+      ResultVals.push_back(Value1);
+      if (Op.Val->getValueType(1) == MVT::i32) {
+        SDOperand Value2 = DAG.getCopyFromReg(Chain, ARM::R1, MVT::i32, InFlag);
+        Chain            = Value2.getValue(1);
+        ResultVals.push_back(Value2);
+        NodeTys.push_back(VT);
+      }
+    }
+    if (VT == MVT::f32) {
+      SDOperand Value = DAG.getNode(ISD::BIT_CONVERT, MVT::f32, Value1);
+      ResultVals.push_back(Value);
+    }
+    if (VT == MVT::f64) {
+      SDOperand Value2 = DAG.getCopyFromReg(Chain, ARM::R1, MVT::i32, InFlag);
+      Chain            = Value2.getValue(1);
+      SDOperand Value  = DAG.getNode(ARMISD::FMDRR, MVT::f64, Value1, Value2);
+      ResultVals.push_back(Value);
+    }
   }
 
   Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
@@ -380,8 +499,7 @@ static SDOperand LowerGlobalAddress(SDOperand Op,
   GlobalValue  *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
   int alignment = 2;
   SDOperand CPAddr = DAG.getConstantPool(GV, MVT::i32, alignment);
-  return DAG.getLoad(MVT::i32, DAG.getEntryNode(), CPAddr,
-                    DAG.getSrcValue(NULL));
+  return DAG.getLoad(MVT::i32, DAG.getEntryNode(), CPAddr, NULL, 0);
 }
 
 static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,
@@ -390,8 +508,9 @@ static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,
   // memory location argument.
   MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
   SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
-  return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), FR, 
-                     Op.getOperand(1), Op.getOperand(2));
+  SrcValueSDNode *SV = cast<SrcValueSDNode>(Op.getOperand(2));
+  return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), SV->getValue(),
+                      SV->getOffset());
 }
 
 static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
@@ -440,7 +559,7 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
         unsigned   Size = MVT::getSizeInBits(VT)/8;
         int          FI = MFI->CreateFixedObject(Size, Offset);
         SDOperand   FIN = DAG.getFrameIndex(FI, VT);
-        Value = DAG.getLoad(VT, Root, FIN, DAG.getSrcValue(NULL));
+        Value = DAG.getLoad(VT, Root, FIN, NULL, 0);
       } else {
         Value = DAG.getNode(ISD::UNDEF, VT);
       }
@@ -467,8 +586,7 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
       MF.addLiveIn(REGS[RegNo], VReg);
 
       SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::i32);
-      SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1),
-                                    Val, FIN, DAG.getSrcValue(NULL));
+      SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
       MemOps.push_back(Store);
     }
     Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
@@ -482,15 +600,35 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
   return DAG.getNode(ISD::MERGE_VALUES, RetVT, &ArgValues[0], ArgValues.size());
 }
 
+static SDOperand GetCMP(ISD::CondCode CC, SDOperand LHS, SDOperand RHS,
+                        SelectionDAG &DAG) {
+  MVT::ValueType vt = LHS.getValueType();
+  assert(vt == MVT::i32 || vt == MVT::f32 || vt == MVT::f64);
+
+  SDOperand Cmp = DAG.getNode(ARMISD::CMP,  MVT::Flag, LHS, RHS);
+
+  if (vt != MVT::i32)
+    Cmp = DAG.getNode(ARMISD::FMSTAT, MVT::Flag, Cmp);
+  return Cmp;
+}
+
+static SDOperand GetARMCC(ISD::CondCode CC, MVT::ValueType vt,
+                          SelectionDAG &DAG) {
+  assert(vt == MVT::i32 || vt == MVT::f32 || vt == MVT::f64);
+  if (vt == MVT::i32)
+    return DAG.getConstant(DAGIntCCToARMCC(CC), MVT::i32);
+  else
+    return DAG.getConstant(DAGFPCCToARMCC(CC), MVT::i32);
+}
+
 static SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
   SDOperand LHS = Op.getOperand(0);
   SDOperand RHS = Op.getOperand(1);
   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
   SDOperand TrueVal = Op.getOperand(2);
   SDOperand FalseVal = Op.getOperand(3);
-  SDOperand    ARMCC = DAG.getConstant(DAGCCToARMCC(CC), MVT::i32);
-
-  SDOperand Cmp = DAG.getNode(ARMISD::CMP, MVT::Flag, LHS, RHS);
+  SDOperand      Cmp = GetCMP(CC, LHS, RHS, DAG);
+  SDOperand    ARMCC = GetARMCC(CC, LHS.getValueType(), DAG);
   return DAG.getNode(ARMISD::SELECT, MVT::i32, TrueVal, FalseVal, ARMCC, Cmp);
 }
 
@@ -500,9 +638,8 @@ static SDOperand LowerBR_CC(SDOperand Op, SelectionDAG &DAG) {
   SDOperand    LHS = Op.getOperand(2);
   SDOperand    RHS = Op.getOperand(3);
   SDOperand   Dest = Op.getOperand(4);
-  SDOperand  ARMCC = DAG.getConstant(DAGCCToARMCC(CC), MVT::i32);
-
-  SDOperand Cmp = DAG.getNode(ARMISD::CMP, MVT::Flag, LHS, RHS);
+  SDOperand    Cmp = GetCMP(CC, LHS, RHS, DAG);
+  SDOperand  ARMCC = GetARMCC(CC, LHS.getValueType(), DAG);
   return DAG.getNode(ARMISD::BR, MVT::Other, Chain, Dest, ARMCC, Cmp);
 }
 
@@ -518,6 +655,40 @@ static SDOperand LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
   return DAG.getNode(op, vt, Tmp);
 }
 
+static SDOperand LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
+  assert(Op.getValueType() == MVT::i32);
+  SDOperand FloatVal = Op.getOperand(0);
+  MVT::ValueType  vt = FloatVal.getValueType();
+  assert(vt == MVT::f32 || vt == MVT::f64);
+
+  ARMISD::NodeType op = vt == MVT::f32 ? ARMISD::FTOSIS : ARMISD::FTOSID;
+  SDOperand Tmp = DAG.getNode(op, MVT::f32, FloatVal);
+  return DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Tmp);
+}
+
+static SDOperand LowerUINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
+  SDOperand IntVal  = Op.getOperand(0);
+  assert(IntVal.getValueType() == MVT::i32);
+  MVT::ValueType vt = Op.getValueType();
+  assert(vt == MVT::f32 ||
+         vt == MVT::f64);
+
+  SDOperand Tmp = DAG.getNode(ISD::BIT_CONVERT, MVT::f32, IntVal);
+  ARMISD::NodeType op = vt == MVT::f32 ? ARMISD::FUITOS : ARMISD::FUITOD;
+  return DAG.getNode(op, vt, Tmp);
+}
+
+static SDOperand LowerFP_TO_UINT(SDOperand Op, SelectionDAG &DAG) {
+  assert(Op.getValueType() == MVT::i32);
+  SDOperand FloatVal = Op.getOperand(0);
+  MVT::ValueType  vt = FloatVal.getValueType();
+  assert(vt == MVT::f32 || vt == MVT::f64);
+
+  ARMISD::NodeType op = vt == MVT::f32 ? ARMISD::FTOUIS : ARMISD::FTOUID;
+  SDOperand Tmp = DAG.getNode(op, MVT::f32, FloatVal);
+  return DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Tmp);
+}
+
 SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
   switch (Op.getOpcode()) {
   default:
@@ -527,8 +698,14 @@ SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
     return LowerConstantPool(Op, DAG);
   case ISD::GlobalAddress:
     return LowerGlobalAddress(Op, DAG);
+  case ISD::FP_TO_SINT:
+    return LowerFP_TO_SINT(Op, DAG);
   case ISD::SINT_TO_FP:
     return LowerSINT_TO_FP(Op, DAG);
+  case ISD::FP_TO_UINT:
+    return LowerFP_TO_UINT(Op, DAG);
+  case ISD::UINT_TO_FP:
+    return LowerUINT_TO_FP(Op, DAG);
   case ISD::FORMAL_ARGUMENTS:
     return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
   case ISD::CALL:
@@ -566,6 +743,7 @@ public:
   bool SelectAddrRegImm(SDOperand N, SDOperand &Offset, SDOperand &Base);
   bool SelectAddrMode1(SDOperand N, SDOperand &Arg, SDOperand &Shift,
                       SDOperand &ShiftType);
+  bool SelectAddrMode5(SDOperand N, SDOperand &Arg, SDOperand &Offset);
 
   // Include the pieces autogenerated from the target description.
 #include "ARMGenDAGISel.inc"
@@ -664,6 +842,14 @@ bool ARMDAGToDAGISel::SelectAddrMode1(SDOperand N,
   return true;
 }
 
+bool ARMDAGToDAGISel::SelectAddrMode5(SDOperand N, SDOperand &Arg,
+                                      SDOperand &Offset) {
+  //TODO: detect offset
+  Offset = CurDAG->getTargetConstant(0, MVT::i32);
+  Arg    = N;
+  return true;
+}
+
 //register plus/minus 12 bit offset
 bool ARMDAGToDAGISel::SelectAddrRegImm(SDOperand N, SDOperand &Offset,
                                    SDOperand &Base) {