diff --git a/cores/esp8266/pgmspace.h b/cores/esp8266/pgmspace.h index 6f04b1022..e8ecd1d99 100644 --- a/cores/esp8266/pgmspace.h +++ b/cores/esp8266/pgmspace.h @@ -87,23 +87,31 @@ int vsnprintf_P(char *str, size_t strSize, PGM_P formatP, va_list ap) __attribut // w1, w0 #ifdef __ets__ -#define pgm_read_byte(addr) \ -(__extension__({ \ - PGM_P __local = (PGM_P)(addr); /* isolate varible for macro expansion */ \ - ptrdiff_t __offset = ((uint32_t)__local & 0x00000003); /* byte aligned mask */ \ - const uint32_t* __addr32 = (const uint32_t*)((const uint8_t*)(__local)-__offset); \ - uint8_t __result = ((*__addr32) >> (__offset * 8)); \ - __result; \ -})) -#define pgm_read_word(addr) \ -(__extension__({ \ - PGM_P __local = (PGM_P)(addr); /* isolate varible for macro expansion */ \ - ptrdiff_t __offset = ((uint32_t)__local & 0x00000002); /* word aligned mask */ \ - const uint32_t* __addr32 = (const uint32_t*)((const uint8_t*)(__local) - __offset); \ - uint16_t __result = ((*__addr32) >> (__offset * 8)); \ - __result; \ -})) +#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 */ +} + #else //__ets__ #define pgm_read_byte(addr) (*reinterpret_cast(addr)) #define pgm_read_word(addr) (*reinterpret_cast(addr))