Skip to content

assembler: forward-ref deferral (immediates + data), gs(), comma .set/.equ, ISR error#10

Merged
begeistert merged 2 commits into
mainfrom
improve/assembler-forward-refs-and-gs
Jun 24, 2026
Merged

assembler: forward-ref deferral (immediates + data), gs(), comma .set/.equ, ISR error#10
begeistert merged 2 commits into
mainfrom
improve/assembler-forward-refs-and-gs

Conversation

@begeistert

@begeistert begeistert commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Two more clean-room validation rounds (compiling programs at -O0…-O3/-Os and probing avr-as constructs) surfaced and closed several gaps that blocked real avr-gcc output. All validated against avr-as/avr-gcc.

Fixes

  • Forward symbol refs in immediates. LDI/SUBI/SBCI/ORI/ANDI/CPI threw on a forward-referenced symbol operand, so the ubiquitous ldi rN, lo8(sym) / hi8(sym) failed when the symbol came later (e.g. a global in .data at the end of the file). They now defer to pass two like LDS/STS. The struct/loop/function sample now assembles at every optimisation level (failed at -O1/-O2/-Os before).
  • Forward symbol refs in data directives. .byte/.word/.dword now defer the same way, so in-flash jump tables / PROGMEM data referencing later labels assemble (.word gs(.L0), .byte lo8(x), hi8(x)).
  • gs() added to the expression evaluator — a symbol's word address (x >> 1) for function pointers / far jumps; byte-identical to avr-as.
  • .set / .equ comma form (NAME, VALUE) accepted in addition to NAME = VALUE.
  • Clearer errors: __gcc_isr now gives an actionable message (recompile with -mno-gas-isr-prologues) instead of "Invalid instruction"; invalid-instruction errors name the mnemonic.

Known remaining limitations (documented)

  • __gcc_isr (avr-gcc default -mgas-isr-prologues): faithfully expanding it means replicating gas's stateful register-clobber optimiser. Workaround -mno-gas-isr-prologues assembles cleanly today (verified).
  • libgcc relocations (call __mulhisi3): need a real linker + libgcc objects — irrelevant for a flat-image simulator assembler.
  • Data-symbol addresses come from a simple allocator (base 0x100), not avr-gcc's linker, so programs using globals assemble + run consistently but aren't byte-identical to avr-gcc on the data-address operands.

Validation

505 tests pass (+5 in this PR), no regressions. Samples assemble across all optimisation levels.

🤖 Generated with Claude Code

…omma .set/.equ

More clean-room validation against avr-gcc -Os/-O0/-O1/-O2/-O3 -S surfaced three
gaps that blocked real compiler output:

- Immediate instructions (LDI/SUBI/SBCI/ORI/ANDI/CPI) threw on a
  forward-referenced symbol operand, so the ubiquitous `ldi rN, lo8(sym)` /
  `hi8(sym)` failed whenever the symbol (e.g. a global in .data emitted at the
  end of the file) came later. They now defer to pass two like LDS/STS. After
  this, the sample program assembles at every optimisation level.
- gs(x) is now supported in the expression evaluator: it yields the word
  address of a symbol (x >> 1) for function pointers / far jumps — verified
  byte-identical to avr-as `ldi lo8(gs(f))` / `hi8(gs(f))`. (On <=128KW parts
  it equals pm(); the >128K stub is not needed for the simulated devices.)
- .set / .equ now accept the GNU `NAME, VALUE` comma form in addition to the
  Atmel `NAME = VALUE` form.

Known remaining limitations (documented, not fixed here):
- `__gcc_isr` pseudo-op: avr-gcc's default -mgas-isr-prologues emits these in
  ISRs; expanding them is stateful avr-as magic. Compile with
  -mno-gas-isr-prologues to get explicit push/pop prologues.
- .byte/.word with a forward-referenced symbol expression are not deferred.

Adds 3 tests. 503 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 24, 2026

Copy link
Copy Markdown

Deploying avr8sharp-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 864c8f1
Status: ✅  Deploy successful!
Preview URL: https://a5b2b861.avr8sharp-docs.pages.dev
Branch Preview URL: https://improve-assembler-forward-re.avr8sharp-docs.pages.dev

View logs

…rrors

- .byte/.word/.dword now defer to pass two when an element is a
  forward-referenced symbol expression (the byte count is always known, so
  byteOffset still advances eagerly). This makes in-flash jump tables and
  PROGMEM data that reference later labels assemble, e.g. `.word gs(.L_case0)`
  or `.byte lo8(x), hi8(x)` with x defined below. The three Emit* methods are
  unified into one EmitData(unit) + BuildDataBytes helper.
- __gcc_isr now produces an actionable error ("recompile with
  -mno-gas-isr-prologues") instead of a generic "Invalid instruction".
  Faithfully expanding it would mean replicating gas's stateful register-clobber
  optimiser; the -mno-gas-isr-prologues output assembles cleanly today.
- "Invalid instruction" errors now name the offending mnemonic.

Adds 2 tests. 505 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@begeistert begeistert changed the title assembler: defer forward symbol refs in immediates, gs(), comma .set/.equ assembler: forward-ref deferral (immediates + data), gs(), comma .set/.equ, ISR error Jun 24, 2026
@begeistert begeistert merged commit 9e1c2d6 into main Jun 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant