summaryrefslogtreecommitdiffstats
path: root/arch/arm/nwfpe
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-01-27 01:05:20 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-01-27 01:05:20 +0000
commit546db14ee74118296f425f3b91634fb767d67290 (patch)
tree22b613a3da8d4bf663eec5e155af01b87fdf9094 /arch/arm/nwfpe
parent1e25e41c4f5474e14452094492dbc169b800e4c8 (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/ChangeLog46
-rw-r--r--arch/arm/nwfpe/Makefile7
-rw-r--r--arch/arm/nwfpe/double_cpdo.c65
-rw-r--r--arch/arm/nwfpe/entry.S17
-rw-r--r--arch/arm/nwfpe/entry26.S2
-rw-r--r--arch/arm/nwfpe/extended_cpdo.c67
-rw-r--r--arch/arm/nwfpe/fpa11.c16
-rw-r--r--arch/arm/nwfpe/fpa11.h20
-rw-r--r--arch/arm/nwfpe/fpa11.inl2
-rw-r--r--arch/arm/nwfpe/fpa11_cpdo.c35
-rw-r--r--arch/arm/nwfpe/fpa11_cpdt.c94
-rw-r--r--arch/arm/nwfpe/fpa11_cprt.c85
-rw-r--r--arch/arm/nwfpe/fpmodule.c81
-rw-r--r--arch/arm/nwfpe/fpmodule.inl78
-rw-r--r--arch/arm/nwfpe/fpopcode.c1
-rw-r--r--arch/arm/nwfpe/single_cpdo.c60
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;
}