Subject: NON FPU cpus - way to go

From: Florian Lohoff <[email-masked]>
Date: Wed, 7 Feb 2001 14:48:58 +0100

Hi,
i would like to know the way to go for NON-FPU cpus - Currently its
partly an Compile Time thing and partly run time config. 

I stumbled over the current tree as on the 3912 we dont have a FPU
so we cant use the default "exit_thread" which simply causes the
CPU to halt (not even an cpu reset works)

arch/mips/process.c

     55 void exit_thread(void)
     56 {
     57         /* Forget lazy fpu state */
     58         if (last_task_used_math == current) {
     59                 set_cp0_status(ST0_CU1, ST0_CU1);
     60                 __asm__ __volatile__("cfc1\t$0,$31");
     61                 last_task_used_math = NULL;
     62         }
     63 }

The Linux-vr people IFDEFed this with CONFIG_NO_FPU which is an option
but then we could even remove the whole cpu probing as everything
would be compile time.

A question here - Which way to go - Compile or Run time config for
CPUs and is 

if(!(mips_cpu.options & MIPS_CPU_FPU))

this also valid for R3k CPU cores ? From my reading it is not as it doesnt
get initialized for R3000 ? As a lot architectures have the R3010
so this should get detected. The R3081 definitly has an FPU from
what i found on the web so this should be correct.

Index: arch/mips/kernel/setup.c
===================================================================
RCS file: /cvs/linux/arch/mips/kernel/setup.c,v
retrieving revision 1.49
diff -u -r1.49 setup.c
--- arch/mips/kernel/setup.c	2001/02/05 01:33:01	1.49
+++ arch/mips/kernel/setup.c	2001/02/07 13:39:16
@@ -182,15 +182,16 @@
 		mips_cpu.tlbsize = 64;
 		break;
 	case PRID_IMP_R3000:
+		mips_cpu.options = MIPS_CPU_TLB;
 		if ((mips_cpu.processor_id & 0xff) == PRID_REV_R3000A)
-			if (cpu_has_confreg())
+			if (cpu_has_confreg()) {
 				mips_cpu.cputype = CPU_R3081E;
-			else
+				mips_cpu.options |= MIPS_CPU_FPU;
+			} else
 				mips_cpu.cputype = CPU_R3000A;
 		else
 			 mips_cpu.cputype = CPU_R3000;
 		mips_cpu.isa_level = MIPS_CPU_ISA_I;
-		mips_cpu.options = MIPS_CPU_TLB;
 		mips_cpu.tlbsize = 64;
 		break;
 	case PRID_IMP_R4000:

Flo
-- 
Florian Lohoff                  [email-masked]             +49-5201-669912
     Why is it called "common sense" when nobody seems to have any?

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Wed, 7 Feb 2001 17:36:33 +0100 (MET)

> partly an Compile Time thing and partly run time config. 

 The i386 way seems reasonable, IMHO.  Have a configure option to enable
an FPU emulator.  Panic upon boot if no FP hardware is available and no
emulator is compiled in. 

> what i found on the web so this should be correct.

 Hmm, I see MIPS_CPU_FPU is hand-coded all over arch/mips/kernel/setup.c.
It's too fragile, I believe.  Why not just use the way IDT recommends in
their "IDT MIPS Microprocessor Family Software Reference Manual" in
Chapter 8 "Floating Point Co-Processor?"  Quoting:

FLOATING-POINT IMPLEMENTATION/REVISION REGISTER

  This read-only registers fields are shown in Figure 8.2, "FPA
implementation/revision register".

 31                           16 15            8 7             0
+-------------------------------+---------------+---------------+
|0                              |Imp            |Rev            |
+-------------------------------+---------------+---------------+

  This register is co-processor 1 control register 0 (mnemonic FCR0),
and is accessed by ctc1 and cfc1 instructions.
  Unlike the CPUcs field, the "Imp" field is useful.  In the R30xx
family it will contain one of two values:

    0   No FPA is available.  Reading this register is the recommended
        way of sensing the presence of an FPA.  Note that software must
        enable "coprocessor 1" instructions before trying to read this
        register.
    3   The FPA is compatible with that used for the R3000 CPU and its
        successors.

  In the R4xxx family the "Imp" field is 0x20 for R4600, 0x21 for R4700
and 0x22 for the R4650.
  The "Rev" field contains no relevant software data.  The "Rev" field
is a value of the form y.x, where y is the major revision number (bits
7:4) and x is a minor revision number (bits 3:0).  Do not rely on this
field.

End of the quote.

 Is there any problem in a particular configuration which makes the FCR0
non-zero Imp field dependency unreliable? 

 The book covers R3081 and it states it contains the 3010A FPA device,
indeed. 

  Maciej

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: [email-masked], PGP key available        +

