Discussion:
FPU
(too old to reply)
muta...@gmail.com
2021-05-02 05:21:34 UTC
Permalink
I have discovered that PDPCLIB-based programs that
use floating point have the following behavior:

On Freedos, they cause a hang.

On PDOS/386 they give incorrect results on the first
run, then correct result on the second run.

On HX under Freedos, they cause an exception, which
HX traps, does an FNINIT, and then on the next
invocation the application works fine.

Am I correct in believing that what I need to do for
both 8086 and 80386 is to unconditionally execute
the FNINIT instruction at PDPCLIB startup, because
no-one else is responsible for doing this.

Note that I expect people to have a floating point
coprocessor and I am not interested in floating
point emulation nor trapping exceptions. Not in
PDPCLIB, anyway. I don't mind if PDOS is enhanced
to trap exceptions and ignore them, or invoke
floating point emulation.

Thanks. Paul.
Rod Pemberton
2021-05-02 10:04:04 UTC
Permalink
On Sat, 1 May 2021 22:21:34 -0700 (PDT)
Post by ***@gmail.com
I have discovered that PDPCLIB-based programs that
On Freedos, they cause a hang.
On PDOS/386 they give incorrect results on the first
run, then correct result on the second run.
On HX under Freedos, they cause an exception, which
HX traps, does an FNINIT, and then on the next
invocation the application works fine.
Am I correct in believing that what I need to do for
both 8086 and 80386 is to unconditionally execute
the FNINIT instruction at PDPCLIB startup,
I never completed my OS code for init of the x87.
From my notes:

a) CR0 bits may need to be set appropriately for
the coprocessor type, such as CR0.EM, CR0.ET,
CR0.MP, and CR0.NE. These bits select hardware
vs software, internal vs external, 287/387/487,
and whether to call Int 0x10 and Int 0x07, etc.
CR0 is probably 286 PM and later. I.e., probably
need to program them all for hardware and internal
coprocessor, except your 8086 would be external?
You'd also need to select 287, 387, 487 correctly.

b) I/O ports 0xF0 and 0xF1 need to be written
with zero to clear the "coprocessor busy latch"
and reset the coprocessor, respectively

c) FNINIT

d) possibly need FSTSW FCLEX sequence and
FNSTCW instruction too
Post by ***@gmail.com
because no-one else is responsible for doing this.
I'm not sure what is responsible for doing
an FNINIT or x87 coprocessor init.
Post by ***@gmail.com
Note that I expect people to have a floating point
coprocessor
Do you have one with your 8086?
Post by ***@gmail.com
and I am not interested in floating
point emulation nor trapping exceptions. Not in
PDPCLIB, anyway. I don't mind if PDOS is enhanced
to trap exceptions and ignore them, or invoke
floating point emulation.
...
--
I'd love to answer that, but it would violate the TOS. Liberals can't
handle the truth, because the truth hurts.
muta...@gmail.com
2021-05-02 21:56:56 UTC
Permalink
Post by Rod Pemberton
b) I/O ports 0xF0 and 0xF1 need to be written
with zero to clear the "coprocessor busy latch"
and reset the coprocessor, respectively
Thanks. To me, this says that HX must do it. You
can't expect an application to do this.

Based on the above I have started negotiating with
Japheth.
Post by Rod Pemberton
Post by ***@gmail.com
Note that I expect people to have a floating point
coprocessor
Do you have one with your 8086?
No, but if I can't do floating point on my 8086, so be it.

BFN. Paul.
Alexei A. Frounze
2021-05-02 19:06:33 UTC
Permalink
Post by ***@gmail.com
I have discovered that PDPCLIB-based programs that
On Freedos, they cause a hang.
On PDOS/386 they give incorrect results on the first
run, then correct result on the second run.
Might want to try clearing CR0.TS with CLTS. I remember without
this DJGPP-compiled programs would hang when run after my
protected-mode experiments that left CR0.TS=1.
Post by ***@gmail.com
On HX under Freedos, they cause an exception, which
HX traps, does an FNINIT, and then on the next
invocation the application works fine.
Am I correct in believing that what I need to do for
both 8086 and 80386 is to unconditionally execute
the FNINIT instruction at PDPCLIB startup, because
no-one else is responsible for doing this.
Yep, nobody does it for you.
Also I'd refresh on practical differences between the 80387
and earlier ones. There might be differences in initialization
and there definitely are differences in operation.

Alex
muta...@gmail.com
2021-05-02 21:58:14 UTC
Permalink
Post by Alexei A. Frounze
Post by ***@gmail.com
Am I correct in believing that what I need to do for
both 8086 and 80386 is to unconditionally execute
the FNINIT instruction at PDPCLIB startup, because
no-one else is responsible for doing this.
Yep, nobody does it for you.
Windows does. It gives me an environment with
usable floating point. I think HX should as well.

BFN. Paul.
muta...@gmail.com
2021-05-04 18:21:14 UTC
Permalink
Post by ***@gmail.com
Post by Alexei A. Frounze
Post by ***@gmail.com
Am I correct in believing that what I need to do for
both 8086 and 80386 is to unconditionally execute
the FNINIT instruction at PDPCLIB startup, because
no-one else is responsible for doing this.
Yep, nobody does it for you.
Windows does. It gives me an environment with
usable floating point. I think HX should as well.
My understanding is that you can execute FNINIT even
if no coprocessor exists.

Is there any reason why I shouldn't do an FNINIT in:

PDOS/86
PDPCLIB startup for MSDOS applications
PDOS/386
PDPCLIB startup for Windows applications

regardless of whether anyone is executing FP code or not
(it is not something I know in advance)?

Doing it in PDOS/86 is an enhancement compared to
MSDOS/Freedos, but maybe there is nothing wrong
with enhancing PDOS/86.

Thanks. Paul.
Scott Lurndal
2021-05-04 20:05:34 UTC
Permalink
Post by ***@gmail.com
My understanding is that you can execute FNINIT even
if no coprocessor exists.
PDOS/86
PDPCLIB startup for MSDOS applications
PDOS/386
PDPCLIB startup for Windows applications
regardless of whether anyone is executing FP code or not
(it is not something I know in advance)?
One of the common (and important) optimizations in operating system
schedulers thirty years ago was to save and restore floating
point registers _only_ if they've been used. This relies the OS
disabling floating point for a process until it first tries to
use a floating point instruction, in which case it will re-enable floating
point and reexecute the trapped instruction. Subsequently the OS
will save and restore the floating point registers on every entry
to the OS (e.g. system calls) or on some systems, on any context switch.

This did end up being a very important optimzation since a significant
fraction of applications (80%+?) never used floating point at all.

This does mean that the operating system itself could not use floating
point instructions.
muta...@gmail.com
2021-05-04 22:10:54 UTC
Permalink
Post by Scott Lurndal
Post by ***@gmail.com
My understanding is that you can execute FNINIT even
if no coprocessor exists.
PDOS/86
PDPCLIB startup for MSDOS applications
PDOS/386
PDPCLIB startup for Windows applications
regardless of whether anyone is executing FP code or not
(it is not something I know in advance)?
One of the common (and important) optimizations in operating system
schedulers thirty years ago was to save and restore floating
point registers _only_ if they've been used. This relies the OS
disabling floating point for a process until it first tries to
use a floating point instruction, in which case it will re-enable floating
point and reexecute the trapped instruction. Subsequently the OS
will save and restore the floating point registers on every entry
to the OS (e.g. system calls) or on some systems, on any context switch.
This did end up being a very important optimzation since a significant
fraction of applications (80%+?) never used floating point at all.
This does mean that the operating system itself could not use floating
point instructions.
Thanks a lot for that nugget explaining the situation!!!

I don't want to paint myself into a corner.

At the same time I'm happy to take a shortcut.

At the moment I'm happy to just run a single process,
and not use floating point in the OS either.

Rather than trap the expected floating point exception
because it has deliberately been put into an unusable
state, I should be able to fudge automatic-initialization
by enabling floating point unconditionally in PDOS.

And I should NOT execute FNINIT in PDPCLIB - this is
a job that should be relegated to the OS, when the
trap occurs.

And PDOS/86 should have the same kludge as PDOS/386.
And because for some reason Freedos and MSDOS have
not implemented the kludge, they should have a 3-byte
COM file that does an FNINIT, to be run unconditionally
from autoexec.bat.

There is no particular need to put an FNINIT into HX,
because of the above autoexec.bat change, but if HX
was being used as a pure Windows system, then it
would be sufficient, and harmless, to put it into HX
and just run hxldr32 from the autoexec.bat instead.

Does that sound like correct philosophy?

Thanks. Paul.
James Harris
2021-05-23 17:51:42 UTC
Permalink
Post by Scott Lurndal
Post by ***@gmail.com
My understanding is that you can execute FNINIT even
if no coprocessor exists.
PDOS/86
PDPCLIB startup for MSDOS applications
PDOS/386
PDPCLIB startup for Windows applications
regardless of whether anyone is executing FP code or not
(it is not something I know in advance)?
One of the common (and important) optimizations in operating system
schedulers thirty years ago was to save and restore floating
point registers _only_ if they've been used. This relies the OS
disabling floating point for a process until it first tries to
use a floating point instruction, in which case it will re-enable floating
point and reexecute the trapped instruction. Subsequently the OS
will save and restore the floating point registers on every entry
to the OS (e.g. system calls) or on some systems, on any context switch.
Is that necessary? AIUI the actions on a floating-point task-switched
interrupt could save/load state only if the task trying to use FP
instructions had changed since the last such interrupt, i.e. on such an
interrupt:

if this is not the active FP task
save floating-point state for the active FP task
set active FP task = the current one
load floating-point state for what is now the active FP task
clear task switched bit
endif

If only one task was using FP facilities the processor's FP state would
never need to be saved. If two FP tasks were running the state would
only be saved if between them if they both used FP facilities in a given
timeslice. Etc.
Post by Scott Lurndal
This did end up being a very important optimzation since a significant
fraction of applications (80%+?) never used floating point at all.
This does mean that the operating system itself could not use floating
point instructions.
OS tasks could use FP instructions, as above. I doubt the kernel would
need FP but if it did I would think it could arrange to do so, e.g. by
noting itself as the 'active FP task' when necessary.
--
James Harris
wolfgang kern
2021-05-24 08:08:30 UTC
Permalink
On 23.05.2021 19:51, James Harris wrote:

[about FPU]
Post by James Harris
OS tasks could use FP instructions, as above. I doubt the kernel would
need FP but if it did I would think it could arrange to do so, e.g. by
noting itself as the 'active FP task' when necessary.
My solution on this (and other REG/VAR-issues too) was pretty simple:

"the one who made it dirty has to clean it up!"

so nothing needs to be changed on task-switches except all FPU-registers
and status were stored for later display on Exception-Faults. My OS use
FPU rare, only on start for initialize and to create few LUTs.
__
wolfgang

Continue reading on narkive:
Loading...