Skip to content
Open
Show file tree
Hide file tree
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
16 changes: 15 additions & 1 deletion src/arch/avr/asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,22 @@ static long io_name(const char *s, int len)
* inline asm statement does. */
int avrasm_is_word(const char *stmt, const char *w, int len)
{
static const char *const op[] = {
"lo8", "hi8", "hlo8", "hh8",
"pm_lo8", "pm_hi8", "pm_hh8", "gs"
};
(void)stmt;
return io_name(w, len) >= 0;
if (io_name(w, len) >= 0)
return 1;
/* These are expression operators, not symbols. Without naming them
* here, gas.c records (for example) `lo8` as the first undefined symbol
* in a multi-statement inline template, then cannot relocate the real
* `call` or `jmp` symbol that follows it. */
for (unsigned i = 0; i < sizeof op / sizeof op[0]; i++)
if ((int)strlen(op[i]) == len &&
strncmp(w, op[i], (size_t)len) == 0)
return 1;
return 0;
}

static long expr_prim(const char **p, struct expr_ctx *x)
Expand Down
23 changes: 23 additions & 0 deletions tests/golden/avr-inline-asm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,29 @@ printf 'unsigned int f(unsigned char a, unsigned char b)\n'\
with 'clr r1' is the idiom -- refusing it forbids using mul at all:"
head -4 "$out/m.err"; exit 1; }

# A constant byte-selection expression in one statement must not change how
# the following statement's symbol is scanned. The 18-character names are
# the two EmbLinkRTOS AVR entry points that exposed the cut at 16 characters.
cat > "$out/long-symbol.c" <<'EOF'
void emb_arch_switch_to(void);
void embk_thread_launch(void);
void f(void)
{
__asm__ volatile("ldi r18, lo8(2303)\n\t"
"call emb_arch_switch_to\n\t"
"jmp embk_thread_launch" ::: "r18");
}
EOF
"$EMBCC" --target=avr -Os -c "$out/long-symbol.c" \
-o "$out/long-symbol.o" 2> "$out/long-symbol.err" || {
echo "lo8() made a following long symbol fail to assemble:"
cat "$out/long-symbol.err"; exit 1; }
for s in emb_arch_switch_to embk_thread_launch; do
llvm-readelf -r "$out/long-symbol.o" | grep -q "$s" || {
echo "the inline asm's long symbol was cut: $s"
llvm-readelf -r "$out/long-symbol.o"; exit 1; }
done

QEMU=${EMBCC_QEMU_AVR:-qemu-system-avr}
command -v "$QEMU" >/dev/null 2>&1 || {
echo "the refusals hold (SKIP: no $QEMU to run the rest)"; exit 0; }
Expand Down