Fixing d2f in interpreter (Was: Re: [kaffe] Re: Re: NetBSD/ppc
now works)
Dalibor Topic
robilad at kaffe.org
Fri Apr 30 11:59:02 PDT 2004
Dalibor Topic wrote:
> Riccardo wrote:
> I suspect that d2f is broken in the interpreter. The Java language spec
> demands that in case of overflow the value of float is a signed
> infinity, but the C standard says oveflow results in undefined
> behaviour. So I assume we'd have to check whether the double is
> representable as a float before we convert it, and handle the special
> cases that would invoke undefined behaviour ourself.
>
> I'm working on a patch.
Okay, I've got a patch for the interpreter. I'm unsure if it's really
necessary, or if it really fixes things, but hey, it's worth a try :)
Could you give this patch a try on netbsd-ppc and see if it fixes the
DoubleCvt test?
cheers,
dalibor topic
-------------- next part --------------
Index: kaffe/kaffevm/intrp/icode.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/intrp/icode.h,v
retrieving revision 1.20
diff -u -r1.20 icode.h
--- kaffe/kaffevm/intrp/icode.h 1 Feb 2004 22:14:53 -0000 1.20
+++ kaffe/kaffevm/intrp/icode.h 30 Apr 2004 18:03:14 -0000
@@ -12,6 +12,10 @@
#ifndef __icode_h
#define __icode_h
+#include <float.h>
+
+#include "jtypes.h"
+
#define move_long_const(t, c) (t)[0].v.tlong = (c)
#define add_long(t, f1, f2) (t)[0].v.tlong = (f1)[0].v.tlong + (f2)[0].v.tlong
#define sub_long(t, f1, f2) (t)[0].v.tlong = (f1)[0].v.tlong - (f2)[0].v.tlong
@@ -269,7 +273,106 @@
#define cvt_float_int(t, f) (t)[0].v.tint = soft_cvtfi((f)[0].v.tfloat)
#define cvt_float_double(t, f) (t)[0].v.tdouble = (f)[0].v.tfloat
#define cvt_double_int(t, f) (t)[0].v.tint = soft_cvtdi((f)[0].v.tdouble)
-#define cvt_double_float(t, f) (t)[0].v.tfloat = (f)[0].v.tdouble
+
+/* A union used to convert bits to floats. */
+/* NOTE: I should probably use functions from fp.h here. */
+typedef union {
+/* jint goes first, since ISO C only allows the first
+ * member of a union to be initialized in an initializer.
+ * If jfloat were first, we wouldn't be able to initialize
+ * it with inf/-inf, since these values are not valid
+ * expressions in C, they would have to be reserved keywords.
+ */
+jint i;
+jfloat f;
+} conv_float_t;
+
+static const conv_float_t FLOAT_POSITIVE_INFINITY = {0x7f800000};
+static const conv_float_t FLOAT_NEGATIVE_INFINITY = {0xff800000};
+static const conv_float_t FLOAT_DENORMALIZED_MINIMUM = {0x00000001};
+
+/**
+ * Convert a double to a float.
+ *
+ * Special case handling is performed to avoid
+ * getting undefined behaviour if the double can not be
+ * represented as a float.
+ *
+ * If the absolute value is lager than FLT_MAX, signed
+ * infinity is returned. If the absolute value is smaller
+ * than the smallest denormalized float value, signed 0
+ * is returned.
+ *
+ * @param d value to convert
+ * @return converted float
+ */
+
+static inline
+jfloat
+soft_convert_double_float(jdouble d) {
+
+ /* Get the absolute value of the parameter. */
+ jdouble abs_val = fabs(d);
+
+ /* Check for overflow. */
+
+ /* An overflow can happen if the absolute value of the
+ * parameter to convert is greater than the maximum
+ * representable float.
+ */
+
+ /* NOTE: I should probably use java_lang_Float_MAX_VALUE
+ * here.
+ */
+ if (abs_val > FLT_MAX) {
+ /* Java Language Specification 2n Ed §4.2.4
+ * demands that overflow results in signed
+ * infinity. C standard says leaving the
+ * domain range results in undefined behaviour,
+ * so we need to check for it and make adjustments.
+ */
+
+ if (d > 0.0) {
+ return FLOAT_POSITIVE_INFINITY.f;
+ }
+ else {
+ return FLOAT_NEGATIVE_INFINITY.f;
+ }
+ }
+
+ /* check for underflow */
+ /* underflow can happen if the parameter to convert is
+ * between (+/-)0.0 and (+/-)smallest denormalized float.
+ */
+ /* NOTE: I'm not sure if this is really necessary, though.
+ */
+ /* NOTE: I'm also not sure whether we're doing the rounding
+ * as per spec. It may be necessary to round
+ * denormalized doubles up to FLOAT_DENORMALIZED_MINIMUM.f
+ * in some cases.
+ */
+ if (abs_val > 0.0 && abs_val < FLOAT_DENORMALIZED_MINIMUM.f) {
+ /* Java Language Specification 2n Ed §4.2.4
+ * demands that underflow results in denormalized
+ * value or signed 0. So if the double is smaller
+ * than smallest denormalized float value, we
+ * return a signed 0.
+ */
+
+ if (d >= 0.0) {
+ return 0.0f;
+ }
+ else {
+ return -0.0f;
+ }
+ }
+
+ /* leave the rest (NaN, in-range-doubles) to the C compiler */
+
+ return d;
+}
+
+#define cvt_double_float(t, f) (t)[0].v.tfloat = soft_convert_double_float((f)[0].v.tdouble)
#define softcall_lookupinterfacemethod(r, n, t) (r)[0].v.taddr = soft_lookupinterfacemethod((t)[0].v.taddr, (n)->class, (n)->idx)
#define softcall_new(r, t) (r)->v.taddr = soft_new(t)
More information about the kaffe
mailing list