Skip to content

Commit 897702f

Browse files
Unaligned access support for pgm_read_word/dword
1 parent 39e31b2 commit 897702f

File tree

1 file changed

+46
-8
lines changed
  • tools/sdk/libc/xtensa-lx106-elf/include/sys

1 file changed

+46
-8
lines changed

tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h

+46-8
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,54 @@ 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*>(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)
77114
#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)
81119
#endif
82120

83121
#define pgm_read_byte_near(addr) pgm_read_byte(addr)

0 commit comments

Comments
 (0)