mirror of
https://github.com/odin-lang/Odin.git
synced 2026-09-02 02:03:35 +00:00
The Mnemonic enum had one member per encoding form -- ADD_IMM, ADD_SR, ADD_ER, ADD_V for what an assembler just calls ADD; LDR, LDR_LIT, LDR_PRE, LDR_POST, LDR_REG, LDR_V for LDR; SVE_ADD_Z / SVE_ADD_PRED / SVE_AND_P for names SVE spells ADD and AND. The encoder never needed that: like x86, it already resolves a mnemonic by scanning its run of forms and matching operand types, so the split bought nothing and cost a printer that had to strip suffixes back off at runtime -- incompletely, so ADD_V printed "add.v", LDR_PRE "ldr.pre" and FCVT_H_S "fcvt.h.s". Collapse the enum to the names assemblers accept: 1104 -> 785 mnemonics, with the variants becoming forms under one name (ADD now has 13, LDR 15). LSLV/LSRV/ASRV/RORV fold into LSL/LSR/ASR/ROR. Form order within a run is precedence, and the original declaration order is already the order an assembler resolves: "add w0,w1,w2" takes the shifted-register form, and only the extended form can encode SP. This needed one structural change. The matcher was blind to addressing mode -- `case .MEM: return op.kind == .MEMORY` -- which is precisely why LDR/LDR_PRE/LDR_POST/LDR_REG had to be separate mnemonics; all 20 merge collisions were this and nothing else. Split Operand_Type.MEM into mode-specific types (MEM_OFFSET/PRE/POST/REG/EXT plus four SVE), matching how W_REG/W_SHIFTED/W_EXTENDED are already distinct types over one register class. The decoder derives Address_Mode from `enc`, so it is unaffected. Encodings are unchanged: the multiset of (ops, enc, bits, mask, feature, flags) over all forms is identical before and after except for two entries deliberately dropped. NOT_V_ALIAS duplicated NOT_V byte for byte, and MOV_V_ALIAS was wrong -- it encoded VN where the ORR-based MOV alias needs VN_VM_DUP, so "mov v1.8b, v2.8b" would have emitted "orr v1.8b, v2.8b, v0.8b". AMX_* keeps its prefix: Apple's coprocessor is undocumented with no assembler spelling, so there is no canonical name to collapse to and bare "set"/"clr"/"ldx" would mislead. The two-token system instructions keep theirs too and print with a space (dc zva, tlbi vae1, bti j). Verified: all 11 rexcode suites match HEAD exactly (arm64 461/461); the three generator stages round-trip idempotently; 754 of 785 mnemonics are accepted by llvm-mc, the rest being AMX (24), TME (4, no +tme in this LLVM build), B_COND/BC_COND and TBL2; and a 39-case encode/print differential against llvm-mc matches 34, with the 5 others confirmed byte-identical at HEAD (pre-existing LSR/ASR immediate and LDP pre-index packing bugs, and printer gaps for vector arrangements and MOVZ/MOVK shifts). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>