authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2020-12-13 22:12:27+07:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-12-23 20:22:43+02:00
log588e8287594803fdc06b6dfc3d7591075b88ff1e
treeb19204ab5de32e92eac2c9f8716071a8438c3e27
parent1d3ceac7707ccacc3a679efebdf0dc636470f44a

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.

3 files changed, 43 insertions(+), 30 deletions(-)

src/stage1/ir.cpp+7-7
...@@ -17,6 +17,7 @@...@@ -17,6 +17,7 @@
17#include "util.hpp"17#include "util.hpp"
18#include "mem_list.hpp"18#include "mem_list.hpp"
19#include "all_types.hpp"19#include "all_types.hpp"
20#include "zigendian.h"
2021
21#include <errno.h>22#include <errno.h>
22#include <math.h>23#include <math.h>
...@@ -11403,7 +11404,7 @@ static void float_negate(ZigValue *out_val, ZigValue *op) {...@@ -11403,7 +11404,7 @@ static void float_negate(ZigValue *out_val, ZigValue *op) {
11403 }11404 }
11404}11405}
1140511406
11406void float_write_ieee597(ZigValue *op, uint8_t *buf, bool is_big_endian) {11407void float_write_ieee597(ZigValue *op, uint8_t *buf, bool target_is_big_endian) {
11407 if (op->type->id != ZigTypeIdFloat)11408 if (op->type->id != ZigTypeIdFloat)
11408 zig_unreachable();11409 zig_unreachable();
1140911410
...@@ -11427,8 +11428,8 @@ void float_write_ieee597(ZigValue *op, uint8_t *buf, bool is_big_endian) {...@@ -11427,8 +11428,8 @@ void float_write_ieee597(ZigValue *op, uint8_t *buf, bool is_big_endian) {
11427 zig_unreachable();11428 zig_unreachable();
11428 }11429 }
1142911430
11430 if (is_big_endian) {11431 // Byteswap if system endianness != target endianness
11431 // Byteswap in place if needed11432 if (native_is_big_endian != target_is_big_endian) {
11432 for (size_t i = 0; i < n / 2; i++) {11433 for (size_t i = 0; i < n / 2; i++) {
11433 uint8_t u = buf[i];11434 uint8_t u = buf[i];
11434 buf[i] = buf[n - 1 - i];11435 buf[i] = buf[n - 1 - i];
...@@ -11437,7 +11438,7 @@ void float_write_ieee597(ZigValue *op, uint8_t *buf, bool is_big_endian) {...@@ -11437,7 +11438,7 @@ void float_write_ieee597(ZigValue *op, uint8_t *buf, bool is_big_endian) {
11437 }11438 }
11438}11439}
1143911440
11440void float_read_ieee597(ZigValue *val, uint8_t *buf, bool is_big_endian) {11441void float_read_ieee597(ZigValue *val, uint8_t *buf, bool target_is_big_endian) {
11441 if (val->type->id != ZigTypeIdFloat)11442 if (val->type->id != ZigTypeIdFloat)
11442 zig_unreachable();11443 zig_unreachable();
1144311444
...@@ -11447,10 +11448,9 @@ void float_read_ieee597(ZigValue *val, uint8_t *buf, bool is_big_endian) {...@@ -11447,10 +11448,9 @@ void float_read_ieee597(ZigValue *val, uint8_t *buf, bool is_big_endian) {
11447 uint8_t tmp[16];11448 uint8_t tmp[16];
11448 uint8_t *ptr = buf;11449 uint8_t *ptr = buf;
1144911450
11450 if (is_big_endian) {11451 // Byteswap if system endianness != target endianness
11452 if (native_is_big_endian != target_is_big_endian) {
11451 memcpy(tmp, buf, n);11453 memcpy(tmp, buf, n);
11452
11453 // Byteswap if needed
11454 for (size_t i = 0; i < n / 2; i++) {11454 for (size_t i = 0; i < n / 2; i++) {
11455 uint8_t u = tmp[i];11455 uint8_t u = tmp[i];
11456 tmp[i] = tmp[n - 1 - i];11456 tmp[i] = tmp[n - 1 - i];
src/stage1/parse_f128.c+2-23
...@@ -3,6 +3,7 @@...@@ -3,6 +3,7 @@
33
4#include "parse_f128.h"4#include "parse_f128.h"
5#include "softfloat.h"5#include "softfloat.h"
6#include "zigendian.h"
6#include <stddef.h>7#include <stddef.h>
7#include <sys/types.h>8#include <sys/types.h>
8#include <errno.h>9#include <errno.h>
...@@ -10,28 +11,6 @@...@@ -10,28 +11,6 @@
10#include <string.h>11#include <string.h>
11#include <math.h>12#include <math.h>
1213
13// Every OSes seem to define endianness macros in different files.
14#if defined(__APPLE__)
15 #include <machine/endian.h>
16 #define ZIG_BIG_ENDIAN BIG_ENDIAN
17 #define ZIG_LITTLE_ENDIAN LITTLE_ENDIAN
18 #define ZIG_BYTE_ORDER BYTE_ORDER
19#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
20 #include <sys/endian.h>
21 #define ZIG_BIG_ENDIAN _BIG_ENDIAN
22 #define ZIG_LITTLE_ENDIAN _LITTLE_ENDIAN
23 #define ZIG_BYTE_ORDER _BYTE_ORDER
24#elif defined(_WIN32) || defined(_WIN64)
25 // Assume that Windows installations are always little endian.
26 #define ZIG_LITTLE_ENDIAN 1
27 #define ZIG_BYTE_ORDER ZIG_LITTLE_ENDIAN
28#else // Linux
29 #include <endian.h>
30 #define ZIG_BIG_ENDIAN __BIG_ENDIAN
31 #define ZIG_LITTLE_ENDIAN __LITTLE_ENDIAN
32 #define ZIG_BYTE_ORDER __BYTE_ORDER
33#endif
34
35#define shcnt(f) ((f)->shcnt + ((f)->rpos - (f)->buf))14#define shcnt(f) ((f)->shcnt + ((f)->rpos - (f)->buf))
36#define shlim(f, lim) __shlim((f), (lim))15#define shlim(f, lim) __shlim((f), (lim))
37#define shgetc(f) (((f)->rpos != (f)->shend) ? *(f)->rpos++ : __shgetc(f))16#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...@@ -783,7 +762,7 @@ static float128_t decfloat(struct MuslFILE *f, int c, int bits, int emin, int si
783 }762 }
784763
785 if ((e2+LDBL_MANT_DIG & INT_MAX) > emax-5) {764 if ((e2+LDBL_MANT_DIG & INT_MAX) > emax-5) {
786 //if (fabsf128(y) >= 0x1p113) 765 //if (fabsf128(y) >= 0x1p113)
787 float128_t abs_y = fabsf128(y);766 float128_t abs_y = fabsf128(y);
788 float128_t mant_f128 = make_f128(0x4070000000000000, 0x0000000000000000);767 float128_t mant_f128 = make_f128(0x4070000000000000, 0x0000000000000000);
789 if (!f128M_lt(&abs_y, &mant_f128)) {768 if (!f128M_lt(&abs_y, &mant_f128)) {
src/stage1/zigendian.h created+34
...@@ -0,0 +1,34 @@
1#ifndef ZIG_ENDIAN_H
2#define ZIG_ENDIAN_H
3
4// Every OSes seem to define endianness macros in different files.
5#if defined(__APPLE__)
6 #include <machine/endian.h>
7 #define ZIG_BIG_ENDIAN BIG_ENDIAN
8 #define ZIG_LITTLE_ENDIAN LITTLE_ENDIAN
9 #define ZIG_BYTE_ORDER BYTE_ORDER
10#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
11 #include <sys/endian.h>
12 #define ZIG_BIG_ENDIAN _BIG_ENDIAN
13 #define ZIG_LITTLE_ENDIAN _LITTLE_ENDIAN
14 #define ZIG_BYTE_ORDER _BYTE_ORDER
15#elif defined(_WIN32) || defined(_WIN64)
16 // Assume that Windows installations are always little endian.
17 #define ZIG_LITTLE_ENDIAN 1
18 #define ZIG_BYTE_ORDER ZIG_LITTLE_ENDIAN
19#else // Linux
20 #include <endian.h>
21 #define ZIG_BIG_ENDIAN __BIG_ENDIAN
22 #define ZIG_LITTLE_ENDIAN __LITTLE_ENDIAN
23 #define ZIG_BYTE_ORDER __BYTE_ORDER
24#endif
25
26#if defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
27 const bool native_is_big_endian = false;
28#elif defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN
29 const bool native_is_big_endian = true;
30#else
31 #error Unsupported endian
32#endif
33
34#endif // ZIG_ENDIAN_H