From 897702f17ee562cf5192e3ee22c11e25a45aa723 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Thu, 24 Jan 2019 14:15:52 -0800 Subject: [PATCH 1/3] Unaligned access support for pgm_read_word/dword --- .../xtensa-lx106-elf/include/sys/pgmspace.h | 54 ++++++++++++++++--- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h b/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h index ba46d84683..f0f5b64fe5 100644 --- a/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h +++ b/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h @@ -68,16 +68,54 @@ static inline uint16_t pgm_read_word_inlined(const void* addr) { return (uint16_t) res; /* This masks the lower half-word from the returned word */ } -#define pgm_read_byte(addr) pgm_read_byte_inlined(addr) -#define pgm_read_word(addr) pgm_read_word_inlined(addr) + + +#define pgm_read_byte(addr) pgm_read_byte_inlined(addr) +#define pgm_read_word_aligned(addr) pgm_read_word_inlined(addr) #ifdef __cplusplus - #define pgm_read_dword(addr) (*reinterpret_cast(addr)) - #define pgm_read_float(addr) (*reinterpret_cast(addr)) - #define pgm_read_ptr(addr) (*reinterpret_cast(addr)) + #define pgm_read_dword_aligned(addr) (*reinterpret_cast(addr)) + #define pgm_read_float_aligned(addr) (*reinterpret_cast(addr)) + #define pgm_read_ptr_aligned(addr) (*reinterpret_cast(addr)) +#else + #define pgm_read_dword_aligned(addr) (*(const uint32_t*)(addr)) + #define pgm_read_float_aligned(addr) (*(const float*)(addr)) + #define pgm_read_ptr_aligned(addr) (*(const void*)(addr)) +#endif + +__attribute__((optimize("-O3"), always_inline)) static inline uint32_t pgm_read_dword_unaligned(const void *addr) { + if (!(((int)addr)&3)) return *(const uint32_t *)addr; + int off = (((int)addr) & 3) << 3; + const uint32_t *p = (const uint32_t *)((int)addr & (~3)); + uint32_t a = *p++; + uint32_t b = *p; + return (a>>off) | (b <<(32-off)); +} + +__attribute__((optimize("-O3"), always_inline)) static inline float pgm_read_float_unaligned(const void *addr) { + return (float)pgm_read_dword_unaligned(addr); +} + +__attribute__((optimize("-O3"), always_inline)) static inline void *pgm_read_ptr_unaligned(const void *addr) { + return (void *)pgm_read_dword_unaligned(addr); +} + +__attribute__((optimize("-O3"), always_inline)) static inline uint16_t pgm_read_word_unaligned(const void *addr) { + return pgm_read_dword_unaligned(addr) & 0xffff; +} + + +// Allow manual selection of _aligned or _unaligned, but default to _unaligned for Arduino compatibility +#define PGM_READ_UNALIGNED_DEFAULT +#ifdef PGM_READ_UNALIGNED_DEFAULT + #define pgm_read_word(a) pgm_read_word_unaligned(a) + #define pgm_read_dword(a) pgm_read_dword_unaligned(a) + #define pgm_read_float(a) pgm_read_float_unaligned(a) + #define pgm_read_ptr(a) pgm_read_ptr_unaligned(a) #else - #define pgm_read_dword(addr) (*(const uint32_t*)(addr)) - #define pgm_read_float(addr) (*(const float)(addr)) - #define pgm_read_ptr(addr) (*(const void*)(addr)) + #define pgm_read_word(a) pgm_read_word_aligned(a) + #define pgm_read_dword(a) pgm_read_dword_aligned(a) + #define pgm_read_float(a) pgm_read_float_aligned(a) + #define pgm_read_ptr(a) pgm_read_ptr_aligned(a) #endif #define pgm_read_byte_near(addr) pgm_read_byte(addr) From 2508e21bd3d88d7419e49de91c44fd05d9135c91 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Thu, 7 Feb 2019 09:01:26 -0800 Subject: [PATCH 2/3] Fix pgm_read_ptr_aligned() per #5735 --- tests/host/sys/pgmspace.h | 4 ++-- tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/host/sys/pgmspace.h b/tests/host/sys/pgmspace.h index 1b052a085b..63d973d72e 100644 --- a/tests/host/sys/pgmspace.h +++ b/tests/host/sys/pgmspace.h @@ -31,13 +31,13 @@ #define pgm_read_word(addr) (*reinterpret_cast(addr)) #define pgm_read_dword(addr) (*reinterpret_cast(addr)) #define pgm_read_float(addr) (*reinterpret_cast(addr)) - #define pgm_read_ptr(addr) (*reinterpret_cast(addr)) + #define pgm_read_ptr(addr) (*reinterpret_cast(addr)) #else #define pgm_read_byte(addr) (*(const uint8_t*)(addr)) #define pgm_read_word(addr) (*(const uint16_t*)(addr)) #define pgm_read_dword(addr) (*(const uint32_t*)(addr)) #define pgm_read_float(addr) (*(const float)(addr)) - #define pgm_read_ptr(addr) (*(const void const *)(addr)) + #define pgm_read_ptr(addr) (*(const void* const *)(addr)) #endif #define pgm_read_byte_near(addr) pgm_read_byte(addr) diff --git a/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h b/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h index f0f5b64fe5..4a3850d251 100644 --- a/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h +++ b/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h @@ -75,11 +75,11 @@ static inline uint16_t pgm_read_word_inlined(const void* addr) { #ifdef __cplusplus #define pgm_read_dword_aligned(addr) (*reinterpret_cast(addr)) #define pgm_read_float_aligned(addr) (*reinterpret_cast(addr)) - #define pgm_read_ptr_aligned(addr) (*reinterpret_cast(addr)) + #define pgm_read_ptr_aligned(addr) (*reinterpret_cast(addr)) #else #define pgm_read_dword_aligned(addr) (*(const uint32_t*)(addr)) #define pgm_read_float_aligned(addr) (*(const float*)(addr)) - #define pgm_read_ptr_aligned(addr) (*(const void*)(addr)) + #define pgm_read_ptr_aligned(addr) (*(const void* const*)(addr)) #endif __attribute__((optimize("-O3"), always_inline)) static inline uint32_t pgm_read_dword_unaligned(const void *addr) { From 15f3dec3c7b0660a348cfa9d67c3ed817f1323ae Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Mon, 25 Feb 2019 13:19:58 -0800 Subject: [PATCH 3/3] Allow users to use aligned-only via a #define Adding -DPGM_READ_UNALIGNED=0 or #define PGM_READ_UNALIGNED 0 will change the default at compile-time to only aligned (faster, but less compatible) macro implementations. Default is still to allow unaligned accesses. --- tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h b/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h index c2c5870a61..e5e1883d4c 100644 --- a/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h +++ b/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h @@ -103,9 +103,13 @@ __attribute__((optimize("-O3"), always_inline)) static inline uint16_t pgm_read_ return pgm_read_dword_unaligned(addr) & 0xffff; } -// Allow manual selection of _aligned or _unaligned, but default to _unaligned for Arduino compatibility -#define PGM_READ_UNALIGNED_DEFAULT -#ifdef PGM_READ_UNALIGNED_DEFAULT +// Allow selection of _aligned or _unaligned, but default to _unaligned for Arduino compatibility +// Add -DPGM_READ_UNALIGNED=0 or "#define PGM_READ_UNALIGNED 0" to code to use aligned-only (faster) macros by default +#ifndef PGM_READ_UNALIGNED + #define PGM_READ_UNALIGNED 1 +#endif + +#if PGM_READ_UNALIGNED #define pgm_read_word(a) pgm_read_word_unaligned(a) #define pgm_read_dword(a) pgm_read_dword_unaligned(a) #define pgm_read_float(a) pgm_read_float_unaligned(a)