@@@ fltfmt wip
[mLib] / utils / fltfmt-convert.c
index 6db742b..cc24dba 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-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 {                                       \
@@ -69,7 +82,7 @@
      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);                                                       \
   }
@@ -188,7 +212,7 @@ CONVERSIONS(DEF_CONV)
     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);                                                       \
   }                                                                    \
@@ -198,7 +222,7 @@ CONVERSIONS(DEF_CONV)
     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);                                                       \
   }