Floating-point exception in pascal

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
inflater
Member
Member
Posts: 1309
Joined: Thu Sep 28, 2006 10:32 am
Location: Slovakia
Contact:

Floating-point exception in pascal

Post by inflater »

Greetings,
after these tiny problems there grew a big one:
I'm trying to use FPU inside free pascal. I didn't make my own functions because I can use the functions from go32v2 extender. And here's the catch:

Code: Select all

{$ASMMODE intel}
    function round(d : extended) : longint;assembler;[internconst:in_const_round];
      var
        oldcw,
        newcw : word;
        res   : longint;
      asm
            cli
            fnstcw oldcw
            fwait
            mov  newcw,1372h
@@blah1:
            cmp  cx,3
            jne @@blah1
            fldcw newcw
            fwait
            fld d
            fist res
            mov eax,res
            fldcw oldcw
            sti
      end ['EAX'];
{$ASMMODE ATT}
This function works fine, but if that function has been called many times (10 or such), Bochs will start to panic:

01236716631i[CPU0 ] math_abort: MSDOS compatibility FPU exception
And this is right in the instrunction "fwait", right before the fldcw. And after fwait, every floating point instruction will fail and Bochs will generate very big log with all this. I wonder why this isn't called right on the first FPU instruction, always it would start after some calls (program is computing circles to draw a color spiral on the screen).
That program worked fine in DOS though...

After PortixOS would boot in protected mode, I initalize the FPU with this:

Code: Select all

feni
	fclex
	fwait
	finit
	fstcw word[TempW]
	mov ax,TempW
        and ax,3FFh
        mov [TempW],ax
	fldcw word[TempW]
	ret

TempW dw 0
This wouldn't generate a exception. That CLI and STI in the code are only for debugging, I thought that i need to disable IRQs or something (I read that Bochs will fire IRQ 13 when this exception arise).

This seems a harder nut to crack... Should I after every calls of round(); call finit?
Thanks for help.

//EDIT: The "MSDOS compatibility exception" will arise only in the second fwait, fld, fist and the last fldcw (the 2nd part of my code). Other code that works with FPU doesn't generate this exception, for example
y := MidY + round(Phase2*cos(Phase1)/1.2);
when counting cosine of Phase1 and dividing it by 1.2, it wont generate this exception:
(disassembly)
fcos
fld qword ptr ss:[ebp+0xffffffe8]
fld qword ptr ss:[ebp+0xfffffff0]
fmulp st(1), st(0)
fld tbyte ptr ds:0x401b59
fdivp st(1), st(0)
- this works fine.

Regards
inflater
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English :P)
User avatar
binutils
Member
Member
Posts: 214
Joined: Thu Apr 05, 2007 6:07 am

Re: Floating-point exception in pascal

Post by binutils »

inflater wrote: 01236716631i[CPU0 ] math_abort: MSDOS compatibility FPU exception
And this is right in the instrunction "fwait", right before the fldcw. And after fwait, every floating point instruction will fail and Bochs will generate very big log with all this. I wonder why this isn't called right on the first FPU instruction, always it would start after some calls (program is computing circles to draw a color spiral on the screen).
That program worked fine in DOS though...
What is your Bochs version? it looks like Bochs has bug for Floating-point, IMHO.

(FYI, i don't even know pascal programming language.)
User avatar
inflater
Member
Member
Posts: 1309
Joined: Thu Sep 28, 2006 10:32 am
Location: Slovakia
Contact:

Post by inflater »

binutils wrote:What is your Bochs version? it looks like Bochs has bug for Floating-point, IMHO.
2.3, the latest Win32 binary. I think I have bug in my code because it refuses to work on QEMU and even physical hardware :( On QEMU it will automatically exit (neither key was pressed or not), and real HW - freeze. :cry:

Any post will be appreciated! :)

Regards
inflater
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English :P)
User avatar
binutils
Member
Member
Posts: 214
Joined: Thu Apr 05, 2007 6:07 am

Post by binutils »

User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

Read: Intel 1, ch 7.7.3. In essence you should at the very least set the native error handling bit if you want to get done with it the easy way. (CR0.NE -> 1)

It is not a bug in bochs.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
inflater
Member
Member
Posts: 1309
Joined: Thu Sep 28, 2006 10:32 am
Location: Slovakia
Contact:

Post by inflater »

Read: Intel 1, ch 7.7.3 (...) CR0.NE -> 1
Already tried this. INT 7 after first FPU instruction, which was weird because I did not set up the EM flag.

The problem was fixed by adding FINIT before every pascal fpu procedure. My dev PC worked fine without it (well almost), but Bochs and my old testbed didn't. :)

I'm sorry for too much posts by the same author... :(

inflater
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English :P)
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

inflater wrote:
Read: Intel 1, ch 7.7.3 (...) CR0.NE -> 1
Already tried this. INT 7 after first FPU instruction, which was weird because I did not set up the EM flag.
If you looked at the possible causes of an int 7 (Intel 3 Ch 5.12, Coprocessor not available), you'll notice three options:
1. CR0.EM is set. Obviously, it should be clear whenever you have a FPU onboard and set when one isn't present. CPUID will tell you wether one is installed, and you can try some manual probing when CPUID isn't available. If you can't bother with 386s and 486s, just clear it to be sure.

2. CR0.TS is set. This is most likely the cause. The processor will set TS whenever you change tasks. Subsequent FPU accesses will generate exceptions until the bit is cleared. Adding a CLTS instruction will fix it.

3. CR0.TS and CR0.MP are set, and a fpu wait instruction is executed. Again, use CLTS

The only reason you wouldn't be getting errors without NE is that those errors are routed via the chipset. Enabling NE gives far more predictable behaviour. The so-called MSDOS compatibility mode is IMHO plain ugly
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply