Commit 588e828759

Koakuma <koachan@protonmail.com>
2020-12-13 16:12:27
float_*_ieee597: only swap bytes when targeting different endianness than native
float_*_ieee597 functions should fill the buffer with the target endianness, instead of always filling it in LE ordering.
1 parent 1d3ceac
Changed files (3)
src/stage1/ir.cpp
@@ -17,6 +17,7 @@
 #include "util.hpp"
 #include "mem_list.hpp"
 #include "all_types.hpp"
+#include "zigendian.h"
 
 #include <errno.h>
 #include <math.h>
@@ -11403,7 +11404,7 @@ static void float_negate(ZigValue *out_val, ZigValue *op) {
     }
 }
 
-void float_write_ieee597(ZigValue *op, uint8_t *buf, bool is_big_endian) {
+void float_write_ieee597(ZigValue *op, uint8_t *buf, bool target_is_big_endian) {
     if (op->type->id != ZigTypeIdFloat)
         zig_unreachable();
 
@@ -11427,8 +11428,8 @@ void float_write_ieee597(ZigValue *op, uint8_t *buf, bool is_big_endian) {
             zig_unreachable();
     }
 
-    if (is_big_endian) {
-        // Byteswap in place if needed
+    // Byteswap if system endianness != target endianness
+    if (native_is_big_endian != target_is_big_endian) {
         for (size_t i = 0; i < n / 2; i++) {
             uint8_t u = buf[i];
             buf[i] = buf[n - 1 - i];
@@ -11437,7 +11438,7 @@ void float_write_ieee597(ZigValue *op, uint8_t *buf, bool is_big_endian) {
     }
 }
 
-void float_read_ieee597(ZigValue *val, uint8_t *buf, bool is_big_endian) {
+void float_read_ieee597(ZigValue *val, uint8_t *buf, bool target_is_big_endian) {
     if (val->type->id != ZigTypeIdFloat)
         zig_unreachable();
 
@@ -11447,10 +11448,9 @@ void float_read_ieee597(ZigValue *val, uint8_t *buf, bool is_big_endian) {
     uint8_t tmp[16];
     uint8_t *ptr = buf;
 
-    if (is_big_endian) {
+    // Byteswap if system endianness != target endianness
+    if (native_is_big_endian != target_is_big_endian) {
         memcpy(tmp, buf, n);
-
-        // Byteswap if needed
         for (size_t i = 0; i < n / 2; i++) {
             uint8_t u = tmp[i];
             tmp[i] = tmp[n - 1 - i];
src/stage1/parse_f128.c
@@ -3,6 +3,7 @@
 
 #include "parse_f128.h"
 #include "softfloat.h"
+#include "zigendian.h"
 #include <stddef.h>
 #include <sys/types.h>
 #include <errno.h>
@@ -10,28 +11,6 @@
 #include <string.h>
 #include <math.h>
 
-// Every OSes seem to define endianness macros in different files.
-#if defined(__APPLE__)
-  #include <machine/endian.h>
-  #define ZIG_BIG_ENDIAN    BIG_ENDIAN
-  #define ZIG_LITTLE_ENDIAN LITTLE_ENDIAN
-  #define ZIG_BYTE_ORDER    BYTE_ORDER
-#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
-  #include <sys/endian.h>
-  #define ZIG_BIG_ENDIAN    _BIG_ENDIAN
-  #define ZIG_LITTLE_ENDIAN _LITTLE_ENDIAN
-  #define ZIG_BYTE_ORDER    _BYTE_ORDER
-#elif defined(_WIN32) || defined(_WIN64)
-  // Assume that Windows installations are always little endian.
-  #define ZIG_LITTLE_ENDIAN 1
-  #define ZIG_BYTE_ORDER    ZIG_LITTLE_ENDIAN
-#else // Linux
-  #include <endian.h>
-  #define ZIG_BIG_ENDIAN    __BIG_ENDIAN
-  #define ZIG_LITTLE_ENDIAN __LITTLE_ENDIAN
-  #define ZIG_BYTE_ORDER    __BYTE_ORDER
-#endif
-
 #define shcnt(f) ((f)->shcnt + ((f)->rpos - (f)->buf))
 #define shlim(f, lim) __shlim((f), (lim))
 #define shgetc(f) (((f)->rpos != (f)->shend) ? *(f)->rpos++ : __shgetc(f))
@@ -783,7 +762,7 @@ static float128_t decfloat(struct MuslFILE *f, int c, int bits, int emin, int si
     }
 
     if ((e2+LDBL_MANT_DIG & INT_MAX) > emax-5) {
-        //if (fabsf128(y) >= 0x1p113) 
+        //if (fabsf128(y) >= 0x1p113)
         float128_t abs_y = fabsf128(y);
         float128_t mant_f128 = make_f128(0x4070000000000000, 0x0000000000000000);
         if (!f128M_lt(&abs_y, &mant_f128)) {
src/stage1/zigendian.h
@@ -0,0 +1,34 @@
+#ifndef ZIG_ENDIAN_H
+#define ZIG_ENDIAN_H
+
+// Every OSes seem to define endianness macros in different files.
+#if defined(__APPLE__)
+  #include <machine/endian.h>
+  #define ZIG_BIG_ENDIAN    BIG_ENDIAN
+  #define ZIG_LITTLE_ENDIAN LITTLE_ENDIAN
+  #define ZIG_BYTE_ORDER    BYTE_ORDER
+#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+  #include <sys/endian.h>
+  #define ZIG_BIG_ENDIAN    _BIG_ENDIAN
+  #define ZIG_LITTLE_ENDIAN _LITTLE_ENDIAN
+  #define ZIG_BYTE_ORDER    _BYTE_ORDER
+#elif defined(_WIN32) || defined(_WIN64)
+  // Assume that Windows installations are always little endian.
+  #define ZIG_LITTLE_ENDIAN 1
+  #define ZIG_BYTE_ORDER    ZIG_LITTLE_ENDIAN
+#else // Linux
+  #include <endian.h>
+  #define ZIG_BIG_ENDIAN    __BIG_ENDIAN
+  #define ZIG_LITTLE_ENDIAN __LITTLE_ENDIAN
+  #define ZIG_BYTE_ORDER    __BYTE_ORDER
+#endif
+
+#if defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
+  const bool native_is_big_endian = false;
+#elif defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN
+  const bool native_is_big_endian = true;
+#else
+  #error Unsupported endian
+#endif
+
+#endif // ZIG_ENDIAN_H