mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
progmem: replace C version of pgm_read_{word,byte} with assembly
See discussion in https://github.com/esp8266/Arduino/issues/3140
This commit is contained in:
parent
a41f55c469
commit
0b672668bf
@ -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<const uint8_t*>(addr))
|
||||
#define pgm_read_word(addr) (*reinterpret_cast<const uint16_t*>(addr))
|
||||
|
Loading…
x
Reference in New Issue
Block a user