VOGONS


First post, by Scali

User metadata
Rank l33t
Rank
l33t

I've been toying with OpenWatcom as a cross-compiler for my old IBM 5160... and I ran into a problem.
It seemed that as soon as I pulled in any code that used floats, it would lock up, even before it ever got to the main() of my program.
I could not reproduce this problem in PCem, DOSBox or any of real PCs.

I have been doing some debugging on the real metal, and eventually I found out that the problem is in the initialization of the FPU emulation routines, a function called __Fini_FPE_handler, which can be found in the file fpe87.asm.
The problem here is that it is assembled with some fwait-instructions. Since there is no actual FPU present to signal that the bus is free, fwait locks the bus indefinitely, locking up the machine.
I have also found some information on this here: http://www.openwatcom.org/index.php/Math_Copr … rface_Evolution

The WAIT/FWAIT instruction thus implements the software-visible portion of the synchronization mechanism. Note that FWAIT is the same instruction as WAIT, and it is a CPU instruction despite the 'F' prefix. The difference between WAIT and FWAIT is that the latter can be eliminated by the linker if an emulation library is used.

Now, apparently these fwaits should have been removed by the linker (I have tried to build it with various settings for FPU emulation), but they were not.
So, I went in there with the ole hex-editor and patched the fwaits to nops in my clibs.lib.
This fixed the lockup, and apparently float-code seemed to execute correctly afterwards, so it seems the rest of the code is working as it should.

However, I was wondering if other people have encountered this problem as well, and perhaps have a better workaround than this (I may have missed some linker switch somehow?).

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 1 of 14, by Scali

User metadata
Rank l33t
Rank
l33t

Upon closer inspection, the code it is running is installing an FPE handler... Which it shouldn't be doing in the first place. Apparently this code is not fully compatible with the emulation settings.
When I looked at the top of fpe87.asm, I also noticed this:
.8087
.286

The .286 directive may be a clue as to why the fwaits were ignored by the linker... On 286 the emulation works in a different way.
I will have to investigate further.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 2 of 14, by Scali

User metadata
Rank l33t
Rank
l33t

The working theory currently is that the FPU-code itself is correct, it should just never be executed on a system without an FPU.
The reason why it gets executed I think is because it looks at the __8087 flag to determine if an FPU is present.
The problem here is that if the FPU emulator is loaded, it will modify that flag to indicate that we have a 387.
I think the problem I'm seeing is because the FPU emulator is loaded before this initialization routine is run.
Therefore the initialization mistakenly assumes it can run FPU code (which it can, on 286+, because the emulator will kick in on the exceptions that will occur when you try to execute an FPU instruction without an FPU... but 8088 doesn't work like that).

I think the problem can be solved by looking at the __real8087 flag instead of the __8087 flag.
I will test this tonight.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 3 of 14, by Scali

User metadata
Rank l33t
Rank
l33t

Okay, I got it...
The problem was indeed with the __8087 value...
In the file ini87086.asm there is a detection routine for the FPU, which is broken.
It does this:
sub AX,AX
push AX ; allocate space for status word
finit ; use default infinity mode
fstcw word ptr [BP-2] ; save control word
fwait
pop AX
mov AL,0
cmp AH,3
jnz nox87

You can't do that on 8088, because finit is actually a wait+finit. The wait will lock up, because there's no 8087 installed to signal that the bus is free.
I looked through some of my old code, and found a routine of my own that was based on an Intel example.
So I do this instead:
fninit
mov AX,5A5Ah
push AX
fnstsw word ptr [BP-2]
pop AX
cmp AL, 0
mov AL, 0
jnz nox87

The fninit is a 'bare' finit, without a wait prefix.
If there is no 8087, it will just do nothing.
Then the fnstsw will store the status word, if there is an 8087... Else it does nothing.
After the finit, the status word should always be 0. So, if the value is now 0, we have an FPU, else we don't.

With this fixed clib, the code should work again on all CPUs, with or without FPU.

You can find my pre-built libs here: http://bohemiq.scali.eu.org/Watcomclibc8088.zip
Replace the libs in lib286\dos with these, and you should be good to go.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 5 of 14, by Scali

User metadata
Rank l33t
Rank
l33t
smeezekitty wrote:

My guess is that it wasn't tested on an actual 8088. 8088's are quite exotic now

Yes, looks like it.
I tried browsing the history, and found a major refactor at some point.
They probably didn't think this code through properly when they rewrote it, it seems based on a 386+ routine (on a 386 you can use either a 287 or a 387 FPU. You can check how it responds to infinity to find out which is which. This is what they seemed to be doing right away... check for no FPU, 287 or 387. But by combining it like that, the no FPU-test would only work on 286+. So I inserted my check above theirs, instead of replacing it).
Ironically enough, there is some example code with proper 8088 detection included elsewhere in the codebase.

Or perhaps they dropped official support for 8086/8088 long ago (going by the library dir name, it is 'lib286', and in various places you find the .286 directive in assembly code... even though removing it does not affect the code at this point, there is no 286-specific stuff as far as I could tell), and the 8086 code generation is just left in as an unsupported feature.

At any rate, I have not found any other problems after I fixed the FPU detection. The compiler generates proper 8086-code, and the float emulation library works correctly on my 8088 machines as far as I have tested it.
I have inspected the makefiles a bit, and it seems that all the libs are still built for 8086 as well. So it looks like it is now 8088-compatible again.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 6 of 14, by Stiletto

User metadata
Rank l33t++
Rank
l33t++

Well, you can always submit a bug to their Bugzilla or something and see what they say. 😀

"I see a little silhouette-o of a man, Scaramouche, Scaramouche, will you
do the Fandango!" - Queen

Stiletto

Reply 7 of 14, by Scali

User metadata
Rank l33t
Rank
l33t
Stiletto wrote:

Well, you can always submit a bug to their Bugzilla or something and see what they say. 😀

Yup, did that already 😀
http://bugzilla.openwatcom.org/show_bug.cgi?id=1161

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 8 of 14, by Stiletto

User metadata
Rank l33t++
Rank
l33t++
Scali wrote:
Stiletto wrote:

Well, you can always submit a bug to their Bugzilla or something and see what they say. 😀

Yup, did that already 😀
http://bugzilla.openwatcom.org/show_bug.cgi?id=1161

Cool. Considering their apparent inactivity, maybe they'll get around to responding to it in five years. 🤣

"I see a little silhouette-o of a man, Scaramouche, Scaramouche, will you
do the Fandango!" - Queen

Stiletto

Reply 10 of 14, by Stiletto

User metadata
Rank l33t++
Rank
l33t++
jwt27 wrote:

Inactivity, you say?

Yeah I know that's not the official branch, but at least this fork sees some active development.

Hah! 🤣

"I see a little silhouette-o of a man, Scaramouche, Scaramouche, will you
do the Fandango!" - Queen

Stiletto

Reply 11 of 14, by Scali

User metadata
Rank l33t
Rank
l33t

Small update: I've been using my own libs for a while now, and both the -fpc (direct calls to FPU emulation) and the -fpi (emit int call + x87 opcode) compiler options work fine on 8088 without FPU, and on machines with FPU (I have no 8088 with FPU, but I assume that works as well).
I have reported this to the OpenWatcom V2 fork as well, and they have made their own fix for this issue: https://github.com/open-watcom/open-watcom-v2 … 73d188a53495966

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 13 of 14, by Scali

User metadata
Rank l33t
Rank
l33t
Harekiet wrote:

We gotta get some of these active watcom folks working on dosbox, I hear the original devs are way too lazy

I heard those devs are too busy doing a Revision prod.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 14 of 14, by Scali

User metadata
Rank l33t
Rank
l33t
Stiletto wrote on 2015-02-27, 16:51:

Cool. Considering their apparent inactivity, maybe they'll get around to responding to it in five years. 🤣

It took a bit longer than that, but apparently they are on the case now:
https://www.os2museum.com/wp/learn-something- … 87-intricacies/
http://openwatcom.org/

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/