* Software FPU emulation in linux kernel
@ 2025-03-03 16:22 Thorsten Otto
2025-03-03 22:10 ` Brad Boyer
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Thorsten Otto @ 2025-03-03 16:22 UTC (permalink / raw)
To: linux-m68k
Hi,
i'm currently trying to port the software FPU emulation of linux-m68k to
FreeMiNT, and got some questions about it.
As seen in https://github.com/torvalds/linux/blob/
7eb172143d5508b4da468ed59ee857c6e5e01da6/arch/m68k/kernel/vectors.c#L96 and
https://github.com/torvalds/linux/blob/
7eb172143d5508b4da468ed59ee857c6e5e01da6/arch/m68k/kernel/vectors.c#L119
the FPSP for 040/060 are not installed when the software emulation is used.
However, almost all trigonometric functions are not implemented: https://
github.com/torvalds/linux/blob/7eb172143d5508b4da468ed59ee857c6e5e01da6/arch/
m68k/math-emu/fp_trig.c#L21-L28
What sense does it then make to use an emulation, when only basic instructions
like fadd/fmul etc. are implemented? Programs are not even aborted when using
one of those functions, uprint just prints an error message, and the functions
just return with their input arguments as result instead of calculating the
expected value.
Then i also noticed, that there seem to be some quirks. Eg. the IS_ZERO macro
is defined as
#define IS_ZERO(a) ((a)->mant.m64 == 0)
But that condition is also true for infinities, and there are several places
where IS_ZERO is used before checking for infinities. Eg. in the emulation of
fmul https://github.com/torvalds/linux/blob/
7eb172143d5508b4da468ed59ee857c6e5e01da6/arch/m68k/math-emu/fp_arith.c#L157
+inf * +inf will return a NAN instead of +inf.
Next problem is the interaction between assembler/C. On entry, a2 is loaded
with a pointer to the emulated FPU register set in the thread struct. However,
all the arithmetic functions call out to C functions, which in turn callback
some assembler functions like fp_long_ext2ext. At that time, a2 may contain
any value. Won't that just crash, or did i miss something?
Another problem: the fsqrt function seems to be broken when using arguments <
1.0. Eg. fsqrt(0.75) yields 1.7320508075. Looks like the returned exponent is
off by one there.
So essentially: is that emulation actually used anywhere?
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Software FPU emulation in linux kernel
2025-03-03 16:22 Software FPU emulation in linux kernel Thorsten Otto
@ 2025-03-03 22:10 ` Brad Boyer
2025-03-04 5:24 ` Thorsten Otto
2025-03-03 23:38 ` Michael Schmitz
2025-03-06 15:24 ` Thorsten Otto
2 siblings, 1 reply; 8+ messages in thread
From: Brad Boyer @ 2025-03-03 22:10 UTC (permalink / raw)
To: Thorsten Otto; +Cc: linux-m68k
On Mon, Mar 03, 2025 at 05:22:09PM +0100, Thorsten Otto wrote:
> i'm currently trying to port the software FPU emulation of linux-m68k to
> FreeMiNT, and got some questions about it.
>
> the FPSP for 040/060 are not installed when the software emulation is used.
> However, almost all trigonometric functions are not implemented: https://
> github.com/torvalds/linux/blob/7eb172143d5508b4da468ed59ee857c6e5e01da6/arch/
> m68k/math-emu/fp_trig.c#L21-L28
The FPSP code relies on having the basic FPU of the 040 or 060 and uses
the actual floating point registers and the FPU instructions which are
implemented in hardware. On the variants without the built-in FPU, it's
expected that the FPU emulator handles all of it since that's faster
than triggering the emulator for each FPU instruction used in FPSP.
> What sense does it then make to use an emulation, when only basic
> instructions like fadd/fmul etc. are implemented? Programs are not even
> aborted when using one of those functions, uprint just prints an error
> message, and the functions just return with their input arguments as
> result instead of calculating the expected value.
Well, most programs that use FPU instructions aren't going to use anything
beyond the basics. The 68881/68882 are kind of unusual in implementing
all of that in hardware. That's why Motorola cut down the instruction
set implemented in hardware when they created the 68040. The extra chip
space wasn't worth the limited usage. The fact that the emulator ignores
the instructions is not correct, obviously.
> So essentially: is that emulation actually used anywhere?
In practice, no. There's a lot of other issues as well. I seem to
recall that it only supports the 020/030 and not the versions of
the 040/060 without FPU. It also doesn't fully implement all the
stuff like rounding modes. It's just a basic outline of how to
emulate an FPU rather than something actually useful. The advice
has always been to use a full 68040/68060 or add a real 68881/68882
chip to the 020/030 systems. Most of them do have a socket for it
or a way to add one. I think there's only a couple 030 Mac models
that don't have that option available. For example, I made sure to
get the expansion card for my IIsi that adds the FPU socket. I'm
not sure what the status is for the other platforms, but I got the
impression that the Amiga systems pretty much all run in practice
with CPU upgrades beyond the factory-original configuration.
Most existing 68LC040 chips also have the bug that causes missed
page faults after software-emulated instructions as well, making
it even less useful to support FPU emulation for them. I think
the PB190 is the only Mac with a 68LC040 new enough to be using
the fixed mask revision. Most desktop systems back then used
sockets for the main CPU making it possible to swap a 68LC040 for
the full 68040.
Brad Boyer
flar@allandria.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Software FPU emulation in linux kernel
2025-03-03 16:22 Software FPU emulation in linux kernel Thorsten Otto
2025-03-03 22:10 ` Brad Boyer
@ 2025-03-03 23:38 ` Michael Schmitz
2025-03-04 4:44 ` Finn Thain
2025-03-04 5:47 ` Thorsten Otto
2025-03-06 15:24 ` Thorsten Otto
2 siblings, 2 replies; 8+ messages in thread
From: Michael Schmitz @ 2025-03-03 23:38 UTC (permalink / raw)
To: Thorsten Otto, linux-m68k
Thorsten,
On 4/03/25 05:22, Thorsten Otto wrote:
> Hi,
>
>
> i'm currently trying to port the software FPU emulation of linux-m68k to
> FreeMiNT, and got some questions about it.
>
>
> As seen in https://github.com/torvalds/linux/blob/
> 7eb172143d5508b4da468ed59ee857c6e5e01da6/arch/m68k/kernel/vectors.c#L96 and
> https://github.com/torvalds/linux/blob/
> 7eb172143d5508b4da468ed59ee857c6e5e01da6/arch/m68k/kernel/vectors.c#L119
>
> the FPSP for 040/060 are not installed when the software emulation is used.
That is correct - the FPSP and IFPSP packages are only meant to handle
unimplemented instructions on the 040 and 060 processors, respectively.
These packages were part of Motorola's developer support for 040/060,
and are used unmodified (aside from kernel specific asm glue) by the
Linux kernel.
The generic math emulation support was added much later, and is largely
incomplete (many functions are just stubs, as you found out). The
Kconfig help text for the M68KFPU_EMU option does note that BTW.
> However, almost all trigonometric functions are not implemented: https://
> github.com/torvalds/linux/blob/7eb172143d5508b4da468ed59ee857c6e5e01da6/arch/
> m68k/math-emu/fp_trig.c#L21-L28
> What sense does it then make to use an emulation, when only basic instructions
> like fadd/fmul etc. are implemented? Programs are not even aborted when using
> one of those functions, uprint just prints an error message, and the functions
> just return with their input arguments as result instead of calculating the
> expected value.
As I recall it, the main purpose was to keep kernel and a few important
system utilities from blowing up on 030 machines with no FPU. User space
programs that need to use trig functions or other FPU implemented
functions can be compiled with -m soft_float (or something along those
lines) on those systems.
>
>
> Then i also noticed, that there seem to be some quirks. Eg. the IS_ZERO macro
> is defined as
> #define IS_ZERO(a) ((a)->mant.m64 == 0)
> But that condition is also true for infinities, and there are several places
> where IS_ZERO is used before checking for infinities. Eg. in the emulation of
> fmul https://github.com/torvalds/linux/blob/
> 7eb172143d5508b4da468ed59ee857c6e5e01da6/arch/m68k/math-emu/fp_arith.c#L157
> +inf * +inf will return a NAN instead of +inf.
I'm sure the FPU emulation code can be improved a great deal. In this
particular instance however, both operands are checked for infinity
first. Only if the mantissa of (one of) those operands is zero will the
NAN condition be raised.
I suspect this is mandated by some sort of standard - zero mantissa at
infinite exponent makes no sense as a number.
> Next problem is the interaction between assembler/C. On entry, a2 is loaded
> with a pointer to the emulated FPU register set in the thread struct. However,
> all the arithmetic functions call out to C functions, which in turn callback
> some assembler functions like fp_long_ext2ext. At that time, a2 may contain
> any value. Won't that just crash, or did i miss something?
a0 - a2 and d0 - d5 are saved on the stack on entry in fpu_emu, and
restored in ret_from_exception. What happens in between to these
registers is up to assembly or C code. These registers are never
expected to be preserved, so code can't rely on them having any specific
content.
I cannot locate the specific assembly function you mention
(fp_long_ext2ext). Can you post code or disassembly to illustrate the
problem?
> Another problem: the fsqrt function seems to be broken when using arguments <
> 1.0. Eg. fsqrt(0.75) yields 1.7320508075. Looks like the returned exponent is
> off by one there.
That might be a genuine error in the sqrt algorithm there - can't see
how it does arise though.
> So essentially: is that emulation actually used anywhere?
Not beyond the very basic stuff that did get implemented, no. You may
have to look elsewhere for a feature complete FPU emulation (does netbsd
have that?).
Cheers,
Michael
>
>
>
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Software FPU emulation in linux kernel
2025-03-03 23:38 ` Michael Schmitz
@ 2025-03-04 4:44 ` Finn Thain
2025-03-04 5:47 ` Thorsten Otto
1 sibling, 0 replies; 8+ messages in thread
From: Finn Thain @ 2025-03-04 4:44 UTC (permalink / raw)
To: Thorsten Otto, Michael Schmitz; +Cc: linux-m68k
On Tue, 4 Mar 2025, Michael Schmitz wrote:
> > However, almost all trigonometric functions are not implemented...
> > What sense does it then make to use an emulation, when only basic
> > instructions like fadd/fmul etc. are implemented?
A good way to answer that question is to disable it and see what breaks
(assuming you have suitable hardware available).
> > Programs are not even aborted when using one of those functions,
> > uprint just prints an error message, and the functions just return
> > with their input arguments as result instead of calculating the
> > expected value.
>
> As I recall it, the main purpose was to keep kernel and a few important
> system utilities from blowing up on 030 machines with no FPU. User space
> programs that need to use trig functions or other FPU implemented
> functions can be compiled with -m soft_float (or something along those
> lines) on those systems.
>
Back in 2019, when I needed to get 'fio' to work on a 680x0 system with no
FPU, I had to make a few small changes to the program to avoid floating
point logarithms. That was sufficient to get it to work. The FPU emulator
took care of the rest.
From the notes I made at the time: "I tried to build fio with -msoft-float
but the build failed with a compiler error in the libc header
mathinline.h. I hacked around that and got it to build but the executable
didn't work correctly. I don't know why. I gave up on that approach."
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Software FPU emulation in linux kernel
2025-03-03 22:10 ` Brad Boyer
@ 2025-03-04 5:24 ` Thorsten Otto
2025-03-04 5:48 ` Brad Boyer
0 siblings, 1 reply; 8+ messages in thread
From: Thorsten Otto @ 2025-03-04 5:24 UTC (permalink / raw)
To: Brad Boyer; +Cc: linux-m68k
On Montag, 3. März 2025 23:10:12 CET Brad Boyer wrote:
> On the variants without the built-in FPU, it's
> expected that the FPU emulator handles all of it since that's faster
> than triggering the emulator for each FPU instruction used in FPSP.
Yes, that's why i was wondering that a lot of functions are not implemented.
> Well, most programs that use FPU instructions aren't going to use anything
> beyond the basics.
Thats true. But if they do, wouldn't it be better to just abort the program so
the user will notice it, rather than continuing with totally bogus values?
Currently, uprint will just use the kernels printk. I guess that will just end
up in the syslog for most cases, and not even seen by the user.
> The 68881/68882 are kind of unusual in implementing
> all of that in hardware.
Its not really unusual. The x87 FPU has almost the same instructions.
> In practice, no. There's a lot of other issues as well. I seem to
> recall that it only supports the 020/030 and not the versions of
> the 040/060 without FPU.
Thats mostly a matter how it is integrated in the system. That will obviously
be totally different in my case.
> The advice
> has always been to use a full 68040/68060 or add a real 68881/68882
> chip to the 020/030 systems.
Sure. But obviously this is not always possible, otherwise we would not need
an emulator. Nowadays, 68EC040 are much easier to find than full 68040.
> Most existing 68LC040 chips also have the bug that causes missed
> page faults after software-emulated instructions as well
Oh, i didn't know that. But handling pagefaults is another thing. But freemint
does not manage virtual memory, so that should not be a problem here.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Software FPU emulation in linux kernel
2025-03-03 23:38 ` Michael Schmitz
2025-03-04 4:44 ` Finn Thain
@ 2025-03-04 5:47 ` Thorsten Otto
1 sibling, 0 replies; 8+ messages in thread
From: Thorsten Otto @ 2025-03-04 5:47 UTC (permalink / raw)
To: linux-m68k, Michael Schmitz
>
> both operands are checked for infinity
> first.
Not really. The code reads
/* Handle infinities */
if (IS_INF(dest)) {
if (IS_ZERO(src))
fp_set_nan(dest);
return dest;
}
So the src argument is checked for ZERO first.
Similar in the implementation of fgetman:
if (IS_ZERO(dest))
return dest;
if (IS_INF(dest))
return dest;
> I cannot locate the specific assembly function you mention
> (fp_long_ext2ext). Can you post code or disassembly to illustrate the
> problem?
A sorry, i meant fp_conv_ext2ext. It is called by the fp_normalize_ext() macro
in fp_emu.h, which in turn is called by fp_monadic_check/fp_dyadic_check.
> That might be a genuine error in the sqrt algorithm there - can't see
> how it does arise though.
I think this is caused by
dest->exp += (exp - 0x3FFF) / 2;
`exp` here is the original exponent of the source, and if that is < 1.0, the
expression `exp - 0x3FFF` will become negative, but the division truncates it
towards zero. IMHO using `>> 1` should fix that.
> You may
> have to look elsewhere for a feature complete FPU emulation (does netbsd
> have that?).
Yes, NetBSD has something similar, and it seems to be almost complete,
including all the trigonometric functions. However they do everything in C,
including all the <ea> calculations. The linux version seems to be much better
in this regard.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Software FPU emulation in linux kernel
2025-03-04 5:24 ` Thorsten Otto
@ 2025-03-04 5:48 ` Brad Boyer
0 siblings, 0 replies; 8+ messages in thread
From: Brad Boyer @ 2025-03-04 5:48 UTC (permalink / raw)
To: Thorsten Otto; +Cc: linux-m68k
On Tue, Mar 04, 2025 at 06:24:30AM +0100, Thorsten Otto wrote:
> On Montag, 3. M?rz 2025 23:10:12 CET Brad Boyer wrote:
> > Well, most programs that use FPU instructions aren't going to use anything
> > beyond the basics.
>
> Thats true. But if they do, wouldn't it be better to just abort the
> program so the user will notice it, rather than continuing with
> totally bogus values? Currently, uprint will just use the kernels
> printk. I guess that will just end up in the syslog for most cases,
> and not even seen by the user.
Yes, it should cause an unimplemented instruction trap or something like
that. I was just pointing out that there aren't likely to be a lot of
programs anyone is using on an m68k Linux system that would notice.
> > In practice, no. There's a lot of other issues as well. I seem to
> > recall that it only supports the 020/030 and not the versions of
> > the 040/060 without FPU.
>
> Thats mostly a matter how it is integrated in the system. That will obviously
> be totally different in my case.
True, but it is further evidence that it doesn't actually get used.
> > Most existing 68LC040 chips also have the bug that causes missed
> > page faults after software-emulated instructions as well
>
> Oh, i didn't know that. But handling pagefaults is another thing. But
> freemint does not manage virtual memory, so that should not be a
> problem here.
If you're curious, it's #10 in this list:
https://www.nxp.com/docs/en/errata/MC68040DE_D.txt
A lack of virtual memory should prevent it, as you pointed out.
Interestingly, it's not actually specific to FPU emulation even
though it was normally known for causing issues with FPU. Apple
had a generic workaround in their OS for everything other than
the floating point exceptions (they use a different frame type).
Brad Boyer
flar@allandria.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Software FPU emulation in linux kernel
2025-03-03 16:22 Software FPU emulation in linux kernel Thorsten Otto
2025-03-03 22:10 ` Brad Boyer
2025-03-03 23:38 ` Michael Schmitz
@ 2025-03-06 15:24 ` Thorsten Otto
2 siblings, 0 replies; 8+ messages in thread
From: Thorsten Otto @ 2025-03-06 15:24 UTC (permalink / raw)
To: linux-m68k
There are problems in fp_fsqrt when using the fp_one constant.
fp_one is declared as
static const struct fp_ext fp_one = {
.exp = 0x3fff,
};
So, despite the comment, this is not normalized (the explicit bit is not set).
This will have the effect that it is changed to zero, when fp_dyadic_check is
called in the entry of fp_add. So this call does not only have no effect, it
will also modify the constant.
And even if that is changed, fp_add will also write to it:
https://github.com/torvalds/linux/blob/
848e076317446f9c663771ddec142d7c2eb4cb43/arch/m68k/math-emu/fp_arith.c#L90:
dest->lowmant = src->lowmant = 0;
And 2 lines later, the call to
fp_denormalize(src, diff);
will also modify the src argument.
Wouldn't that crash the kernel, if it tries to write to a write-protected
section?
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-03-06 15:24 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-03 16:22 Software FPU emulation in linux kernel Thorsten Otto
2025-03-03 22:10 ` Brad Boyer
2025-03-04 5:24 ` Thorsten Otto
2025-03-04 5:48 ` Brad Boyer
2025-03-03 23:38 ` Michael Schmitz
2025-03-04 4:44 ` Finn Thain
2025-03-04 5:47 ` Thorsten Otto
2025-03-06 15:24 ` Thorsten Otto
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).