MPYL/M/H and 2's compliment

Archived bsnes development news, feature requests and bug reports. Forum is now located at http://board.byuu.org/
Locked
maxxus
New Member
Posts: 4
Joined: Fri Sep 05, 2008 11:53 pm

MPYL/M/H and 2's compliment

Post by maxxus »

I'm sure this isn't a bug as A) I don't know the bsnes sorce that well and B) somebody would have found this before me. But maybe some one can tell me what I'm missing here.

Registers $2134, $2135 adn $2136 hold the product of the 16bit value written to $211B and the 8bit value in the high byte of $211C. Now the MPYL/M/H registers store the product in a 2's compliment form, meaing that the most significant bit is negitive and the following bits are postive (E.g. 0x01 is positve 1 and 0xFF is negitive 1). Since the SNES is only using 3 bytes to store the product bit 7 of $2136 would be the most significant bit. But in the bsnes code I can see the product is calculated with a 4 byte variable so the result is going to have different 'most significant' bit and as a result a completely different bit pattern than if it were calculated with a 3 byte variable. I thought this would be taken into account later in the code, but I couldnt see any place that tries to convert it from a 4 byte signed value to a 3 byte signed value.

As I said, obviously I'm missing something, because it plays most roms with no problem and if it were wrong I think it would have been found and corrected already.
byuu

Post by byuu »

The input values are sign-extended*, so the size of the output variable does not matter, so long as it's greater than or equal to the desired precision. In this case, 24-bits.

*:
(int8)0xff = 0xffffffff = -1
(int16)0x8000 = 0xffff8000 = -32768
blargg
Regular
Posts: 327
Joined: Thu Jun 30, 2005 1:54 pm
Location: USA
Contact:

Post by blargg »

Here's portable code which implements that multiply (I verified that it matches the SNES). The first two lines sign-extend the values in a fully portable way. Note how unsigned multiply works fine, since the result is the same as long as the result has the same number of bits as the operands. The person who came up with two's complement deserves a compliment!

Code: Select all

unsigned long mpy( unsigned long a, unsigned long b )
{
    a = (a ^ 0x8000) - 0x8000;
    b = (b ^   0x80) -   0x80;
    return (a * b) & 0xFFFFFF;
}
Locked