FPU emulation code v0.6


This is what you need to get Linux to work if you are not
fortunate enough to own an 68881/2. The file 

/usr/src/linux/arch/m68k/kerlenl/traps.c

needs to be adjusted like I did in the included traps.c file.
You will also need to adjust your bootstrap program to make the
68881 the default processor if no FPU is found.
Also you will have to link math_emu.o to your kernel (of course ;-)

This program is based on the NetBSD FPU emulator.
The original README is included below. Some changes made by me are:

-Added FSAVE/FRESTORE support (essential for Linux)
-patches for supervisor mode; new trap handler
-Linux compatible signal handling
-bugfixes
-added the following instructions:
 FSIN,FCOS,FSINCOS,FTAN (more to follow)
 

					Paul Coene

-----------------------------------------------------------------------

++roman: I've did all the patches to the rest of the kernel source
mentioned above.

-----------------------------------------------------------------------
1. LIST OF IMPLEMENTED AND UNIMPLEMENTED INSTRUCTIONS

This is the list of implemented and unimplemented FPU instructions.
All 040's FP instructions except FSAVE and FRESTORE are implemented.

Type field = bit 8-6 of opcode word

1-1. Implemented Instructions

Type=0: FMOVE (mem->FPr), FINT, FINTRZ, FSQRT, FABS, FNEG, FGETEXP,
	FGETMAN, FDIV, FADD, FMUL, FSGLDIV, FSCALE, FSGLMUL, FSUB,
	FCMP, FTST, FMOVE (FPr->mem), FMOVEM (FPr), FMOVEM (FPcr),
	FMOVECR, FLOGNP1, FLOGN, FLOG10, FLOG2, FMOD, FREM

Type=1: FDBcc, FScc, FTRAPcc,

Type=2: FBcc (word, incl. FNOP)

Type=3: FBcc (long)

Type=4: none

Type=5: none

1-2. Unimplemented Instructions

Type=0: FSINH, FETOXM1, FTANH, FATAN, FASIN, FATANH, FSIN, FTAN,
	FETOX, FTWOTOX, FTENTOX, FCOSH, FACOS, FCOS, FSINCOS

Type=1: none

Type=2: none

Type=3: none

Type=4: FSAVE

Type=5: FRESTORE


2. WHAT ARE MISSING BESIDES UNIMPLEMENTED INSTRUCTIONS

Missing is Packed BCD support, but I do not feel any particular need
for it.  But if anyone wants it, feel free to add the PBCD support;
all we need is type conversion from PBCD external type to internal FP
number format and vice versa.  No FP arithmetic is done in external
formats (i.e. byte/word/long integers, single/double/extended IEEE FPs
or PBCD); they are first converted into the internal format then used
for calculations.


3. HOW TO ADD A NEW INSTRUCTION SUPPORT

Since we need not support FSAVE and FRESTORE operations, all
instructions we have to implement are type 0, all of which are
arithmetic operations.  It is particularly easy to add a new
arithmetic instruction to the existing ones (not to say it is easy to
write a "stable" function to perform floating point
operations... that's entirely another matter).  In "fpu_emulate.c",
there's a function fpu_emul_arith().  In it, there's a large switch()
{ case ... } which dispatch each instruction emulator function.  An
emulator function of any type 0 arithmetic instruction follows this
prototype:

	struct fpn *fpu_op(struct fpemu *fe);

Where fe is a pointer to a struct where frame, fpframe, and fetched
operands are accessible.  That's right, you don't have to fetch the
operands by yourself in you emulation funtion.  For instance, the parts
calling FSQRT, FSUB, FADD and FTST look like:

	switch(word1 & 0x3F) {
[...]
	case 0x04:	/* fsqrt */
		res = fpu_sqrt(fe);
		break;
[...]
	case 0x28:	/* fsub */
		fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; /* f2 = -f2 */
	case 0x22:	/* fadd */
		res = fpu_add(fe);
		break;
[...]
	case 0x3A:	/* ftst */
		res = &fe->fe_f2;
		no_store = 1;
		break;
[...]
	default:
		sig = SIGILL;
	} /* switch */

Here, fe->fe_f1 and fe->fe_f2 are fetched operands.  You can use
fe->fe_f3 for storing the result, or you can return a pointer to
either operand if you want to.  At any rate, you have to follow
the following rules:

	1) A diadic instruction takes two operands fe->fe_f1 & fe->fe_f2.
	2) A monadic instruction takes one operands fe->fe_f2 (NOT fe_f1).
	3) Must return a pointer to struct fpn where the result is stored.
	4) If exceptions are detected, set corresponding bits in fe->fe_fpsr.
	The rest is taken care of in fpu_emul_arith().
	5) Condition code need not be calculated.  It's taken care of in
	fpu_emul_arith().

Actually, after above was written, stubs for the missing functions are
added to the source, so you do not have to change fpu_emul_arith() at
all.  Function names and prototypes are in fpu_arith_proto.h, and all
(except fpu_sincos()) follows the rules above.


4. OTHER POSSIBLE IMPROVEMENTS

4-1. THINGS NOT MENTIONED HERE

I'm sure we could use any kind of improvements from anyone.  The
following thing(s) is(are) what I can think of off hand.

4-2. SPEED

Probably the precision (115-bit significand) derived from Sparc FPE is
not necessary and slowing things down.  Reducing precision to
something which would make more sense in the context of m68k, like
67-bits (64 + guard/round/sticky bits), would not be trivial since
reference to 4 significand words is scattered all over the code
whether Sparc-derived or not.  But it would be a good project.

Also, addition/subtraction of significand (= long integer) could be
done in assembly instead of C as is currently done.  This might speed
things up a little bit.

