1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-21 10:26:06 +03:00

sys/pgmspace.h: Refactor inline asm (#7510)

* Refactor asm tabs for `.S` cosmetics

* Avoid fixed regname (`a14`) allocation

* Remove unnecessary explicit cast and word masking
This commit is contained in:
Takayuki 'January June' Suwa 2020-08-09 09:29:30 +09:00 committed by GitHub
parent 79fc0b3b4a
commit fc2426a5e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -61,42 +61,43 @@ extern "C" {
// w1, w0 // w1, w0
#define pgm_read_with_offset(addr, res) \ #define pgm_read_with_offset(addr, res) \
__asm__("extui %0, %1, 0, 2\n" /* Extract offset within word (in bytes) */ \ __asm__( \
"sub %1, %1, %0\n" /* Subtract offset from addr, yielding an aligned address */ \ "extui\t%0, %1, 0, 2\n\t" /* Extract offset within word (in bytes) */ \
"l32i.n %1, %1, 0x0\n" /* Load word from aligned address */ \ "sub\t%1, %1, %0\n\t" /* Subtract offset from addr, yielding an aligned address */ \
"ssa8l %0\n" /* Prepare to shift by offset (in bits) */ \ "l32i.n\t%1, %1, 0\n\t" /* Load word from aligned address */ \
"src %0, %1, %1\n" /* Shift right; now the requested byte is the first one */ \ "ssa8l\t%0\n\t" /* Prepare to shift by offset (in bits) */ \
:"=r"(res), "=r"(addr) \ "src\t%0, %1, %1" /* Shift right; now the requested byte is the first one */ \
:"1"(addr) \ : "=r"(res), "+r"(addr))
:);
#define pgm_read_dword_with_offset(addr, res) \ #define pgm_read_dword_with_offset(addr, res) \
__asm__("extui %0, %1, 0, 2\n" /* Extract offset within word (in bytes) */ \ do { \
"sub %1, %1, %0\n" /* Subtract offset from addr, yielding an aligned address */ \ uint32_t temp; \
"l32i a14, %1, 0\n" \ __asm__( \
"l32i %1, %1, 4\n" \ "extui\t%0, %1, 0, 2\n\t" /* Extract offset within word (in bytes) */ \
"ssa8l %0\n" \ "sub\t%1, %1, %0\n\t" /* Subtract offset from addr, yielding an aligned address */ \
"src %0, %1, a14\n" \ "l32i.n\t%2, %1, 0\n\t" /* Load 2 words */ \
:"=r"(res), "=r"(addr) \ "l32i.n\t%1, %1, 4\n\t" /* from aligned address */ \
:"1"(addr) \ "ssa8l\t%0\n\t" /* Prepare to shift by offset (in bits) */ \
:"a14"); "src\t%0, %1, %2" /* Shift right in order to extract the requested dword */ \
: "=r"(res), "+r"(addr), "=r"(temp)); \
} while(0)
static inline uint8_t pgm_read_byte_inlined(const void* addr) { static inline uint8_t pgm_read_byte_inlined(const void* addr) {
uint32_t res; uint32_t res;
pgm_read_with_offset(addr, res); pgm_read_with_offset(addr, res);
return (uint8_t) res; /* This masks the lower byte from the returned word */ return res; /* Implicit cast to uint8_t masks the lower byte from the returned word */
} }
/* Although this says "word", it's actually 16 bit, i.e. half word on Xtensa */ /* Although this says "word", it's actually 16 bit, i.e. half word on Xtensa */
static inline uint16_t pgm_read_word_inlined(const void* addr) { static inline uint16_t pgm_read_word_inlined(const void* addr) {
uint32_t res; uint32_t res;
pgm_read_with_offset(addr, res); pgm_read_with_offset(addr, res);
return (uint16_t) res; /* This masks the lower half-word from the returned word */ return res; /* Implicit cast to uint16_t masks the lower half-word from the returned word */
} }
/* Can't legally cast bits of uint32_t to a float w/o conversion or std::memcpy, which is inefficient. */ /* Can't legally cast bits of uint32_t to a float w/o conversion or std::memcpy, which is inefficient. */
/* The ASM block doesn't care the type, so just pass in what C thinks is a float and return in custom fcn. */ /* The ASM block doesn't care the type, so just pass in what C thinks is a float and return in custom fcn. */
static inline float pgm_read_float_unaligned(const void *addr) { static inline float pgm_read_float_unaligned(const void* addr) {
float res; float res;
pgm_read_with_offset(addr, res); pgm_read_with_offset(addr, res);
return res; return res;
@ -121,7 +122,7 @@ static inline uint32_t pgm_read_dword_unaligned(const void *addr) {
} }
#define pgm_read_ptr_unaligned(addr) ((void*)pgm_read_dword_unaligned(addr)) #define pgm_read_ptr_unaligned(addr) ((void*)pgm_read_dword_unaligned(addr))
#define pgm_read_word_unaligned(addr) ((uint16_t)(pgm_read_dword_unaligned(addr) & 0xffff)) #define pgm_read_word_unaligned(addr) ((uint16_t)pgm_read_dword_unaligned(addr))
// Allow selection of _aligned or _unaligned, but default to _unaligned for Arduino compatibility // Allow selection of _aligned or _unaligned, but default to _unaligned for Arduino compatibility