@@ -68,16 +68,57 @@ static inline uint16_t pgm_read_word_inlined(const void* addr) {
6868 return (uint16_t ) res ; /* This masks the lower half-word from the returned word */
6969}
7070
71- #define pgm_read_byte (addr ) pgm_read_byte_inlined(addr)
72- #define pgm_read_word (addr ) pgm_read_word_inlined(addr)
71+
72+
73+ #define pgm_read_byte (addr ) pgm_read_byte_inlined(addr)
74+ #define pgm_read_word_aligned (addr ) pgm_read_word_inlined(addr)
7375#ifdef __cplusplus
74- #define pgm_read_dword (addr ) (*reinterpret_cast<const uint32_t*>(addr))
75- #define pgm_read_float (addr ) (*reinterpret_cast<const float*>(addr))
76- #define pgm_read_ptr (addr ) (*reinterpret_cast<const void* const *>(addr))
76+ #define pgm_read_dword_aligned (addr ) (*reinterpret_cast<const uint32_t*>(addr))
77+ #define pgm_read_float_aligned (addr ) (*reinterpret_cast<const float*>(addr))
78+ #define pgm_read_ptr_aligned (addr ) (*reinterpret_cast<const void* const*>(addr))
79+ #else
80+ #define pgm_read_dword_aligned (addr ) (*(const uint32_t*)(addr))
81+ #define pgm_read_float_aligned (addr ) (*(const float*)(addr))
82+ #define pgm_read_ptr_aligned (addr ) (*(const void* const*)(addr))
83+ #endif
84+
85+ __attribute__((optimize ("-O3" ), always_inline )) static inline uint32_t pgm_read_dword_unaligned (const void * addr ) {
86+ if (!(((int )addr )& 3 )) return * (const uint32_t * )addr ;
87+ int off = (((int )addr ) & 3 ) << 3 ;
88+ const uint32_t * p = (const uint32_t * )((int )addr & (~3 ));
89+ uint32_t a = * p ++ ;
90+ uint32_t b = * p ;
91+ return (a >>off ) | (b <<(32 - off ));
92+ }
93+
94+ __attribute__((optimize ("-O3" ), always_inline )) static inline float pgm_read_float_unaligned (const void * addr ) {
95+ return (float )pgm_read_dword_unaligned (addr );
96+ }
97+
98+ __attribute__((optimize ("-O3" ), always_inline )) static inline void * pgm_read_ptr_unaligned (const void * addr ) {
99+ return (void * )pgm_read_dword_unaligned (addr );
100+ }
101+
102+ __attribute__((optimize ("-O3" ), always_inline )) static inline uint16_t pgm_read_word_unaligned (const void * addr ) {
103+ return pgm_read_dword_unaligned (addr ) & 0xffff ;
104+ }
105+
106+ // Allow selection of _aligned or _unaligned, but default to _unaligned for Arduino compatibility
107+ // Add -DPGM_READ_UNALIGNED=0 or "#define PGM_READ_UNALIGNED 0" to code to use aligned-only (faster) macros by default
108+ #ifndef PGM_READ_UNALIGNED
109+ #define PGM_READ_UNALIGNED 1
110+ #endif
111+
112+ #if PGM_READ_UNALIGNED
113+ #define pgm_read_word (a ) pgm_read_word_unaligned(a)
114+ #define pgm_read_dword (a ) pgm_read_dword_unaligned(a)
115+ #define pgm_read_float (a ) pgm_read_float_unaligned(a)
116+ #define pgm_read_ptr (a ) pgm_read_ptr_unaligned(a)
77117#else
78- #define pgm_read_dword (addr ) (*(const uint32_t*)(addr))
79- #define pgm_read_float (addr ) (*(const float*)(addr))
80- #define pgm_read_ptr (addr ) (*(const void* const*)(addr))
118+ #define pgm_read_word (a ) pgm_read_word_aligned(a)
119+ #define pgm_read_dword (a ) pgm_read_dword_aligned(a)
120+ #define pgm_read_float (a ) pgm_read_float_aligned(a)
121+ #define pgm_read_ptr (a ) pgm_read_ptr_aligned(a)
81122#endif
82123
83124#define pgm_read_byte_near (addr ) pgm_read_byte(addr)
0 commit comments