OSDN Git Service

Intrinsics for float/int and double/long conversions.
authorElliott Hughes <enh@google.com>
Sat, 21 Aug 2010 01:47:36 +0000 (18:47 -0700)
committerElliott Hughes <enh@google.com>
Thu, 2 Sep 2010 01:01:24 +0000 (18:01 -0700)
[cherry-picked e22bd84c8c8a57ddd86c21a1f65137d549b07935 from dalvik-dev to gingerbread]

Bug: 2935622
Change-Id: Ib4de19033dc4a08f41bf0eb0f7a21dcde216aae3

vm/InlineNative.c
vm/InlineNative.h
vm/compiler/codegen/arm/CodegenDriver.c

index d021002..a3a9ac8 100644 (file)
@@ -487,6 +487,17 @@ static bool javaLangString_fastIndexOf_II(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
  * ===========================================================================
  */
 
+typedef union {
+    u4 arg;
+    float ff;
+} Convert32;
+
+typedef union {
+    u4 arg[2];
+    s8 ll;
+    double dd;
+} Convert64;
+
 /*
  * public static int abs(int)
  */
@@ -504,11 +515,7 @@ static bool javaLangMath_abs_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
 static bool javaLangMath_abs_long(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
     JValue* pResult)
 {
-    union {
-        u4 arg[2];
-        s8 ll;
-    } convert;
-
+    Convert64 convert;
     convert.arg[0] = arg0;
     convert.arg[1] = arg1;
     s8 val = convert.ll;
@@ -522,11 +529,7 @@ static bool javaLangMath_abs_long(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
 static bool javaLangMath_abs_float(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
     JValue* pResult)
 {
-    union {
-        u4 arg;
-        float ff;
-    } convert;
-
+    Convert32 convert;
     /* clear the sign bit; assumes a fairly common fp representation */
     convert.arg = arg0 & 0x7fffffff;
     pResult->f = convert.ff;
@@ -539,15 +542,10 @@ static bool javaLangMath_abs_float(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
 static bool javaLangMath_abs_double(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
     JValue* pResult)
 {
-    union {
-        u4 arg[2];
-        s8 ll;
-        double dd;
-    } convert;
-
-    /* clear the sign bit in the (endian-dependent) high word */
+    Convert64 convert;
     convert.arg[0] = arg0;
     convert.arg[1] = arg1;
+    /* clear the sign bit in the (endian-dependent) high word */
     convert.ll &= 0x7fffffffffffffffULL;
     pResult->d = convert.dd;
     return true;
@@ -583,11 +581,7 @@ static bool javaLangMath_max_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
 static bool javaLangMath_sqrt(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
     JValue* pResult)
 {
-    union {
-        u4 arg[2];
-        double dd;
-    } convert;
-
+    Convert64 convert;
     convert.arg[0] = arg0;
     convert.arg[1] = arg1;
     pResult->d = sqrt(convert.dd);
@@ -600,11 +594,7 @@ static bool javaLangMath_sqrt(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
 static bool javaLangMath_cos(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
     JValue* pResult)
 {
-    union {
-        u4 arg[2];
-        double dd;
-    } convert;
-
+    Convert64 convert;
     convert.arg[0] = arg0;
     convert.arg[1] = arg1;
     pResult->d = cos(convert.dd);
@@ -617,17 +607,79 @@ static bool javaLangMath_cos(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
 static bool javaLangMath_sin(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
     JValue* pResult)
 {
-    union {
-        u4 arg[2];
-        double dd;
-    } convert;
-
+    Convert64 convert;
     convert.arg[0] = arg0;
     convert.arg[1] = arg1;
     pResult->d = sin(convert.dd);
     return true;
 }
 
+/*
+ * ===========================================================================
+ *      java.lang.Float
+ * ===========================================================================
+ */
+
+static bool javaLangFloat_floatToIntBits(u4 arg0, u4 arg1, u4 arg2, u4 arg,
+    JValue* pResult)
+{
+    Convert32 convert;
+    convert.arg = arg0;
+    pResult->i = isnanf(convert.ff) ? 0x7fc00000 : arg0;
+    return true;
+}
+
+static bool javaLangFloat_floatToRawIntBits(u4 arg0, u4 arg1, u4 arg2, u4 arg,
+    JValue* pResult)
+{
+    pResult->i = arg0;
+    return true;
+}
+
+static bool javaLangFloat_intBitsToFloat(u4 arg0, u4 arg1, u4 arg2, u4 arg,
+    JValue* pResult)
+{
+    Convert32 convert;
+    convert.arg = arg0;
+    pResult->f = convert.ff;
+    return true;
+}
+
+/*
+ * ===========================================================================
+ *      java.lang.Double
+ * ===========================================================================
+ */
+
+static bool javaLangDouble_doubleToLongBits(u4 arg0, u4 arg1, u4 arg2, u4 arg,
+    JValue* pResult)
+{
+    Convert64 convert;
+    convert.arg[0] = arg0;
+    convert.arg[1] = arg1;
+    pResult->j = isnan(convert.dd) ? 0x7ff8000000000000LL : convert.ll;
+    return true;
+}
+
+static bool javaLangDouble_doubleToRawLongBits(u4 arg0, u4 arg1, u4 arg2,
+    u4 arg, JValue* pResult)
+{
+    Convert64 convert;
+    convert.arg[0] = arg0;
+    convert.arg[1] = arg1;
+    pResult->j = convert.ll;
+    return true;
+}
+
+static bool javaLangDouble_longBitsToDouble(u4 arg0, u4 arg1, u4 arg2, u4 arg,
+    JValue* pResult)
+{
+    Convert64 convert;
+    convert.arg[0] = arg0;
+    convert.arg[1] = arg1;
+    pResult->d = convert.dd;
+    return true;
+}
 
 /*
  * ===========================================================================
@@ -685,6 +737,20 @@ const InlineOperation gDvmInlineOpsTable[] = {
         "Ljava/lang/Math;", "cos", "(D)D" },
     { javaLangMath_sin,
         "Ljava/lang/Math;", "sin", "(D)D" },
+
+    { javaLangFloat_floatToIntBits,
+        "Ljava/lang/Float;", "floatToIntBits", "(F)I" },
+    { javaLangFloat_floatToRawIntBits,
+        "Ljava/lang/Float;", "floatToRawIntBits", "(F)I" },
+    { javaLangFloat_intBitsToFloat,
+        "Ljava/lang/Float;", "intBitsToFloat", "(I)F" },
+
+    { javaLangDouble_doubleToLongBits,
+        "Ljava/lang/Double;", "doubleToLongBits", "(D)J" },
+    { javaLangDouble_doubleToRawLongBits,
+        "Ljava/lang/Double;", "doubleToRawLongBits", "(D)J" },
+    { javaLangDouble_longBitsToDouble,
+        "Ljava/lang/Double;", "longBitsToDouble", "(J)D" },
 };
 
 /*
index 9b9ae39..a54d9bd 100644 (file)
@@ -66,6 +66,12 @@ typedef enum NativeInlineOps {
     INLINE_MATH_SQRT = 13,
     INLINE_MATH_COS = 14,
     INLINE_MATH_SIN = 15,
+    INLINE_FLOAT_TO_INT_BITS = 16,
+    INLINE_FLOAT_TO_RAW_INT_BITS = 17,
+    INLINE_INT_BITS_TO_FLOAT = 18,
+    INLINE_DOUBLE_TO_LONG_BITS = 19,
+    INLINE_DOUBLE_TO_RAW_LONG_BITS = 20,
+    INLINE_LONG_BITS_TO_DOUBLE = 21,
 } NativeInlineOps;
 
 /*
index 7716eb2..86c2e29 100644 (file)
@@ -3309,7 +3309,7 @@ static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir)
 {
     RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
     rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
-    RegLocation rlDest = inlinedTarget(cUnit, mir, false);;
+    RegLocation rlDest = inlinedTarget(cUnit, mir, false);
     RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
     int signReg = dvmCompilerAllocTemp(cUnit);
     /*
@@ -3346,6 +3346,24 @@ static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir)
     return false;
 }
 
+static bool genInlinedIntFloatConversion(CompilationUnit *cUnit, MIR *mir)
+{
+    // Just move from source to destination...
+    RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
+    RegLocation rlDest = inlinedTarget(cUnit, mir, false);
+    storeValue(cUnit, rlDest, rlSrc);
+    return false;
+}
+
+static bool genInlinedLongDoubleConversion(CompilationUnit *cUnit, MIR *mir)
+{
+    // Just move from source to destination...
+    RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
+    RegLocation rlDest = inlinedTargetWide(cUnit, mir, false);
+    storeValueWide(cUnit, rlDest, rlSrc);
+    return false;
+}
+
 /*
  * NOTE: Handles both range and non-range versions (arguments
  * have already been normalized by this point).
@@ -3402,9 +3420,17 @@ static bool handleExecuteInline(CompilationUnit *cUnit, MIR *mir)
                         return false;
                     else
                         break;
+                case INLINE_FLOAT_TO_RAW_INT_BITS:
+                case INLINE_INT_BITS_TO_FLOAT:
+                    return genInlinedIntFloatConversion(cUnit, mir);
+                case INLINE_DOUBLE_TO_RAW_LONG_BITS:
+                case INLINE_LONG_BITS_TO_DOUBLE:
+                    return genInlinedLongDoubleConversion(cUnit, mir);
                 case INLINE_STRING_EQUALS:
                 case INLINE_MATH_COS:
                 case INLINE_MATH_SIN:
+                case INLINE_FLOAT_TO_INT_BITS:
+                case INLINE_DOUBLE_TO_LONG_BITS:
                     break;   /* Handle with C routine */
                 default:
                     dvmCompilerAbort(cUnit);