Battle on the edge possible CPU emulation bug

Technical discussion for those interested in Supermodel development and Model 3 reverse engineering. Prospective contributors welcome.
Forum rules
Keep it classy!

  • No ROM requests or links.
  • Do not ask to be a play tester.
  • Do not ask about release dates.
  • No drama!

Re: Battle on the edge possible CPU emulation bug

Postby Bart » Tue Jun 28, 2022 10:31 pm

Ian wrote:Edit: well i tried messing with the multiplier, but it made no difference to playback. So yeah it could well be some sort of floating point bug. The question is, if it is how can we even check this? Buy an old mac with a 603e processor? lol


If I recall correctly, there is some sort of PowerPC emulation test suite written by Gwenole Beauchesne (who wrote the SheepShaver Mac emulator). We used part of it at some point when writing our PPC emulators ca. 2003-2006 during the first Supermodel project. I don't know if it thoroughly exercises the floating point instructions, though.

[qupte]
The
PowerPC architecture provides for hardware to implement a floating-point system as
defined in ANSI/IEEE Standard 754-1985, IEEE Standard for Binary Floating Point
Arithmetic.


Sounds similar to what i assume modern cpus would comply to?
[/quote]

Yup. I do think that there can be some implementation differences, though. For example, Intel chips have that weird 80-bit floating point type, and I thought I had read somewhere once that double precision operations on Intel are performed in this 80-bit format internally before being down-converted back to 64 bits.


The standard also recommends extended format(s) to be used to perform internal computations at a higher precision than that required for the final result, to minimise round-off errors: the standard only specifies minimum precision and exponent requirements for such formats. The x87 80-bit extended format is the most commonly implemented extended format that meets these requirements.


Maybe these older cpus didn't use any kind of float extended format?


Hah! I had just written that above :) Yes, this is indeed true. But could that really make such a large difference?

I wonder if a lower hanging fruit is to check to see if there are any instructions performing compound operations (like multiply-and-add) where the emulator is doing something that could be causing a loss of precision. There's also always the pesky issue of whether some godforsaken floating point status flag is actually being used somewhere but being emulated incorrectly.

Another project that would have encountered this kind of stuff is the Dolphin emulator. The GameCube and Wii libraries are vast and they've had to deal with all kinds of weird behavior. They have a dev log I think and it'd be interesting to do some searching to see if they've documented any unusual floating point issues. We could even try to finally just port the Dolphin core (I think Nik had done so at some point but I never saw the code).

Finally, we can see if there is a C library that implements the IEEE standard with 64-bit precision directly (with integral math, not falling back on processor-specific floats and doubles).

EDIT:
4.0-2729 - Fix Floating-Point Multiply Floating-Point Multiply Add

EDIT 2:

I looked at the Dolphin code. The interpreter doesn't seem to be doing anything special but the JIT is definitely doing something. It's hard to follow but I can probably figure it out. If I understand correctly, the trick is that the PowerPC internally truncates the mantissa to 25 bits. Embarrassingly, I've never really studied floating point encodings thoroughly but I think the mantissa is the fraction part plus some implicit bit. IEEE 64-bit has a 52-bit fraction, so if you drop 28 bits as a comment in the Dolphin code suggests, you are left with 24 bits, and then I guess the implicit bit makes 25. This might not be that difficult to implement. The comment says this happens to the RHS of every multiplication instruction. Their PowerPC is a different model, though, and a cursory search doesn't yield any documentation of this phenomenon so I am not sure how they deduced this.
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Re: Battle on the edge possible CPU emulation bug

Postby Ian » Wed Jun 29, 2022 7:25 am

I looked at the Dolphin code. The interpreter doesn't seem to be doing anything special but the JIT is definitely doing something. It's hard to follow but I can probably figure it out. If I understand correctly, the trick is that the PowerPC internally truncates the mantissa to 25 bits. Embarrassingly, I've never really studied floating point encodings thoroughly but I think the mantissa is the fraction part plus some implicit bit. IEEE 64-bit has a 52-bit fraction, so if you drop 28 bits as a comment in the Dolphin code suggests, you are left with 24 bits, and then I guess the implicit bit makes 25. This might not be that difficult to implement. The comment says this happens to the RHS of every multiplication instruction. Their PowerPC is a different model, though, and a cursory search doesn't yield any documentation of this phenomenon so I am not sure how they deduced this.


I assume it would just happen when it writes a float back to memory instead of a double?

Yeah I just discovered this yesterday. There is a stackoverflow post about this behavior here:
https://stackoverflow.com/questions/587 ... s-expected

I assume they made it like for performance reasons.

Here is the code in dolphin that does it.
https://github.com/dolphin-emu/dolphin/ ... ils.h#L325

Code: Select all
inline u32 ConvertToSingle(u64 x)
{
  const u32 exp = u32((x >> 52) & 0x7ff);

  if (exp > 896 || (x & ~Common::DOUBLE_SIGN) == 0)
  {
    return u32(((x >> 32) & 0xc0000000) | ((x >> 29) & 0x3fffffff));
  }
  else if (exp >= 874)
  {
    u32 t = u32(0x80000000 | ((x & Common::DOUBLE_FRAC) >> 21));
    t = t >> (905 - exp);
    t |= u32((x >> 32) & 0x80000000);
    return t;
  }
  else
  {
    // This is said to be undefined.
    // The code is based on hardware tests.
    return u32(((x >> 32) & 0xc0000000) | ((x >> 29) & 0x3fffffff));
  }
}


It's only used in a few places. Should be fairly easy to add.
Ian
 
Posts: 2044
Joined: Tue Feb 23, 2016 9:23 am

Re: Battle on the edge possible CPU emulation bug

Postby Bart » Wed Jun 29, 2022 1:36 pm

I think that's a separate issue in addition to the mantissa truncation that is unique to the multiplication instructions. We should implement both of these things. I can take a look at it this weekend.
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Re: Battle on the edge possible CPU emulation bug

Postby Ian » Fri Jul 01, 2022 11:44 am

Ian
 
Posts: 2044
Joined: Tue Feb 23, 2016 9:23 am

Re: Battle on the edge possible CPU emulation bug

Postby Bart » Fri Jul 01, 2022 2:16 pm

This raises the uncomfortable prospect that the PowerPC 603's FPU is different from the PowerPC 750 used on GameCube. But at the very least, if we're on the right track we will see some sort of change of behavior.
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Previous

Return to The Dark Room

Who is online

Users browsing this forum: No registered users and 1 guest