From 0e51b921202b83a789e08d065d1bb0f0659e624a Mon Sep 17 00:00:00 2001 From: Tinic Uro Date: Wed, 30 Sep 2026 21:55:31 -0700 Subject: [PATCH] rt: keep MULU.W and DIVU.W operands in data registers 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 --- src/common/ami_udivdi3.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/common/ami_udivdi3.c b/src/common/ami_udivdi3.c index de44f1933..851e141f0 100644 --- a/src/common/ami_udivdi3.c +++ b/src/common/ami_udivdi3.c @@ -153,7 +153,9 @@ static u32 ami_umul16(u32 a, u32 b) u32 product = a; - __asm__ ("mulu.w %1,%0" : "+d" (product) : "dmi" (b)); + /* "d", not "dmi": MULU.W reads 16 bits, and a u32 in memory gives it + the high word on this big-endian machine. */ + __asm__ ("mulu.w %1,%0" : "+d" (product) : "d" (b)); return(product); @@ -188,7 +190,8 @@ static u32 ami_divu32_16_step(u32 numerator, u32 divisor, u32 *remainder) u32 step = numerator; - __asm__ ("divu.w %1,%0" : "+d" (step) : "dmi" (divisor)); + /* "d", not "dmi", for the reason ami_umul16() gives. */ + __asm__ ("divu.w %1,%0" : "+d" (step) : "d" (divisor)); *remainder = step >> 16; return((u32)(u16)step);