diff --git a/.github/workflows/build-and-test-other.yaml b/.github/workflows/build-and-test-other.yaml index 98d160c00..c7a1bcee4 100644 --- a/.github/workflows/build-and-test-other.yaml +++ b/.github/workflows/build-and-test-other.yaml @@ -108,11 +108,11 @@ jobs: tag: "bullseye" cflags: "-O2" - # It looks like we don't really support big-endian - # - arch: "powerpc" - # distro: "jessie" - # base_url: "http://archive.debian.org/debian" - # cflags: "-std=gnu99 -Os" + # Required for testing big endian archs + - arch: "s390x" + platform: "s390x" + tag: "bullseye" + cflags: "-O2" steps: - name: Checkout repo diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b8a59954..d347ee58c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fixed a bug where guards would raise exceptions instead of just being false +- Fixed support for big endian CPUs (such as some MIPS CPUs). ## [0.6.0-alpha.1] - 2023-10-09 diff --git a/src/libAtomVM/iff.c b/src/libAtomVM/iff.c index 374a94503..6bb2c428c 100644 --- a/src/libAtomVM/iff.c +++ b/src/libAtomVM/iff.c @@ -53,7 +53,9 @@ void scan_iff(const void *iff_binary, int buf_size, unsigned long *offsets, unsi uint32_t iff_size = READ_32_ALIGNED(data + 4); int file_size = iff_size; if (UNLIKELY(buf_size < file_size)) { - fprintf(stderr, "warning: buffer holding IFF is smaller than IFF size: %i", buf_size); + fprintf(stderr, "error: buffer holding IFF is smaller than IFF size: %i\n", buf_size); + // TODO: return error instead of crashing + AVM_ABORT(); } do { diff --git a/src/libAtomVM/utils.h b/src/libAtomVM/utils.h index 260adccfd..2d396dfa5 100644 --- a/src/libAtomVM/utils.h +++ b/src/libAtomVM/utils.h @@ -28,7 +28,7 @@ #ifndef _UTILS_H_ #define _UTILS_H_ -#ifdef __ORDER_LITTLE_ENDIAN__ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #ifdef __GNUC__ #define READ_32_ALIGNED(ptr) \ __builtin_bswap32(*((uint32_t *) (ptr))) @@ -102,7 +102,26 @@ #define ENDIAN_SWAP_32(value) ((((value) & 0xFF) << 24) | (((value) & 0xFF00) << 8) | (((value) & 0xFF0000) >> 8) | (((value) & 0xFF000000) >> 24)) #endif -#else +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + + #define READ_64_UNALIGNED(ptr) \ + ( (((uint64_t) ((uint8_t *)(ptr))[0]) << 56) | (((uint64_t) ((uint8_t *) (ptr))[1]) << 48) | \ + (((uint64_t) ((uint8_t *)(ptr))[2]) << 40) | (((uint64_t) ((uint8_t *) (ptr))[3]) << 32) | \ + (((uint64_t) ((uint8_t *)(ptr))[4]) << 24) | (((uint64_t) ((uint8_t *) (ptr))[5]) << 16) | \ + (((uint64_t) ((uint8_t *)(ptr))[6]) << 8) | (((uint64_t) ((uint8_t *) (ptr))[7])) ) + + #define WRITE_64_UNALIGNED(ptr, val) \ + { \ + ((uint8_t *)(ptr))[0] = (((uint64_t) val) >> 56) & 0xff; \ + ((uint8_t *)(ptr))[1] = (((uint64_t) val) >> 48) & 0xff; \ + ((uint8_t *)(ptr))[2] = (((uint64_t) val) >> 40) & 0xff; \ + ((uint8_t *)(ptr))[3] = (((uint64_t) val) >> 32) & 0xff; \ + ((uint8_t *)(ptr))[4] = (((uint64_t) val) >> 24) & 0xff; \ + ((uint8_t *)(ptr))[5] = (((uint64_t) val) >> 16) & 0xff; \ + ((uint8_t *)(ptr))[6] = (((uint64_t) val) >> 8) & 0xff; \ + ((uint8_t *)(ptr))[7] = ((uint64_t) val) & 0xff; \ + } + #define READ_32_ALIGNED(ptr) \ (*((uint32_t *) (ptr))) @@ -110,15 +129,26 @@ ( (((uint8_t *)(ptr))[0] << 24) | (((uint8_t *) (ptr))[1] << 16) | (((uint8_t *)(ptr))[2] << 8) | ((uint8_t *)(ptr))[3] ) #define WRITE_32_UNALIGNED(ptr, val) \ - *((uint32_t *) (ptr)) = ( (((uint8_t *)(&val))[0] << 24) | (((uint8_t *) (&val))[1] << 16) | (((uint8_t *)(&val))[2] << 8) | ((uint8_t *)(&val))[3] ) + { \ + ((uint8_t *)(ptr))[0] = (((uint32_t) val) >> 24) & 0xff; \ + ((uint8_t *)(ptr))[1] = (((uint32_t) val) >> 16) & 0xff; \ + ((uint8_t *)(ptr))[2] = (((uint32_t) val) >> 8) & 0xff; \ + ((uint8_t *)(ptr))[3] = ((uint32_t) val) & 0xff; \ + } #define READ_16_UNALIGNED(ptr) \ ( (((uint8_t *)(ptr))[0] << 8) | ((uint8_t *)(ptr))[1] ) #define WRITE_16_UNALIGNED(ptr, val) \ - *((uint16_t *) (ptr)) = ( (((uint8_t *)(&val))[0] << 8) | ((uint8_t *)(&val))[1] ) + { \ + ((uint8_t *)(ptr))[0] = (((uint16_t) val) >> 8) & 0xff; \ + ((uint8_t *)(ptr))[1] = ((uint16_t) val) & 0xff; \ + } #define ENDIAN_SWAP_32(value) (value) + +#else + #error "Unsupported __BYTE_ORDER__ value." #endif #define UNUSED(x) (void) (x);