Skip to content

UCI register fencing for turbo speed support - #19

Closed
JC-000 wants to merge 1 commit into
masterfrom
fix/uci-turbo-fencing
Closed

UCI register fencing for turbo speed support#19
JC-000 wants to merge 1 commit into
masterfrom
fix/uci-turbo-fencing

Conversation

@JC-000

Copy link
Copy Markdown
Owner

Summary

  • Add LDA UCI_STATUS bus fence after every STA to UCI_CONTROL or UCI_CMD_DATA across the UCI backend. At turbo speeds (4-48 MHz) the 6502 writes registers faster than the FPGA can latch them, causing double-writes and command corruption. The read forces the bus cycle to complete before the next write.
  • 11 fences total: 8 in src/net/uci/uci_cmd.s (uci_abort, uci_begin_cmd, uci_put_byte, uci_push_wait, uci_check_err CLR_ERR, uci_drain_resp, uci_drain_status, uci_ack) and 3 in src/net/uci/net.s (hostname write loop, null terminator, send data loop).
  • Cost: 4 CPU cycles per fenced write, regardless of clock speed. No logic changes, no new control flow.

Test plan

  • make BACKEND=uci builds cleanly (no new warnings)
  • make (ip65 backend) still builds cleanly — no regressions
  • Test A: HTTP GET at 1 MHz on U64E hardware (baseline, not yet passing due to pre-existing boot timing issue)
  • Test B: HTTP GET at 48 MHz on U64E hardware (turbo validation)

🤖 Generated with Claude Code


Originally posted by @JC-000 on 2026-04-16

Add LDA UCI_STATUS after every STA to UCI_CONTROL/UCI_CMD_DATA.
The read acts as a bus fence, preventing double-latched writes
at CPU speeds above 2 MHz. Self-pacing: adds 4 cycles per write
regardless of clock speed.
11 fences total: 8 in uci_cmd.s (abort, begin_cmd, put_byte,
push_wait, check_err CLR_ERR, drain_resp, drain_status, ack),
3 in net.s (host_loop, null terminator, send data loop).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@JC-000

Copy link
Copy Markdown
OwnerAuthor

Originally posted by @JC-000 on 2026-04-17

Superseded by PR #20 which uses a delay-loop fence instead of LDA UCI_STATUS. The STATUS-read approach broke the UCI init sequence; the delay loop works at all speeds 1-48 MHz.