---

From: Florian Lohoff <[email-masked]>
Date: Wed, 7 Feb 2001 17:59:35 +0100

> an FPU emulator.  Panic upon boot if no FP hardware is available and no

The problem with not compiling in the FPU Emulator at all means some
of your FPU instructions (even on FPU hardware) will fail as on some
specific operators the hardware decides to handle it in software. So
usually you would need an FPU Emulator even on FPU enabled CPUs.

This isnt true if you decide to compile your complete userland with
fpu emulation.

> family it will contain one of two values:

I dont know if this is a generic way to go - I saw complete "full-stops"
on an R3912 using the ctc/cfc instructions - I'll try the autodection
when i come home.

Flo

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Wed, 7 Feb 2001 19:19:45 +0100 (MET)

> usually you would need an FPU Emulator even on FPU enabled CPUs.

 I mean a full emulator.  I know that for simplicity certain actions
required by the IEEE spec are handled in software (Alpha does it as well). 
These bits have to be always included, of course.  I would like to save
wasted bits for hardware that always has an FPU, though.

> This isnt true if you decide to compile your complete userland with

 I'm not sure if that approach has any advantages when using an operating
system such as Linux.  It might certainly be beneficial for firmware or
similar dedicated software.

> on an R3912 using the ctc/cfc instructions - I'll try the autodection

 We might work around pathological cases as usual -- such a behaviour
should count as a bug (I hope IDT did have a clue here -- is there any
original MIPS statement on how to handle FPU presence detection?).  You
might use the i386 setup code for a reference as a large mine of bug
workarounds. 

 Maciej

---

From: Alan Cox <[email-masked]>
Date: Wed, 7 Feb 2001 18:53:29 +0000 (GMT)

> an FPU emulator.  Panic upon boot if no FP hardware is available and no

Its an interesting question whether it belongs in the kernel or libc. 
Discuss ;)

Also we missed a trick on the x86 and I want to fix that one day, which is
to have an __fpu ELF segment so if you boot an FPU emu kernel on an fpu
box you regain 47K

---

From: Jun Sun <[email-masked]>
Date: Wed, 07 Feb 2001 11:01:20 -0800

> partly an Compile Time thing and partly run time config.

Flo,

My vote is to use config option.

Moving forward I see MIPS mainly used in embedded systems.  I think need of
using the same kernel binary for multiple CPUs is rare, especially for the
"same" CPU with or without FPU.  Therefore having run-time detection is a
waste of effort.  Half-config-half-runtime solution is pretty messy too.

For CPUs with the same PrID that may or may not have a FPU, we can add an
optional FPU selection in the config.in file.

To be complete, I probably would add a check for the existence of FPU, if we
can infer from PrID, when FPU config option is enabled.

Jun

---

From: Jun Sun <[email-masked]>
Date: Wed, 07 Feb 2001 11:37:00 -0800

> Its an interesting question whether it belongs in the kernel or libc.

I favor the libc approach as it is faster.

Unfortunately I don't think glibc for MIPS can be configured with
--without-fp.  I modified a patch to get glibc 2.0.6 working for no-fp config,
but it is not a clean one.  Is anybody working on that for the latest glibc
2.2?

> to have an __fpu ELF segment so if you boot an FPU emu kernel on an fpu

Ironically for MIPS you MUST have the FPU emulater when the CPU actually has a
FPU. :-)

Jun

---

From: Joe deBlaquiere <[email-masked]>
Date: Wed, 07 Feb 2001 14:43:52 -0600

> I favor the libc approach as it is faster.

You can still compile in the FP emulator just 'in case'... That way you 
leave it up to the application as to whether to do be quick or cheap. 
This also ensures binary portability (well, mostly, there's always .so 
ABI issues and the like...)

> but it is not a clean one.  Is anybody working on that for the latest glibc

AFAIK, 2.0.7-20 (from Jay Carlson), 2.1.95 (from SGI), 2.2, and the 
current CVS can all be configured for soft float.

> Ironically for MIPS you MUST have the FPU emulater when the CPU actually has a

I'm confused here... why is this?

-- 
Joe

---

From: "Kevin D. Kissell" <[email-masked]>
Date: Wed, 7 Feb 2001 23:51:25 +0100

> optional FPU selection in the config.in file.b
>

A few comments here:

Moving forward,  MIPS CPUs will have a specific FPU-present bit
in one of the CP0 Config registers, as specified by MIPS32/MIPS64.
So the effort wasted in run-time detection will be pretty damned small.

As other people have observed, having the FPU emulator in
the kernel is necessary for full IEEE math even if one *has*
an FPU.  When I bolted the Algorithmics emulator into the 2.2
kernel at MIPS, I made it optional so that people could regress
to Ralf's old not-fully-compliant mini-emulator if they were really
desperate for memory and didn't need full IEEE.  Maybe I
should have just nuked it and made the full emulator mandatory.

