commit 79fec5699a0062b63c3c49b97b4adafc61a1d5de
parent 7b5e7555d188cf472b3cc976fe9e822bfe44bc56
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Wed, 17 Jun 2026 12:11:44 -0700
doc/ARM32: record DSP/flag-macro/density/disasm follow-ons + parse-corpus triage
Mark the four landed follow-on items (full -mcpu/-march/-mfpu/-mfloat-abi parsing
+ __ARM_* macros [done]; DSP saturating asm/disasm [partial — packed-SIMD +
builtin lowering deferred]; 16-bit density [done] + shifted-register fold
[gated off]; cosmetic shifted-MOV disasm [done]). Document the O1 frameless-leaf
return-address fix and list the remaining 17 broad-parse-corpus reds as a triage
TODO (i128/ldbl now skip-sidecar'd, parse lane 921/17/58).
Diffstat:
| M | doc/plan/ARM32.md | | | 99 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
1 file changed, 84 insertions(+), 15 deletions(-)
diff --git a/doc/plan/ARM32.md b/doc/plan/ARM32.md
@@ -11,10 +11,62 @@ emit `.ARM.attributes`, ARM32 `.thumb_func` symbols carry the ABI Thumb bit, and
C inline asm templates now route real Thumb-2 mnemonics through
`src/arch/arm32/asm.c`.
-Verification note: `make test-cross TARGET=freestanding-arm32 DEPTH=full`
-currently fails in the broad parse lane (89 parse-corpus failures, many outside
-the arm32 core scope such as i128 / long-double cases). The core signals above
-are green; the broad parse corpus still needs separate skip/portability triage.
+### Follow-on landed — 2026-06-17 — DSP, flag/macro parsing, code density, disasm
+
+Four follow-on items landed (parallel worktree agents, serial cherry-pick behind
+the qemu gate). See the "Follow-on variants / polish" checklist below for status:
+- **Full `-mcpu`/`-march`/`-mfpu`/`-mfloat-abi` parsing + the `__ARM_*` macro
+ set** — done. New `ArchImpl` hooks `target_feature_apply_cpu` (the previously
+ unconsumed `opts->cpu` now maps cortex-m3→armv7-m, cortex-m4/m7→armv7e-m+`dsp`)
+ and `feature_predefines` (feature-keyed `__ARM_ARCH_7M__`/`7EM__`,
+ `__ARM_FEATURE_DSP`/`SIMD32`, and the `__ARM_FP`/`__SOFTFP__`/`__ARM_PCS_VFP`
+ float set). Validated against host clang (`test/smoke/arm32_macros.sh`, 8/0).
+- **ARMv7E-M DSP saturating** — SSAT/USAT/QADD/QSUB/QDADD/QDSUB encoders + ISA
+ rows + asm/disasm (assembler-permissive, inline-asm usable). Packed-SIMD and
+ automatic saturating-builtin lowering deferred (no frontend builtin exists).
+- **16-bit-encoding density** — narrow PUSH/POP, LDR/STR (T1 imm5 + T2 sp), ADD/
+ SUB sp, ADDS/SUBS/MOVS/LSLS/LSRS/ASRS where operands fit (−5%…−25% .text on
+ samples). Shifted-register operand folding is implemented but **gated off** —
+ enabling it tripped a shared `src/opt/pass_combine.c` addr-synth rule that
+ drops the L7 shift rider for `base+(i<<k)` (k≥4); re-enable once that's fixed.
+- **Cosmetic disasm** — shifted-MOV now renders `lsl.w/lsr.w/asr.w/ror.w/rrx`
+ (and MVN shift suffix) matching llvm-objdump.
+
+Verification note: `make test-cross TARGET=freestanding-arm32 DEPTH=full` toy lane
+is **423/0/2**; the broad parse lane is **921 pass / 17 fail / 58 skip**. The 58
+skips are the i128 + binary128-long-double cases (unsupported by design, now
+`.arm32.skip`-sidecar'd to match rv32). The remaining 17 fails are a genuine
+follow-on triage list — see "Broad parse-corpus triage" below. The fix that took
+the parse lane from 33 to 17 fails: the O1 frameless-leaf tier returned through a
+bare `BX lr` while the backend uses `lr` as an emit scratch (global-address
+staging, overflow/popcount/bitfield/byte-copy), so any such leaf clobbered its
+return address (the 16-case O1 globals/statics/attributes `rc 134` cluster). The
+slim tier now saves `lr` (`PUSH {lr}`/`POP {pc}`).
+
+### Broad parse-corpus triage — outstanding (NOT core; freestanding-arm32 parse lane)
+
+17 reds remain in `make test-cross TARGET=freestanding-arm32 DEPTH=full` (parse
+lane). None are in the closed core checklist; each needs separate triage:
+- **Emit/codegen gaps (5):**
+ - [ ] `asm_01_grammar` O0+O1 — `arm32 inline asm: optimizer asm input not in a
+ register` (inline-asm operand binding at the parse-corpus's harder cases).
+ - [ ] `builtin_31_readcyclecounter` O0+O1 — `arm32` does not support the
+ `readcyclecounter` intrinsic (needs a DWT/CYCCNT or unsupported gate).
+ - [ ] `gnu_labels_as_values_threaded` O1 — `opt native emit: no scratch
+ register` (computed-goto under -O1 register pressure).
+- **Wrong runtime result (12):**
+ - [ ] `6_5_2_2_06_struct_param_mixed_fp_int` O0 (got 229) + O1 (got 5) — mixed
+ fp/int struct-param ABI lowering.
+ - [ ] `6_5_64_unsigned_size_division` O0+O1 (got 10) — unsigned size division.
+ - [ ] `6_8_29_switch_signed_negative` O1 (got 42, want 100) — signed-negative
+ switch at O1.
+ - [ ] `builtin_generic_overflow` O0+O1 (got 6, want 7) — `__builtin_*_overflow`
+ generic-selection edge.
+ - [ ] `far_slot_large_frame` O0+O1 (got 4, want 7) — large-frame far slot
+ addressing.
+ - [ ] `rv64_atomic_widths_orders` O0+O1 (got 9, want 42) — atomics widths/orders
+ (the case is rv64-named but runs in the arm32 lane).
+ - [ ] `variadic_02_many_ints` O1 (got 0) — many-int varargs at O1.
## Core checklist — remaining items (single source of truth)
@@ -63,14 +115,28 @@ are now checked there too).
**Follow-on variants / polish** (NOT required for "core"; the `variant` seam, §4/§5):
- [ ] Hard-float (FPv4-SP, `arm-none-eabihf`): VFP codegen + softfp/hard axis.
-- [ ] DSP / ARMv7E-M saturating + packed-SIMD behind the `dsp` feature.
+ (The macro/feature machinery — `vfp`/`fpv5` features, `__ARM_FP`/
+ `__ARM_PCS_VFP`, the softfp/hard `resolve_float_abi` branch — is in; the
+ driver still rejects non-soft `-mfloat-abi` until VFP codegen lands.)
+- [~] DSP / ARMv7E-M saturating behind the `dsp` feature — SSAT/USAT/QADD/QSUB/
+ QDADD/QDSUB encoders + ISA rows + asm/disasm landed (2026-06-17), usable
+ from inline asm. **Remaining:** packed-SIMD (SADD16/SEL/… + GE flags) and
+ automatic saturating-builtin lowering (no frontend builtin / CG intrinsic
+ exists yet; the `KIT_CG_INTOP_SATURATE_*` flags are unwired).
- [ ] ARMv6-M / Thumb-1 (no IT / MOVW-MOVT / hardware divide / 32-bit Thumb).
-- [ ] Full `-mcpu`/`-march`/`-mfpu`/`-mfloat-abi` parsing + the complete
- `__ARM_FEATURE_*` predefined-macro set.
+- [x] Full `-mcpu`/`-march`/`-mfpu`/`-mfloat-abi` parsing + the `__ARM_*`
+ predefined-macro set (2026-06-17; `target_feature_apply_cpu` +
+ `feature_predefines` hooks, clang-cross-validated).
- [ ] Multi-threaded TLS (variant-I tp-relative; replaces TLS-as-static).
-- [ ] 16-bit-encoding density + shifted-register-operand peephole (toward tcc).
-- [ ] (cosmetic) disassembler renders shifted-MOV (`mov.w rd,rs,lsl #N`) as plain
- `mov` — encodings are correct; listings lose the shift.
+- [~] 16-bit-encoding density (landed 2026-06-17, −5%…−25% .text) +
+ shifted-register-operand peephole (**implemented but gated off** — a shared
+ `src/opt/pass_combine.c` addr-synth rule drops the L7 shift rider on
+ `base+(i<<k)`, k≥4; re-enable `arm_can_fold_shift_into_alu` once fixed).
+ Narrow intra-function branches (16-bit B/Bcond) still deferred. Note: the
+ O1 frameless-leaf tier now costs +2 bytes/leaf (`PUSH {lr}`/`POP {pc}`) for
+ return-address correctness — see the O1-leaf fix above.
+- [x] (cosmetic) disassembler renders shifted-MOV as `lsl.w/lsr.w/asr.w/ror.w/
+ rrx` (+ MVN shift suffix), matching llvm-objdump (2026-06-17).
---
@@ -451,16 +517,19 @@ names the design, not a workaround.
### 4. Profiles / ABIs — new variants via the clean `variant` seam, not forks
- [ ] **Hard-float** (FPv4-SP, `arm-none-eabihf`): VFP codegen + the softfp/hard
float-abi axis (`double` stays soft on FPv4-SP).
-- [ ] **DSP / ARMv7E-M** saturating + packed-SIMD behind the `dsp` feature.
+- [~] **DSP / ARMv7E-M** saturating behind the `dsp` feature — SSAT/USAT/QADD/
+ QSUB/QDADD/QDSUB asm+disasm landed (2026-06-17); packed-SIMD + automatic
+ saturating-builtin lowering deferred.
- [ ] **ARMv6-M / Thumb-1** (no IT / MOVW-MOVT / hardware divide / 32-bit Thumb).
-- [ ] Full **`-mcpu`/`-march`/`-mfpu`/`-mfloat-abi`** parsing + the complete
- `__ARM_FEATURE_*` predefined-macro set.
+- [x] Full **`-mcpu`/`-march`/`-mfpu`/`-mfloat-abi`** parsing + the
+ `__ARM_*` predefined-macro set (2026-06-17).
### 5. Polish (correctness-neutral, do last)
- [x] `.ARM.attributes` (Tag_ABI build attributes) for external-toolchain interop.
-- [ ] 16-bit-encoding density + shifted-register operands (deferred peephole);
- `-O0` code density toward tcc.
+- [~] 16-bit-encoding density landed (2026-06-17); shifted-register-operand
+ peephole implemented but gated off (pass_combine shift-rider drop).
- [x] The kit-compiled Cortex-M reset stub.
+- [x] (cosmetic) disassembler shifted-MOV rendering (2026-06-17).
### Exit criterion
Core closure is the top checklist: toy X 423/0/2, `test-smoke-arm32`, the