JC-000 added a commit that referenced this pull request May 6, 2026
…#31)
* chore(integration): phase 0 — pre-seed sibling allowlists + helper scripts
Adds tools/integration/ helpers that downstream integration-phase agents
will call. Also pre-seeds the allowlists of the three sibling crypto
repos (c64-x25519, c64-ChaCha20-Poly1305, c64-nist-curves) so cross-repo
agent dispatches no longer stall on bash-approval prompts.
New scripts:
- allowlist_preseed.sh / _merge_allow.py — merge allow + deny patterns
into each sibling's .claude/settings.local.json (dedupe against
existing; preserve order; append new at the end).
- worktree_up.sh / worktree_merge.sh — wrap git worktree add and
--no-ff merge-with-tests for Phase C parallel work.
- build_x25519.sh / build_chacha20poly1305.sh / build_nistcurves.sh —
stub placeholders; Phase C agents fill them in.
- run_vice_suite.sh — one-arg wrapper around tools/run_all_tests.py
honoring C64_SKIP_BUILD.
- run_u64_suite.sh — intentional refuse-to-run; U64E runs must be
dispatched via a live Phase F agent per feedback_never_inline_u64e.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(crypto): Phase C.0 — REU-overlay infra + cfg rework
Adds shared crypto infrastructure (zp_canon.inc, reu_layout.inc,
crypto_swap.s, mul_tables.s, crypto_init.s stub, zp_define.mk)
that Phases C.1-.3 will populate with the sibling libs.
cfg reshaped for the REU-overlay design per plan:
- UCI: CRYPTO_RESIDENT \$6000-\$BFFF (24 KB), CRYPTO_OVERLAY
\$4100-\$5FFF (7.5 KB) active.
- ip65: CRYPTO_RESIDENT \$6000-\$BFFF (24 KB). CRYPTO_OVERLAY
deferred until Phase C.1 lands an overlay image — ip65 can't
shrink CRYPTO_RESIDENT below 24 KB without Profile B + sibling
CODE savings that don't exist yet.
No sibling libs linked yet; in-tree src/crypto/*.s unchanged.
Both backends build; run_all_tests.py --skip-slow passes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(crypto): Phase C.1 — x25519 as REU overlay (UCI backend)
Adds libs/x25519/ submodule (pinned to cd9a663) + integration build
script tools/integration/build_x25519.sh that splits the c64-x25519
sibling sources into three segments when assembled into
build/lib/x25519.a:
OVERLAY_X25519 runtime code (fe25519/x25519/mul_8x8 body) loaded at
boot into the CRYPTO_OVERLAY slot ($4200-$5FFF under
UCI). Actual size 3484 B of the 7680 B budget (45%).
CRYPTO_INIT_CODE boot-only routines (x25519_reu_mul_init,
x25519_sqtab_init) placed in the pre-SQTAB half of
CRYPTO_RESIDENT so they survive overlay swaps.
DATA sibling's page-aligned RW buffers and constant
lookup tables, placed below $A000.
Under BACKEND=uci the Makefile filters out src/crypto/x25519.s +
src/crypto/fe25519.s, defines USE_X25519_SIBLING, and links
build/lib/x25519.a. ip65 continues using the in-tree sources until
Phase C.2 frees enough CRYPTO_RESIDENT headroom.
cfg/c64-https-uci.cfg splits CRYPTO_RESIDENT around a 1 KB hole at
$7800-$7BFF reserved for the sibling's hardcoded sqtab_lo/hi tables
(built at boot by `x25519_sqtab_init`). New DATA + CRYPTO_INIT_CODE
segments flow into the split halves.
src/crypto/shared/crypto_init.s now drives x25519_sqtab_init +
x25519_reu_mul_init + crypto_overlay_stash_x25519 (DMAs the overlay
image from $4200 to REU bank 2 offset $0100 so future P-256 / P-384
swaps can restore it). reu_layout.inc bumps overlay offsets to $0100
to dodge the 64-byte zero buffer at bank 2 offset $0000 used by
`reu_clear_wide`.
src/crypto/x25519_aliases.s aliases the legacy `fe_*` names to the
sibling's `fe25519_*` exports for test-harness compatibility. fe_mul
and fe_sqr are trampolines that append fe25519_reduce_final because
the sibling intentionally skips final reduction in mul/sqr.
Verification:
- `make BACKEND=uci` clean build, OVERLAY_X25519 = 3484 B (≤ 8192 B).
- CRYPTO_RESIDENT total fill 98.2% (23126 / 23552 B).
- `make BACKEND=ip65` clean build, no regression.
- `BACKEND=uci python3 tools/test_x25519.py` — 71/71 pass.
- `BACKEND=ip65 python3 tools/test_x25519.py` — 71/71 pass (baseline).
- `python3 tools/test_entropy.py` under ip65 — 7/7 pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(crypto): Phase C.2 — relocate aux crypto code to LOADER_OVERFLOW
Rescopes Phase C.2: the original ccp sibling integration overflows
CRYPTO_RESIDENT by ~20 KB (measurement, not estimate) and is
abandoned — in-tree chacha20/poly1305/aead/word32 stay permanently.
Instead, reorganize memory to open headroom for Phase C.3:
- New CRYPTO_AUX_CODE segment for SHA-256, HMAC-DRBG, ecdsa_verify
dispatcher (always-resident, addressable from anywhere).
- CRYPTO_AUX_CODE + TLS_CODE now load into NET_CODE (LOADER_OVERFLOW
neighborhood) under UCI. Under ip65, only the CRYPTO_AUX_CODE
rename happens — it still loads into CRYPTO_RESIDENT because
ip65's NET_CODE is already 88% full with the ip65 blob and
cannot absorb either TLS_CODE (~1.8 KB) or CRYPTO_AUX_CODE
(~3.1 KB).
UCI fill deltas:
- NET_CODE: 23.4% → 83.3% (absorbed 1.8 KB TLS_CODE + 3.1 KB
CRYPTO_AUX_CODE)
- CRYPTO_RESIDENT ($6000-$77FF, 6 KB): 100% → 70.8% (TLS_CODE
left; ~1.8 KB reclaimed)
- CRYPTO_RESIDENT_2 ($7C00-$BFFF, 17 KB): 97.8% → 80.1%
(~3.1 KB reclaimed)
ip65 fill deltas: unchanged (CRYPTO_AUX_CODE routes to
CRYPTO_RESIDENT, same region as before). Backend divergence
documented in both cfg files.
No test regressions: 251/253 passing on both backends (the 2
chacha20/poly1305 failures pre-date this commit and are
unrelated).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(crypto): Phase C.3 — nist-curves P-384 primitives (build artifacts)
Adds the libs/nistcurves/ submodule (pinned at 1e72e6c) and the build
plumbing for a narrow P-384 integration under BACKEND=uci:
- build/lib/nistcurves-p384.a emits OVERLAY_P384 containing ONLY
the three variable-base primitives that TLS would consume:
ec_point_double_384, ec_point_add_384, ec_jacobian_to_affine_384
plus their fp384/mod384 helpers. Fixed-base ec_scalar_mul_384 +
ec_precompute_384 and the Lim-Lee anchor tables are sed-stripped
from the sibling sources since they're unused here and would
bloat the overlay. Size: 5,879 B (≤ 7,680 B ceiling).
- src/crypto/p384_force_link.s forces ld65 to pull the archive
members via a 6-byte reference table in CRYPTO_AUX_CODE.
- tools/test_p384_symbols.py exercises the primitives against NIST
P-384 reference values computed from the generator (2G, 3G, 17G,
Jacobian->affine).
P-256 ECDSA stays in-tree under both backends pending upstream work
on variable-base scalar-mult and big-endian I/O
(JC-000/c64-nist-curves#17).
The USE_NISTCURVES_P384 Makefile gate is present but commented: with
both OVERLAY_X25519 (3.4 KB) and OVERLAY_P384 (5.7 KB) active, ld65
stacks them sequentially in CRYPTO_OVERLAY ($4200-$5FFF, 7.5 KB) and
overflows by 1.6 KB. Architecturally max(x25519,p384)=5.7 KB fits the
slot, but the cfg needs `run=CRYPTO_OVERLAY, load=<staging>` for one
overlay plus a contiguous file-backed staging region to hold the
displaced image. That restructure exceeds Phase C.3's stop-on-overflow
hard rule and is deferred pending supervisor OK. Uncomment the two
CA65FLAGS/SIBLING_LIB_ARCHIVES lines in Makefile once the cfg is
extended to enable the integration end-to-end.
ip65 and UCI builds both succeed with the gate commented
(p384_force_link.s is inert when USE_NISTCURVES_P384 is undefined).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(crypto): Phase C.3b — P-384 as external overlay image (no PRG link)
Previous Phase C.3 landed a P-384 archive but couldn't link it
alongside x25519 due to ld65's load= segment concatenation (two
segments with load=CRYPTO_OVERLAY stack rather than overlay).
New approach: P-384 is smoke-test-only, so keep it out of the
production PRG entirely. A new cfg/p384-overlay.cfg + build script
tools/integration/build_nistcurves_p384_bin.sh link the archive
standalone to extract:
build/lib/overlay-p384.bin (8 KB raw OVERLAY_P384 image,
padded with $00)
build/labels-p384.txt (VICE labels for P-384 symbols +
DATA buffers at $C000-$C635 inside
TCP_BUF)
Makefile target `p384-overlay` produces both; the main PRG build
under BACKEND=uci is unchanged (production PRG still does NOT link
nistcurves-p384.a — the USE_NISTCURVES_P384 gate stays commented).
Production PRG size: 47105 B before and after.
tools/test_p384_symbols.py now:
- Skips cleanly under BACKEND=ip65.
- Uploads the 8 KB image to REU bank 2 offset $4100 in two 4 KB
halves staged via TCP_BUF ($C000-$CFFF — networking is off),
using a 55-byte SEI/LDA/STA trampoline injected at $0340 that
reads DMA params from $0380.
- Calls crypto_swap_to_p384 — REU→$4200 DMA, then restores REU
registers ($DF02/$DF03=$6600, $DF07/$DF08=512, $DF0A=0) to the
"mul-row FETCH config" that x25519's reu_fetch_mul_row expects
(fp_mul_384 / fp_sqr_384 only overwrite $DF05 / $DF06 / $DF01).
- Exercises ec_point_double_384 / ec_point_add_384 /
ec_jacobian_to_affine_384 against NIST P-384 generator vectors.
Known issue: fp_mul_384 verifies correctly (2*3=6 smoke-tested) but
fp_sqr_384 hangs on any nonzero input in this standalone link,
causing ec_point_double_384 (which calls ec_sqrp_384 -> fp_sqr_384)
to time out on Test 1. The test infrastructure (overlay upload,
swap, REU restore, ZP/fp_src wiring, readback) is verified working
via the fp_mul_384 path; the root cause of the fp_sqr hang has not
been identified yet — full details in the module docstring.
Build artifacts:
- Main UCI PRG: 47105 B (unchanged).
- overlay-p384.bin: 8192 B.
- labels-p384.txt: 96 entries covering ec_point_double_384,
ec_point_add_384, ec_jacobian_to_affine_384, fp_* helpers,
ec384_p1/p2/p3 buffers, ec384_affine_x/y, etc.
- x25519 non-regression: tools/test_x25519.py passes 71/71.
* test(crypto): Phase E — crypto_init regression test
Boot-only sanity check that crypto_init seeds:
- Shared sqtab tables (sqtab_lo, sqtab_hi at $7800/$7A00)
- x25519 REU mul-row stash (row 42 spot-check via DMA pull-back
to C64 $C000)
- x25519 overlay correctly paged into live slot at
$4200-$5FFF, with idempotent re-swap
Narrowed from the original plan: ccp Shoup + nist-curves P-256/P-384
precompute samples were dropped because those integrations were
deferred (Profile A ccp too large; P-256 blocked on upstream
variable-base scalar-mult; P-384 is external-image-only).
UCI runs the three checks; ip65 skips cleanly (no sibling libs).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(exports): promote cc20_data_ptr, cc20_remain, zp_ptr to labels.txt
Phase F surfaced two unit-test failures under both backends:
test_crypto.py and test_http.py were FATAL on `cc20_data_ptr` and
`zp_ptr` lookups, cascading to a later failure on `cc20_remain`.
All three symbols are equates in src/constants.inc without any
`.export` directive, so they never reached build/labels.txt and
Labels.from_file() couldn't resolve them. Promote the three here
in src/exports.s, following the same pattern Phase C.1 used for
fe_src1/fe_src2/fe_dst.
Baseline improvement: run_all_tests.py --skip-slow goes from 251/253
to 253/253 under ip65.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(tools/uci): defensive skip of non-C labels in _load_labels()
Phase C.1 added REU_OVERLAY_{X25519,P256,P384} labels at offsets
$020100/$022100/$024100. ld65 emits these as "al XXXXXX .name" (no
"C:" prefix) because they're outside the 16-bit C64 code space.
The hand-rolled _load_labels() parsers in tools/uci/test_https_local.py
and tools/uci/bench_ecdsa_u64e.py crashed with ValueError on these
lines (split(":", 1) on "022100" returns a 1-element list).
Skip non-C lines — the UCI harness scripts only need CPU addresses
and the REU offsets aren't useful for them anyway.
Upstream c64-test-harness Labels.from_file() got the proper fix
in JC-000/c64-test-harness#62 (0.12.3) — parses both forms into
one map. A follow-up can migrate these scripts to use the upstream
parser once Labels grows a public iteration API.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(tools/uci): migrate _load_labels() to c64_test_harness.Labels
Replaces the 8-line hand-rolled parser with a single Labels.from_file()
call in both tools/uci/test_https_local.py and tools/uci/bench_ecdsa_u64e.py.
This is now possible because the upstream Labels class gained:
- JC-000/c64-test-harness#62: parse non-C-prefixed label lines
("al XXXXXX .name") for REU offsets and other >16-bit addresses.
- JC-000/c64-test-harness#64: implement collections.abc.Mapping so
dict(labels), .items(), .keys(), .values(), iteration all work.
Behavioral change: _load_labels() now returns REU_OVERLAY_* entries
too (1183 labels vs ~1180 before). Callers looking up by name are
unaffected; any code iterating over every label gets three extra
keys that it didn't previously see. No such iteration callers exist
in either script today.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(submodules): bump nist-curves + switch URLs to GitHub HTTPS
libs/nistcurves 1e72e6c → dfdfb59 picks up:
- PR #19 (JC-000/c64-nist-curves): variable-base ec_scalar_mul_var
for both P-256 and P-384, fp_mod_mul_n / fp_mod_mul_n_384,
packaged ecdsa_verify_256 / ecdsa_verify_384 (160/240-byte
BE structs, C=0 valid / C=1 invalid), fp_reverse32/48 BE↔LE
helpers. Closes issue #17.
- PR #20: reu_fetch_mul_row relocated from main.s into mul_8x8.s
so standalone-overlay links (like c64-https) reach it.
Closes issue #18 (fp_sqr_384 hang).
Also switch libs/x25519 and libs/nistcurves .gitmodules URLs from
local file paths to HTTPS — recent git releases reject "file://"
transports for submodule fetches (CVE-2022-39253 mitigation), which
was blocking `git submodule update --remote`.
Integration of the new ECDSA API lands in a follow-up phase.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(phase-f): narrow x25519 TLS hang to Montgomery ladder
Root-cause investigation under BACKEND=uci. Progressive
`tls_last_state` probing (reverted) bisected the hang to
the `jsr x25519_scalarmult` call inside `tls_ecdh_generate_keypair`:
$82 reached (pre tls_ecdh_generate_keypair)
$91 reached (post privkey-copy)
$92/$93 reached (post fe25519_copy + pre clamp)
$94 reached (pre x25519_scalarmult)
$9E never seen (post return)
x25519_scalarmult in isolation (tools/test_x25519.py) still
passes, so the defect is stateful: something in the boot or
early-handshake path corrupts state between x25519's init and
its first TLS invocation.
Three leads documented (ZP overlap from legacy sqtab_init at
src/boot.s:211, REU register state, IRQ racing ZP) plus a
small recommended experiment: gate the legacy sqtab_init call
the same way reu_mul_init is already gated under
USE_X25519_SIBLING.
No functional code changes — diagnostic instrumentation was
reverted after capturing the bisection.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* revert(crypto): roll back x25519 REU overlay integration (C.1)
Phase F validation showed x25519_scalarmult hangs deterministically
in TLS context under BACKEND=uci at 48 MHz — scalarmult enters and
never returns (tls_last_state=$94 pre-jsr, never reaches $9E post).
Standalone tools/test_x25519.py passes 71/71, so the defect is
stateful / context-dependent.
Rolling back libs/x25519 submodule + overlay machinery while
keeping the rest of Phase C (shared infra in Phase C.0, aux code
relocation in C.2, P-384 external smoke test in C.3b, submodule
URL fix, Labels migration). In-tree src/crypto/{fe25519,x25519}.s
return as the active x25519 implementation under both backends.
Specific changes:
- Remove -D USE_X25519_SIBLING=1 and the build/lib/x25519.a rule
from Makefile; drop the x25519.s + fe25519.s filter-out.
- cfg/c64-https-uci.cfg: revert CRYPTO_RESIDENT to a single
contiguous $6000-$BFFF region; drop the $7800-$7BFF sqtab hole,
CRYPTO_RESIDENT_2 split, X25519_SQTAB region, OVERLAY_X25519
segment, and DATA segment declarations. CRYPTO_OVERLAY region
stays for the external P-384 smoke test.
- cfg/c64-https-ip65.cfg: drop the OVERLAY_X25519 placeholder.
- src/crypto/shared/crypto_init.s: simplify back to a single
mul_tables_init dispatch, drop the .ifdef USE_X25519_SIBLING
branch (REU mul init + overlay stash).
- src/crypto/shared/crypto_swap.s: drop crypto_swap_to_x25519
(remaining dispatcher serves the P-384 external smoke test only).
- src/crypto/shared/reu_layout.inc: drop REU_OVERLAY_X25519 equate.
- src/boot.s: drop all .ifndef USE_X25519_SIBLING guards — reu_mul_init,
the REU table inits, and their BSS come back unconditionally.
- src/data.s: drop all .ifndef USE_X25519_SIBLING guards — fe_p,
x25_basepoint, mul38_lo/hi_tab, mul_dma_lo/hi, sqtab_lo/hi,
fe_tmp1..4, x25_scalar/u/result/ladder state, mul_cached_a/_src2_buf
come back unconditionally.
- src/crypto/poly1305.s: drop .ifndef guard around poly_prod_lo/hi,
mul_8x8 exports (these are back in-tree).
- src/crypto/x25519_aliases.s: delete (alias layer no longer needed).
- tools/integration/build_x25519.sh: delete (sibling overlay builder).
- tools/test_crypto_init.py: delete (Phase E regression test
was overlay-specific; shared sqtab coverage is retained in
tools/test_crypto.py).
- libs/x25519/ submodule + .gitmodules entry: remove.
Verification:
- make BACKEND=ip65: clean build.
- make BACKEND=uci: clean build.
- C64_SKIP_BUILD=1 python3 tools/run_all_tests.py --skip-slow: 253/253.
Filed upstream follow-up: JC-000/c64-x25519#33.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(crypto): Phase C.4 — sibling P-256 ECDSA (c64-nist-curves)
Replaces in-tree ecdsa_{points,fp,mod,curve}.s with the sibling's
ecdsa_verify_256 (JC-000/c64-nist-curves PR #19 — variable-base
scalar-mult, mod-order multiply, packaged ECDSA verify, BE-struct I/O
with fp_reverse32 helper).
src/crypto/ecdsa_verify.s collapses from the ~673 B in-tree verifier
body into a ~234 B thin TLS dispatcher that banks ROM out, dispatches
on ecdsa_curve_id (P-384 still stubbed), hands the 160-byte packed
r|s|h|Qx|Qy BE struct to ecdsa_verify_256, and forwards its C flag.
src/data.s lays ecdsa_sig_r/s + ecdsa_hash + ecdsa_pubkey_x/y out as
five contiguous 32-byte BE fields so the dispatcher can pass
ecdsa_sig_r as the struct base with no explicit pack step.
Sibling code lives in CRYPTO_CODE (fp256 + mod256 + points256 +
ecdsa256), CRYPTO_RODATA (curve256 constants), and CRYPTO_BSS (data
buffers). ~7.3 KB of always-resident code + ~1.3 KB of BSS; no overlay
mechanism. The dispatcher provides an ec_scalar_mul shim that
redirects u1*G (which the sibling's ecdsa_verify_256 dispatches to a
Lim-Lee 8-way fixed-base comb) to ec_scalar_mul_var with G pre-loaded
as the base point, avoiding the 16 KB REU bank-2 precompute table that
the comb would otherwise need at boot.
Shared mul infrastructure (mul_cached_a, mul_src2_buf, mul_dma_lo/hi,
sqtab_lo/hi, mul_8x8, reu_fetch_mul_row, poly_prod_lo/hi) is reused
from the in-tree src/data.s + src/crypto/poly1305.s + src/boot.s; the
sibling's copies are excluded from the archive to avoid collisions.
src/data.s grows mul_src2_buf from 32 to 35 bytes so the sibling
fp256's 4x-unrolled mul over-read into j=32..34 reads zeros. REU DMA
register equates (reu_reu_hi/bank/command) are promoted to linker-
visible exports via src/exports.s so fp256's .import resolves.
Memory-fit work: the sibling + dispatcher pushed CRYPTO_RESIDENT over
its 24 KB budget under BOTH backends. Under UCI we added a new
CRYPTO_AUX_CODE2 segment (carrying only hmac_drbg) alongside the
existing CRYPTO_AUX_CODE; both route to NET_CODE under UCI so Phase
C.2's aux-code-in-NET_CODE arrangement is preserved. Under ip65
NET_BSS is split into the blob-owned $4000-$4F8B region and a
NET_BSS_TAIL slack region at $4F8C-$5FFF ($1074 B); TLS_CODE +
sha256's CRYPTO_AUX_CODE relocate there while hmac_drbg's
CRYPTO_AUX_CODE2 rides the NET_CODE tail. BSS reclaim: removed six
now-dead ecdsa scratch buffers (ecdsa_verify_tmp, ev_u1/u2/point_save
and their P-384 twins, ~432 B) from src/data.s and pruned unused
sibling result registers (fp_r1/r2/r3 + fp_tmp2/3/4 + fp_inv_iter,
~194 B) from data_p256_raw.s.
Validated:
- run_all_tests.py --skip-slow: 253/253
- test_x509.py (ECDSA full sweep): 11/11, valid P-256 verify
under VICE warp in ~30 s
- tools/uci/test_https_local.py on U64E at 48 MHz: PASS, body
"HELLO FROM TLS SERVER" decrypted, handshake progress=0x03 →
progress=0x05 sentinel in 81.9 s wall-clock (~3 s under the
82 s Phase F ECDSA bench baseline)
In-tree ecdsa_{curve,fp,mod,points}.s remain on disk but are filtered
out of CRYPTO_SRCS_ALL in the Makefile; Phase G will delete them.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(phase-f): trace capture analysis — bus-tap undersampling
Captured before Phase C.4 landed. Explains why trace.bin couldn't
pinpoint the x25519 hang loop (~48:1 undersampling at 48 MHz).
Retained for future diagnosis attempts on JC-000/c64-x25519#33.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(phase-g): delete orphan in-tree ECDSA primitives
Phase C.4 stopped linking the in-tree P-256 primitives
(ecdsa_{curve,fp,mod,points}.s) in favour of the sibling
c64-nist-curves integration via build/lib/nistcurves-p256.a.
The files remained on disk for reference but have been unused
since 06bf475. Delete them now, along with the legacy ACME-era
P-384 .asm stubs (ecdsa_*_384.asm) which were never assembled
under ca65.
The corresponding Makefile filter-out list becomes a no-op and
is simplified back to a plain wildcard.
Verified: both `make BACKEND=ip65` and `make BACKEND=uci` build
clean after deletion.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(phase-g): update CLAUDE.md for Phase C.4 end state
- Crypto ABI: point P-256 at libs/nistcurves sibling via
ecdsa_verify_256 / ec_scalar_mul_var; note X25519 stays in-tree
pending JC-000/c64-x25519#33; note ChaCha20-Poly1305 stays
in-tree permanently.
- MEMORY requirements: REU banks 0-1 no longer used by shipped
build (x25519 overlay rolled back); banks 4-7 reserved for
P-384 external overlay smoke test. Note crypto_init currently
bootstraps mul_tables_init only.
- P-384 entry: sibling primitives buildable via `make p384-overlay`
(Phase C.3b), but the target has a pre-existing unresolved-
symbol bug (ec_base384_x/y in points384_raw.s); TLS-level
P-384 verify still stubbed.
- End-to-end HTTPS status: handshake wall-clock now 81.9 s on
U64E 48 MHz under the sibling P-256 path.
- Summary of recent fixes: add bullet 11 for Phase C.4 (06bf475).
- Known issues: add X25519 overlay deferred (#33) and
`make p384-overlay` unresolved-symbol bug.
- ECDSA benchmark: note 81.9 s handshake wall-clock post-Phase-C.4;
speedup path becomes a libs/nistcurves submodule bump.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@JC-000JC-000 closed this May 6, 2026
@JC-000
JC-000 deleted the fix/uci-turbo-fencing branch May 6, 2026 19:03
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@JC-000