Skip to content

rt: keep MULU.W/DIVU.W operands in data registers - #123

Merged
tinic merged 1 commit into
mainfrom
fix/rt-word-op-register
Oct 1, 2026
Merged

tinic merged 1 commit into
mainfrom
fix/rt-word-op-register

Conversation

@tinic

@tinic tinic commented Oct 1, 2026

Copy link
Copy Markdown
Owner

ami_umul16() and ami_divu32_16_step() used the "dmi" constraint on a u32 operand of mulu.w/divu.w. Under -mregparm=3 GCC spills it, and a memory operand makes the word op read the high half of the big-endian u32. Constraint is now "d".

Scope: -m68000 builds only (AMINETXDUO_CPU=any, which both emulator arms boot). -m68020 emits no word ops.

Proof (vamos, rt_test, toolchain 16.2.2):

Build sha256 68000 68020 68030 68040
-m68000 main 314fd35 6d4b9cfa69fdc120 50 FAIL 50 FAIL 50 FAIL 50 FAIL
-m68000 this branch d42095611ba3da13 PASS PASS PASS PASS
-m68020 main = this branch 6a7b01b2363c496e - PASS - PASS

Static: main emits mulu.w 36(sp),d1 twice in ami_divu64_32_soft; this branch emits 0 memory operands (reproduced by zz9k-fpga, NO BLOCKER).

🤖 Generated with Claude Code

ami_umul16() and ami_divu32_16_step() gave a u32 to MULU.W and DIVU.W
with the constraint "dmi".  Those instructions read 16 bits, so when GCC
chose the memory alternative they read the high word of the u32 on this
big-endian machine: 0 for every operand these routines pass.  Under
-mregparm=3 it did: ami_divu64_32_soft() multiplied by "mulu.w 36(sp),d1",
and every divide with a divisor of 65536 or more came out wrong
(udivsi3(0x10000,0x10001) = 1, the rt_test and Emulator failures).  Both
operands are now "d".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tinic
tinic merged commit 047965a into main Oct 1, 2026
43 checks passed
@tinic
tinic deleted the fix/rt-word-op-register branch October 1, 2026 05:36
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.

1 participant