Files
Odin/core/rexcode
Brendan PunskyandClaude Opus 5.5 738bf0a0a7 rexcode/arm32: A32 field fixes, CDE, and an encoder check on real words
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
2026-10-21 18:10:21 -04:00
..