From 649eaf9bfd466d7e98f1ba41e57ac39f440c989e Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Fri, 21 Mar 2003 17:10:02 +0000 Subject: [PATCH] javaop.h (jfloat, jdouble): Make them structures mirroring the bit fields of IEEE float and double respectively. * javaop.h (jfloat, jdouble): Make them structures mirroring the bit fields of IEEE float and double respectively. (JFLOAT_FINITE, JFLOAT_QNAN_MASK, JFLOAT_EXP_BIAS, JDOUBLE_FINITE, JDOUBLE_QNAN_MASK, JDOUBLE_EXP_BIAS): New. (union Word, union DWord): Delete. (WORD_TO_FLOAT, WORDS_TO_DOUBLE): Update to match. * gjavah.c (java_float_finite, java_double_finite, F_NAN_MASK, D_NAN_MASK): Delete. (jni_print_float, jni_print_double): New. Generate hexadecimal floating constants. (print_field_info): Use jni_print_float/double. * jcf-dump.c: Include math.h. Use ldexp/frexp to assemble finite floating point numbers for output; special case non-finite floats. From-SVN: r64671 --- gcc/java/ChangeLog | 39 +++++++++++++++------ gcc/java/gjavah.c | 84 +++++++++++++++++++++++++------------------- gcc/java/javaop.h | 68 +++++++++++++++++++----------------- gcc/java/jcf-dump.c | 85 +++++++++++++++++++++++++++++++++++++++------ 4 files changed, 188 insertions(+), 88 deletions(-) diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index db5651b37e2..1b980aea610 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,22 @@ +2003-03-21 Zack Weinberg + + * javaop.h (jfloat, jdouble): Make them structures mirroring + the bit fields of IEEE float and double respectively. + (JFLOAT_FINITE, JFLOAT_QNAN_MASK, JFLOAT_EXP_BIAS, + JDOUBLE_FINITE, JDOUBLE_QNAN_MASK, JDOUBLE_EXP_BIAS): New. + (union Word, union DWord): Delete. + (WORD_TO_FLOAT, WORDS_TO_DOUBLE): Update to match. + + * gjavah.c (java_float_finite, java_double_finite, F_NAN_MASK, + D_NAN_MASK): Delete. + (jni_print_float, jni_print_double): New. Generate + hexadecimal floating constants. + (print_field_info): Use jni_print_float/double. + + * jcf-dump.c: Include math.h. Use ldexp/frexp to assemble + finite floating point numbers for output; special case + non-finite floats. + 2003-03-19 Nathanael Nerode * lang.c (java_dump_tree): Change return type from 'int' to 'bool'. @@ -16,10 +35,10 @@ 2003-03-04 Andrew Haley - * gjavah.c (is_first_data_member): New global variable. - (print_c_decl): If it's the first data member, align it as the - superclass. - (process_file): Set is_first_data_member. + * gjavah.c (is_first_data_member): New global variable. + (print_c_decl): If it's the first data member, align it as the + superclass. + (process_file): Set is_first_data_member. 2003-03-11 Tom Tromey @@ -57,7 +76,7 @@ "strcmp" to compare file name components. Use IS_DIR_SEPARATOR instead of comparing directly against DIR_SEPARATOR. - (jcf_path_extdirs_arg): Use IS_DIR_SEPARATOR instead of + (jcf_path_extdirs_arg): Use IS_DIR_SEPARATOR instead of comparing directly against DIR_SEPARATOR. 2003-03-04 Tom Tromey @@ -91,7 +110,7 @@ * java/decl.c (java_init_decl_processing): Get soft_fmod_node from built_in_decls[BUILT_IN_FMOD] rather than define it ourselves. - + 2003-02-23 Tom Tromey * lang-options.h: Added -Wdeprecated. @@ -133,12 +152,12 @@ 2003-02-12 Ranjit Mathew - * decl.c (java_init_decl_processing): Change + * decl.c (java_init_decl_processing): Change soft_lookupjnimethod_node to reflect the change in signature of _Jv_LookupJNIMethod in libjava/jni.cc * expr.c (build_jni_stub): Calculate and pass the size on the stack of the arguments to a JNI function. Use - new target macro MODIFY_JNI_METHOD_CALL to allow a + new target macro MODIFY_JNI_METHOD_CALL to allow a target to modify the call to a JNI method. 2003-02-08 Roger Sayle @@ -324,7 +343,7 @@ 2003-01-14 Andrew Haley * decl.c (java_init_decl_processing): _Jv_NewMultiArray is a - varargs function -- correct. + varargs function -- correct. 2003-01-14 Andrew Haley @@ -571,7 +590,7 @@ * gcj.texi: Change version number to 3.4. 2002-12-05 Ranjit Mathew - Andrew Haley + Andrew Haley * parse.y (source_end_java_method): Remove custom encoding of line numbers for a function decl before passing it to the back end. diff --git a/gcc/java/gjavah.c b/gcc/java/gjavah.c index 23af65ab352..51cfe7cffbc 100644 --- a/gcc/java/gjavah.c +++ b/gcc/java/gjavah.c @@ -134,8 +134,6 @@ static void print_full_cxx_name (FILE*, JCF*, int, int, int, const char *, int); static void decompile_method (FILE*, JCF*, int); static void add_class_decl (FILE*, JCF*, JCF_u2); -static int java_float_finite (jfloat); -static int java_double_finite (jdouble); static void print_name (FILE *, JCF *, int); static void print_base_classname (FILE *, JCF *, int); static int utf8_cmp (const unsigned char *, int, const char *); @@ -158,6 +156,8 @@ static void version (void) ATTRIBUTE_NORETURN; static int overloaded_jni_method_exists_p (const unsigned char *, int, const char *, int); static void jni_print_char (FILE *, int); +static void jni_print_float (FILE *, jfloat); +static void jni_print_double (FILE *, jdouble); static void decompile_return_statement (FILE *, JCF *, int, int, int); JCF_u2 current_field_name; @@ -247,36 +247,54 @@ static int decompiled = 0; #include "jcf-reader.c" -/* Some useful constants. */ -#define F_NAN_MASK 0x7f800000 -#if (1 == HOST_FLOAT_WORDS_BIG_ENDIAN) && ! defined (HOST_WORDS_BIG_ENDIAN) -#define D_NAN_MASK 0x000000007ff00000LL -#else -#define D_NAN_MASK 0x7ff0000000000000LL -#endif - -/* Return 1 if F is not Inf or NaN. */ -static int -java_float_finite (jfloat f) +/* Print a single-precision float, suitable for parsing by g++. */ +static void +jni_print_float (FILE *stream, jfloat f) { - union Word u; - u.f = f; - - /* We happen to know that F_NAN_MASK will match all NaN values, and - also positive and negative infinity. That's why we only need one - test here. See The Java Language Specification, section 20.9. */ - return (u.i & F_NAN_MASK) != F_NAN_MASK; + /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't + work in data initializers. FIXME. */ + if (JFLOAT_FINITE (f)) + { + fputs (" = ", stream); + if (f.negative) + putc ('-', stream); + if (f.exponent) + fprintf (stream, "0x1.%.6xp%+df", + ((unsigned int)f.mantissa) << 1, + f.exponent - JFLOAT_EXP_BIAS); + else + /* Exponent of 0x01 is -125; exponent of 0x00 is *also* -125, + because the implicit leading 1 bit is no longer present. */ + fprintf (stream, "0x0.%.6xp%+df", + ((unsigned int)f.mantissa) << 1, + f.exponent + 1 - JFLOAT_EXP_BIAS); + } + fputs (";\n", stream); } -/* Return 1 if D is not Inf or NaN. */ -static int -java_double_finite (jdouble d) +/* Print a double-precision float, suitable for parsing by g++. */ +static void +jni_print_double (FILE *stream, jdouble f) { - union DWord u; - u.d = d; - - /* Now check for all NaNs. */ - return (u.l & D_NAN_MASK) != D_NAN_MASK; + /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't + work in data initializers. FIXME. */ + if (JDOUBLE_FINITE (f)) + { + fputs (" = ", stream); + if (f.negative) + putc ('-', stream); + if (f.exponent) + fprintf (stream, "0x1.%.5x%.8xp%+d", + f.mantissa0, f.mantissa1, + f.exponent - JDOUBLE_EXP_BIAS); + else + /* Exponent of 0x001 is -1022; exponent of 0x000 is *also* -1022, + because the implicit leading 1 bit is no longer present. */ + fprintf (stream, "0x0.%.5x%.8xp%+d", + f.mantissa0, f.mantissa1, + f.exponent + 1 - JDOUBLE_EXP_BIAS); + } + fputs (";\n", stream); } /* Print a character, appropriately mangled for JNI. */ @@ -732,10 +750,7 @@ print_field_info (FILE *stream, JCF* jcf, int name_index, int sig_index, jfloat fnum = JPOOL_FLOAT (jcf, current_field_value); fputs ("const jfloat ", out); print_field_name (out, jcf, name_index, 0); - if (! java_float_finite (fnum)) - fputs (";\n", out); - else - fprintf (out, " = %.10g;\n", fnum); + jni_print_float (out, fnum); } break; case CONSTANT_Double: @@ -743,10 +758,7 @@ print_field_info (FILE *stream, JCF* jcf, int name_index, int sig_index, jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value); fputs ("const jdouble ", out); print_field_name (out, jcf, name_index, 0); - if (! java_double_finite (dnum)) - fputs (";\n", out); - else - fprintf (out, " = %.17g;\n", dnum); + jni_print_double (out, dnum); } break; default: diff --git a/gcc/java/javaop.h b/gcc/java/javaop.h index da09254ad10..bdf3fa6e41f 100644 --- a/gcc/java/javaop.h +++ b/gcc/java/javaop.h @@ -55,21 +55,26 @@ typedef int32 jint; typedef int64 jlong; typedef void* jref; -/* A 32-bit IEEE single-precision float. */ -#ifndef jfloat -#define jfloat float -#endif - -/* A 32-bit IEEE double-precision float. */ -#ifndef jdouble -#define jdouble double -#endif - -union Word { - jint i; - jfloat f; - void *p; -}; +/* A 32-bit big-endian IEEE single-precision float. */ +typedef struct _jfloat { + unsigned int negative : 1; + unsigned int exponent : 8; + unsigned int mantissa : 23; +} jfloat; +#define JFLOAT_FINITE(f) ((f).exponent != 0xFF) +#define JFLOAT_QNAN_MASK 0x400000 +#define JFLOAT_EXP_BIAS 0x7f + +/* A 32-bit big-endian IEEE double-precision float. */ +typedef struct _jdouble { + unsigned int negative : 1; + unsigned int exponent : 11; + unsigned int mantissa0: 20; + unsigned int mantissa1: 32; +} jdouble; +#define JDOUBLE_FINITE(f) ((f).exponent != 0x7FF) +#define JDOUBLE_QNAN_MASK 0x80000 /* apply to mantissa0 */ +#define JDOUBLE_EXP_BIAS 0x3ff /* A jword is an unsigned integral type big enough for a 32-bit jint or jfloat *or* a pointer. It is the type appropriate for stack @@ -102,9 +107,14 @@ union Word { static inline jfloat WORD_TO_FLOAT(jword w) -{ union Word wu; - wu.i = w; - return wu.f; +{ + jfloat f; + + f.negative = (w & 0x80000000) >> 31; + f.exponent = (w & 0x7f800000) >> 23; + f.mantissa = (w & 0x007fffff); + + return f; } /* Sign extend w. If the host on which this cross-compiler runs uses @@ -126,21 +136,17 @@ WORDS_TO_LONG(jword hi, jword lo) return ((jlong) hi << 32) | ((jlong)lo & (((jlong)1 << 32) -1)); } -union DWord { - jdouble d; - jlong l; - jword w[2]; -}; - static inline jdouble WORDS_TO_DOUBLE(jword hi, jword lo) -{ union DWord wu; -#if (1 == HOST_FLOAT_WORDS_BIG_ENDIAN) - wu.l = WORDS_TO_LONG(lo, hi); -#else - wu.l = WORDS_TO_LONG(hi, lo); -#endif - return wu.d; +{ + jdouble d; + + d.negative = (hi & 0x80000000) >> 31; + d.exponent = (hi & 0x7ff00000) >> 20; + d.mantissa0 = (hi & 0x000fffff); + d.mantissa1 = lo; + + return d; } /* If PREFIX_CHAR is the first character of the Utf8 encoding of a character, diff --git a/gcc/java/jcf-dump.c b/gcc/java/jcf-dump.c index 6d976e53450..a87dd401e0f 100644 --- a/gcc/java/jcf-dump.c +++ b/gcc/java/jcf-dump.c @@ -62,6 +62,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "version.h" #include +#include /* Outout file. */ FILE *out; @@ -504,24 +505,86 @@ print_constant (FILE *out, JCF *jcf, int index, int verbosity) break; case CONSTANT_Float: { - union - { - jfloat f; - int32 i; - } pun; - - pun.f = JPOOL_FLOAT (jcf, index); - fprintf (out, "%s%.10g", - verbosity > 0 ? "Float " : "", (double) pun.f); + jfloat fnum = JPOOL_FLOAT (jcf, index); + + if (verbosity > 0) + fputs ("Float ", out); + + if (fnum.negative) + putc ('-', out); + + if (JFLOAT_FINITE (fnum)) + { + int dummy; + int exponent = fnum.exponent - JFLOAT_EXP_BIAS; + double f; + uint32 mantissa = fnum.mantissa; + if (fnum.exponent == 0) + /* Denormal. */ + exponent++; + else + /* Normal; add the implicit bit. */ + mantissa |= ((uint32)1 << 23); + + f = frexp (mantissa, &dummy); + f = ldexp (f, exponent + 1); + fprintf (out, "%.10g", f); + } + else + { + if (fnum.mantissa == 0) + fputs ("Inf", out); + else if (fnum.mantissa & JFLOAT_QNAN_MASK) + fprintf (out, "QNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK)); + else + fprintf (out, "SNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK)); + } + if (verbosity > 1) - fprintf (out, ", bits = 0x%08lx", (long) pun.i); + fprintf (out, ", bits = 0x%08lx", JPOOL_UINT (jcf, index)); break; } case CONSTANT_Double: { jdouble dnum = JPOOL_DOUBLE (jcf, index); - fprintf (out, "%s%.20g", verbosity > 0 ? "Double " : "", dnum); + + if (verbosity > 0) + fputs ("Double ", out); + + if (dnum.negative) + putc ('-', out); + + if (JDOUBLE_FINITE (dnum)) + { + int dummy; + int exponent = dnum.exponent - JDOUBLE_EXP_BIAS; + double d; + uint64 mantissa = ((((uint64) dnum.mantissa0) << 32) + + dnum.mantissa1); + if (dnum.exponent == 0) + /* Denormal. */ + exponent++; + else + /* Normal; add the implicit bit. */ + mantissa |= ((uint64)1 << 52); + + d = frexp (mantissa, &dummy); + d = ldexp (d, exponent + 1); + fprintf (out, "%.20g", d); + } + else + { + uint64 mantissa = dnum.mantissa0 & ~JDOUBLE_QNAN_MASK; + mantissa = (mantissa << 32) + dnum.mantissa1; + + if (dnum.mantissa0 == 0 && dnum.mantissa1 == 0) + fputs ("Inf", out); + else if (dnum.mantissa0 & JDOUBLE_QNAN_MASK) + fprintf (out, "QNaN(%llu)", (unsigned long long)mantissa); + else + fprintf (out, "SNaN(%llu)", (unsigned long long)mantissa); + } if (verbosity > 1) { int32 hi, lo; -- 2.30.2