30 Commits

Author SHA1 Message Date
gingerBill
07b5c2ee0f Support enable_target_feature and require_target_feature for asm templates 2026-08-31 16:39:17 +01:00
gingerBill
df3b988db8 asm: add new operand kind for lanes (arm64) 2026-08-31 15:45:44 +01:00
gingerBill
c789811597 Add a form transfer bytes check for memory operands 2026-08-31 15:15:46 +01:00
gingerBill
210defa21b Handle system registers and conditional branching instructions correctly. 2026-08-31 09:55:01 +01:00
gingerBill
7773596beb Handle status snapshot style instructions 2026-08-30 18:03:26 +01:00
gingerBill
87b9b39749 Begin integrating arm64 into the Odin compiler 2026-08-27 11:39:23 +01:00
gingerBill
d805730c67 Correct cpp-gen.odin files 2026-08-27 10:59:54 +01:00
Brendan Punsky
5cba6402f6 rexcode: fix the mnemonic problems in arm32, mips, riscv and mos6502
The arm64 pass turned up the same class of bug elsewhere: mnemonics named
after an encoding rather than after what an assembler accepts, and forms
that no caller can reach because the thing that tells them apart is not
checked.

mips
  * The printer mapped every `_` to `.`, but MSA spells the sign qualifier
    with an underscore and only the element size with a dot: `adds_s.b`,
    `max_s.h`, `copy_u.w`. `adds.s.b` is rejected by an assembler. 91
    mnemonics were printing text that would not reassemble. The name alone
    cannot decide it -- MSA's ADDS_S_D and the FP convert CVT_S_D have the
    same shape and want opposite treatment -- so the family is read off the
    form's feature.
  * `encode` now takes `features: Feature_Set = FEATURES_ALL` and skips
    forms outside it, mirroring `decode`, which has had that parameter all
    along. That asymmetry was the reason 12 mnemonics carried an ISA-variant
    suffix: with no way to say which MIPS you were targeting, the pre-R6 and
    R6 encodings of `mul` had to be two enum members. They are now one
    mnemonic with two forms. Eight of the twelve did not even need the
    feature filter -- pre-R6 MADD takes rs,rt while the PS2 MMI MADD takes
    rd,rs,rt, so operand matching alone separates them. Verified against
    llvm-mc: pre-R6 `mul` 712a4002, R6 `mul` 012a4098, `madd $t1,$t2`
    712a0000. The printer's hand-written override table is gone.

arm32
  * 20 `*_LANE` mnemonics folded into their base. The lane form differs from
    the base in an operand TYPE already (DPR_ELEM vs DPR), so the matcher
    could always tell them apart; the split only cost us the printed name,
    which was the enum name verbatim -- `vqdmulh_lane`, which no assembler
    takes. VMOV/VLD1-4/VST1-4 are left alone: their lane forms collide with
    the base because register lists and lane indices are not modelled.

riscv
  * ZEXT_H and REV8 each carry an RV32 and an RV64 encoding with identical
    operands, and the forms were already tagged rv32_only / rv64_only -- the
    encoder just never looked. `encode` now takes `xlen: XLEN = .RV64` and
    filters, so the RV64 encodings are reachable at all: zext.h 0805c53b and
    rev8 6b85d513, both confirmed against llvm-mc.

mos6502
  * SAX_NMOS folded into SAX. The undocumented NMOS store-A&X and the
    HuC6280 register swap share the mnemonic `sax`; one takes a memory
    operand and the other takes none, so they are just two form sets.

Verified: every rexcode suite matches HEAD exactly, all 13 packages build,
and MIPS mnemonics llvm-mc does not recognise drop from 448 to 354.

Still open: arm32 has 201 form signatures no caller can select, because the
NEON data type (.i8/.i16/.f32) is not an operand -- `inst_vadd(d0,d1,d2)`
always yields the first form, and only a decoder-supplied form_id hint can
pick another. 38 arm32 mnemonics still carry encoding-shaped names
(VPADD_F, VCEQ_Z, VLDRB_GATHER, VMOV_Q_R, ...).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 20:46:33 -04:00
gingerBill
f7f3d3f198 asm: reenable riscv64 2026-08-25 19:30:38 +01:00
gingerBill
032566714c asm: correctly handle flags in the CFG 2026-08-24 22:56:49 +01:00
gingerBill
322f59dae0 Implement a CFG for the assembler to improve the soundness of the checks 2026-08-24 21:49:32 +01:00
gingerBill
9ae9a9bf99 asm: Add support for constraint checks such as division by zero or overshifting 2026-08-24 18:18:28 +01:00
gingerBill
39afdfc609 Begin work on improving #pure error handling 2026-08-24 12:13:24 +01:00
gingerBill
c3c3aa1533 Add #pure directive for asm templates 2026-08-24 11:46:07 +01:00
gingerBill
c41c0fb376 Add non-deterministic flags to x86 2026-08-24 11:01:22 +01:00
kalsprite
deb45f3e6a asm named slots 2026-08-23 21:34:31 -07:00
gingerBill
648c418fc4 Restrict riscv to only allow [base + disp] (i.e. disallow index*scale style things) 2026-08-21 14:31:58 +01:00
gingerBill
4a4a5045f8 Check for float register width exactly for risc-v frontend 2026-08-21 12:19:02 +01:00
gingerBill
a604ddceb1 Support pseudo macro mnemonics (for RISC-V) in the frontend 2026-08-21 11:47:41 +01:00
gingerBill
d0fb380c20 Support riscv _aq _rl _aqrl suffixes for mnemonics 2026-08-21 01:05:47 +01:00
gingerBill
de8c0dc4fe Fix register width test for risc-v, and improve operand slot type inference for risc-v 2026-08-21 00:38:34 +01:00
gingerBill
7a7bfea0bd Begin work on pseudo mnemonics in the checker 2026-08-20 19:12:44 +01:00
gingerBill
cfb8a109b6 Begin work on pseudo-aliases 2026-08-20 17:51:47 +01:00
gingerBill
84f9bc76f9 Mockout inline asm for riscv 2026-08-20 14:42:42 +01:00
gingerBill
1009ab0c62 Add riscv.clobber_forms.bin 2026-08-20 11:45:50 +01:00
gingerBill
f3899c1825 rexcode: riscv INSTRUCTION_TABLE which includes the clobber information 2026-08-20 11:43:26 +01:00
gingerBill
2ebc25001d Add missing risc-v instructions to rexcode 2026-08-20 11:08:03 +01:00
Flāvius
2e8d3b9e10 rexcode/isa: display-side label naming — address order, offset-keyed names
Internal label ids are allocation-order handles: the encoder's creation
order, or the decoder's branch-DISCOVERY order (a loop's latch names the
header before an earlier forward target). Printing labels by raw id leaked
that accident into listings — label numbers appeared out of order down the
page — and the printers' `label_names: ^map[u32]string` keyed the caller's
names by those synthesized ids, which a decode consumer cannot know without
re-deriving them (the practical result: naming "label 0" could caption a
random interior branch target).