As far as the library-versus-kernel-emulation debate is
concerned, yes, user-level emulation will always be faster.
However, you end up with a rather unpleasant configration
management problem - every application and library
distributed needs to be built both with and without FP.
And this affects *every* binary - even those that do zero
FP computation will try to save and restore FPU state
on setjmp/longjmp operations in the best of cases,
and in the existing subobtimal reality, whatever the
hell GCC calls crt0.o touches the floating control
registers on program startup.   My own opinion has
been that people who care about FP performance
run their applications on CPUs with hardware FP,
so the performance advantage of library-based
FP emulation is largely wasted on those who don't
care about it.  But I would understand if the Vr-Linux guys
disagreed with me on that!

            Regards,

            Kevin K.

---

From: Geert Uytterhoeven <[email-masked]>
Date: Thu, 8 Feb 2001 09:45:57 +0100 (MET)

> I'm confused here... why is this?

Because a MIPS CPU may implement only some functionality with some operands,
and decide to throw an `unsupported' exception if the operation is too complex.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven ------------- Sony Software Development Center Europe (SDCE)
[email-masked] ------------------- Sint-Stevens-Woluwestraat 55
Voice +32-2-7248626 Fax +32-2-7262686 ---------------- B-1130 Brussels, Belgium

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Thu, 8 Feb 2001 11:13:55 +0100 (MET)

> I favor the libc approach as it is faster.

 No difference in speed, actually.  In both cases you switch to the kernel
mode when an FPU-related exception happens and then back to the user mode,
either after or before invoking the handler.  The libc approach has the
advantage of running unprivileged. 

> but it is not a clean one.  Is anybody working on that for the latest glibc

 You never want to configure glibc with the --without-fp option.

> Ironically for MIPS you MUST have the FPU emulater when the CPU actually has a

 The same for Alpha.  You don't need a full emulator anyway -- most of it
can be left out for FPU-equipped systems.

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Thu, 8 Feb 2001 11:24:14 +0100 (MET)

> waste of effort.  Half-config-half-runtime solution is pretty messy too.

 Since the run-time detection is about three lines of code (and the
resulting code consists of a similar number of CPU instructions) I
consider it no effort at all.  And remember not only hackers want to use
Linux -- not everyone is going to recompile his own kernel, and the MIPS
world is not limited to embedded devices -- there is quite a number of
MIPS workstation and server systems out there. 

 Neither crashing silently nor printing an obscure oops is not an option
when no FP hw is available and we require it for one reason or another. 

 I hope we will be able to build a generic MIPS kernel one day, just like
we can do for Alpha -- it would encourage redundant code removal which in 
turn would improve cleanness and consistency.

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Thu, 8 Feb 2001 11:42:45 +0100 (MET)

> Its an interesting question whether it belongs in the kernel or libc. 

 Hmm, emulating a missing part of CPU seems more natural in the kernel
mode.  It's completely transparent -- no difference to userland software
whether there is a real part or an emulator.

 The libc approach has the advantage of being unprivileged -- a fault in
an emulator cannot itself bring a system down.  It's non-transparent,
though -- it may give interesting effects when debugging. 

> to have an __fpu ELF segment so if you boot an FPU emu kernel on an fpu

 A good idea, even though hardly anyone needs the emulator for i386 these
days. ;-)

---

From: "Kevin D. Kissell" <[email-masked]>
Date: Thu, 8 Feb 2001 11:52:01 +0100

> advantage of running unprivileged.

Do you have some numbers to support this?  A proper library
implementation does *not* trap to the kernel on each FPU
instruction, and as such is considerably faster (and considerably
larger - a factor for embedded apps!) than a kernel emulation.
The Algorithmics emulator does have the virtue of being smart
enough to check if there is a sequence of consecutive FP
instructions, and to emulate the whole sequence without
returning to user mode, but such "runs" are not all that
common in real code - there are almost always loads,
stores, and address computations interspersed, because
the compiler is "clever" about hiding FP latencies!

>  You never want to configure glibc with the --without-fp option.

That's certainly what we had to do for OpenBSD without FP
emulation!  What is the alternative?

> can be left out for FPU-equipped systems.

That may be true for Alpha, but not for MIPS.  The only
instructions that can *never* generate an unimplented
operation trap on a denormalized operand are the
loads, stores, and moves.  That's why we didn't bother
breaking up the Algorithmics emulator into with-FPU
and without-FPU modules - there was surprisingly little
that could really be left out.

            Regards,

            Kevin K.

---

From: Geert Uytterhoeven <[email-masked]>
Date: Thu, 8 Feb 2001 11:53:52 +0100 (MET)

>  A good idea, even though hardly anyone needs the emulator for i386 these

Yep, I put it on my m68k TODO list as well ;-)

Alternatively you can make (most of) it a loadable module. I don't think
/sbin/modprobe needs the FPU :-)

Gr{oetje,eeting}s,

						Geert

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Thu, 8 Feb 2001 11:54:56 +0100 (MET)

> in one of the CP0 Config registers, as specified by MIPS32/MIPS64.

 Thanks for pointing this out -- this might prove useful.  Though the old
IDT detection method is not any more complicated and it's universal.  It
should work for MIPS32/MIPS64 anyway, right? 

> should have just nuked it and made the full emulator mandatory.

 How much of the emulator is really required for every system?  Can we
assume R[23]010 functionality if there is FP hw present?

> concerned, yes, user-level emulation will always be faster.

 Why would be faster?  You need to handle SIGFPE, which needs a
user->kernel->user transition anyway.  I think a kernel emulation might be
marginally faster as we may skip signal interface handling (and such
details like an integer overflow/division by zero) and handle exceptions
directly. 

> distributed needs to be built both with and without FP.

 Nope -- you just require an emulator in glibc (or whatever libc you
decide to use).  No need to change application software -- FP opcodes will
just trap into libc.

  Maciej

---

From: Alan Cox <[email-masked]>
Date: Thu, 8 Feb 2001 10:58:09 +0000 (GMT)

> /sbin/modprobe needs the FPU :-)

Task state init ?

m68k wants __mac __amiga and __atari as well of course ;)

---

From: Geert Uytterhoeven <[email-masked]>
Date: Thu, 8 Feb 2001 12:05:14 +0100 (MET)

> > /sbin/modprobe needs the FPU :-)

That's why I wrote `(most of)'.

