From a1227409084c4a675cc83ada128f364506528b9c Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 20 Aug 2010 18:47:36 -0700 Subject: [PATCH] Intrinsics for float/int and double/long conversions. [cherry-picked e22bd84c8c8a57ddd86c21a1f65137d549b07935 from dalvik-dev to gingerbread] Bug: 2935622 Change-Id: Ib4de19033dc4a08f41bf0eb0f7a21dcde216aae3 --- vm/InlineNative.c | 130 ++++++++++++++++++++++++-------- vm/InlineNative.h | 6 ++ vm/compiler/codegen/arm/CodegenDriver.c | 28 ++++++- 3 files changed, 131 insertions(+), 33 deletions(-) diff --git a/vm/InlineNative.c b/vm/InlineNative.c index d021002f9..a3a9ac87d 100644 --- a/vm/InlineNative.c +++ b/vm/InlineNative.c @@ -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" }, }; /* diff --git a/vm/InlineNative.h b/vm/InlineNative.h index 9b9ae3910..a54d9bdc1 100644 --- a/vm/InlineNative.h +++ b/vm/InlineNative.h @@ -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; /* diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c index 7716eb252..86c2e29c2 100644 --- a/vm/compiler/codegen/arm/CodegenDriver.c +++ b/vm/compiler/codegen/arm/CodegenDriver.c @@ -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); -- 2.11.0