Skip to content

Make pgm_read_byte() and pgm_read_word() again backwards compatible c… #3319

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 18 additions & 23 deletions cores/esp8266/pgmspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,29 +88,24 @@ int vsnprintf_P(char *str, size_t strSize, PGM_P formatP, va_list ap) __attribut

#ifdef __ets__

#define pgm_read_with_offset(addr, res) \
asm("extui %0, %1, 0, 2\n" /* Extract offset within word (in bytes) */ \
"sub %1, %1, %0\n" /* Subtract offset from addr, yielding an aligned address */ \
"l32i.n %1, %1, 0x0\n" /* Load word from aligned address */ \
"slli %0, %0, 3\n" /* Mulitiply offset by 8, yielding an offset in bits */ \
"ssr %0\n" /* Prepare to shift by offset (in bits) */ \
"srl %0, %1\n" /* Shift right; now the requested byte is the first one */ \
:"=r"(res), "=r"(addr) \
:"1"(addr) \
:);

static inline uint8_t pgm_read_byte(const void* addr) {
register uint32_t res;
pgm_read_with_offset(addr, res);
return (uint8_t) res; /* This masks the lower byte from the returned word */
}

/* Although this says "word", it's actually 16 bit, i.e. half word on Xtensa */
static inline uint16_t pgm_read_word(const void* addr) {
register uint32_t res;
pgm_read_with_offset(addr, res);
return (uint16_t) res; /* This masks the lower half-word from the returned word */
}
#define pgm_read_abstract(addr, result_type) \
(__extension__({ \
PGM_P __local = (PGM_P)(addr); \
register uint32_t __res; \
asm volatile("extui %0, %1, 0, 2\n" /* Extract offset within word (in bytes) */\
"sub %1, %1, %0\n" /* Subtract offset from addr, yielding an aligned address */\
"_l32i %1, %1, 0x0\n" /* Load word from aligned address */\
"slli %0, %0, 3\n" /* Multiply offset by 8, yielding an offset in bits */\
"ssr %0\n" /* Prepare to shift by offset (in bits) */\
"srl %0, %1\n" /* Shift right; now the requested byte is the first one */\
:"=r"(__res), "=r"(__local) \
:"1"(__local) \
:); \
(result_type) __res; \
}))

#define pgm_read_byte(addr) pgm_read_abstract(addr, uint8_t)
#define pgm_read_word(addr) pgm_read_abstract(addr, uint16_t)

#else //__ets__
#define pgm_read_byte(addr) (*reinterpret_cast<const uint8_t*>(addr))
Expand Down