A.D.A. Amiga Demoscene Archive

  Welcome guest! Please register a new account or log in

  

  

  

log in with SceneID

  

Demos Amiga Demoscene Archive Forum / Coding / WinUAE FPU bugs

 

Author Message
Blueberry
Member
#1 - Posted: 31 Jan 2007 22:52 - Edited
Reply Quote
Hi ADA-folks!

There has been some talk around here about the FPU emulation bugs in WinUAE. I thought they deserved their own thread, so I will start out by describing how I work around some of them...

The most serious bugs in the FPU emulation (that I have encountered) are in the float to int conversion, in the fmove.b/w/l fpn,<ea> instruction.

Here is how it works on a real Amiga:
If the float value is not an integer, it is rounded to the nearest integer. If it is exactly between two integers, the even one is chosen.
If the value is outside the range representable by the integer size of the instruction, it is set to the largest (if larger) or smallest (if smaller) value representable.
This resulting value is put into the target integer.

Now, here is how WinUAE does it:
If the value is not an integer, the decimals are chopped off, i.e. it is rounded towards zero.
If the value is outside the range representable by the target, it wraps around, i.e. for an n-bit integer, the lowest n bits of the exact integer value are taken.

Needless to say, this incorrect rounding and clamping causes lots of trouble.

So, here is how I deal with it: I always do float to int conversion using a macro, and then the macro expands to different code depending on the value of a WINUAE define (indicating whether I am assembling for testing on WinUAE). Here is what I have come up with:

f2i_clamp macro ; FPx,Dy,bottom,top,size
if WINUAE
move.w ccr,-(a7)
clr.\5 -(a7)
fmovem.x fp0/fp1,-(a7)
move.l d0,-(a7)
fmove \1,fp1
fblt .neg\@
fadd.s #0.5,fp1
bra.b .ok\@
.neg\@: fsub.s #0.5,fp1
.ok\@: fmove fp1,fp0
fcmp.d #\3,fp0
fbge .bottom\@
fmove.d #\3,fp0
.bottom\@: fcmp.d #\4,fp0
fble .top\@
fmove.d #\4,fp0
.top\@: fmove.\5 fp0,d0
fmove.\5 d0,fp0
fcmp fp0,fp1
fbne .nothalf\@
rol.\5 #1,d0
addq.\5 #1,d0
asr.\5 #1,d0
and.\5 #-2,d0
.nothalf\@: move.\5 d0,28(a7)
move.l (a7)+,d0
fmovem.x (a7)+,fp0/fp1
move.\5 (a7)+,\2
move.w (a7)+,ccr
else
fmove.\5 \1,\2
endc
endm

f2i.b macro ; FPx,Dy
f2i_clamp \1,\2,-128,127,b
endm

f2i.w macro ; FPx,Dy
f2i_clamp \1,\2,-32768,32767,w
endm

f2i.l macro ; FPx,Dy
f2i_clamp \1,\2,-2147483648,2147483647,l
endm

As far as I can see, it handles all input values and all forms of the instruction except pushing the value onto the stack. Onto the stack works if the condition code saving is removed, but then condition codes aren't right. Not obvious how to have both possibilities (without using a global variable).

Any comments? Something I have missed? Any smarter way to do it? ;-)

Of course, I ought to put this in a WinUAE bug report. Although last time I mentioned it, Toni didn't seem particularly keen to fix it. Thought is was more of a missing feature than an actual bug. Oh well...

Any other emulation bugs that people want to complain about? :-)
Jamie
Member
#2 - Posted: 31 Jan 2007 23:08
Reply Quote
Patch winuae source code:)
Blueberry
Member
#3 - Posted: 31 Jan 2007 23:26
Reply Quote
Don't think I haven't thought of that. :)

I actually found the places in the source code that need to be changed (two places: Interpreted and JIT emulation). I just need to figure out how to use those macros that the code is made up of. And not least, how to make the whole thing compile in the first place.

And then to convince Toni that my patch should actually be included.

Until then, the macro does a quite good job at hiding the bug, at least from a demo coding perspective.

P.S.: Welcome back, Jamie. Really looking forward to seeing that new 3D engine of yours. :-D
z5_
Member
#4 - Posted: 1 Feb 2007 13:00
Reply Quote
@blueberry:
As i can't comment on the topic (i'm not a coder), i'll just stick to wishing you a warm welcome here :o)
Blueberry
Member
#5 - Posted: 1 Feb 2007 23:55
Reply Quote
Thanks. Ougt to have joined this forum long ago. Really interesting discussions going on here I must say.
Cefa
Member
#6 - Posted: 10 Feb 2007 01:47 - Edited
Reply Quote
The fpu bug is fixed in the latest winuae but you may have to wait until winuae team releases a new version, or compile your own winuae using the winuae cvs server.
Blueberry
Member
#7 - Posted: 12 Feb 2007 10:31
Reply Quote
Yeah, I managed to get the thing to compile and fixed the bugs. Next in line is the MOVE16 bug. :-)

