From 43e42b2dcaf84c41d09c49745d82f8515e4f7771 Mon Sep 17 00:00:00 2001 From: Alcaro Date: Wed, 23 Nov 2022 20:47:04 +0100 Subject: [PATCH] Simplify sa1 division Removes the branch and the double modulo I have verified that it gives the same results for all 2^32 pairs of inputs --- bsnes/sfc/coprocessor/sa1/io.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/bsnes/sfc/coprocessor/sa1/io.cpp b/bsnes/sfc/coprocessor/sa1/io.cpp index 58229379..12e5e8f7 100644 --- a/bsnes/sfc/coprocessor/sa1/io.cpp +++ b/bsnes/sfc/coprocessor/sa1/io.cpp @@ -431,14 +431,17 @@ auto SA1::writeIOSA1(uint address, uint8 data) -> void { mmio.mr = (uint32)((int16)mmio.ma * (int16)mmio.mb); mmio.mb = 0; } else { - //unsigned division + //signed division if(mmio.mb == 0) { mmio.mr = 0; } else { int16 dividend = mmio.ma; uint16 divisor = mmio.mb; - uint16 remainder = dividend >= 0 ? uint16(dividend % divisor) : uint16((dividend % divisor + divisor) % divisor); - uint16 quotient = (dividend - remainder) / divisor; + //sa1 division rounds toward negative infinity, but C division rounds toward zero + //adding divisor*65536 ensures it rounds down + uint32 dividend_ext = dividend + (uint32)divisor*65536; + uint16 remainder = dividend_ext % divisor; + uint16 quotient = dividend_ext / divisor - 65536; mmio.mr = remainder << 16 | quotient; } mmio.ma = 0;