Skip to content

func_02057410: the digit loop divides unsigned, and the reloc says so - #1383

Merged
andrewboudreau merged 1 commit into
mainfrom
fix/func_02057410-unsigned-divide
Aug 10, 2026
Merged

func_02057410: the digit loop divides unsigned, and the reloc says so#1383
andrewboudreau merged 1 commit into
mainfrom
fix/func_02057410-unsigned-divide

Conversation

@andrewboudreau

Copy link
Copy Markdown
Collaborator

A fakematch, found by pr_linkcheck and not by any byte gate.

What is wrong

func_02057410 is a printf-style formatter. At 0x02057b64 its digit loop calls a 64-bit divide helper, and we call the wrong one:

word destination symbol
ROM 0xebfe8b9c 0x01ffa9dc __aeabi_uldiv — unsigned
ours 0xebfe8bb2 0x01ffaa34 _ll_sdiv — signed

The bytes agreed regardless, because a relocated word is a wildcard to the byte comparison. So this has been sitting in the matched set with a call that resolves to the wrong function.

Why unsigned is right

The sign is consumed above the loop — the 0x80000000 test emits the minus prefix and negates v:

if ((((s64)zero << 32 | (u32)(v >> 32)) & 0x80000000) != 0) {
    prefixbuf[0] = minus;
    v = ~v + 1;            // from here v is a magnitude
    nprefix = one;
}

Every division below that point is on a magnitude, so the original divides unsigned. v stays s64 in our source, which selects the signed helper. Casting both operands to u64 at the two use sites selects the one the ROM uses.

Verified

gate before after
pr_linkcheck --files src/func_02057410.c WRONG _ll_sdiv -> 0x01ffaa34 ok (verified, 1 slot)
rombuild.py -j16, full ROM 106/106 exact 106/106 exact, 10,813 reproducing, 0 mismatching, 87.88%
port_refcheck 393 checked, 0 stale

Byte-neutral: the change selects a different relocation target, and the relocated word was never part of the comparison.

How it surfaced

It blocks #1382, which touches none of this. pr_linkcheck expands a changed header through the reverse include graph, so that PR link-checks consumers it never names — including this file, whose blob is identical to main's. The verdict reproduces on a clean origin/main worktree, so it is main's defect, not that PR's.

🤖 Generated with Claude Code

https://claude.ai/code/session_015AXm5k53WFPjCYcDHRDX3x

`bl` at 0x02057b64 relocated to `_ll_sdiv` (0x01ffaa34) where the ROM calls
`__aeabi_uldiv` (0x01ffa9dc). The bytes agreed anyway -- a relocated word is a
wildcard to the byte comparison -- so the function sat in the matched set as a
fakematch. `pr_linkcheck` is what sees it.

The sign is already consumed above the loop: the 0x80000000 test emits the minus
prefix and negates `v`, so every division below it is on a magnitude. Casting the
two operands to u64 selects the unsigned helper the ROM uses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015AXm5k53WFPjCYcDHRDX3x
@tangos-validator

tangos-validator Bot commented Aug 10, 2026

Copy link
Copy Markdown

✅ PR validation — Passed

Committed merge introduces no reconstruction or attribution regression.

Full merge validation

Check Result
Committed test merge yes
Matched functions 11,178 / 11,347 (98.5%, +0)
Matched code bytes 2,078,800 / 2,211,124 (94.0%, +0)
Tracked source enrollment 10,785 functions, 1,936,196 bytes (87.57%, +0)
Perfect source moves 0 R100
Contributor credit 0 added, 0 changed, 0 lost
Relocation check 1 checked; 1 VERIFIED
Port reference check 393 checked; 0 stale
Module fidelity 106/106 exact; 100.000000% compared bytes
Code linked from verified source 10,813 functions, 1,943,084 bytes (87.88%)
Per-file link-check detail

All 1 changed file(s) compile to the ROM byte-for-byte with correct relocation targets.

File Symbol Result Slots checked
src/func_02057410.c func_02057410 ✅ verified 1

The private worker commits a test merge, builds the stock ROM profile, compares every executable module, measures matched and source-built code, checks contributor lineage, and verifies affected relocations. The mod profile is opt-in and is not part of this merge gate.

@andrewboudreau
andrewboudreau merged commit d9f8b71 into main Aug 10, 2026
3 checks passed
@andrewboudreau
andrewboudreau deleted the fix/func_02057410-unsigned-divide branch August 10, 2026 19:07
Sign up for free to 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.

2 participants