diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-01-27 01:05:20 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-01-27 01:05:20 +0000 |
commit | 546db14ee74118296f425f3b91634fb767d67290 (patch) | |
tree | 22b613a3da8d4bf663eec5e155af01b87fdf9094 /arch/arm/nwfpe | |
parent | 1e25e41c4f5474e14452094492dbc169b800e4c8 (diff) |
Merge with Linux 2.3.23. The new bootmem stuff has broken various
platforms. At this time I've only verified that IP22 support compiles
and IP27 actually works.
Diffstat (limited to 'arch/arm/nwfpe')
-rw-r--r-- | arch/arm/nwfpe/ChangeLog | 46 | ||||
-rw-r--r-- | arch/arm/nwfpe/Makefile | 7 | ||||
-rw-r--r-- | arch/arm/nwfpe/double_cpdo.c | 65 | ||||
-rw-r--r-- | arch/arm/nwfpe/entry.S | 17 | ||||
-rw-r--r-- | arch/arm/nwfpe/entry26.S | 2 | ||||
-rw-r--r-- | arch/arm/nwfpe/extended_cpdo.c | 67 | ||||
-rw-r--r-- | arch/arm/nwfpe/fpa11.c | 16 | ||||
-rw-r--r-- | arch/arm/nwfpe/fpa11.h | 20 | ||||
-rw-r--r-- | arch/arm/nwfpe/fpa11.inl | 2 | ||||
-rw-r--r-- | arch/arm/nwfpe/fpa11_cpdo.c | 35 | ||||
-rw-r--r-- | arch/arm/nwfpe/fpa11_cpdt.c | 94 | ||||
-rw-r--r-- | arch/arm/nwfpe/fpa11_cprt.c | 85 | ||||
-rw-r--r-- | arch/arm/nwfpe/fpmodule.c | 81 | ||||
-rw-r--r-- | arch/arm/nwfpe/fpmodule.inl | 78 | ||||
-rw-r--r-- | arch/arm/nwfpe/fpopcode.c | 1 | ||||
-rw-r--r-- | arch/arm/nwfpe/single_cpdo.c | 60 |
16 files changed, 346 insertions, 330 deletions
diff --git a/arch/arm/nwfpe/ChangeLog b/arch/arm/nwfpe/ChangeLog index e160d36c3..8d76e09ba 100644 --- a/arch/arm/nwfpe/ChangeLog +++ b/arch/arm/nwfpe/ChangeLog @@ -1,10 +1,50 @@ -1998-11-23 Scott Bambrough <scottb@corelcomputer.com> +1999-08-19 Scott Bambrough <scottb@netwinder.org> + + * fpmodule.c - Changed version number to 0.95 + * fpa11.h - modified FPA11, FPREG structures + * fpa11.c - Changes due to FPA11, FPREG structure alterations. + * fpa11_cpdo.c - Changes due to FPA11, FPREG structure alterations. + * fpa11_cpdt.c - Changes due to FPA11, FPREG structure alterations. + * fpa11_cprt.c - Changes due to FPA11, FPREG structure alterations. + * single_cpdo.c - Changes due to FPA11, FPREG structure alterations. + * double_cpdo.c - Changes due to FPA11, FPREG structure alterations. + * extended_cpdo.c - Changes due to FPA11, FPREG structure alterations. + + * I discovered several bugs. First and worst is that the kernel + passes in a pointer to the FPE's state area. This is defined + as a struct user_fp (see user.h). This pointer was cast to a + FPA11*. Unfortunately FPA11 and user_fp are of different sizes; + user_fp is smaller. This meant that the FPE scribbled on things + below its area, which is bad, as the area is in the thread_struct + embedded in the process task structure. Thus we were scribbling + over one of the most important structures in the entire OS. + + * user_fp and FPA11 have now been harmonized. Most of the changes + in the above code were dereferencing problems due to moving the + register type out of FPREG, and getting rid of the union variable + fpvalue. + + * Second I noticed resetFPA11 was not always being called for a + task. This should happen on the first floating point exception + that occurs. It is controlled by init_flag in FPA11. The + comment in the code beside init_flag state the kernel guarantees + this to be zero. Not so. I found that the kernel recycles task + structures, and that recycled ones may not have init_flag zeroed. + I couldn't even find anything that guarantees it is zeroed when + when the task structure is initially allocated. In any case + I now initialize the entire FPE state in the thread structure to + zero when allocated and recycled. See alloc_task_struct() and + flush_thread() in arch/arm/process.c. The change to + alloc_task_struct() may not be necessary, but I left it in for + completeness (better safe than sorry). + +1998-11-23 Scott Bambrough <scottb@netwinder.org> * README.FPE - fix typo in description of lfm/sfm instructions * NOTES - Added file to describe known bugs/problems * fpmodule.c - Changed version number to 0.94 -1998-11-20 Scott Bambrough <scottb@corelcomputer.com> +1998-11-20 Scott Bambrough <scottb@netwinder.org> * README.FPE - fix description of URD, NRM instructions * TODO - remove URD, NRM instructions from TODO list @@ -12,7 +52,7 @@ * double_cpdo.c - implement URD, NRM * extended_cpdo.c - implement URD, NRM -1998-11-19 Scott Bambrough <scottb@corelcomputer.com> +1998-11-19 Scott Bambrough <scottb@netwinder.org> * ChangeLog - Added this file to track changes made. * fpa11.c - added code to initialize register types to typeNone diff --git a/arch/arm/nwfpe/Makefile b/arch/arm/nwfpe/Makefile index 5db79c6d4..a14371e5d 100644 --- a/arch/arm/nwfpe/Makefile +++ b/arch/arm/nwfpe/Makefile @@ -14,16 +14,15 @@ else NWFPE_OBJS += entry.o endif -L_TARGET := math-emu.a - ifeq ($(CONFIG_NWFPE),y) -L_OBJS = $(NWFPE_OBJS) +O_TARGET := math-emu.o +O_OBJS = $(NWFPE_OBJS) else ifeq ($(CONFIG_NWFPE),m) M_OBJS = nwfpe.o MI_OBJS = $(NWFPE_OBJS) endif -endif +endif include $(TOPDIR)/Rules.make diff --git a/arch/arm/nwfpe/double_cpdo.c b/arch/arm/nwfpe/double_cpdo.c index 3db9e7066..0415f31e0 100644 --- a/arch/arm/nwfpe/double_cpdo.c +++ b/arch/arm/nwfpe/double_cpdo.c @@ -19,7 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" #include "softfloat.h" #include "fpopcode.h" #include "fpa11.h" @@ -54,14 +53,14 @@ unsigned int DoubleCPDO(const unsigned int opcode) } else { - switch (fpa11->fpreg[Fm].fType) + switch (fpa11->fType[Fm]) { case typeSingle: - rFm = float32_to_float64(fpa11->fpreg[Fm].fValue.fSingle); + rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle); break; case typeDouble: - rFm = fpa11->fpreg[Fm].fValue.fDouble; + rFm = fpa11->fpreg[Fm].fDouble; break; case typeExtended: @@ -80,14 +79,14 @@ unsigned int DoubleCPDO(const unsigned int opcode) if (!MONADIC_INSTRUCTION(opcode)) { Fn = getFn(opcode); - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: - rFn = float32_to_float64(fpa11->fpreg[Fn].fValue.fSingle); + rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle); break; case typeDouble: - rFn = fpa11->fpreg[Fn].fValue.fDouble; + rFn = fpa11->fpreg[Fn].fDouble; break; default: return 0; @@ -100,62 +99,62 @@ unsigned int DoubleCPDO(const unsigned int opcode) { /* dyadic opcodes */ case ADF_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_add(rFn,rFm); + fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm); break; case MUF_CODE: case FML_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_mul(rFn,rFm); + fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm); break; - case SUF_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_sub(rFn,rFm); + case SUF_CODE: + fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm); break; case RSF_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_sub(rFm,rFn); + fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn); break; case DVF_CODE: case FDV_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_div(rFn,rFm); + fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm); break; case RDF_CODE: case FRD_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_div(rFm,rFn); + fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn); break; #if 0 case POW_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_pow(rFn,rFm); + fpa11->fpreg[Fd].fDouble = float64_pow(rFn,rFm); break; case RPW_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_pow(rFm,rFn); + fpa11->fpreg[Fd].fDouble = float64_pow(rFm,rFn); break; #endif case RMF_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_rem(rFn,rFm); + fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm); break; #if 0 case POL_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_pol(rFn,rFm); + fpa11->fpreg[Fd].fDouble = float64_pol(rFn,rFm); break; #endif /* monadic opcodes */ case MVF_CODE: - fpa11->fpreg[Fd].fValue.fDouble = rFm; + fpa11->fpreg[Fd].fDouble = rFm; break; case MNF_CODE: { unsigned int *p = (unsigned int*)&rFm; p[1] ^= 0x80000000; - fpa11->fpreg[Fd].fValue.fDouble = rFm; + fpa11->fpreg[Fd].fDouble = rFm; } break; @@ -163,55 +162,55 @@ unsigned int DoubleCPDO(const unsigned int opcode) { unsigned int *p = (unsigned int*)&rFm; p[1] &= 0x7fffffff; - fpa11->fpreg[Fd].fValue.fDouble = rFm; + fpa11->fpreg[Fd].fDouble = rFm; } break; case RND_CODE: case URD_CODE: - fpa11->fpreg[Fd].fValue.fDouble = + fpa11->fpreg[Fd].fDouble = int32_to_float64(float64_to_int32(rFm)); break; case SQT_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_sqrt(rFm); + fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm); break; #if 0 case LOG_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_log(rFm); + fpa11->fpreg[Fd].fDouble = float64_log(rFm); break; case LGN_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_ln(rFm); + fpa11->fpreg[Fd].fDouble = float64_ln(rFm); break; case EXP_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_exp(rFm); + fpa11->fpreg[Fd].fDouble = float64_exp(rFm); break; case SIN_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_sin(rFm); + fpa11->fpreg[Fd].fDouble = float64_sin(rFm); break; case COS_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_cos(rFm); + fpa11->fpreg[Fd].fDouble = float64_cos(rFm); break; case TAN_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_tan(rFm); + fpa11->fpreg[Fd].fDouble = float64_tan(rFm); break; case ASN_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_arcsin(rFm); + fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm); break; case ACS_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_arccos(rFm); + fpa11->fpreg[Fd].fDouble = float64_arccos(rFm); break; case ATN_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_arctan(rFm); + fpa11->fpreg[Fd].fDouble = float64_arctan(rFm); break; #endif @@ -224,7 +223,7 @@ unsigned int DoubleCPDO(const unsigned int opcode) } } - if (0 != nRc) fpa11->fpreg[Fd].fType = typeDouble; + if (0 != nRc) fpa11->fType[Fd] = typeDouble; return nRc; } diff --git a/arch/arm/nwfpe/entry.S b/arch/arm/nwfpe/entry.S index 6f0077fbe..f6a9a9799 100644 --- a/arch/arm/nwfpe/entry.S +++ b/arch/arm/nwfpe/entry.S @@ -3,7 +3,7 @@ (c) Corel Computer Corporation, 1998 (c) Philip Blundell 1998-1999 - Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com> + Direct questions, comments to Scott Bambrough <scottb@netwinder.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -85,14 +85,15 @@ nwfpe_enter: mov r10, lr @ save the failure-return addresses ldr r5, [r4, #60] @ get contents of PC; - ldr r0, [r5, #-4] @ get actual instruction into r0 + sub r8, r5, #4 +.Lx2: ldrt r0, [r8], #0 @ get actual instruction into r0 emulate: bl EmulateAll @ emulate the instruction cmp r0, #0 @ was emulation successful moveq pc, r10 @ no, return failure next: -__x1: ldrt r6, [r5], #4 @ get the next instruction and +.Lx1: ldrt r6, [r5], #4 @ get the next instruction and @ increment PC and r2, r6, #0x0F000000 @ test for FP insns @@ -114,13 +115,15 @@ __x1: ldrt r6, [r5], #4 @ get the next instruction and mov r0, r6 @ prepare for EmulateAll() b emulate @ if r0 != 0, goto EmulateAll - @ We need to be prepared for the instruction at __x1 to fault. - @ Emit the appropriate exception gunk to fix things up. + @ We need to be prepared for the instruction at .Lx1 or .Lx2 + @ to fault. .section .fixup,"ax" .align -__f1: mov pc, r9 +.Lfix: mov pc, r9 .previous + .section __ex_table,"a" .align 3 - .long __x1, __f1 + .long .Lx2, .Lfix + .long .Lx1, .Lfix .previous diff --git a/arch/arm/nwfpe/entry26.S b/arch/arm/nwfpe/entry26.S index 6b1ec3354..5108ce63d 100644 --- a/arch/arm/nwfpe/entry26.S +++ b/arch/arm/nwfpe/entry26.S @@ -3,7 +3,7 @@ (c) Corel Computer Corporation, 1998 (c) Philip Blundell 1998-1999 - Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com> + Direct questions, comments to Scott Bambrough <scottb@netwinder.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/arch/arm/nwfpe/extended_cpdo.c b/arch/arm/nwfpe/extended_cpdo.c index 4f55333fc..810f57102 100644 --- a/arch/arm/nwfpe/extended_cpdo.c +++ b/arch/arm/nwfpe/extended_cpdo.c @@ -19,7 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" #include "softfloat.h" #include "fpopcode.h" #include "fpa11.h" @@ -52,18 +51,18 @@ unsigned int ExtendedCPDO(const unsigned int opcode) } else { - switch (fpa11->fpreg[Fm].fType) + switch (fpa11->fType[Fm]) { case typeSingle: - rFm = float32_to_floatx80(fpa11->fpreg[Fm].fValue.fSingle); + rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); break; case typeDouble: - rFm = float64_to_floatx80(fpa11->fpreg[Fm].fValue.fDouble); + rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); break; case typeExtended: - rFm = fpa11->fpreg[Fm].fValue.fExtended; + rFm = fpa11->fpreg[Fm].fExtended; break; default: return 0; @@ -73,18 +72,18 @@ unsigned int ExtendedCPDO(const unsigned int opcode) if (!MONADIC_INSTRUCTION(opcode)) { Fn = getFn(opcode); - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: - rFn = float32_to_floatx80(fpa11->fpreg[Fn].fValue.fSingle); + rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); break; case typeDouble: - rFn = float64_to_floatx80(fpa11->fpreg[Fn].fValue.fDouble); + rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); break; case typeExtended: - rFn = fpa11->fpreg[Fn].fValue.fExtended; + rFn = fpa11->fpreg[Fn].fExtended; break; default: return 0; @@ -96,112 +95,112 @@ unsigned int ExtendedCPDO(const unsigned int opcode) { /* dyadic opcodes */ case ADF_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_add(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_add(rFn,rFm); break; case MUF_CODE: case FML_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_mul(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_mul(rFn,rFm); break; case SUF_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_sub(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_sub(rFn,rFm); break; case RSF_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_sub(rFm,rFn); + fpa11->fpreg[Fd].fExtended = floatx80_sub(rFm,rFn); break; case DVF_CODE: case FDV_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_div(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_div(rFn,rFm); break; case RDF_CODE: case FRD_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_div(rFm,rFn); + fpa11->fpreg[Fd].fExtended = floatx80_div(rFm,rFn); break; #if 0 case POW_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_pow(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_pow(rFn,rFm); break; case RPW_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_pow(rFm,rFn); + fpa11->fpreg[Fd].fExtended = floatx80_pow(rFm,rFn); break; #endif case RMF_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_rem(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_rem(rFn,rFm); break; #if 0 case POL_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_pol(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_pol(rFn,rFm); break; #endif /* monadic opcodes */ case MVF_CODE: - fpa11->fpreg[Fd].fValue.fExtended = rFm; + fpa11->fpreg[Fd].fExtended = rFm; break; case MNF_CODE: rFm.high ^= 0x8000; - fpa11->fpreg[Fd].fValue.fExtended = rFm; + fpa11->fpreg[Fd].fExtended = rFm; break; case ABS_CODE: rFm.high &= 0x7fff; - fpa11->fpreg[Fd].fValue.fExtended = rFm; + fpa11->fpreg[Fd].fExtended = rFm; break; case RND_CODE: case URD_CODE: - fpa11->fpreg[Fd].fValue.fExtended = + fpa11->fpreg[Fd].fExtended = int32_to_floatx80(floatx80_to_int32(rFm)); break; case SQT_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_sqrt(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_sqrt(rFm); break; #if 0 case LOG_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_log(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_log(rFm); break; case LGN_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_ln(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_ln(rFm); break; case EXP_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_exp(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_exp(rFm); break; case SIN_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_sin(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_sin(rFm); break; case COS_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_cos(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_cos(rFm); break; case TAN_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_tan(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_tan(rFm); break; case ASN_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_arcsin(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_arcsin(rFm); break; case ACS_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_arccos(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_arccos(rFm); break; case ATN_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_arctan(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_arctan(rFm); break; #endif @@ -214,7 +213,7 @@ unsigned int ExtendedCPDO(const unsigned int opcode) } } - if (0 != nRc) fpa11->fpreg[Fd].fType = typeExtended; + if (0 != nRc) fpa11->fType[Fd] = typeExtended; return nRc; } diff --git a/arch/arm/nwfpe/fpa11.c b/arch/arm/nwfpe/fpa11.c index 3e11d5ddd..dfc4663b7 100644 --- a/arch/arm/nwfpe/fpa11.c +++ b/arch/arm/nwfpe/fpa11.c @@ -19,9 +19,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" +#include <asm/system.h> + #include "fpa11.h" -#include "milieu.h" #include "fpopcode.h" #include "fpmodule.h" @@ -39,17 +39,18 @@ FPA11 *fpa11; void resetFPA11(void) { int i; - /* initialize the registers */ + + /* initialize the register type array */ for (i=0;i<=7;i++) { - fpa11->fpreg[i].fType = typeNone; + fpa11->fType[i] = typeNone; } /* FPSR: set system id to FP_EMULATOR, clear all other bits */ fpa11->fpsr = FP_EMULATOR; /* FPCR: set SB, AB and DA bits, clear all others */ -#if MAINTAIN_FPCR +#if MAINTAIN_FPCR fpa11->fpcr = MASK_RESET; #endif } @@ -128,6 +129,9 @@ void SetRoundingPrecision(const unsigned int opcode) unsigned int EmulateAll(unsigned int opcode) { unsigned int nRc = 0; + unsigned long flags; + + save_flags(flags); sti(); if (fpa11->initflag == 0) /* good place for __builtin_expect */ { @@ -162,6 +166,8 @@ unsigned int EmulateAll(unsigned int opcode) nRc = 0; } + restore_flags(flags); + return(nRc); } diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h index f7040dbb6..c55ac6f9b 100644 --- a/arch/arm/nwfpe/fpa11.h +++ b/arch/arm/nwfpe/fpa11.h @@ -31,25 +31,25 @@ #define typeDouble 0x02 #define typeExtended 0x03 -typedef struct tagFPREG { - unsigned int fType; - union { - float32 fSingle; - float64 fDouble; - floatx80 fExtended; - } fValue; +typedef union tagFPREG { + float32 fSingle; + float64 fDouble; + floatx80 fExtended; } FPREG; /* FPA11 device model */ typedef struct tagFPA11 { + FPREG fpreg[8]; /* 8 floating point registers */ + FPSR fpsr; /* floating point status register */ + FPCR fpcr; /* floating point control register */ + unsigned char fType[8]; /* type of floating point value held in + floating point registers. One of none + single, double or extended. */ int initflag; /* this is special. The kernel guarantees to set it to 0 when a thread is launched, so we can use it to detect whether this instance of the emulator needs to be initialised. */ - FPREG fpreg[8]; /* 8 floating point registers */ - FPSR fpsr; /* floating point status register */ - FPCR fpcr; /* floating point control register */ } FPA11; extern void resetFPA11(void); diff --git a/arch/arm/nwfpe/fpa11.inl b/arch/arm/nwfpe/fpa11.inl index 321ab7c1c..bc86317a2 100644 --- a/arch/arm/nwfpe/fpa11.inl +++ b/arch/arm/nwfpe/fpa11.inl @@ -2,7 +2,7 @@ NetWinder Floating Point Emulator (c) Corel Computer Corporation, 1998 - Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com> + Direct questions, comments to Scott Bambrough <scottb@netwinder.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/arch/arm/nwfpe/fpa11_cpdo.c b/arch/arm/nwfpe/fpa11_cpdo.c index 19dd08802..fd39a59f7 100644 --- a/arch/arm/nwfpe/fpa11_cpdo.c +++ b/arch/arm/nwfpe/fpa11_cpdo.c @@ -19,7 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" #include "fpa11.h" #include "fpopcode.h" @@ -48,14 +47,14 @@ unsigned int EmulateCPDO(const unsigned int opcode) if (MONADIC_INSTRUCTION(opcode)) nType = nDest; else - nType = fpa11->fpreg[getFn(opcode)].fType; + nType = fpa11->fType[getFn(opcode)]; if (!CONSTANT_FM(opcode)) { register unsigned int Fm = getFm(opcode); - if (nType < fpa11->fpreg[Fm].fType) + if (nType < fpa11->fType[Fm]) { - nType = fpa11->fpreg[Fm].fType; + nType = fpa11->fType[Fm]; } } @@ -71,7 +70,7 @@ unsigned int EmulateCPDO(const unsigned int opcode) destination register is the correct size. If not force it to be. */ Fd = getFd(opcode); - nType = fpa11->fpreg[Fd].fType; + nType = fpa11->fType[Fd]; if ((0 != nRc) && (nDest != nType)) { switch (nDest) @@ -79,38 +78,38 @@ unsigned int EmulateCPDO(const unsigned int opcode) case typeSingle: { if (typeDouble == nType) - fpa11->fpreg[Fd].fValue.fSingle = - float64_to_float32(fpa11->fpreg[Fd].fValue.fDouble); + fpa11->fpreg[Fd].fSingle = + float64_to_float32(fpa11->fpreg[Fd].fDouble); else - fpa11->fpreg[Fd].fValue.fSingle = - floatx80_to_float32(fpa11->fpreg[Fd].fValue.fExtended); + fpa11->fpreg[Fd].fSingle = + floatx80_to_float32(fpa11->fpreg[Fd].fExtended); } break; case typeDouble: { if (typeSingle == nType) - fpa11->fpreg[Fd].fValue.fDouble = - float32_to_float64(fpa11->fpreg[Fd].fValue.fSingle); + fpa11->fpreg[Fd].fDouble = + float32_to_float64(fpa11->fpreg[Fd].fSingle); else - fpa11->fpreg[Fd].fValue.fDouble = - floatx80_to_float64(fpa11->fpreg[Fd].fValue.fExtended); + fpa11->fpreg[Fd].fDouble = + floatx80_to_float64(fpa11->fpreg[Fd].fExtended); } break; case typeExtended: { if (typeSingle == nType) - fpa11->fpreg[Fd].fValue.fExtended = - float32_to_floatx80(fpa11->fpreg[Fd].fValue.fSingle); + fpa11->fpreg[Fd].fExtended = + float32_to_floatx80(fpa11->fpreg[Fd].fSingle); else - fpa11->fpreg[Fd].fValue.fExtended = - float64_to_floatx80(fpa11->fpreg[Fd].fValue.fDouble); + fpa11->fpreg[Fd].fExtended = + float64_to_floatx80(fpa11->fpreg[Fd].fDouble); } break; } - fpa11->fpreg[Fd].fType = nDest; + fpa11->fType[Fd] = nDest; } return nRc; diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c index e32bf3421..0bad18769 100644 --- a/arch/arm/nwfpe/fpa11_cpdt.c +++ b/arch/arm/nwfpe/fpa11_cpdt.c @@ -20,7 +20,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" #include "softfloat.h" #include "fpopcode.h" #include "fpa11.h" @@ -32,16 +31,16 @@ extern __inline__ void loadSingle(const unsigned int Fn,const unsigned int *pMem) { - fpa11->fpreg[Fn].fType = typeSingle; - get_user(fpa11->fpreg[Fn].fValue.fSingle, pMem); + fpa11->fType[Fn] = typeSingle; + get_user(fpa11->fpreg[Fn].fSingle, pMem); } extern __inline__ void loadDouble(const unsigned int Fn,const unsigned int *pMem) { unsigned int *p; - p = (unsigned int*)&fpa11->fpreg[Fn].fValue.fDouble; - fpa11->fpreg[Fn].fType = typeDouble; + p = (unsigned int*)&fpa11->fpreg[Fn].fDouble; + fpa11->fType[Fn] = typeDouble; get_user(p[0], &pMem[1]); get_user(p[1], &pMem[0]); /* sign & exponent */ } @@ -50,8 +49,8 @@ extern __inline__ void loadExtended(const unsigned int Fn,const unsigned int *pMem) { unsigned int *p; - p = (unsigned int*)&fpa11->fpreg[Fn].fValue.fExtended; - fpa11->fpreg[Fn].fType = typeExtended; + p = (unsigned int*)&fpa11->fpreg[Fn].fExtended; + fpa11->fType[Fn] = typeExtended; get_user(p[0], &pMem[0]); /* sign & exponent */ get_user(p[1], &pMem[2]); /* ls bits */ get_user(p[2], &pMem[1]); /* ms bits */ @@ -63,11 +62,11 @@ void loadMultiple(const unsigned int Fn,const unsigned int *pMem) register unsigned int *p; unsigned long x; - p = (unsigned int*)&(fpa11->fpreg[Fn].fValue); + p = (unsigned int*)&(fpa11->fpreg[Fn]); get_user(x, &pMem[0]); - fpa11->fpreg[Fn].fType = (x >> 14) & 0x00000003; + fpa11->fType[Fn] = (x >> 14) & 0x00000003; - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: case typeDouble: @@ -94,17 +93,17 @@ void storeSingle(const unsigned int Fn,unsigned int *pMem) float32 val; register unsigned int *p = (unsigned int*)&val; - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeDouble: - val = float64_to_float32(fpa11->fpreg[Fn].fValue.fDouble); + val = float64_to_float32(fpa11->fpreg[Fn].fDouble); break; case typeExtended: - val = floatx80_to_float32(fpa11->fpreg[Fn].fValue.fExtended); + val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended); break; - default: val = fpa11->fpreg[Fn].fValue.fSingle; + default: val = fpa11->fpreg[Fn].fSingle; } put_user(p[0], pMem); @@ -116,17 +115,17 @@ void storeDouble(const unsigned int Fn,unsigned int *pMem) float64 val; register unsigned int *p = (unsigned int*)&val; - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: - val = float32_to_float64(fpa11->fpreg[Fn].fValue.fSingle); + val = float32_to_float64(fpa11->fpreg[Fn].fSingle); break; case typeExtended: - val = floatx80_to_float64(fpa11->fpreg[Fn].fValue.fExtended); + val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended); break; - default: val = fpa11->fpreg[Fn].fValue.fDouble; + default: val = fpa11->fpreg[Fn].fDouble; } put_user(p[1], &pMem[0]); /* msw */ put_user(p[0], &pMem[1]); /* lsw */ @@ -138,17 +137,17 @@ void storeExtended(const unsigned int Fn,unsigned int *pMem) floatx80 val; register unsigned int *p = (unsigned int*)&val; - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: - val = float32_to_floatx80(fpa11->fpreg[Fn].fValue.fSingle); + val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); break; case typeDouble: - val = float64_to_floatx80(fpa11->fpreg[Fn].fValue.fDouble); + val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); break; - default: val = fpa11->fpreg[Fn].fValue.fExtended; + default: val = fpa11->fpreg[Fn].fExtended; } put_user(p[0], &pMem[0]); /* sign & exp */ @@ -161,8 +160,8 @@ void storeMultiple(const unsigned int Fn,unsigned int *pMem) { register unsigned int nType, *p; - p = (unsigned int*)&(fpa11->fpreg[Fn].fValue); - nType = fpa11->fpreg[Fn].fType; + p = (unsigned int*)&(fpa11->fpreg[Fn]); + nType = fpa11->fType[Fn]; switch (nType) { @@ -187,12 +186,17 @@ void storeMultiple(const unsigned int Fn,unsigned int *pMem) unsigned int PerformLDF(const unsigned int opcode) { - unsigned int *pBase, *pAddress, *pFinal, nRc = 1; - + unsigned int *pBase, *pAddress, *pFinal, nRc = 1, + write_back = WRITE_BACK(opcode); + //fp_printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) pBase += 2; + if (REG_PC == getRn(opcode)) + { + pBase += 2; + write_back = 0; + } pFinal = pBase; if (BIT_UP_SET(opcode)) @@ -210,19 +214,24 @@ unsigned int PerformLDF(const unsigned int opcode) default: nRc = 0; } - if (WRITE_BACK(opcode)) writeRegister(getRn(opcode),(unsigned int)pFinal); + if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); return nRc; } unsigned int PerformSTF(const unsigned int opcode) { - unsigned int *pBase, *pAddress, *pFinal, nRc = 1; + unsigned int *pBase, *pAddress, *pFinal, nRc = 1, + write_back = WRITE_BACK(opcode); //fp_printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); SetRoundingMode(ROUND_TO_NEAREST); pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) pBase += 2; + if (REG_PC == getRn(opcode)) + { + pBase += 2; + write_back = 0; + } pFinal = pBase; if (BIT_UP_SET(opcode)) @@ -240,15 +249,21 @@ unsigned int PerformSTF(const unsigned int opcode) default: nRc = 0; } - if (WRITE_BACK(opcode)) writeRegister(getRn(opcode),(unsigned int)pFinal); + if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); return nRc; } unsigned int PerformLFM(const unsigned int opcode) { - unsigned int i, Fd, *pBase, *pAddress, *pFinal; + unsigned int i, Fd, *pBase, *pAddress, *pFinal, + write_back = WRITE_BACK(opcode); + pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) pBase += 2; + if (REG_PC == getRn(opcode)) + { + pBase += 2; + write_back = 0; + } pFinal = pBase; if (BIT_UP_SET(opcode)) @@ -266,16 +281,21 @@ unsigned int PerformLFM(const unsigned int opcode) if (Fd == 8) Fd = 0; } - if (WRITE_BACK(opcode)) writeRegister(getRn(opcode),(unsigned int)pFinal); + if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); return 1; } unsigned int PerformSFM(const unsigned int opcode) { - unsigned int i, Fd, *pBase, *pAddress, *pFinal; + unsigned int i, Fd, *pBase, *pAddress, *pFinal, + write_back = WRITE_BACK(opcode); pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) pBase += 2; + if (REG_PC == getRn(opcode)) + { + pBase += 2; + write_back = 0; + } pFinal = pBase; if (BIT_UP_SET(opcode)) @@ -293,7 +313,7 @@ unsigned int PerformSFM(const unsigned int opcode) if (Fd == 8) Fd = 0; } - if (WRITE_BACK(opcode)) writeRegister(getRn(opcode),(unsigned int)pFinal); + if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); return 1; } diff --git a/arch/arm/nwfpe/fpa11_cprt.c b/arch/arm/nwfpe/fpa11_cprt.c index cbfde092e..d479ee932 100644 --- a/arch/arm/nwfpe/fpa11_cprt.c +++ b/arch/arm/nwfpe/fpa11_cprt.c @@ -20,7 +20,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" #include "milieu.h" #include "softfloat.h" #include "fpopcode.h" @@ -65,37 +64,10 @@ unsigned int EmulateCPRT(const unsigned int opcode) case WFS_CODE >> 20: writeFPSR(readRegister(getRd(opcode))); break; case RFS_CODE >> 20: writeRegister(getRd(opcode),readFPSR()); break; -#if 0 - /* ?? Not at all sure about the mode checks here. Linux never - calls the emulator from a non-USR fault but we always run in SVC - mode. Is there even any point trying to emulate the way FPA11 - behaves in this respect? - - No - and I quote: 'The FPCR may only be present in some - implementations: it is there to control the hardware in an - implementation-specific manner, ... The user mode of the - ARM is not permitted to use this register, and the WFC and - RFC instructions will trap if tried from user mode.' - Therefore, we do not provide the RFC and WFC instructions. - (rmk, 3/05/1999) - */ - case WFC_CODE >> 20: - { - int mode = 0; - __asm__ volatile ("mrs %0, cpsr; and %0, %0, #0x1f;" : : "g" (mode)); - nRc = (0x13 == mode) ? 1 : 0; /* in SVC processor mode? */ - if (nRc) writeFPCR(readRegister(getRd(opcode))); - } - break; - - case RFC_CODE >> 20: - { - int mode = 0; - __asm__ volatile ("mrs %0, cpsr; and %0, %0, #0x1f;" : : "g" (mode)); - nRc = (0x13 == mode) ? 1 : 0; /* in SVC processor mode? */ - if (nRc) writeRegister(getRd(opcode),readFPCR()); break; - } - break; +#if 0 /* We currently have no use for the FPCR, so there's no point + in emulating it. */ + case WFC_CODE >> 20: writeFPCR(readRegister(getRd(opcode))); + case RFC_CODE >> 20: writeRegister(getRd(opcode),readFPCR()); break; #endif default: nRc = 0; @@ -114,24 +86,24 @@ unsigned int PerformFLT(const unsigned int opcode) { case ROUND_SINGLE: { - fpa11->fpreg[getFn(opcode)].fType = typeSingle; - fpa11->fpreg[getFn(opcode)].fValue.fSingle = + fpa11->fType[getFn(opcode)] = typeSingle; + fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode))); } break; case ROUND_DOUBLE: { - fpa11->fpreg[getFn(opcode)].fType = typeDouble; - fpa11->fpreg[getFn(opcode)].fValue.fDouble = + fpa11->fType[getFn(opcode)] = typeDouble; + fpa11->fpreg[getFn(opcode)].fDouble = int32_to_float64(readRegister(getRd(opcode))); } break; case ROUND_EXTENDED: { - fpa11->fpreg[getFn(opcode)].fType = typeExtended; - fpa11->fpreg[getFn(opcode)].fValue.fExtended = + fpa11->fType[getFn(opcode)] = typeExtended; + fpa11->fpreg[getFn(opcode)].fExtended = int32_to_floatx80(readRegister(getRd(opcode))); } break; @@ -149,26 +121,26 @@ unsigned int PerformFIX(const unsigned int opcode) SetRoundingMode(opcode); - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: { writeRegister(getRd(opcode), - float32_to_int32(fpa11->fpreg[Fn].fValue.fSingle)); + float32_to_int32(fpa11->fpreg[Fn].fSingle)); } break; case typeDouble: { writeRegister(getRd(opcode), - float64_to_int32(fpa11->fpreg[Fn].fValue.fDouble)); + float64_to_int32(fpa11->fpreg[Fn].fDouble)); } break; case typeExtended: { writeRegister(getRd(opcode), - floatx80_to_int32(fpa11->fpreg[Fn].fValue.fExtended)); + floatx80_to_int32(fpa11->fpreg[Fn].fExtended)); } break; @@ -226,27 +198,27 @@ static unsigned int PerformComparison(const unsigned int opcode) ?? Might be some mileage in avoiding this conversion if possible. Eg, if both operands are 32-bit, detect this and do a 32-bit comparison (cheaper than an 80-bit one). */ - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: //fp_printk("single.\n"); - if (float32_is_nan(fpa11->fpreg[Fn].fValue.fSingle)) + if (float32_is_nan(fpa11->fpreg[Fn].fSingle)) goto unordered; - rFn = float32_to_floatx80(fpa11->fpreg[Fn].fValue.fSingle); + rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); break; case typeDouble: //fp_printk("double.\n"); - if (float64_is_nan(fpa11->fpreg[Fn].fValue.fDouble)) + if (float64_is_nan(fpa11->fpreg[Fn].fDouble)) goto unordered; - rFn = float64_to_floatx80(fpa11->fpreg[Fn].fValue.fDouble); + rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); break; case typeExtended: //fp_printk("extended.\n"); - if (floatx80_is_nan(fpa11->fpreg[Fn].fValue.fExtended)) + if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended)) goto unordered; - rFn = fpa11->fpreg[Fn].fValue.fExtended; + rFn = fpa11->fpreg[Fn].fExtended; break; default: return 0; @@ -262,27 +234,27 @@ static unsigned int PerformComparison(const unsigned int opcode) else { //fp_printk("Fm = r%d which contains a ",Fm); - switch (fpa11->fpreg[Fm].fType) + switch (fpa11->fType[Fm]) { case typeSingle: //fp_printk("single.\n"); - if (float32_is_nan(fpa11->fpreg[Fm].fValue.fSingle)) + if (float32_is_nan(fpa11->fpreg[Fm].fSingle)) goto unordered; - rFm = float32_to_floatx80(fpa11->fpreg[Fm].fValue.fSingle); + rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); break; case typeDouble: //fp_printk("double.\n"); - if (float64_is_nan(fpa11->fpreg[Fm].fValue.fDouble)) + if (float64_is_nan(fpa11->fpreg[Fm].fDouble)) goto unordered; - rFm = float64_to_floatx80(fpa11->fpreg[Fm].fValue.fDouble); + rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); break; case typeExtended: //fp_printk("extended.\n"); - if (floatx80_is_nan(fpa11->fpreg[Fm].fValue.fExtended)) + if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended)) goto unordered; - rFm = fpa11->fpreg[Fm].fValue.fExtended; + rFm = fpa11->fpreg[Fm].fExtended; break; default: return 0; @@ -303,6 +275,7 @@ static unsigned int PerformComparison(const unsigned int opcode) the data sheet, observation of how the Acorn emulator actually behaves (and how programs expect it to) and guesswork. */ flags |= CC_OVERFLOW; + flags &= ~(CC_ZERO | CC_NEGATIVE); if (BIT_AC & readFPSR()) flags |= CC_CARRY; diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c index de28e39f5..b9ca935eb 100644 --- a/arch/arm/nwfpe/fpmodule.c +++ b/arch/arm/nwfpe/fpmodule.c @@ -1,3 +1,4 @@ + /* NetWinder Floating Point Emulator (c) Rebel.com, 1998-1999 @@ -20,30 +21,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" - -#ifdef MODULE #include <linux/module.h> #include <linux/version.h> -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif +#include <linux/config.h> /* XXX */ #include <linux/types.h> #include <linux/kernel.h> #include <linux/signal.h> #include <linux/sched.h> -#include <linux/mm.h> #include <linux/init.h> -#include <linux/spinlock.h> - -#include <asm/system.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/atomic.h> -#include <asm/pgtable.h> /* XXX */ #include "softfloat.h" @@ -62,7 +49,7 @@ typedef struct task_struct* PTASK; int fp_printk(const char *,...); void fp_send_sig(unsigned long sig, PTASK p, int priv); #if LINUX_VERSION_CODE > 0x20115 -MODULE_AUTHOR("Scott Bambrough <scottb@netwinder.org>"); +MODULE_AUTHOR("Scott Bambrough <scottb@rebel.com>"); MODULE_DESCRIPTION("NWFPE floating point emulator"); #endif @@ -73,57 +60,51 @@ MODULE_DESCRIPTION("NWFPE floating point emulator"); #endif /* kernel function prototypes required */ -void C_SYMBOL_NAME(fp_setup)(void); +void fp_setup(void); /* external declarations for saved kernel symbols */ -extern unsigned int C_SYMBOL_NAME(kern_fp_enter); +extern void (*kern_fp_enter)(void); + +/* Original value of fp_enter from kernel before patched by fpe_init. */ +static void (*orig_fp_enter)(void); /* forward declarations */ extern void nwfpe_enter(void); -/* Original value of fp_enter from kernel before patched by fpe_init. */ -static unsigned int orig_fp_enter; - /* Address of user registers on the kernel stack. */ unsigned int *userRegisters; -void __init C_SYMBOL_NAME(fpe_version)(void) +void __init fpe_version(void) { static const char szTitle[] = "<4>NetWinder Floating Point Emulator "; - static const char szVersion[] = "V0.94.1 "; + static const char szVersion[] = "V0.95 "; static const char szCopyright[] = "(c) 1998-1999 Rebel.com\n"; - C_SYMBOL_NAME(fp_printk)(szTitle); - C_SYMBOL_NAME(fp_printk)(szVersion); - C_SYMBOL_NAME(fp_printk)(szCopyright); + fp_printk(szTitle); + fp_printk(szVersion); + fp_printk(szCopyright); } int __init fpe_init(void) { - /* Display title, version and copyright information. */ - C_SYMBOL_NAME(fpe_version)(); - - /* Save pointer to the old FP handler and then patch ourselves in */ - orig_fp_enter = C_SYMBOL_NAME(kern_fp_enter); - C_SYMBOL_NAME(kern_fp_enter) = (unsigned int)C_SYMBOL_NAME(nwfpe_enter); + if (sizeof(FPA11) > sizeof(union fp_state)) + printk(KERN_ERR "nwfpe: bad structure size\n"); + else { + /* Display title, version and copyright information. */ + fpe_version(); + + /* Save pointer to the old FP handler and then patch ourselves in */ + orig_fp_enter = kern_fp_enter; + kern_fp_enter = nwfpe_enter; + } return 0; } -#ifdef MODULE -int init_module(void) -{ - return(fpe_init()); -} - -void cleanup_module(void) +void __exit fpe_exit(void) { /* Restore the values we saved earlier. */ - C_SYMBOL_NAME(kern_fp_enter) = orig_fp_enter; + kern_fp_enter = orig_fp_enter; } -#endif - -#define _ARM_pc 60 -#define _ARM_cpsr 64 /* ScottB: November 4, 1998 @@ -135,7 +116,7 @@ fpmodule.c to integrate with the NetBSD kernel (I hope!). [1/1/99: Not quite true any more unfortunately. There is Linux-specific code to access data in user space in some other source files at the -moment. --philb] +moment (grep for get_user / put_user calls). --philb] float_exception_flags is a global variable in SoftFloat. @@ -147,8 +128,9 @@ cumulative exceptions flag byte are set and we return. void float_raise(signed char flags) { -#if 0 - printk(KERN_DEBUG "NWFPE: exception %08x at %08x from %08x\n", flags, +#ifdef CONFIG_DEBUG_USER + printk(KERN_DEBUG "NWFPE: %s[%d] takes exception %08x at %p from %08x\n", + current->comm, current->pid, flags, __builtin_return_address(0), userRegisters[15]); #endif @@ -156,7 +138,7 @@ void float_raise(signed char flags) if (readFPSR() & (flags << 16)) { /* raise exception */ - C_SYMBOL_NAME(fp_send_sig)(SIGFPE,C_SYMBOL_NAME(current),1); + fp_send_sig(SIGFPE, current, 1); } else { @@ -164,3 +146,6 @@ void float_raise(signed char flags) writeFPSR(flags); } } + +module_init(fpe_init); +module_exit(fpe_exit); diff --git a/arch/arm/nwfpe/fpmodule.inl b/arch/arm/nwfpe/fpmodule.inl index c76b7fd55..127b24218 100644 --- a/arch/arm/nwfpe/fpmodule.inl +++ b/arch/arm/nwfpe/fpmodule.inl @@ -1,23 +1,23 @@ /* NetWinder Floating Point Emulator - (c) Corel Computer Corporation, 1998 + (c) Rebel.com, 1998-1999 - Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com> + Direct questions, comments to Scott Bambrough <scottb@netwinder.org> - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ /* Address of user registers on the kernel stack. */ extern unsigned int *userRegisters; @@ -25,64 +25,60 @@ extern unsigned int *userRegisters; extern __inline__ unsigned int readRegister(const unsigned int nReg) { - /* Note: The CPU thinks it has dealt with the current instruction. As - a result the program counter has been advanced to the next - instruction, and points 4 bytes beyond the actual instruction - that caused the invalid instruction trap to occur. We adjust - for this in this routine. LDF/STF instructions with Rn = PC - depend on the PC being correct, as they use PC+8 in their - address calculations. */ - unsigned int val = userRegisters[nReg]; - - if (REG_PC == nReg) - val -= 4; - - return val; + /* Note: The CPU thinks it has dealt with the current instruction. As + a result the program counter has been advanced to the next + instruction, and points 4 bytes beyond the actual instruction + that caused the invalid instruction trap to occur. We adjust + for this in this routine. LDF/STF instructions with Rn = PC + depend on the PC being correct, as they use PC+8 in their + address calculations. */ + unsigned int val = userRegisters[nReg]; + if (REG_PC == nReg) val -= 4; + return val; } extern __inline__ void writeRegister(const unsigned int nReg, const unsigned int val) { - userRegisters[nReg] = val; + userRegisters[nReg] = val; } extern __inline__ unsigned int readCPSR(void) { - return (readRegister(REG_CPSR)); + return(readRegister(REG_CPSR)); } extern __inline__ void writeCPSR(const unsigned int val) { - writeRegister(REG_CPSR, val); + writeRegister(REG_CPSR,val); } extern __inline__ unsigned int readConditionCodes(void) { #ifdef __FPEM_TEST__ - return (0); + return(0); #else - return (readCPSR() & CC_MASK); + return(readCPSR() & CC_MASK); #endif } extern __inline__ void writeConditionCodes(const unsigned int val) { - unsigned int rval; - - /* - * Operate directly on userRegisters since - * the CPSR may be the PC register itself. - */ - rval = userRegisters[REG_CPSR] & ~CC_MASK; - userRegisters[REG_CPSR] = rval | (val & CC_MASK); + unsigned int rval; + /* + * Operate directly on userRegisters since + * the CPSR may be the PC register itself. + */ + rval = userRegisters[REG_CPSR] & ~CC_MASK; + userRegisters[REG_CPSR] = rval | (val & CC_MASK); } extern __inline__ unsigned int readMemoryInt(unsigned int *pMem) { - return *pMem; + return *pMem; } diff --git a/arch/arm/nwfpe/fpopcode.c b/arch/arm/nwfpe/fpopcode.c index 0d12f7269..4b01b43c6 100644 --- a/arch/arm/nwfpe/fpopcode.c +++ b/arch/arm/nwfpe/fpopcode.c @@ -19,7 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" #include "softfloat.h" #include "fpopcode.h" #include "fpsr.h" diff --git a/arch/arm/nwfpe/single_cpdo.c b/arch/arm/nwfpe/single_cpdo.c index a2a9f6f81..77bb73515 100644 --- a/arch/arm/nwfpe/single_cpdo.c +++ b/arch/arm/nwfpe/single_cpdo.c @@ -19,8 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" -#include "milieu.h" #include "softfloat.h" #include "fpopcode.h" #include "fpa11.h" @@ -51,10 +49,10 @@ unsigned int SingleCPDO(const unsigned int opcode) } else { - switch (fpa11->fpreg[Fm].fType) + switch (fpa11->fType[Fm]) { case typeSingle: - rFm = fpa11->fpreg[Fm].fValue.fSingle; + rFm = fpa11->fpreg[Fm].fSingle; break; default: return 0; @@ -64,10 +62,10 @@ unsigned int SingleCPDO(const unsigned int opcode) if (!MONADIC_INSTRUCTION(opcode)) { Fn = getFn(opcode); - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: - rFn = fpa11->fpreg[Fn].fValue.fSingle; + rFn = fpa11->fpreg[Fn].fSingle; break; default: return 0; @@ -79,112 +77,112 @@ unsigned int SingleCPDO(const unsigned int opcode) { /* dyadic opcodes */ case ADF_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_add(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_add(rFn,rFm); break; case MUF_CODE: case FML_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_mul(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_mul(rFn,rFm); break; case SUF_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_sub(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_sub(rFn,rFm); break; case RSF_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_sub(rFm,rFn); + fpa11->fpreg[Fd].fSingle = float32_sub(rFm,rFn); break; case DVF_CODE: case FDV_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_div(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_div(rFn,rFm); break; case RDF_CODE: case FRD_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_div(rFm,rFn); + fpa11->fpreg[Fd].fSingle = float32_div(rFm,rFn); break; #if 0 case POW_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_pow(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_pow(rFn,rFm); break; case RPW_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_pow(rFm,rFn); + fpa11->fpreg[Fd].fSingle = float32_pow(rFm,rFn); break; #endif case RMF_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_rem(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_rem(rFn,rFm); break; #if 0 case POL_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_pol(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_pol(rFn,rFm); break; #endif /* monadic opcodes */ case MVF_CODE: - fpa11->fpreg[Fd].fValue.fSingle = rFm; + fpa11->fpreg[Fd].fSingle = rFm; break; case MNF_CODE: rFm ^= 0x80000000; - fpa11->fpreg[Fd].fValue.fSingle = rFm; + fpa11->fpreg[Fd].fSingle = rFm; break; case ABS_CODE: rFm &= 0x7fffffff; - fpa11->fpreg[Fd].fValue.fSingle = rFm; + fpa11->fpreg[Fd].fSingle = rFm; break; case RND_CODE: case URD_CODE: - fpa11->fpreg[Fd].fValue.fSingle = + fpa11->fpreg[Fd].fSingle = int32_to_float32(float32_to_int32(rFm)); break; case SQT_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_sqrt(rFm); + fpa11->fpreg[Fd].fSingle = float32_sqrt(rFm); break; #if 0 case LOG_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_log(rFm); + fpa11->fpreg[Fd].fSingle = float32_log(rFm); break; case LGN_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_ln(rFm); + fpa11->fpreg[Fd].fSingle = float32_ln(rFm); break; case EXP_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_exp(rFm); + fpa11->fpreg[Fd].fSingle = float32_exp(rFm); break; case SIN_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_sin(rFm); + fpa11->fpreg[Fd].fSingle = float32_sin(rFm); break; case COS_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_cos(rFm); + fpa11->fpreg[Fd].fSingle = float32_cos(rFm); break; case TAN_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_tan(rFm); + fpa11->fpreg[Fd].fSingle = float32_tan(rFm); break; case ASN_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_arcsin(rFm); + fpa11->fpreg[Fd].fSingle = float32_arcsin(rFm); break; case ACS_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_arccos(rFm); + fpa11->fpreg[Fd].fSingle = float32_arccos(rFm); break; case ATN_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_arctan(rFm); + fpa11->fpreg[Fd].fSingle = float32_arctan(rFm); break; #endif @@ -197,7 +195,7 @@ unsigned int SingleCPDO(const unsigned int opcode) } } - if (0 != nRc) fpa11->fpreg[Fd].fType = typeSingle; + if (0 != nRc) fpa11->fType[Fd] = typeSingle; return nRc; } |