Starting to implement fly2iceland.

Thanks to logan:
Fix WIP FPCompare implementation.

Change-Id: Ia8816d7092bc99d87ccb8abf524dad0e5fd5b7bc
diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc
index dd16ef7..f29cab1 100644
--- a/src/compiler_llvm/gbc_expander.cc
+++ b/src/compiler_llvm/gbc_expander.cc
@@ -175,6 +175,19 @@
 
   void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
 
+  //----------------------------------------------------------------------------
+  // Quick
+  //----------------------------------------------------------------------------
+
+  llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
+                                llvm::Value* src2_value,
+                                bool gt_bias);
+
+  llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
+
+  llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
+                                          llvm::Value* cmp_lt);
+
  public:
   static char ID;
 
@@ -977,6 +990,41 @@
   return EmitStackOverflowCheck(&*first_non_alloca);
 }
 
+llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
+                                               llvm::Value* src2_value,
+                                               bool gt_bias) {
+  llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
+  llvm::Value* cmp_lt;
+
+  if (gt_bias) {
+    cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
+  } else {
+    cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
+  }
+
+  return EmitCompareResultSelection(cmp_eq, cmp_lt);
+}
+
+llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
+  llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
+  llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
+
+  return EmitCompareResultSelection(cmp_eq, cmp_lt);
+}
+
+llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
+                                                         llvm::Value* cmp_lt) {
+
+  llvm::Constant* zero = irb_.getJInt(0);
+  llvm::Constant* pos1 = irb_.getJInt(1);
+  llvm::Constant* neg1 = irb_.getJInt(-1);
+
+  llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
+  llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
+
+  return result_eq;
+}
+
 llvm::Value*
 GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
                                  llvm::CallInst& call_inst) {
@@ -1515,6 +1563,44 @@
       Expand_UpdateDexPC(call_inst.getArgOperand(0));
       return NULL;
     }
+
+
+    //==- Quick ------------------------------------------------------------==//
+    case IntrinsicHelper::IntToChar: {
+      return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
+                             irb_.getJIntTy());
+    }
+    case IntrinsicHelper::IntToShort: {
+      return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
+                             irb_.getJIntTy());
+    }
+    case IntrinsicHelper::IntToByte: {
+      return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
+                             irb_.getJIntTy());
+    }
+    case IntrinsicHelper::CmplFloat:
+    case IntrinsicHelper::CmplDouble: {
+      return Expand_FPCompare(call_inst.getArgOperand(0), call_inst.getArgOperand(0), false);
+    }
+    case IntrinsicHelper::CmpgFloat:
+    case IntrinsicHelper::CmpgDouble: {
+      return Expand_FPCompare(call_inst.getArgOperand(0), call_inst.getArgOperand(0), true);
+    }
+    case IntrinsicHelper::CmpLong: {
+      return Expand_LongCompare(call_inst.getArgOperand(0), call_inst.getArgOperand(0));
+    }
+    case greenland::IntrinsicHelper::SHLLong: {
+    }
+    case greenland::IntrinsicHelper::SHRLong: {
+    }
+    case greenland::IntrinsicHelper::USHRLong: {
+    }
+    case greenland::IntrinsicHelper::SHLInt: {
+    }
+    case greenland::IntrinsicHelper::SHRInt: {
+    }
+    case greenland::IntrinsicHelper::USHRInt: {
+    }
     default: {
       const IntrinsicHelper::IntrinsicInfo& intr_info =
           IntrinsicHelper::GetInfo(intr_id);