Hand-written m68k asm for the SHA-1 crypto hot loop (#47) - #86
Merged
Merged
Conversation
sha1_compress() and chacha20_block() are the only real hot loops in the crypto core - HMAC and PBKDF2 have none of their own, they're built entirely on calls into SHA-1, so speeding up sha1_compress() transitively speeds up both (including PBKDF2's iteration loop, the dominant cost of vault unlock/creation). Both are now reached through a function-pointer seam (src/core/crypto_dispatch.h) defaulting to the portable C reference. src/amiga/crypto_select.c repoints both at hand-written m68k assembly (src/core/sha1_asm.s / chacha20_asm.s) at startup, unless ENVARC:AmiAuth/cryptoasm=off forces the C reference back on. Unlike a typical 020+-gated accelerated path, this asm is restricted to instructions available on the plain 68000 baseline - verified in CI under amitools' vamos on both -C 000 and -C 020, reusing every existing SHA-1/ HMAC/PBKDF2/ChaCha20 RFC vector already in the test suite - so it's the default on every CPU tier this project supports, not an opt-in extra; 68020+ still runs it faster purely by being a faster CPU on the same instructions. The optional AmiSSL-backed provider originally scoped alongside this is tracked separately as #85, since AmiSSL requires OS3.0+/68020+ and is meaningfully more effort/surface for less certain value than the asm path alone. Also cleans up several stale "see docs/ROADMAP.md PhaseN" comments left over from that file's removal (#74). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ware Measured both hand-written 68000 asm hot loops on a real 68000 under Copperline (timer.device EClock, real Kickstart 3.1 ROM), comparing against the portable C reference: - SHA-1 (via PBKDF2-HMAC-SHA1, 600 iterations): asm is ~17% faster. - ChaCha20 (4096-byte keystream): asm is ~17% *slower*. Disassembling GCC's -O2 output for chacha20_block_c showed why: it keeps almost the entire 16-word state resident in registers across all 10 rounds, spilling only a couple of overflow values. The hand-written asm instead reloaded all 16 words from the stack on every single quarter-round - closing that gap needs a substantially more involved register-resident rewrite, which wasn't judged worth the risk/effort for this pass given ChaCha20 isn't the hot loop that matters most (PBKDF2's iteration loop is, and that's SHA-1-bound). g_chacha20_block now stays on the C reference unconditionally; crypto_select.c only repoints SHA-1. Drops chacha20_asm.s, its dedicated vamos test, and the now-unused asm-test-chacha20 Makefile/CI wiring. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This was referenced Jul 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements #47 (asm scope only - the AmiSSL provider half is split out to #85).
sha1_compress()andchacha20_block()are the only real hot loops in the crypto core (HMAC and PBKDF2 have none of their own, built entirely on SHA-1) - reached through a function-pointer seam (src/core/crypto_dispatch.h) that defaults to the portable C reference.src/amiga/crypto_select.crepoints SHA-1 at hand-written m68k assembly (src/core/sha1_asm.s) at startup, unlessENVARC:AmiAuth/cryptoasm=offforces the C reference back on (a safety valve).-O2output showed it keeps almost the entire 16-word state resident in registers across all 10 rounds, while the naive asm reloaded everything from the stack every quarter-round. Closing that gap needs a substantially more involved register-resident rewrite, judged not worth the risk for this pass since ChaCha20 isn't the hot loop that matters most (PBKDF2's iteration loop is, and that's SHA-1-bound).g_chacha20_blockstays on the C reference unconditionally.asm-crypto-tests) cross-builds a test binary (tests/asm/test_sha1_asm.c) that forces the dispatch onto the asm and re-runs every existing SHA-1/HMAC/PBKDF2 RFC vector already in the test suite, under amitools'vamoson both-C 000(68000) and-C 020.docs/ROADMAP.mdreferences left over from that file's removal (docs: remove ROADMAP.md, use GitHub issues/milestones as the single tracker #74).Measured real-hardware performance (Copperline, real Kickstart 3.1 ROM, PAL EClock)
PBKDF2-HMAC-SHA1 (600 iterations), C reference vs. SHA-1 asm, across every CPU tier Copperline models:
The advantage holds at every tier — "68020+ still runs it faster purely by being a faster CPU on the same instructions" is measured here, not assumed. (ChaCha20's asm attempt, by contrast, measured ~17% slower than C on the 68000 — see above for why it was dropped.)
Test plan
make test— 173/173 host tests pass (dispatch defaults to C, unaffected)make m68k-docker/make gui-docker— both binaries build cleanly with the asm linked inmake asm-tests-docker+vamos -C 000/-C 020— 22 SHA-1/HMAC/PBKDF2 assertions, all pass on both CPU tiers🤖 Generated with Claude Code