diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 8a86227..0f8120f 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -7130,6 +7130,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 	*total = COSTS_N_INSNS (2);
       else if (TARGET_HARD_FLOAT && mode == DFmode && !TARGET_VFP_SINGLE)
 	*total = COSTS_N_INSNS (4);
+      else if (mode == DImode) 
+        *total = COSTS_N_INSNS (50);
       else
 	*total = COSTS_N_INSNS (20);
       return false;
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 5bcb7a8..57bb4cc 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -3879,8 +3879,13 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	    }
 	  *total = COSTS_N_INSNS (mips_idiv_insns ());
 	}
-      else if (mode == DImode)
+      else if (mode == DImode) {
+	if (!TARGET_64BIT)
+	   /* divide double integer libcall is expensive.  */
+	   *total = COSTS_N_INSNS (200);
+	  else
         *total = mips_cost->int_div_di;
+	}
       else
 	*total = mips_cost->int_div_si;
       return false;
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 98f7c09..5108df9 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -3539,6 +3539,84 @@ expand_mult_highpart_optab (enum machine_mode mode, rtx op0, rtx op1,
 	}
     }
 
+  if (unsignedp
+      && size - 1 > BITS_PER_WORD 
+      && (!optimize_size && (optimize>1))
+      && (4 * mul_cost[speed][mode] + 4 * add_cost[speed][mode]
+          + shift_cost[speed][mode][31] < max_cost))
+    {
+      rtx x1, x0, y1, y0, z2, z0, tmp, u0, u0tmp, u1, carry, carry_result, result;
+
+      /* Extracting the higher part of the 64-bit multiplier.  */
+      x1 = gen_highpart (word_mode, op0);
+      x1 = force_reg (word_mode, x1);
+
+      /* Extracting the lower part of the 64-bit multiplier.  */
+      x0 = gen_lowpart (word_mode, op0);
+      x0 = force_reg (word_mode, x0);
+
+      /* Splitting the 64-bit constant for the higher and the lower parts.  */
+      y0 = gen_lowpart (word_mode, op1);
+      y0 = force_reg (word_mode, y0);
+      y1 = gen_highpart_mode (word_mode, mode, op1);
+
+      z2 = gen_reg_rtx (mode);
+      u0 = gen_reg_rtx (mode);
+
+      z2 = expand_widening_mult (mode, x1, y1, z2, 1, umul_widen_optab);
+
+      u0 = expand_widening_mult (mode, x0, y1, u0, 1, umul_widen_optab);
+
+      z0 = gen_reg_rtx (mode);
+      u1 = gen_reg_rtx (mode);
+
+      z0 = expand_widening_mult (mode, x0, y0, z0, 1, umul_widen_optab);
+
+      u1 = expand_widening_mult (mode, x1, y0, u1, 1, umul_widen_optab);
+
+      /* Compute the middle word of the three-word intermediate result.  */
+      u0tmp = gen_highpart (word_mode, z0);
+      u0tmp = force_reg (word_mode, u0tmp);
+      u0tmp = convert_to_mode (mode, u0tmp, 1);
+
+      /* We have to return
+	 z2 + ((u0 + u1) >> BITS_PER_WORD)
+	 u0 + u1 are the upper two words of the three-word
+	 intermediate result and they could have up to
+	 2 * BITS_PER_WORD + 1 bits of precision.
+	 We compute the extra bit by checking for carry, and add
+	 1 << BITS_PER_WORD to z2 if there is carry.  */
+
+      expand_inc (u0, u0tmp);
+      tmp = gen_reg_rtx (mode);
+
+      tmp = expand_binop (mode, add_optab, u0, u1, tmp, 1, OPTAB_LIB_WIDEN);
+      if (!tmp)
+             return 0;
+
+      /* Checking for carry here.  */
+      carry = gen_reg_rtx (mode);
+
+      emit_store_flag_force (carry, GT, u0, tmp, mode, 1, 1);
+
+      carry_result = gen_reg_rtx (mode);
+      carry_result = expand_shift (LSHIFT_EXPR, mode, carry, BITS_PER_WORD, carry_result, 1);
+
+      /* Adding 0x100000000 as carry here if required.  */
+      expand_inc (z2, carry_result);
+
+      /* Extracting the higher part of the sum.  */
+      tmp = gen_highpart (word_mode, tmp);
+      tmp = force_reg (word_mode, tmp);
+      tmp = convert_to_mode (mode, tmp, 1);
+
+      /* The final result */
+      expand_inc (z2, tmp);
+
+      return z2;
+
+    }
+
   /* Try widening multiplication of opposite signedness, and adjust.  */
   moptab = unsignedp ? smul_widen_optab : umul_widen_optab;
   if (widening_optab_handler (moptab, wider_mode, mode) != CODE_FOR_nothing
