@@ -61,42 +61,43 @@ extern "C" {
6161// w1, w0
6262
6363#define pgm_read_with_offset (addr, res ) \
64- __asm__ (" extui %0, %1, 0, 2\n " /* Extract offset within word (in bytes) */ \
65- " sub %1, %1, %0\n " /* Subtract offset from addr, yielding an aligned address */ \
66- " l32i.n %1, %1, 0x0\n " /* Load word from aligned address */ \
67- " ssa8l %0\n " /* Prepare to shift by offset (in bits) */ \
68- " src %0, %1, %1\n " /* Shift right; now the requested byte is the first one */ \
69- :" =r" (res), "=r"(addr) \
70- :"1"(addr) \
71- :);
64+ __asm__ ( \
65+ " extui\t %0, %1, 0, 2\n\t " /* Extract offset within word (in bytes) */ \
66+ " sub\t %1, %1, %0\n\t " /* Subtract offset from addr, yielding an aligned address */ \
67+ " l32i.n\t %1, %1, 0\n\t " /* Load word from aligned address */ \
68+ " ssa8l\t %0\n\t " /* Prepare to shift by offset (in bits) */ \
69+ " src\t %0, %1, %1" /* Shift right; now the requested byte is the first one */ \
70+ : " =r" (res), "+r"(addr))
7271
7372#define pgm_read_dword_with_offset (addr, res ) \
74- __asm__ (" extui %0, %1, 0, 2\n " /* Extract offset within word (in bytes) */ \
75- " sub %1, %1, %0\n " /* Subtract offset from addr, yielding an aligned address */ \
76- " l32i a14, %1, 0\n " \
77- " l32i %1, %1, 4\n " \
78- " ssa8l %0\n " \
79- " src %0, %1, a14\n " \
80- :" =r" (res), "=r"(addr) \
81- :"1"(addr) \
82- :"a14");
73+ do { \
74+ uint32_t temp; \
75+ __asm__ ( \
76+ " extui\t %0, %1, 0, 2\n\t " /* Extract offset within word (in bytes) */ \
77+ " sub\t %1, %1, %0\n\t " /* Subtract offset from addr, yielding an aligned address */ \
78+ " l32i.n\t %2, %1, 0\n\t " /* Load 2 words */ \
79+ " l32i.n\t %1, %1, 4\n\t " /* from aligned address */ \
80+ " ssa8l\t %0\n\t " /* Prepare to shift by offset (in bits) */ \
81+ " src\t %0, %1, %2" /* Shift right in order to extract the requested dword */ \
82+ : " =r" (res), " +r" (addr), " =r" (temp)); \
83+ } while (0 )
8384
8485static inline uint8_t pgm_read_byte_inlined (const void * addr) {
8586 uint32_t res;
8687 pgm_read_with_offset (addr, res);
87- return ( uint8_t ) res; /* This masks the lower byte from the returned word */
88+ return res; /* Implicit cast to uint8_t masks the lower byte from the returned word */
8889}
8990
9091/* Although this says "word", it's actually 16 bit, i.e. half word on Xtensa */
9192static inline uint16_t pgm_read_word_inlined (const void * addr) {
9293 uint32_t res;
9394 pgm_read_with_offset (addr, res);
94- return ( uint16_t ) res; /* This masks the lower half-word from the returned word */
95+ return res; /* Implicit cast to uint16_t masks the lower half-word from the returned word */
9596}
9697
9798/* Can't legally cast bits of uint32_t to a float w/o conversion or std::memcpy, which is inefficient. */
9899/* The ASM block doesn't care the type, so just pass in what C thinks is a float and return in custom fcn. */
99- static inline float pgm_read_float_unaligned (const void * addr) {
100+ static inline float pgm_read_float_unaligned (const void * addr) {
100101 float res;
101102 pgm_read_with_offset (addr, res);
102103 return res;
@@ -121,7 +122,7 @@ static inline uint32_t pgm_read_dword_unaligned(const void *addr) {
121122}
122123
123124#define pgm_read_ptr_unaligned (addr ) ((void *)pgm_read_dword_unaligned(addr))
124- #define pgm_read_word_unaligned (addr ) ((uint16_t )( pgm_read_dword_unaligned(addr) & 0xffff ))
125+ #define pgm_read_word_unaligned (addr ) ((uint16_t )pgm_read_dword_unaligned(addr))
125126
126127
127128// Allow selection of _aligned or _unaligned, but default to _unaligned for Arduino compatibility
0 commit comments