Naming is now derived at the presentation seam, shared by every ISA
(`isa.Label_Display` in isa/print.odin):

  - display numbers are assigned in ASCENDING ADDRESS order, so a listing
    reads L0, L1, L2 … top to bottom regardless of id allocation;
  - caller names are keyed by BYTE OFFSET (`isa.Label_Names`, with a
    `distinct` Label_Offset key so an id-keyed map from the old contract
    fails to compile instead of silently mis-naming);
  - a named offset is guaranteed a label row even when no Label_Definition
    points at it — `names[0] = "factorial"` heads a function's listing.

All ten ISA printers (x86, mips, rsp, arm32, arm64, riscv, ppc, ppc_vle,
mos6502, mos65816) drop their per-printer offset_to_label maps and
write_label helpers for the shared display; each arch re-exports
Label_Offset/Label_Names beside Label_Definition. En route this fixes an
arm32/ppc/ppc_vle bug where passing ANY names map suppressed the default
L<n> label rows for unnamed labels. Decode-side id assignment is untouched:
the reloc round-trip contract (encoder ids surviving decode) and the
sparse-id padding it relies on stay exactly as they were.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Riok9vMpkLmo78wsVKJHhz
2026-08-03 20:52:11 -04:00
Brendan Punsky
fae15847a3 rexcode: buffer-sizing helpers across all ISAs + naming-contract doc
Roll the encode/decode buffer-sizing helpers (added for x86 in 49787b7de) out
to every other ISA, and document them in the cross-arch naming contract.

Per arch (arm32, arm64, mips, riscv, ppc, ppc_vle, rsp, mos6502, mos65816):
  - encode_max_code_size / encode_max_relocation_count now key off the
    []Instruction slice (were int counts); bodies unchanged (* MAX_INST_SIZE).
  - encode_reserve(code, relocs, instructions): grows the caller's code []u8 by
    length and reserves relocs by capacity; allocates no new buffers.
  - decode_max_instruction_count / decode_estimate_instruction_count: exact
    ceiling and typical estimate, keyed off the min/avg instruction size per
    arch (fixed-4: arm64/mips/ppc/rsp; min-2: arm32/riscv/ppc_vle; min-1: mos).
  - decode_reserve(instructions, inst_info, label_defs, data, exact=false).

docs/cross_arch_design.md: helpers added to the naming contract.

No behavior change to the existing size helpers (signature only). All 10 ISAs
check + test green (x86 2282, arm32 600, arm64 461, mips 281, riscv 154, ppc 31,
ppc_vle 281, rsp 70, mos6502 148, mos65816 53).
2026-06-19 04:11:30 -04:00
Brendan Punsky
95df04fbe1 rexcode: re-house ISA packages under core:rexcode/isa/<arch>
Move all ten ISA packages (x86, arm32, arm64, mips, riscv, ppc, ppc_vle,
rsp, mos6502, mos65816) from core/rexcode/<arch> to core/rexcode/isa/<arch>,
so the import pattern is now `import "core:rexcode/isa/x86"`. The shared
core stays at core:rexcode/isa.

Mechanical: relative `import "../isa"` / "../../isa" -> absolute
"core:rexcode/isa" (the only path that survives the move; the "../" and
"../.." self/generated imports move with their packages). build.lua now
builds paths as <root>/isa/<name>; stale `cd <arch>` hints in the verify
tools and the doc.odin paths updated.

WASM stays at core/rexcode/wasm for now -- it is an IR, not an ISA, and
will move under the forthcoming core:rexcode/ir once that layer lands.

All 10 arches gen/builders/check/test green; import core:rexcode/isa/x86
verified working; wasm still compiles.
2026-06-18 19:03:27 -04:00