@@ -68,16 +68,57 @@ 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* 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)
77
117
#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)
81
122
#endif
82
123
83
124
#define pgm_read_byte_near (addr ) pgm_read_byte(addr)
0 commit comments