Getting WinUAE to compile is extremely cumbersome, as the sources are missing a lot of .h files that you have to find in various places (and you have to install the Windows DDK as well). I would not advise anyone to try unless you really need it. And if you do, ask me for the .h files to save you the trouble of finding them yourself.

Anyway, the next version is scheduled for release very soon, so it will not be a long wait.
Cefa
Member
#8 - Posted: 14 Feb 2007 07:04
Reply Quote
If you don't mind using a beta version they have released one here URL
z5_
Member
#9 - Posted: 3 Mar 2007 19:53
Reply Quote
Winuae 1.4 is out now and mentions "FPU emulation floating point to integer conversion fixed (proper clamping instead of truncating)" so i suppose that this is what Blueberry was talking about?
Cefa
Member
#10 - Posted: 12 Apr 2007 23:34 - Edited
Reply Quote
After hearing about the FPU bug on this post i decided to (being a beginner i did not want any surprises :) postpone any FPU coding until the bug was fixed by the WinUAE guys. So i downloaded today the latest official version 1.4.1. But i still get the same clamping error is there any setting i forgot to set for the correct fpu behavior?? Already tried "more accurate fpu" setting but i still get the same error i also tried different cpus settings.
doom
Member
#11 - Posted: 18 Apr 2007 09:41
Reply Quote
So is it actually fixed? Or is it "fixed" similarly to how the audio emulation was "improved" by introducing latency?
StingRay
Member
#12 - Posted: 19 Apr 2007 10:53 - Edited
Reply Quote
I don't believe in anything I read in the UAE history.txt anymore. So often I read "bug xxx fixed" even though the bug was still present and nothing was fixed at all. So if you want to have 100% accurate fpu emulation you have to do it yourself I suppose. :) At least you don't need to tell the UAE coder about it, he doesn't care anyway! :) And if you let him know that a bug still exists, he more or less tells you to fuck off. :)
Blueberry
Member
#13 - Posted: 25 Apr 2007 17:41
Reply Quote
The rounding and clamping errors that I mentioned in the beginning of this thread are definitely fixed. I sent the fix to Toni and he included it in 1.4.0. And as far as I can tell from a quick test of 1.4.1, he has not removed it again. ;)

If you do not believe me, try running the non-UAE version of Noxie on 1.4.0 and pre-1.4.0 and hear the difference. :)

The fix is not dependent on the "more accurate FPU" setting. This issue is about correctness, not accuracy.

Cefa, what kind of clamping errors are you experiencing?
Cefa
Member
#14 - Posted: 26 Apr 2007 17:58 - Edited
Reply Quote
I just wanted to see if there was problems doing stuff like this in 1.4.1
fmove.l #65536,fp0
fmove.w fp0,d0

According to Asm-pro d0 is zero but if i use your f2i.w macro i get $7FFF
I don't know maybe i did something wrong :) but i am assuming d0 should be $7FFF ?
doom
Member
#15 - Posted: 26 Apr 2007 23:02
Reply Quote
So apparently 1.4.1 gets it wrong after all?
Cefa
Member
#16 - Posted: 27 Apr 2007 01:44
Reply Quote
I thinks so but someone that knows more about M68k coding should test it further because i am assuming that it is wrong (according to Asm-Pros debugger) but i don't know for sure, i am hoping that it's something i am doing wrong :)
Blueberry
Member
#17 - Posted: 28 Apr 2007 12:20
Reply Quote
Damn you Toni! ;)

From the WinUAE 1.4.1 sources:

m68k_dreg (regs, reg) = (uae_u32)(((toint(value, -32768.0, 327676.0) & 0xffff) | (m68k_dreg (regs, reg) & ~0xffff)));

:-O

So, Cefa, you are absolutely right - your code gives the wrong result. More precisely, the upper-bound clamping for word-sized conversions is wrong when executed in interpreted mode. Byte and long conversions and all conversions in the JIT seem to be fine (note that the first few times some code is executed, it is interpreted, even when JIT is enabled).

I guess it is time for a little mail to Toni... Should be in time for the 1.4.2 release.
doom
Member
#18 - Posted: 28 Apr 2007 14:37
Reply Quote
What a beautiful bug.
Blueberry
Member
#19 - Posted: 13 May 2007 14:02
Reply Quote
And now, with version 1.4.2, it is REALLY fixed. :)

By the way, does anyone know what the "More accurate FPU" option (called "More compatible" in 1.4.2) actually does? The source mentions extended precision here and there, but I recall Doom saying (many times) that the UAE FPU is always just in double precision. Is that also the case when this option is enabled?

 

  Please register a new account or log in to comment

  

  

  

 

A.D.A. Amiga Demoscene Archive, Version 3.0