Basilisk II - Odd FPU Behaviour

Phipli

68040
@cheesestraws @Snial @Crutch @David Cook

So a little while back I was having trouble debugging some software I was writing when testing it in Basilisk II. After blaming RealBasic and myself, I realised that maths was been incorrectly evaluated, tested on real hardware and moved on.

I was writing something much simpler yesterday and it happened again, but this time the program was compiled C using CodeWarrior and the code in question was so basic it was insane that it wouldn't work... so I investigated.

What I found was that my install of Basilisk II... shows floating point values incorrectly! Note that everything is fine in 68k QEMU (emulated 68040).

In Basilisk II, I was using a IIci ROM with a 68040 and FPU, running B1-7.5.5. So to experiment, I set it to a 68030+68882... same issue... so I set it to be a 68030 without FPU... and the code works (using the SANE traps). Given this, I have written a little test program. I'm curious how widespread this issue is - is it just my setup? Is it just on Linux? Is it a specific version of Basilisk II? (By the way - how do you check the version easily?)

The weirdest thing is it is actually difficult to detect in code - if I test the value and compare with an integer, they compare as normal! It is almost as if the bug is in the code that displays a float, or converts it to a string, but only when emulating a physical FPU? (Edit - or possibly they've modified how floats are stored in their patches, but not updated the routine that displays a float?)

Here is my program run under an emulated 68030 without FPU :

1767438201304.png

Here it is run under an emulated 68030 with FPU :

1767438301356.png

Here it is run under an emulated 68040 :

1767438013331.png

I'd be interested to know if other people see similar behaviour? You can change the CPU / FPU under the "Memory/Misc" tab in Basilisk II Settings. For now I'll be leaving mine set to 68030 without FPU.
1767438099990.png

Edit - attached the test app.
 

Attachments

Last edited:
Can you upload your test program? I don't have the mental wherewithal to dig deeply into this (or anything else) at present but I can try it out here and check that it's reproducible and try to have opinions about it, for what little those are worth...
 
Can you upload your test program? I don't have the mental wherewithal to dig deeply into this (or anything else) at present but I can try it out here and check that it's reproducible and try to have opinions about it, for what little those are worth...
Just have - sorry, just forgot to attach it.

Whatever the issue is is reversible because casting back to a long works fine. It just seems to simply display wrong. Weird weird weird.

Yeah, not hugely worried about solving it - I use QEMU for emulation mostly now because of a few things, but I'd be interested to know if it was a widespread issue, because it will be impacting commercial software as well as stuff I've written.
 
To verify you do have a problem, you can take a pointer to the FP value, cast it to something integer, and then display as hex. Then you can compare the hex values between implementation.

One issue will be which FP you use. FP32 and FP64 are supposed to be IEEE-compliant but rounding might behave "interestingly" due to the '881 and '882 doing higher accuracy computation and appropriate rounding. 80-bits native (which are roughly IEEE FP79 but with the implicit 1 at the beginning of the mantissa being explicit hence the 80 bits) have their won quirks. Getting everything right in SW is not obvious. Which specific FP the SW will be using might be language and compiler dependent, though most of the recent C stuff use float == FP32, double == FP64, and likely long double == Moto FP80.
 
To verify you do have a problem, you can take a pointer to the FP value, cast it to something integer, and then display as hex. Then you can compare the hex values between implementation.

One issue will be which FP you use. FP32 and FP64 are supposed to be IEEE-compliant but rounding might behave "interestingly" due to the '881 and '882 doing higher accuracy computation and appropriate rounding. 80-bits native (which are roughly IEEE FP79 but with the implicit 1 at the beginning of the mantissa being explicit hence the 80 bits) have their won quirks. Getting everything right in SW is not obvious. Which specific FP the SW will be using might be language and compiler dependent, though most of the recent C stuff use float == FP32, double == FP64, and likely long double == Moto FP80.
Thanks for the suggestion @Melkhior.

In QEMU (works) :
1767439713656.png

In Basilisk II (with FPU) (doesn't) :
1767439798770.png

So interestingly, the raw value in RAM is consistent. (I cast the memory to a long as both should be 32bit).
 
Firstly, 12345 will be represented exactly in every FP format, it's 0.11000000111001₂ *2^14 (the highlighted part here: 0.1100000011100100 is what the "40E4" is in the hex representation, because the MSB is left off).

And, interestingly, 12345/0.000021 is approximately 2^29, though not quite. So, 12345/2^29=0.00002299, which ought to display as 0.000023.

Nevertheless, it looks too close for coincidence. It's possible that Basilisk II emulates a 680x0 FPU by computing floats using the host FPU and just converting back, assuming that the IEEE format is always the same. Does the 68882 (or 68881) have a float to string function? It has float to decimal conversions. So, from the 68881 manual.

1767443796981.png
So, perhaps 0.00002299 could be rounded down to 0.000021?

This implies that Basilisk II I is making some kind of mantissa error, i.e. that the error is in an FPU float to decimal conversion, rather than a patched routine for float to string.
 
For interest, I just ran my program in a newer version of Basilisk II compiled from source (it says 1.1 in the about, the one from the repository says 1.0 - but I don't know how informative these are).

The same thing happens, with this being a 68030+FPU :

1767445202886.png

Using Infinite Mac to emulate a IIfx 030+FPU (which uses Basilisk II), the FPU does behave. Curious :
1767446400205.png

assuming that the IEEE format is always the same
Is a 64bit host confusing it?
 
Last edited:
For interest, I just ran my program in a newer version of Basilisk II compiled from source (it says 1.1 in the about, the one from the repository says 1.0 - but I don't know how informative these are).

Is a 64bit host confusing it?
Doesn't infinite Mac take the C/C++ emulators and compile to WebAssembly (@joevt , @mihai )? If so, the host is still 64-bit. But it could be a big-endian/little-endian thing (e.g. a G5 PowerMac running Basilisk II under Mac OS X would be OK).
 
Back
Top