mirror of
https://github.com/odin-lang/Odin.git
synced 2026-11-01 16:28:30 -05:00
Most of A32's remaining residue came from a handful of systematic gaps:
* A conditional row matched a word whose condition is 1111. That is
the unconditional space -- other instructions -- and the decoder
now refuses it before trying the row.
* Load and store had no register-shifted, pre-indexed or post-indexed
register forms; LDM and STM had no writeback-free or `^` forms; the
16-bit immediates of MOVW, MOVT, BKPT, HVC, UDF and HLT were read
from one field instead of two. A modified immediate whose rotation
is not the one an assembler would pick now decodes to its parts,
`#imm8, #rot`, which is the only text that gives the word back.
* The extends ignored their rotation. CPS, SETPAN, VEXT, the BLX
halfword bit, the exclusive pairs and VMOVL each read a field from
the wrong place.
* Generic coprocessor instructions decoded in coprocessors 10 and 11,
which are the floating-point unit's; on v8.1-M also in 8, 9, 14 and
15 (MVE's). MRC's Rt of 1111 is APSR_nzcv. LDC and STC had no
unindexed form, `[Rn], {option}`.
* A register pair (LDRD, LDREXD, STREXD, the CDE D forms) starts on an
even register; the decoder accepted an odd one and the encoder took
any second register at all, not just the next.
CDE was laid out wrong throughout, and is re-specified from llvm-mc
bit by bit. Whether coprocessors 0 to 7 hold CDE or generic coprocessor
instructions is a property of the core, not of the code, so decode takes
a CDE_Coprocessors set, empty by default.
T32 data processing (shifted register) did not pin its bit 15, and LDM,
STM, PUSH and POP did not keep SP and PC out of their lists.
The encoder had bugs no check reached: SVC emitted a branch relocation
in place of its immediate, MRS could not name SPSR, and VMRS and VMSR
ORed the register number onto a canonical one left in the form's bits.
The llvm harness could not see any of them, since llvm only ever reads
rexcode's text. It now also re-encodes every word rexcode decodes, with
rexcode's own encoder, and requires the bytes back wherever llvm agrees
the word is the one way to write that text. The sweep fills operands
around the bits a form pins, so a form that requires an even register
gets one.
Dead code removed: the printer's unused data-type inference, with the
#partial switch and the temporary allocation it carried, and nineteen
Operand_Encodings no row used.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbUtG4UwNiMydtMW2qGhw4