Skip to content

Commit fc2426a

Browse files
authored
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
1 parent 79fc0b3 commit fc2426a

File tree

1 file changed

+22
-21
lines changed
  • tools/sdk/libc/xtensa-lx106-elf/include/sys

1 file changed

+22
-21
lines changed

Diff for: tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h

+22-21
Original file line numberDiff line numberDiff line change
@@ -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

8485
static 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 */
9192
static 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

Comments
 (0)