/* -*-c-*-
*
- * Floating-point format conversions
+ * Direct floating-point format conversions
*
* (c) 2024 Straylight/Edgeware
*/
_(float, flt, f32) \
_(double, dbl, f64)
+#if defined(__hppa__) || (defined(__mips__) && !defined(__mips_nan2008))
+# define FROB_NANS
+#endif
+
#define CONV_DECLS_flt_f32 uint32 t
#if (FLT_FORMAT&(FLTFMT_ORGMASK | FLTFMT_TYPEMASK)) == FLTFMT_IEEE_F32
# if (FLT_FORMAT&FLTFMT_ENDMASK) == FLTFMT_BE
# else
# error "unimplemented byte order"
# endif
-# ifdef FLTFMT__MUST_FROB_NANS
-# define CONV_FROB_flt_f32 do { FLTFMT__FROB_NAN_F32(&t, rc); } while (0)
+# ifdef FROB_NANS
+# define CONV_FROBNANflt_f32 do { \
+ if ((t&0x7f800000) != 0x7f800000 || !(t&0x007fffff)) \
+ ; \
+ else if (t&0x003fffff) \
+ t ^= 0x00400000; \
+ else { \
+ t = (t&0x80000000) | 0x00000001; \
+ rc |= FLTERR_INEXACT; \
+ } \
+ } while (0)
# else
-# define CONV_FROB_flt_f32 do ; while (0)
+# define CONV_FROBNANflt_f32 do ; while (0)
# endif
#else
# define CONV_LOAD_flt_f32 do { \
rc |= fltfmt_encflt(z_out, &u, r); \
fltfmt_freebits(&u); \
} while (0)
-# define CONV_FROB_flt_f32 do ; while (0)
+# define CONV_FROBNANflt_f32 do ; while (0)
#endif
#define CONV_LOADB_flt_f32 do { t = LOAD32_B(p); } while (0)
#define CONV_LOADL_flt_f32 do { t = LOAD32_L(p); } while (0)
# else
# error "unimplemented byte order"
# endif
-# ifdef FLTFMT__MUST_FROB_NANS
-# define CONV_FROB_dbl_f64 do { \
- uint32 u[2]; \
- u[0] = HI64(t); u[1] = LO64(t); \
- FLTFMT__FROB_NAN_F64(&u, rc); \
- SET64(t, u[0], u[1]); \
+# ifdef FROB_NANS
+# define CONV_FROBNANdbl_f64 do { \
+ kludge64 u, v; \
+ SET64(u, 0x7ff00000, 0x00000000); AND64(v, t, u); \
+ if (CMP64(v, ==, u)) { \
+ SET64(u, 0x000fffff, 0xffffffff); AND64(v, t, u); \
+ if (!ZERO64(v)) { \
+ SET64(u, 0x0007ffff, 0xffffffff); AND64(v, t, u); \
+ if (!ZERO64(v)) \
+ { SET64(u, 0x00080000, 0x00000000); XOR64(t, t, u); } \
+ else { \
+ SET64(u, 0x80000000, 0x00000000); AND64(t, t, u); \
+ SET64(u, 0x00000000, 0x00000001); OR64(t, t, u); \
+ rc |= FLTERR_INEXACT; \
+ } \
+ } \
+ } \
} while (0)
# else
-# define CONV_FROB_dbl_f64 do ; while (0)
+# define CONV_FROBNANdbl_f64 do ; while (0)
# endif
#else
# define CONV_LOAD_dbl_f64 do { \
rc |= fltfmt_encdbl(z_out, &u, r); \
fltfmt_freebits(&u); \
} while (0)
-# define CONV_FROB_dbl_f64 do ; while (0)
+# define CONV_FROBNANdbl_f64 do ; while (0)
#endif
#define CONV_LOADB_dbl_f64 do { LOAD64_B_(t, p); } while (0)
#define CONV_LOADL_dbl_f64 do { LOAD64_L_(t, p); } while (0)
unsigned rc = 0; CONV_DECLS_##cty##_##fty; \
\
CONV_LOAD_##cty##_##fty; \
- CONV_FROB_##cty##_##fty; \
+ CONV_FROBNAN##cty##_##fty; \
CONV_STOREL_##cty##_##fty; \
return (rc); \
} \
unsigned rc = 0; CONV_DECLS_##cty##_##fty; \
\
CONV_LOAD_##cty##_##fty; \
- CONV_FROB_##cty##_##fty; \
+ CONV_FROBNAN##cty##_##fty; \
CONV_STOREB_##cty##_##fty; \
return (rc); \
}
unsigned rc = 0; CONV_DECLS_##cty##_##fty; \
\
CONV_LOADL_##cty##_##fty; \
- CONV_FROB_##cty##_##fty; \
+ CONV_FROBNAN##cty##_##fty; \
CONV_STORE_##cty##_##fty; \
return (rc); \
} \
unsigned rc = 0; CONV_DECLS_##cty##_##fty; \
\
CONV_LOADB_##cty##_##fty; \
- CONV_FROB_##cty##_##fty; \
+ CONV_FROBNAN##cty##_##fty; \
CONV_STORE_##cty##_##fty; \
return (rc); \
}