@@ -68,16 +68,54 @@ static inline uint16_t pgm_read_word_inlined(const void* addr) {
68
68
return (uint16_t ) res ; /* This masks the lower half-word from the returned word */
69
69
}
70
70
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)
73
75
#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*>(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*>(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*)(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
+
107
+ // Allow manual selection of _aligned or _unaligned, but default to _unaligned for Arduino compatibility
108
+ #define PGM_READ_UNALIGNED_DEFAULT
109
+ #ifdef PGM_READ_UNALIGNED_DEFAULT
110
+ #define pgm_read_word (a ) pgm_read_word_unaligned(a)
111
+ #define pgm_read_dword (a ) pgm_read_dword_unaligned(a)
112
+ #define pgm_read_float (a ) pgm_read_float_unaligned(a)
113
+ #define pgm_read_ptr (a ) pgm_read_ptr_unaligned(a)
77
114
#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*)(addr))
115
+ #define pgm_read_word (a ) pgm_read_word_aligned(a)
116
+ #define pgm_read_dword (a ) pgm_read_dword_aligned(a)
117
+ #define pgm_read_float (a ) pgm_read_float_aligned(a)
118
+ #define pgm_read_ptr (a ) pgm_read_ptr_aligned(a)
81
119
#endif
82
120
83
121
#define pgm_read_byte_near (addr ) pgm_read_byte(addr)
0 commit comments