> m68k wants __mac __amiga and __atari as well of course ;)

Yep, one more thing for the list...

Gr{oetje,eeting}s,

						Geert

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Thu, 8 Feb 2001 12:19:43 +0100 (MET)

> larger - a factor for embedded apps!) than a kernel emulation.

 Now you are writing of a compiler emulation and not a library one.  While
such a solution is reasonable for firmware or other OS-less or even
libc-less environment, its much too painful for normal use.  Either you
lose for real FPU environments due to extra overhead to invoke FPU
operations or you have two sets of incompatible binaries (one that invokes
FPU diractly and the other one with emulator hooks).

> emulation!  What is the alternative?

 Write one. ;-)

> that could really be left out.

 I dont know the gory details of the Alpha FPU implementation, but from
what I've read, it's denormal handling that needs the emulation.  And all
bits are already present in our generic emulator -- the only glue needed
is mapping of opcodes to FP operations -- see arch/alpha/math-emu/math.c
how its done (the file is "whole" 9kB!). 

 There are no FP-less Alpha parts, though.  And that's not surprising --
the FPU is one of Alpha aces.

  Maciej

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Thu, 8 Feb 2001 12:22:15 +0100 (MET)

> /sbin/modprobe needs the FPU :-)

 I bet libc will want to initialize FPU's control word or something like
that at the least expected moment. ;-)

---

From: "Kevin D. Kissell" <[email-masked]>
Date: Thu, 8 Feb 2001 12:38:23 +0100

>  Now you are writing of a compiler emulation and not a library one.

Well, in fact it ends up being both.  The compiler substitutes library
invocations for FP instructions, one-for-one.

> While

Which was my whole point about it not being a good idea.

The notion of using libc emulation based on catching SIGFP,
on the other hand, is so silly that I didn't even understand that
that's what you were referring to!  It would be an amazing pig,
and there are corner cases, such as the emulation of the
instructions in the delay slot of branch-on-floating-condition,
that would be damned difficult to handle that way.

> > emulation!  What is the alternative?

I don't understand, the alternative to building a --without-fp
glibc (which Carsten and I did for OpenBSD once already)
is to write *what*?

            Regards,

            Kevin K.

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Thu, 8 Feb 2001 13:05:12 +0100 (MET)

> invocations for FP instructions, one-for-one.

 That's a compiler emulator.  You need to generate special code and place
handlers in libgcc just like it's already being done for integer
operations not supported by a CPU.  I suppose all necessary glue code is
already present in gcc.

> that would be damned difficult to handle that way.

 How much more difficult than in the kernel?  The kernel needs to take
care of these case as well.  Do you mean we miss certain information that
is available for the kernel in the epc register?  Well, we may always make
the kernel pass it back, if needed. 

 I'm not particularly amazed by the idea, but it's certainly doable.

> glibc (which Carsten and I did for OpenBSD once already)

 An FP emulator for OpenBSD.  Not that I care much...