aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/nwfpe
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/arm/nwfpe
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/arm/nwfpe')
-rw-r--r--arch/arm/nwfpe/ARM-gcc.h120
-rw-r--r--arch/arm/nwfpe/ChangeLog91
-rw-r--r--arch/arm/nwfpe/Makefile13
-rw-r--r--arch/arm/nwfpe/double_cpdo.c167
-rw-r--r--arch/arm/nwfpe/entry.S119
-rw-r--r--arch/arm/nwfpe/entry26.S112
-rw-r--r--arch/arm/nwfpe/extended_cpdo.c154
-rw-r--r--arch/arm/nwfpe/fpa11.c143
-rw-r--r--arch/arm/nwfpe/fpa11.h93
-rw-r--r--arch/arm/nwfpe/fpa11.inl51
-rw-r--r--arch/arm/nwfpe/fpa11_cpdo.c132
-rw-r--r--arch/arm/nwfpe/fpa11_cpdt.c392
-rw-r--r--arch/arm/nwfpe/fpa11_cprt.c369
-rw-r--r--arch/arm/nwfpe/fpmodule.c173
-rw-r--r--arch/arm/nwfpe/fpmodule.h47
-rw-r--r--arch/arm/nwfpe/fpmodule.inl74
-rw-r--r--arch/arm/nwfpe/fpopcode.c90
-rw-r--r--arch/arm/nwfpe/fpopcode.h479
-rw-r--r--arch/arm/nwfpe/fpsr.h108
-rw-r--r--arch/arm/nwfpe/milieu.h48
-rw-r--r--arch/arm/nwfpe/single_cpdo.c124
-rw-r--r--arch/arm/nwfpe/softfloat-macros740
-rw-r--r--arch/arm/nwfpe/softfloat-specialize366
-rw-r--r--arch/arm/nwfpe/softfloat.c3443
-rw-r--r--arch/arm/nwfpe/softfloat.h278
25 files changed, 7926 insertions, 0 deletions
diff --git a/arch/arm/nwfpe/ARM-gcc.h b/arch/arm/nwfpe/ARM-gcc.h
new file mode 100644
index 000000000000..e6598470b076
--- /dev/null
+++ b/arch/arm/nwfpe/ARM-gcc.h
@@ -0,0 +1,120 @@
1/*
2-------------------------------------------------------------------------------
3The macro `BITS64' can be defined to indicate that 64-bit integer types are
4supported by the compiler.
5-------------------------------------------------------------------------------
6*/
7#define BITS64
8
9/*
10-------------------------------------------------------------------------------
11Each of the following `typedef's defines the most convenient type that holds
12integers of at least as many bits as specified. For example, `uint8' should
13be the most convenient type that can hold unsigned integers of as many as
148 bits. The `flag' type must be able to hold either a 0 or 1. For most
15implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
16to the same as `int'.
17-------------------------------------------------------------------------------
18*/
19typedef char flag;
20typedef unsigned char uint8;
21typedef signed char int8;
22typedef int uint16;
23typedef int int16;
24typedef unsigned int uint32;
25typedef signed int int32;
26#ifdef BITS64
27typedef unsigned long long int bits64;
28typedef signed long long int sbits64;
29#endif
30
31/*
32-------------------------------------------------------------------------------
33Each of the following `typedef's defines a type that holds integers
34of _exactly_ the number of bits specified. For instance, for most
35implementation of C, `bits16' and `sbits16' should be `typedef'ed to
36`unsigned short int' and `signed short int' (or `short int'), respectively.
37-------------------------------------------------------------------------------
38*/
39typedef unsigned char bits8;
40typedef signed char sbits8;
41typedef unsigned short int bits16;
42typedef signed short int sbits16;
43typedef unsigned int bits32;
44typedef signed int sbits32;
45#ifdef BITS64
46typedef unsigned long long int uint64;
47typedef signed long long int int64;
48#endif
49
50#ifdef BITS64
51/*
52-------------------------------------------------------------------------------
53The `LIT64' macro takes as its argument a textual integer literal and if
54necessary ``marks'' the literal as having a 64-bit integer type. For
55example, the Gnu C Compiler (`gcc') requires that 64-bit literals be
56appended with the letters `LL' standing for `long long', which is `gcc's
57name for the 64-bit integer type. Some compilers may allow `LIT64' to be
58defined as the identity macro: `#define LIT64( a ) a'.
59-------------------------------------------------------------------------------
60*/
61#define LIT64( a ) a##LL
62#endif
63
64/*
65-------------------------------------------------------------------------------
66The macro `INLINE' can be used before functions that should be inlined. If
67a compiler does not support explicit inlining, this macro should be defined
68to be `static'.
69-------------------------------------------------------------------------------
70*/
71#define INLINE extern __inline__
72
73
74/* For use as a GCC soft-float library we need some special function names. */
75
76#ifdef __LIBFLOAT__
77
78/* Some 32-bit ops can be mapped straight across by just changing the name. */
79#define float32_add __addsf3
80#define float32_sub __subsf3
81#define float32_mul __mulsf3
82#define float32_div __divsf3
83#define int32_to_float32 __floatsisf
84#define float32_to_int32_round_to_zero __fixsfsi
85#define float32_to_uint32_round_to_zero __fixunssfsi
86
87/* These ones go through the glue code. To avoid namespace pollution
88 we rename the internal functions too. */
89#define float32_eq ___float32_eq
90#define float32_le ___float32_le
91#define float32_lt ___float32_lt
92
93/* All the 64-bit ops have to go through the glue, so we pull the same
94 trick. */
95#define float64_add ___float64_add
96#define float64_sub ___float64_sub
97#define float64_mul ___float64_mul
98#define float64_div ___float64_div
99#define int32_to_float64 ___int32_to_float64
100#define float64_to_int32_round_to_zero ___float64_to_int32_round_to_zero
101#define float64_to_uint32_round_to_zero ___float64_to_uint32_round_to_zero
102#define float64_to_float32 ___float64_to_float32
103#define float32_to_float64 ___float32_to_float64
104#define float64_eq ___float64_eq
105#define float64_le ___float64_le
106#define float64_lt ___float64_lt
107
108#if 0
109#define float64_add __adddf3
110#define float64_sub __subdf3
111#define float64_mul __muldf3
112#define float64_div __divdf3
113#define int32_to_float64 __floatsidf
114#define float64_to_int32_round_to_zero __fixdfsi
115#define float64_to_uint32_round_to_zero __fixunsdfsi
116#define float64_to_float32 __truncdfsf2
117#define float32_to_float64 __extendsfdf2
118#endif
119
120#endif
diff --git a/arch/arm/nwfpe/ChangeLog b/arch/arm/nwfpe/ChangeLog
new file mode 100644
index 000000000000..eeb5a7c5ff09
--- /dev/null
+++ b/arch/arm/nwfpe/ChangeLog
@@ -0,0 +1,91 @@
12003-03-22 Ralph Siemsen <ralphs@netwinder.org>
2 * Reformat all but softfloat files to get a consistent coding style.
3 Used "indent -kr -i8 -ts8 -sob -l132 -ss" and a few manual fixups.
4 * Removed dead code and fixed function protypes to match definitions.
5 * Consolidated use of (opcode && MASK_ARITHMETIC_OPCODE) >> 20.
6 * Make 80-bit precision a compile-time option. (1%)
7 * Only initialize FPE state once in repeat-FP situations. (6%)
8
92002-01-19 Russell King <rmk@arm.linux.org.uk>
10
11 * fpa11.h - Add documentation
12 - remove userRegisters pointer from this structure.
13 - add new method to obtain integer register values.
14 * softfloat.c - Remove float128
15 * softfloat.h - Remove float128
16 * softfloat-specialize - Remove float128
17
18 * The FPA11 structure is not a kernel-specific data structure.
19 It is used by users of ptrace to examine the values of the
20 floating point registers. Therefore, any changes to the
21 FPA11 structure (size or position of elements contained
22 within) have to be well thought out.
23
24 * Since 128-bit float requires the FPA11 structure to change
25 size, it has been removed. 128-bit float is currently unused,
26 and needs various things to be re-worked so that we won't
27 overflow the available space in the task structure.
28
29 * The changes are designed to break any patch that goes on top
30 of this code, so that the authors properly review their changes.
31
321999-08-19 Scott Bambrough <scottb@netwinder.org>
33
34 * fpmodule.c - Changed version number to 0.95
35 * fpa11.h - modified FPA11, FPREG structures
36 * fpa11.c - Changes due to FPA11, FPREG structure alterations.
37 * fpa11_cpdo.c - Changes due to FPA11, FPREG structure alterations.
38 * fpa11_cpdt.c - Changes due to FPA11, FPREG structure alterations.
39 * fpa11_cprt.c - Changes due to FPA11, FPREG structure alterations.
40 * single_cpdo.c - Changes due to FPA11, FPREG structure alterations.
41 * double_cpdo.c - Changes due to FPA11, FPREG structure alterations.
42 * extended_cpdo.c - Changes due to FPA11, FPREG structure alterations.
43
44 * I discovered several bugs. First and worst is that the kernel
45 passes in a pointer to the FPE's state area. This is defined
46 as a struct user_fp (see user.h). This pointer was cast to a
47 FPA11*. Unfortunately FPA11 and user_fp are of different sizes;
48 user_fp is smaller. This meant that the FPE scribbled on things
49 below its area, which is bad, as the area is in the thread_struct
50 embedded in the process task structure. Thus we were scribbling
51 over one of the most important structures in the entire OS.
52
53 * user_fp and FPA11 have now been harmonized. Most of the changes
54 in the above code were dereferencing problems due to moving the
55 register type out of FPREG, and getting rid of the union variable
56 fpvalue.
57
58 * Second I noticed resetFPA11 was not always being called for a
59 task. This should happen on the first floating point exception
60 that occurs. It is controlled by init_flag in FPA11. The
61 comment in the code beside init_flag state the kernel guarantees
62 this to be zero. Not so. I found that the kernel recycles task
63 structures, and that recycled ones may not have init_flag zeroed.
64 I couldn't even find anything that guarantees it is zeroed when
65 when the task structure is initially allocated. In any case
66 I now initialize the entire FPE state in the thread structure to
67 zero when allocated and recycled. See alloc_task_struct() and
68 flush_thread() in arch/arm/process.c. The change to
69 alloc_task_struct() may not be necessary, but I left it in for
70 completeness (better safe than sorry).
71
721998-11-23 Scott Bambrough <scottb@netwinder.org>
73
74 * README.FPE - fix typo in description of lfm/sfm instructions
75 * NOTES - Added file to describe known bugs/problems
76 * fpmodule.c - Changed version number to 0.94
77
781998-11-20 Scott Bambrough <scottb@netwinder.org>
79
80 * README.FPE - fix description of URD, NRM instructions
81 * TODO - remove URD, NRM instructions from TODO list
82 * single_cpdo.c - implement URD, NRM
83 * double_cpdo.c - implement URD, NRM
84 * extended_cpdo.c - implement URD, NRM
85
861998-11-19 Scott Bambrough <scottb@netwinder.org>
87
88 * ChangeLog - Added this file to track changes made.
89 * fpa11.c - added code to initialize register types to typeNone
90 * fpa11_cpdt.c - fixed bug in storeExtended (typeExtended changed to
91 typeDouble in switch statement)
diff --git a/arch/arm/nwfpe/Makefile b/arch/arm/nwfpe/Makefile
new file mode 100644
index 000000000000..ed7b26bf73f5
--- /dev/null
+++ b/arch/arm/nwfpe/Makefile
@@ -0,0 +1,13 @@
1#
2# Copyright (C) 1998, 1999, 2001 Philip Blundell
3#
4
5obj-$(CONFIG_FPE_NWFPE) += nwfpe.o
6
7nwfpe-y += fpa11.o fpa11_cpdo.o fpa11_cpdt.o \
8 fpa11_cprt.o fpmodule.o fpopcode.o \
9 softfloat.o single_cpdo.o double_cpdo.o
10
11nwfpe-$(CONFIG_FPE_NWFPE_XP) += extended_cpdo.o
12nwfpe-$(CONFIG_CPU_26) += entry26.o
13nwfpe-$(CONFIG_CPU_32) += entry.o
diff --git a/arch/arm/nwfpe/double_cpdo.c b/arch/arm/nwfpe/double_cpdo.c
new file mode 100644
index 000000000000..7ffd8cb9bc96
--- /dev/null
+++ b/arch/arm/nwfpe/double_cpdo.c
@@ -0,0 +1,167 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.COM, 1998,1999
4
5 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include "fpa11.h"
23#include "softfloat.h"
24#include "fpopcode.h"
25
26union float64_components {
27 float64 f64;
28 unsigned int i[2];
29};
30
31float64 float64_exp(float64 Fm);
32float64 float64_ln(float64 Fm);
33float64 float64_sin(float64 rFm);
34float64 float64_cos(float64 rFm);
35float64 float64_arcsin(float64 rFm);
36float64 float64_arctan(float64 rFm);
37float64 float64_log(float64 rFm);
38float64 float64_tan(float64 rFm);
39float64 float64_arccos(float64 rFm);
40float64 float64_pow(float64 rFn, float64 rFm);
41float64 float64_pol(float64 rFn, float64 rFm);
42
43static float64 float64_rsf(float64 rFn, float64 rFm)
44{
45 return float64_sub(rFm, rFn);
46}
47
48static float64 float64_rdv(float64 rFn, float64 rFm)
49{
50 return float64_div(rFm, rFn);
51}
52
53static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = {
54 [ADF_CODE >> 20] = float64_add,
55 [MUF_CODE >> 20] = float64_mul,
56 [SUF_CODE >> 20] = float64_sub,
57 [RSF_CODE >> 20] = float64_rsf,
58 [DVF_CODE >> 20] = float64_div,
59 [RDF_CODE >> 20] = float64_rdv,
60 [RMF_CODE >> 20] = float64_rem,
61
62 /* strictly, these opcodes should not be implemented */
63 [FML_CODE >> 20] = float64_mul,
64 [FDV_CODE >> 20] = float64_div,
65 [FRD_CODE >> 20] = float64_rdv,
66};
67
68static float64 float64_mvf(float64 rFm)
69{
70 return rFm;
71}
72
73static float64 float64_mnf(float64 rFm)
74{
75 union float64_components u;
76
77 u.f64 = rFm;
78#ifdef __ARMEB__
79 u.i[0] ^= 0x80000000;
80#else
81 u.i[1] ^= 0x80000000;
82#endif
83
84 return u.f64;
85}
86
87static float64 float64_abs(float64 rFm)
88{
89 union float64_components u;
90
91 u.f64 = rFm;
92#ifdef __ARMEB__
93 u.i[0] &= 0x7fffffff;
94#else
95 u.i[1] &= 0x7fffffff;
96#endif
97
98 return u.f64;
99}
100
101static float64 (*const monadic_double[16])(float64 rFm) = {
102 [MVF_CODE >> 20] = float64_mvf,
103 [MNF_CODE >> 20] = float64_mnf,
104 [ABS_CODE >> 20] = float64_abs,
105 [RND_CODE >> 20] = float64_round_to_int,
106 [URD_CODE >> 20] = float64_round_to_int,
107 [SQT_CODE >> 20] = float64_sqrt,
108 [NRM_CODE >> 20] = float64_mvf,
109};
110
111unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd)
112{
113 FPA11 *fpa11 = GET_FPA11();
114 float64 rFm;
115 unsigned int Fm, opc_mask_shift;
116
117 Fm = getFm(opcode);
118 if (CONSTANT_FM(opcode)) {
119 rFm = getDoubleConstant(Fm);
120 } else {
121 switch (fpa11->fType[Fm]) {
122 case typeSingle:
123 rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle);
124 break;
125
126 case typeDouble:
127 rFm = fpa11->fpreg[Fm].fDouble;
128 break;
129
130 default:
131 return 0;
132 }
133 }
134
135 opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
136 if (!MONADIC_INSTRUCTION(opcode)) {
137 unsigned int Fn = getFn(opcode);
138 float64 rFn;
139
140 switch (fpa11->fType[Fn]) {
141 case typeSingle:
142 rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle);
143 break;
144
145 case typeDouble:
146 rFn = fpa11->fpreg[Fn].fDouble;
147 break;
148
149 default:
150 return 0;
151 }
152
153 if (dyadic_double[opc_mask_shift]) {
154 rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm);
155 } else {
156 return 0;
157 }
158 } else {
159 if (monadic_double[opc_mask_shift]) {
160 rFd->fDouble = monadic_double[opc_mask_shift](rFm);
161 } else {
162 return 0;
163 }
164 }
165
166 return 1;
167}
diff --git a/arch/arm/nwfpe/entry.S b/arch/arm/nwfpe/entry.S
new file mode 100644
index 000000000000..1dc13bc6d810
--- /dev/null
+++ b/arch/arm/nwfpe/entry.S
@@ -0,0 +1,119 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.COM, 1998
4 (c) 1998, 1999 Philip Blundell
5
6 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23/* This is the kernel's entry point into the floating point emulator.
24It is called from the kernel with code similar to this:
25
26 sub r4, r5, #4
27 ldrt r0, [r4] @ r0 = instruction
28 adrsvc al, r9, ret_from_exception @ r9 = normal FP return
29 adrsvc al, lr, fpundefinstr @ lr = undefined instr return
30
31 get_current_task r10
32 mov r8, #1
33 strb r8, [r10, #TSK_USED_MATH] @ set current->used_math
34 add r10, r10, #TSS_FPESAVE @ r10 = workspace
35 ldr r4, .LC2
36 ldr pc, [r4] @ Call FP emulator entry point
37
38The kernel expects the emulator to return via one of two possible
39points of return it passes to the emulator. The emulator, if
40successful in its emulation, jumps to ret_from_exception (passed in
41r9) and the kernel takes care of returning control from the trap to
42the user code. If the emulator is unable to emulate the instruction,
43it returns via _fpundefinstr (passed via lr) and the kernel halts the
44user program with a core dump.
45
46On entry to the emulator r10 points to an area of private FP workspace
47reserved in the thread structure for this process. This is where the
48emulator saves its registers across calls. The first word of this area
49is used as a flag to detect the first time a process uses floating point,
50so that the emulator startup cost can be avoided for tasks that don't
51want it.
52
53This routine does three things:
54
551) The kernel has created a struct pt_regs on the stack and saved the
56user registers into it. See /usr/include/asm/proc/ptrace.h for details.
57
582) It calls EmulateAll to emulate a floating point instruction.
59EmulateAll returns 1 if the emulation was successful, or 0 if not.
60
613) If an instruction has been emulated successfully, it looks ahead at
62the next instruction. If it is a floating point instruction, it
63executes the instruction, without returning to user space. In this
64way it repeatedly looks ahead and executes floating point instructions
65until it encounters a non floating point instruction, at which time it
66returns via _fpreturn.
67
68This is done to reduce the effect of the trap overhead on each
69floating point instructions. GCC attempts to group floating point
70instructions to allow the emulator to spread the cost of the trap over
71several floating point instructions. */
72
73 .globl nwfpe_enter
74nwfpe_enter:
75 mov r4, lr @ save the failure-return addresses
76 mov sl, sp @ we access the registers via 'sl'
77
78 ldr r5, [sp, #60] @ get contents of PC;
79emulate:
80 bl EmulateAll @ emulate the instruction
81 cmp r0, #0 @ was emulation successful
82 moveq pc, r4 @ no, return failure
83
84next:
85.Lx1: ldrt r6, [r5], #4 @ get the next instruction and
86 @ increment PC
87
88 and r2, r6, #0x0F000000 @ test for FP insns
89 teq r2, #0x0C000000
90 teqne r2, #0x0D000000
91 teqne r2, #0x0E000000
92 movne pc, r9 @ return ok if not a fp insn
93
94 str r5, [sp, #60] @ update PC copy in regs
95
96 mov r0, r6 @ save a copy
97 ldr r1, [sp, #64] @ fetch the condition codes
98 bl checkCondition @ check the condition
99 cmp r0, #0 @ r0 = 0 ==> condition failed
100
101 @ if condition code failed to match, next insn
102 beq next @ get the next instruction;
103
104 mov r0, r6 @ prepare for EmulateAll()
105 b emulate @ if r0 != 0, goto EmulateAll
106
107 @ We need to be prepared for the instructions at .Lx1 and .Lx2
108 @ to fault. Emit the appropriate exception gunk to fix things up.
109 @ ??? For some reason, faults can happen at .Lx2 even with a
110 @ plain LDR instruction. Weird, but it seems harmless.
111 .section .fixup,"ax"
112 .align 2
113.Lfix: mov pc, r9 @ let the user eat segfaults
114 .previous
115
116 .section __ex_table,"a"
117 .align 3
118 .long .Lx1, .Lfix
119 .previous
diff --git a/arch/arm/nwfpe/entry26.S b/arch/arm/nwfpe/entry26.S
new file mode 100644
index 000000000000..0ed38b0913db
--- /dev/null
+++ b/arch/arm/nwfpe/entry26.S
@@ -0,0 +1,112 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.COM, 1998
4 (c) Philip Blundell 1998-1999
5
6 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#include <asm/constants.h>
24
25/* This is the kernel's entry point into the floating point emulator.
26It is called from the kernel with code similar to this:
27
28 mov fp, #0
29 teqp pc, #PSR_I_BIT | MODE_SVC
30 ldr r4, .LC2
31 ldr pc, [r4] @ Call FP module USR entry point
32
33The kernel expects the emulator to return via one of two possible
34points of return it passes to the emulator. The emulator, if
35successful in its emulation, jumps to ret_from_exception and the
36kernel takes care of returning control from the trap to the user code.
37If the emulator is unable to emulate the instruction, it returns to
38fpundefinstr and the kernel halts the user program with a core dump.
39
40This routine does four things:
41
421) It saves SP into a variable called userRegisters. The kernel has
43created a struct pt_regs on the stack and saved the user registers
44into it. See /usr/include/asm/proc/ptrace.h for details. The
45emulator code uses userRegisters as the base of an array of words from
46which the contents of the registers can be extracted.
47
482) It locates the FP emulator work area within the TSS structure and
49points `fpa11' to it.
50
513) It calls EmulateAll to emulate a floating point instruction.
52EmulateAll returns 1 if the emulation was successful, or 0 if not.
53
544) If an instruction has been emulated successfully, it looks ahead at
55the next instruction. If it is a floating point instruction, it
56executes the instruction, without returning to user space. In this
57way it repeatedly looks ahead and executes floating point instructions
58until it encounters a non floating point instruction, at which time it
59returns via _fpreturn.
60
61This is done to reduce the effect of the trap overhead on each
62floating point instructions. GCC attempts to group floating point
63instructions to allow the emulator to spread the cost of the trap over
64several floating point instructions. */
65
66 .globl nwfpe_enter
67nwfpe_enter:
68 mov sl, sp
69 ldr r5, [sp, #60] @ get contents of PC
70 bic r5, r5, #0xfc000003
71 ldr r0, [r5, #-4] @ get actual instruction into r0
72 bl EmulateAll @ emulate the instruction
731: cmp r0, #0 @ was emulation successful
74 beq fpundefinstr @ no, return failure
75
76next:
77.Lx1: ldrt r6, [r5], #4 @ get the next instruction and
78 @ increment PC
79
80 and r2, r6, #0x0F000000 @ test for FP insns
81 teq r2, #0x0C000000
82 teqne r2, #0x0D000000
83 teqne r2, #0x0E000000
84 bne ret_from_exception @ return ok if not a fp insn
85
86 ldr r9, [sp, #60] @ get new condition codes
87 and r9, r9, #0xfc000003
88 orr r7, r5, r9
89 str r7, [sp, #60] @ update PC copy in regs
90
91 mov r0, r6 @ save a copy
92 mov r1, r9 @ fetch the condition codes
93 bl checkCondition @ check the condition
94 cmp r0, #0 @ r0 = 0 ==> condition failed
95
96 @ if condition code failed to match, next insn
97 beq next @ get the next instruction;
98
99 mov r0, r6 @ prepare for EmulateAll()
100 adr lr, 1b
101 orr lr, lr, #3
102 b EmulateAll @ if r0 != 0, goto EmulateAll
103
104.Lret: b ret_from_exception @ let the user eat segfaults
105
106 @ We need to be prepared for the instruction at .Lx1 to fault.
107 @ Emit the appropriate exception gunk to fix things up.
108 .section __ex_table,"a"
109 .align 3
110 .long .Lx1
111 ldr lr, [lr, $(.Lret - .Lx1)/4]
112 .previous
diff --git a/arch/arm/nwfpe/extended_cpdo.c b/arch/arm/nwfpe/extended_cpdo.c
new file mode 100644
index 000000000000..c39f68a3449e
--- /dev/null
+++ b/arch/arm/nwfpe/extended_cpdo.c
@@ -0,0 +1,154 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.COM, 1998,1999
4
5 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include "fpa11.h"
23#include "softfloat.h"
24#include "fpopcode.h"
25
26floatx80 floatx80_exp(floatx80 Fm);
27floatx80 floatx80_ln(floatx80 Fm);
28floatx80 floatx80_sin(floatx80 rFm);
29floatx80 floatx80_cos(floatx80 rFm);
30floatx80 floatx80_arcsin(floatx80 rFm);
31floatx80 floatx80_arctan(floatx80 rFm);
32floatx80 floatx80_log(floatx80 rFm);
33floatx80 floatx80_tan(floatx80 rFm);
34floatx80 floatx80_arccos(floatx80 rFm);
35floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm);
36floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm);
37
38static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm)
39{
40 return floatx80_sub(rFm, rFn);
41}
42
43static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm)
44{
45 return floatx80_div(rFm, rFn);
46}
47
48static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = {
49 [ADF_CODE >> 20] = floatx80_add,
50 [MUF_CODE >> 20] = floatx80_mul,
51 [SUF_CODE >> 20] = floatx80_sub,
52 [RSF_CODE >> 20] = floatx80_rsf,
53 [DVF_CODE >> 20] = floatx80_div,
54 [RDF_CODE >> 20] = floatx80_rdv,
55 [RMF_CODE >> 20] = floatx80_rem,
56
57 /* strictly, these opcodes should not be implemented */
58 [FML_CODE >> 20] = floatx80_mul,
59 [FDV_CODE >> 20] = floatx80_div,
60 [FRD_CODE >> 20] = floatx80_rdv,
61};
62
63static floatx80 floatx80_mvf(floatx80 rFm)
64{
65 return rFm;
66}
67
68static floatx80 floatx80_mnf(floatx80 rFm)
69{
70 rFm.high ^= 0x8000;
71 return rFm;
72}
73
74static floatx80 floatx80_abs(floatx80 rFm)
75{
76 rFm.high &= 0x7fff;
77 return rFm;
78}
79
80static floatx80 (*const monadic_extended[16])(floatx80 rFm) = {
81 [MVF_CODE >> 20] = floatx80_mvf,
82 [MNF_CODE >> 20] = floatx80_mnf,
83 [ABS_CODE >> 20] = floatx80_abs,
84 [RND_CODE >> 20] = floatx80_round_to_int,
85 [URD_CODE >> 20] = floatx80_round_to_int,
86 [SQT_CODE >> 20] = floatx80_sqrt,
87 [NRM_CODE >> 20] = floatx80_mvf,
88};
89
90unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd)
91{
92 FPA11 *fpa11 = GET_FPA11();
93 floatx80 rFm;
94 unsigned int Fm, opc_mask_shift;
95
96 Fm = getFm(opcode);
97 if (CONSTANT_FM(opcode)) {
98 rFm = getExtendedConstant(Fm);
99 } else {
100 switch (fpa11->fType[Fm]) {
101 case typeSingle:
102 rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
103 break;
104
105 case typeDouble:
106 rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
107 break;
108
109 case typeExtended:
110 rFm = fpa11->fpreg[Fm].fExtended;
111 break;
112
113 default:
114 return 0;
115 }
116 }
117
118 opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
119 if (!MONADIC_INSTRUCTION(opcode)) {
120 unsigned int Fn = getFn(opcode);
121 floatx80 rFn;
122
123 switch (fpa11->fType[Fn]) {
124 case typeSingle:
125 rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
126 break;
127
128 case typeDouble:
129 rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
130 break;
131
132 case typeExtended:
133 rFn = fpa11->fpreg[Fn].fExtended;
134 break;
135
136 default:
137 return 0;
138 }
139
140 if (dyadic_extended[opc_mask_shift]) {
141 rFd->fExtended = dyadic_extended[opc_mask_shift](rFn, rFm);
142 } else {
143 return 0;
144 }
145 } else {
146 if (monadic_extended[opc_mask_shift]) {
147 rFd->fExtended = monadic_extended[opc_mask_shift](rFm);
148 } else {
149 return 0;
150 }
151 }
152
153 return 1;
154}
diff --git a/arch/arm/nwfpe/fpa11.c b/arch/arm/nwfpe/fpa11.c
new file mode 100644
index 000000000000..bf61696865ec
--- /dev/null
+++ b/arch/arm/nwfpe/fpa11.c
@@ -0,0 +1,143 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.COM, 1998,1999
4 (c) Philip Blundell, 2001
5
6 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#include "fpa11.h"
24#include "fpopcode.h"
25
26#include "fpmodule.h"
27#include "fpmodule.inl"
28
29#include <linux/config.h>
30#include <linux/compiler.h>
31#include <linux/string.h>
32#include <asm/system.h>
33
34/* forward declarations */
35unsigned int EmulateCPDO(const unsigned int);
36unsigned int EmulateCPDT(const unsigned int);
37unsigned int EmulateCPRT(const unsigned int);
38
39/* Reset the FPA11 chip. Called to initialize and reset the emulator. */
40static void resetFPA11(void)
41{
42 int i;
43 FPA11 *fpa11 = GET_FPA11();
44
45 /* initialize the register type array */
46 for (i = 0; i <= 7; i++) {
47 fpa11->fType[i] = typeNone;
48 }
49
50 /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */
51 fpa11->fpsr = FP_EMULATOR | BIT_AC;
52}
53
54void SetRoundingMode(const unsigned int opcode)
55{
56 switch (opcode & MASK_ROUNDING_MODE) {
57 default:
58 case ROUND_TO_NEAREST:
59 float_rounding_mode = float_round_nearest_even;
60 break;
61
62 case ROUND_TO_PLUS_INFINITY:
63 float_rounding_mode = float_round_up;
64 break;
65
66 case ROUND_TO_MINUS_INFINITY:
67 float_rounding_mode = float_round_down;
68 break;
69
70 case ROUND_TO_ZERO:
71 float_rounding_mode = float_round_to_zero;
72 break;
73 }
74}
75
76void SetRoundingPrecision(const unsigned int opcode)
77{
78#ifdef CONFIG_FPE_NWFPE_XP
79 switch (opcode & MASK_ROUNDING_PRECISION) {
80 case ROUND_SINGLE:
81 floatx80_rounding_precision = 32;
82 break;
83
84 case ROUND_DOUBLE:
85 floatx80_rounding_precision = 64;
86 break;
87
88 case ROUND_EXTENDED:
89 floatx80_rounding_precision = 80;
90 break;
91
92 default:
93 floatx80_rounding_precision = 80;
94 }
95#endif
96}
97
98void nwfpe_init_fpa(union fp_state *fp)
99{
100 FPA11 *fpa11 = (FPA11 *)fp;
101#ifdef NWFPE_DEBUG
102 printk("NWFPE: setting up state.\n");
103#endif
104 memset(fpa11, 0, sizeof(FPA11));
105 resetFPA11();
106 SetRoundingMode(ROUND_TO_NEAREST);
107 SetRoundingPrecision(ROUND_EXTENDED);
108 fpa11->initflag = 1;
109}
110
111/* Emulate the instruction in the opcode. */
112unsigned int EmulateAll(unsigned int opcode)
113{
114 unsigned int code;
115
116#ifdef NWFPE_DEBUG
117 printk("NWFPE: emulating opcode %08x\n", opcode);
118#endif
119 code = opcode & 0x00000f00;
120 if (code == 0x00000100 || code == 0x00000200) {
121 /* For coprocessor 1 or 2 (FPA11) */
122 code = opcode & 0x0e000000;
123 if (code == 0x0e000000) {
124 if (opcode & 0x00000010) {
125 /* Emulate conversion opcodes. */
126 /* Emulate register transfer opcodes. */
127 /* Emulate comparison opcodes. */
128 return EmulateCPRT(opcode);
129 } else {
130 /* Emulate monadic arithmetic opcodes. */
131 /* Emulate dyadic arithmetic opcodes. */
132 return EmulateCPDO(opcode);
133 }
134 } else if (code == 0x0c000000) {
135 /* Emulate load/store opcodes. */
136 /* Emulate load/store multiple opcodes. */
137 return EmulateCPDT(opcode);
138 }
139 }
140
141 /* Invalid instruction detected. Return FALSE. */
142 return 0;
143}
diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h
new file mode 100644
index 000000000000..45cc65426a22
--- /dev/null
+++ b/arch/arm/nwfpe/fpa11.h
@@ -0,0 +1,93 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.com, 1998-1999
4
5 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#ifndef __FPA11_H__
23#define __FPA11_H__
24
25#define GET_FPA11() ((FPA11 *)(&current_thread_info()->fpstate))
26
27/*
28 * The processes registers are always at the very top of the 8K
29 * stack+task struct. Use the same method as 'current' uses to
30 * reach them.
31 */
32register unsigned long *user_registers asm("sl");
33
34#define GET_USERREG() (user_registers)
35
36#include <linux/config.h>
37#include <linux/thread_info.h>
38
39/* includes */
40#include "fpsr.h" /* FP control and status register definitions */
41#include "milieu.h"
42#include "softfloat.h"
43
44#define typeNone 0x00
45#define typeSingle 0x01
46#define typeDouble 0x02
47#define typeExtended 0x03
48
49/*
50 * This must be no more and no less than 12 bytes.
51 */
52typedef union tagFPREG {
53 float32 fSingle;
54 float64 fDouble;
55#ifdef CONFIG_FPE_NWFPE_XP
56 floatx80 fExtended;
57#else
58 int padding[3];
59#endif
60} FPREG;
61
62/*
63 * FPA11 device model.
64 *
65 * This structure is exported to user space. Do not re-order.
66 * Only add new stuff to the end, and do not change the size of
67 * any element. Elements of this structure are used by user
68 * space, and must match struct user_fp in include/asm-arm/user.h.
69 * We include the byte offsets below for documentation purposes.
70 *
71 * The size of this structure and FPREG are checked by fpmodule.c
72 * on initialisation. If the rules have been broken, NWFPE will
73 * not initialise.
74 */
75typedef struct tagFPA11 {
76/* 0 */ FPREG fpreg[8]; /* 8 floating point registers */
77/* 96 */ FPSR fpsr; /* floating point status register */
78/* 100 */ FPCR fpcr; /* floating point control register */
79/* 104 */ unsigned char fType[8]; /* type of floating point value held in
80 floating point registers. One of
81 none, single, double or extended. */
82/* 112 */ int initflag; /* this is special. The kernel guarantees
83 to set it to 0 when a thread is launched,
84 so we can use it to detect whether this
85 instance of the emulator needs to be
86 initialised. */
87} FPA11;
88
89extern void SetRoundingMode(const unsigned int);
90extern void SetRoundingPrecision(const unsigned int);
91extern void nwfpe_init_fpa(union fp_state *fp);
92
93#endif
diff --git a/arch/arm/nwfpe/fpa11.inl b/arch/arm/nwfpe/fpa11.inl
new file mode 100644
index 000000000000..10c3caf2868f
--- /dev/null
+++ b/arch/arm/nwfpe/fpa11.inl
@@ -0,0 +1,51 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.COM, 1998,1999
4
5 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include "fpa11.h"
23
24/* Read and write floating point status register */
25extern __inline__ unsigned int readFPSR(void)
26{
27 FPA11 *fpa11 = GET_FPA11();
28 return (fpa11->fpsr);
29}
30
31extern __inline__ void writeFPSR(FPSR reg)
32{
33 FPA11 *fpa11 = GET_FPA11();
34 /* the sysid byte in the status register is readonly */
35 fpa11->fpsr = (fpa11->fpsr & MASK_SYSID) | (reg & ~MASK_SYSID);
36}
37
38/* Read and write floating point control register */
39extern __inline__ FPCR readFPCR(void)
40{
41 FPA11 *fpa11 = GET_FPA11();
42 /* clear SB, AB and DA bits before returning FPCR */
43 return (fpa11->fpcr & ~MASK_RFC);
44}
45
46extern __inline__ void writeFPCR(FPCR reg)
47{
48 FPA11 *fpa11 = GET_FPA11();
49 fpa11->fpcr &= ~MASK_WFC; /* clear SB, AB and DA bits */
50 fpa11->fpcr |= (reg & MASK_WFC); /* write SB, AB and DA bits */
51}
diff --git a/arch/arm/nwfpe/fpa11_cpdo.c b/arch/arm/nwfpe/fpa11_cpdo.c
new file mode 100644
index 000000000000..1bea67437b6f
--- /dev/null
+++ b/arch/arm/nwfpe/fpa11_cpdo.c
@@ -0,0 +1,132 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.COM, 1998,1999
4 (c) Philip Blundell, 2001
5
6 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#include <linux/config.h>
24#include "fpa11.h"
25#include "fpopcode.h"
26
27unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd);
28unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd);
29unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd);
30
31unsigned int EmulateCPDO(const unsigned int opcode)
32{
33 FPA11 *fpa11 = GET_FPA11();
34 FPREG *rFd;
35 unsigned int nType, nDest, nRc;
36
37 /* Get the destination size. If not valid let Linux perform
38 an invalid instruction trap. */
39 nDest = getDestinationSize(opcode);
40 if (typeNone == nDest)
41 return 0;
42
43 SetRoundingMode(opcode);
44
45 /* Compare the size of the operands in Fn and Fm.
46 Choose the largest size and perform operations in that size,
47 in order to make use of all the precision of the operands.
48 If Fm is a constant, we just grab a constant of a size
49 matching the size of the operand in Fn. */
50 if (MONADIC_INSTRUCTION(opcode))
51 nType = nDest;
52 else
53 nType = fpa11->fType[getFn(opcode)];
54
55 if (!CONSTANT_FM(opcode)) {
56 register unsigned int Fm = getFm(opcode);
57 if (nType < fpa11->fType[Fm]) {
58 nType = fpa11->fType[Fm];
59 }
60 }
61
62 rFd = &fpa11->fpreg[getFd(opcode)];
63
64 switch (nType) {
65 case typeSingle:
66 nRc = SingleCPDO(opcode, rFd);
67 break;
68 case typeDouble:
69 nRc = DoubleCPDO(opcode, rFd);
70 break;
71#ifdef CONFIG_FPE_NWFPE_XP
72 case typeExtended:
73 nRc = ExtendedCPDO(opcode, rFd);
74 break;
75#endif
76 default:
77 nRc = 0;
78 }
79
80 /* The CPDO functions used to always set the destination type
81 to be the same as their working size. */
82
83 if (nRc != 0) {
84 /* If the operation succeeded, check to see if the result in the
85 destination register is the correct size. If not force it
86 to be. */
87
88 fpa11->fType[getFd(opcode)] = nDest;
89
90#ifdef CONFIG_FPE_NWFPE_XP
91 if (nDest != nType) {
92 switch (nDest) {
93 case typeSingle:
94 {
95 if (typeDouble == nType)
96 rFd->fSingle = float64_to_float32(rFd->fDouble);
97 else
98 rFd->fSingle = floatx80_to_float32(rFd->fExtended);
99 }
100 break;
101
102 case typeDouble:
103 {
104 if (typeSingle == nType)
105 rFd->fDouble = float32_to_float64(rFd->fSingle);
106 else
107 rFd->fDouble = floatx80_to_float64(rFd->fExtended);
108 }
109 break;
110
111 case typeExtended:
112 {
113 if (typeSingle == nType)
114 rFd->fExtended = float32_to_floatx80(rFd->fSingle);
115 else
116 rFd->fExtended = float64_to_floatx80(rFd->fDouble);
117 }
118 break;
119 }
120 }
121#else
122 if (nDest != nType) {
123 if (nDest == typeSingle)
124 rFd->fSingle = float64_to_float32(rFd->fDouble);
125 else
126 rFd->fDouble = float32_to_float64(rFd->fSingle);
127 }
128#endif
129 }
130
131 return nRc;
132}
diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c
new file mode 100644
index 000000000000..95fb63fa9d18
--- /dev/null
+++ b/arch/arm/nwfpe/fpa11_cpdt.c
@@ -0,0 +1,392 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.com, 1998-1999
4 (c) Philip Blundell, 1998, 2001
5
6 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#include <linux/config.h>
24#include "fpa11.h"
25#include "softfloat.h"
26#include "fpopcode.h"
27#include "fpmodule.h"
28#include "fpmodule.inl"
29
30#include <asm/uaccess.h>
31
32static inline void loadSingle(const unsigned int Fn, const unsigned int __user *pMem)
33{
34 FPA11 *fpa11 = GET_FPA11();
35 fpa11->fType[Fn] = typeSingle;
36 get_user(fpa11->fpreg[Fn].fSingle, pMem);
37}
38
39static inline void loadDouble(const unsigned int Fn, const unsigned int __user *pMem)
40{
41 FPA11 *fpa11 = GET_FPA11();
42 unsigned int *p;
43 p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
44 fpa11->fType[Fn] = typeDouble;
45#ifdef __ARMEB__
46 get_user(p[0], &pMem[0]); /* sign & exponent */
47 get_user(p[1], &pMem[1]);
48#else
49 get_user(p[0], &pMem[1]);
50 get_user(p[1], &pMem[0]); /* sign & exponent */
51#endif
52}
53
54#ifdef CONFIG_FPE_NWFPE_XP
55static inline void loadExtended(const unsigned int Fn, const unsigned int __user *pMem)
56{
57 FPA11 *fpa11 = GET_FPA11();
58 unsigned int *p;
59 p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
60 fpa11->fType[Fn] = typeExtended;
61 get_user(p[0], &pMem[0]); /* sign & exponent */
62 get_user(p[1], &pMem[2]); /* ls bits */
63 get_user(p[2], &pMem[1]); /* ms bits */
64}
65#endif
66
67static inline void loadMultiple(const unsigned int Fn, const unsigned int __user *pMem)
68{
69 FPA11 *fpa11 = GET_FPA11();
70 register unsigned int *p;
71 unsigned long x;
72
73 p = (unsigned int *) &(fpa11->fpreg[Fn]);
74 get_user(x, &pMem[0]);
75 fpa11->fType[Fn] = (x >> 14) & 0x00000003;
76
77 switch (fpa11->fType[Fn]) {
78 case typeSingle:
79 case typeDouble:
80 {
81 get_user(p[0], &pMem[2]); /* Single */
82 get_user(p[1], &pMem[1]); /* double msw */
83 p[2] = 0; /* empty */
84 }
85 break;
86
87#ifdef CONFIG_FPE_NWFPE_XP
88 case typeExtended:
89 {
90 get_user(p[1], &pMem[2]);
91 get_user(p[2], &pMem[1]); /* msw */
92 p[0] = (x & 0x80003fff);
93 }
94 break;
95#endif
96 }
97}
98
99static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)
100{
101 FPA11 *fpa11 = GET_FPA11();
102 union {
103 float32 f;
104 unsigned int i[1];
105 } val;
106
107 switch (fpa11->fType[Fn]) {
108 case typeDouble:
109 val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble);
110 break;
111
112#ifdef CONFIG_FPE_NWFPE_XP
113 case typeExtended:
114 val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
115 break;
116#endif
117
118 default:
119 val.f = fpa11->fpreg[Fn].fSingle;
120 }
121
122 put_user(val.i[0], pMem);
123}
124
125static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)
126{
127 FPA11 *fpa11 = GET_FPA11();
128 union {
129 float64 f;
130 unsigned int i[2];
131 } val;
132
133 switch (fpa11->fType[Fn]) {
134 case typeSingle:
135 val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle);
136 break;
137
138#ifdef CONFIG_FPE_NWFPE_XP
139 case typeExtended:
140 val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
141 break;
142#endif
143
144 default:
145 val.f = fpa11->fpreg[Fn].fDouble;
146 }
147
148#ifdef __ARMEB__
149 put_user(val.i[0], &pMem[0]); /* msw */
150 put_user(val.i[1], &pMem[1]); /* lsw */
151#else
152 put_user(val.i[1], &pMem[0]); /* msw */
153 put_user(val.i[0], &pMem[1]); /* lsw */
154#endif
155}
156
157#ifdef CONFIG_FPE_NWFPE_XP
158static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMem)
159{
160 FPA11 *fpa11 = GET_FPA11();
161 union {
162 floatx80 f;
163 unsigned int i[3];
164 } val;
165
166 switch (fpa11->fType[Fn]) {
167 case typeSingle:
168 val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
169 break;
170
171 case typeDouble:
172 val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
173 break;
174
175 default:
176 val.f = fpa11->fpreg[Fn].fExtended;
177 }
178
179 put_user(val.i[0], &pMem[0]); /* sign & exp */
180 put_user(val.i[1], &pMem[2]);
181 put_user(val.i[2], &pMem[1]); /* msw */
182}
183#endif
184
185static inline void storeMultiple(const unsigned int Fn, unsigned int __user *pMem)
186{
187 FPA11 *fpa11 = GET_FPA11();
188 register unsigned int nType, *p;
189
190 p = (unsigned int *) &(fpa11->fpreg[Fn]);
191 nType = fpa11->fType[Fn];
192
193 switch (nType) {
194 case typeSingle:
195 case typeDouble:
196 {
197 put_user(p[0], &pMem[2]); /* single */
198 put_user(p[1], &pMem[1]); /* double msw */
199 put_user(nType << 14, &pMem[0]);
200 }
201 break;
202
203#ifdef CONFIG_FPE_NWFPE_XP
204 case typeExtended:
205 {
206 put_user(p[2], &pMem[1]); /* msw */
207 put_user(p[1], &pMem[2]);
208 put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);
209 }
210 break;
211#endif
212 }
213}
214
215unsigned int PerformLDF(const unsigned int opcode)
216{
217 unsigned int __user *pBase, *pAddress, *pFinal;
218 unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
219
220 pBase = (unsigned int __user *) readRegister(getRn(opcode));
221 if (REG_PC == getRn(opcode)) {
222 pBase += 2;
223 write_back = 0;
224 }
225
226 pFinal = pBase;
227 if (BIT_UP_SET(opcode))
228 pFinal += getOffset(opcode);
229 else
230 pFinal -= getOffset(opcode);
231
232 if (PREINDEXED(opcode))
233 pAddress = pFinal;
234 else
235 pAddress = pBase;
236
237 switch (opcode & MASK_TRANSFER_LENGTH) {
238 case TRANSFER_SINGLE:
239 loadSingle(getFd(opcode), pAddress);
240 break;
241 case TRANSFER_DOUBLE:
242 loadDouble(getFd(opcode), pAddress);
243 break;
244#ifdef CONFIG_FPE_NWFPE_XP
245 case TRANSFER_EXTENDED:
246 loadExtended(getFd(opcode), pAddress);
247 break;
248#endif
249 default:
250 nRc = 0;
251 }
252
253 if (write_back)
254 writeRegister(getRn(opcode), (unsigned long) pFinal);
255 return nRc;
256}
257
258unsigned int PerformSTF(const unsigned int opcode)
259{
260 unsigned int __user *pBase, *pAddress, *pFinal;
261 unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
262
263 SetRoundingMode(ROUND_TO_NEAREST);
264
265 pBase = (unsigned int __user *) readRegister(getRn(opcode));
266 if (REG_PC == getRn(opcode)) {
267 pBase += 2;
268 write_back = 0;
269 }
270
271 pFinal = pBase;
272 if (BIT_UP_SET(opcode))
273 pFinal += getOffset(opcode);
274 else
275 pFinal -= getOffset(opcode);
276
277 if (PREINDEXED(opcode))
278 pAddress = pFinal;
279 else
280 pAddress = pBase;
281
282 switch (opcode & MASK_TRANSFER_LENGTH) {
283 case TRANSFER_SINGLE:
284 storeSingle(getFd(opcode), pAddress);
285 break;
286 case TRANSFER_DOUBLE:
287 storeDouble(getFd(opcode), pAddress);
288 break;
289#ifdef CONFIG_FPE_NWFPE_XP
290 case TRANSFER_EXTENDED:
291 storeExtended(getFd(opcode), pAddress);
292 break;
293#endif
294 default:
295 nRc = 0;
296 }
297
298 if (write_back)
299 writeRegister(getRn(opcode), (unsigned long) pFinal);
300 return nRc;
301}
302
303unsigned int PerformLFM(const unsigned int opcode)
304{
305 unsigned int __user *pBase, *pAddress, *pFinal;
306 unsigned int i, Fd, write_back = WRITE_BACK(opcode);
307
308 pBase = (unsigned int __user *) readRegister(getRn(opcode));
309 if (REG_PC == getRn(opcode)) {
310 pBase += 2;
311 write_back = 0;
312 }
313
314 pFinal = pBase;
315 if (BIT_UP_SET(opcode))
316 pFinal += getOffset(opcode);
317 else
318 pFinal -= getOffset(opcode);
319
320 if (PREINDEXED(opcode))
321 pAddress = pFinal;
322 else
323 pAddress = pBase;
324
325 Fd = getFd(opcode);
326 for (i = getRegisterCount(opcode); i > 0; i--) {
327 loadMultiple(Fd, pAddress);
328 pAddress += 3;
329 Fd++;
330 if (Fd == 8)
331 Fd = 0;
332 }
333
334 if (write_back)
335 writeRegister(getRn(opcode), (unsigned long) pFinal);
336 return 1;
337}
338
339unsigned int PerformSFM(const unsigned int opcode)
340{
341 unsigned int __user *pBase, *pAddress, *pFinal;
342 unsigned int i, Fd, write_back = WRITE_BACK(opcode);
343
344 pBase = (unsigned int __user *) readRegister(getRn(opcode));
345 if (REG_PC == getRn(opcode)) {
346 pBase += 2;
347 write_back = 0;
348 }
349
350 pFinal = pBase;
351 if (BIT_UP_SET(opcode))
352 pFinal += getOffset(opcode);
353 else
354 pFinal -= getOffset(opcode);
355
356 if (PREINDEXED(opcode))
357 pAddress = pFinal;
358 else
359 pAddress = pBase;
360
361 Fd = getFd(opcode);
362 for (i = getRegisterCount(opcode); i > 0; i--) {
363 storeMultiple(Fd, pAddress);
364 pAddress += 3;
365 Fd++;
366 if (Fd == 8)
367 Fd = 0;
368 }
369
370 if (write_back)
371 writeRegister(getRn(opcode), (unsigned long) pFinal);
372 return 1;
373}
374
375unsigned int EmulateCPDT(const unsigned int opcode)
376{
377 unsigned int nRc = 0;
378
379 if (LDF_OP(opcode)) {
380 nRc = PerformLDF(opcode);
381 } else if (LFM_OP(opcode)) {
382 nRc = PerformLFM(opcode);
383 } else if (STF_OP(opcode)) {
384 nRc = PerformSTF(opcode);
385 } else if (SFM_OP(opcode)) {
386 nRc = PerformSFM(opcode);
387 } else {
388 nRc = 0;
389 }
390
391 return nRc;
392}
diff --git a/arch/arm/nwfpe/fpa11_cprt.c b/arch/arm/nwfpe/fpa11_cprt.c
new file mode 100644
index 000000000000..db01fbc97216
--- /dev/null
+++ b/arch/arm/nwfpe/fpa11_cprt.c
@@ -0,0 +1,369 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.COM, 1998,1999
4 (c) Philip Blundell, 1999, 2001
5
6 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#include <linux/config.h>
24#include "fpa11.h"
25#include "fpopcode.h"
26#include "fpa11.inl"
27#include "fpmodule.h"
28#include "fpmodule.inl"
29
30#ifdef CONFIG_FPE_NWFPE_XP
31extern flag floatx80_is_nan(floatx80);
32#endif
33extern flag float64_is_nan(float64);
34extern flag float32_is_nan(float32);
35
36void SetRoundingMode(const unsigned int opcode);
37
38unsigned int PerformFLT(const unsigned int opcode);
39unsigned int PerformFIX(const unsigned int opcode);
40
41static unsigned int PerformComparison(const unsigned int opcode);
42
43unsigned int EmulateCPRT(const unsigned int opcode)
44{
45
46 if (opcode & 0x800000) {
47 /* This is some variant of a comparison (PerformComparison
48 will sort out which one). Since most of the other CPRT
49 instructions are oddball cases of some sort or other it
50 makes sense to pull this out into a fast path. */
51 return PerformComparison(opcode);
52 }
53
54 /* Hint to GCC that we'd like a jump table rather than a load of CMPs */
55 switch ((opcode & 0x700000) >> 20) {
56 case FLT_CODE >> 20:
57 return PerformFLT(opcode);
58 break;
59 case FIX_CODE >> 20:
60 return PerformFIX(opcode);
61 break;
62
63 case WFS_CODE >> 20:
64 writeFPSR(readRegister(getRd(opcode)));
65 break;
66 case RFS_CODE >> 20:
67 writeRegister(getRd(opcode), readFPSR());
68 break;
69
70 default:
71 return 0;
72 }
73
74 return 1;
75}
76
77unsigned int PerformFLT(const unsigned int opcode)
78{
79 FPA11 *fpa11 = GET_FPA11();
80 SetRoundingMode(opcode);
81 SetRoundingPrecision(opcode);
82
83 switch (opcode & MASK_ROUNDING_PRECISION) {
84 case ROUND_SINGLE:
85 {
86 fpa11->fType[getFn(opcode)] = typeSingle;
87 fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode)));
88 }
89 break;
90
91 case ROUND_DOUBLE:
92 {
93 fpa11->fType[getFn(opcode)] = typeDouble;
94 fpa11->fpreg[getFn(opcode)].fDouble = int32_to_float64(readRegister(getRd(opcode)));
95 }
96 break;
97
98#ifdef CONFIG_FPE_NWFPE_XP
99 case ROUND_EXTENDED:
100 {
101 fpa11->fType[getFn(opcode)] = typeExtended;
102 fpa11->fpreg[getFn(opcode)].fExtended = int32_to_floatx80(readRegister(getRd(opcode)));
103 }
104 break;
105#endif
106
107 default:
108 return 0;
109 }
110
111 return 1;
112}
113
114unsigned int PerformFIX(const unsigned int opcode)
115{
116 FPA11 *fpa11 = GET_FPA11();
117 unsigned int Fn = getFm(opcode);
118
119 SetRoundingMode(opcode);
120
121 switch (fpa11->fType[Fn]) {
122 case typeSingle:
123 {
124 writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle));
125 }
126 break;
127
128 case typeDouble:
129 {
130 writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble));
131 }
132 break;
133
134#ifdef CONFIG_FPE_NWFPE_XP
135 case typeExtended:
136 {
137 writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended));
138 }
139 break;
140#endif
141
142 default:
143 return 0;
144 }
145
146 return 1;
147}
148
149/* This instruction sets the flags N, Z, C, V in the FPSR. */
150static unsigned int PerformComparison(const unsigned int opcode)
151{
152 FPA11 *fpa11 = GET_FPA11();
153 unsigned int Fn = getFn(opcode), Fm = getFm(opcode);
154 int e_flag = opcode & 0x400000; /* 1 if CxFE */
155 int n_flag = opcode & 0x200000; /* 1 if CNxx */
156 unsigned int flags = 0;
157
158#ifdef CONFIG_FPE_NWFPE_XP
159 floatx80 rFn, rFm;
160
161 /* Check for unordered condition and convert all operands to 80-bit
162 format.
163 ?? Might be some mileage in avoiding this conversion if possible.
164 Eg, if both operands are 32-bit, detect this and do a 32-bit
165 comparison (cheaper than an 80-bit one). */
166 switch (fpa11->fType[Fn]) {
167 case typeSingle:
168 //printk("single.\n");
169 if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
170 goto unordered;
171 rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
172 break;
173
174 case typeDouble:
175 //printk("double.\n");
176 if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
177 goto unordered;
178 rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
179 break;
180
181 case typeExtended:
182 //printk("extended.\n");
183 if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
184 goto unordered;
185 rFn = fpa11->fpreg[Fn].fExtended;
186 break;
187
188 default:
189 return 0;
190 }
191
192 if (CONSTANT_FM(opcode)) {
193 //printk("Fm is a constant: #%d.\n",Fm);
194 rFm = getExtendedConstant(Fm);
195 if (floatx80_is_nan(rFm))
196 goto unordered;
197 } else {
198 //printk("Fm = r%d which contains a ",Fm);
199 switch (fpa11->fType[Fm]) {
200 case typeSingle:
201 //printk("single.\n");
202 if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
203 goto unordered;
204 rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
205 break;
206
207 case typeDouble:
208 //printk("double.\n");
209 if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
210 goto unordered;
211 rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
212 break;
213
214 case typeExtended:
215 //printk("extended.\n");
216 if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
217 goto unordered;
218 rFm = fpa11->fpreg[Fm].fExtended;
219 break;
220
221 default:
222 return 0;
223 }
224 }
225
226 if (n_flag)
227 rFm.high ^= 0x8000;
228
229 /* test for less than condition */
230 if (floatx80_lt(rFn, rFm))
231 flags |= CC_NEGATIVE;
232
233 /* test for equal condition */
234 if (floatx80_eq(rFn, rFm))
235 flags |= CC_ZERO;
236
237 /* test for greater than or equal condition */
238 if (floatx80_lt(rFm, rFn))
239 flags |= CC_CARRY;
240
241#else
242 if (CONSTANT_FM(opcode)) {
243 /* Fm is a constant. Do the comparison in whatever precision
244 Fn happens to be stored in. */
245 if (fpa11->fType[Fn] == typeSingle) {
246 float32 rFm = getSingleConstant(Fm);
247 float32 rFn = fpa11->fpreg[Fn].fSingle;
248
249 if (float32_is_nan(rFn))
250 goto unordered;
251
252 if (n_flag)
253 rFm ^= 0x80000000;
254
255 /* test for less than condition */
256 if (float32_lt_nocheck(rFn, rFm))
257 flags |= CC_NEGATIVE;
258
259 /* test for equal condition */
260 if (float32_eq_nocheck(rFn, rFm))
261 flags |= CC_ZERO;
262
263 /* test for greater than or equal condition */
264 if (float32_lt_nocheck(rFm, rFn))
265 flags |= CC_CARRY;
266 } else {
267 float64 rFm = getDoubleConstant(Fm);
268 float64 rFn = fpa11->fpreg[Fn].fDouble;
269
270 if (float64_is_nan(rFn))
271 goto unordered;
272
273 if (n_flag)
274 rFm ^= 0x8000000000000000ULL;
275
276 /* test for less than condition */
277 if (float64_lt_nocheck(rFn, rFm))
278 flags |= CC_NEGATIVE;
279
280 /* test for equal condition */
281 if (float64_eq_nocheck(rFn, rFm))
282 flags |= CC_ZERO;
283
284 /* test for greater than or equal condition */
285 if (float64_lt_nocheck(rFm, rFn))
286 flags |= CC_CARRY;
287 }
288 } else {
289 /* Both operands are in registers. */
290 if (fpa11->fType[Fn] == typeSingle
291 && fpa11->fType[Fm] == typeSingle) {
292 float32 rFm = fpa11->fpreg[Fm].fSingle;
293 float32 rFn = fpa11->fpreg[Fn].fSingle;
294
295 if (float32_is_nan(rFn)
296 || float32_is_nan(rFm))
297 goto unordered;
298
299 if (n_flag)
300 rFm ^= 0x80000000;
301
302 /* test for less than condition */
303 if (float32_lt_nocheck(rFn, rFm))
304 flags |= CC_NEGATIVE;
305
306 /* test for equal condition */
307 if (float32_eq_nocheck(rFn, rFm))
308 flags |= CC_ZERO;
309
310 /* test for greater than or equal condition */
311 if (float32_lt_nocheck(rFm, rFn))
312 flags |= CC_CARRY;
313 } else {
314 /* Promote 32-bit operand to 64 bits. */
315 float64 rFm, rFn;
316
317 rFm = (fpa11->fType[Fm] == typeSingle) ?
318 float32_to_float64(fpa11->fpreg[Fm].fSingle)
319 : fpa11->fpreg[Fm].fDouble;
320
321 rFn = (fpa11->fType[Fn] == typeSingle) ?
322 float32_to_float64(fpa11->fpreg[Fn].fSingle)
323 : fpa11->fpreg[Fn].fDouble;
324
325 if (float64_is_nan(rFn)
326 || float64_is_nan(rFm))
327 goto unordered;
328
329 if (n_flag)
330 rFm ^= 0x8000000000000000ULL;
331
332 /* test for less than condition */
333 if (float64_lt_nocheck(rFn, rFm))
334 flags |= CC_NEGATIVE;
335
336 /* test for equal condition */
337 if (float64_eq_nocheck(rFn, rFm))
338 flags |= CC_ZERO;
339
340 /* test for greater than or equal condition */
341 if (float64_lt_nocheck(rFm, rFn))
342 flags |= CC_CARRY;
343 }
344 }
345
346#endif
347
348 writeConditionCodes(flags);
349
350 return 1;
351
352 unordered:
353 /* ?? The FPA data sheet is pretty vague about this, in particular
354 about whether the non-E comparisons can ever raise exceptions.
355 This implementation is based on a combination of what it says in
356 the data sheet, observation of how the Acorn emulator actually
357 behaves (and how programs expect it to) and guesswork. */
358 flags |= CC_OVERFLOW;
359 flags &= ~(CC_ZERO | CC_NEGATIVE);
360
361 if (BIT_AC & readFPSR())
362 flags |= CC_CARRY;
363
364 if (e_flag)
365 float_raise(float_flag_invalid);
366
367 writeConditionCodes(flags);
368 return 1;
369}
diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c
new file mode 100644
index 000000000000..a806fea5c3ed
--- /dev/null
+++ b/arch/arm/nwfpe/fpmodule.c
@@ -0,0 +1,173 @@
1
2/*
3 NetWinder Floating Point Emulator
4 (c) Rebel.com, 1998-1999
5 (c) Philip Blundell, 1998-1999
6
7 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24#include "fpa11.h"
25
26#include <linux/module.h>
27#include <linux/version.h>
28#include <linux/config.h>
29
30/* XXX */
31#include <linux/errno.h>
32#include <linux/types.h>
33#include <linux/kernel.h>
34#include <linux/signal.h>
35#include <linux/sched.h>
36#include <linux/init.h>
37/* XXX */
38
39#include "softfloat.h"
40#include "fpopcode.h"
41#include "fpmodule.h"
42#include "fpa11.inl"
43
44/* kernel symbols required for signal handling */
45#ifdef CONFIG_FPE_NWFPE_XP
46#define NWFPE_BITS "extended"
47#else
48#define NWFPE_BITS "double"
49#endif
50
51#ifdef MODULE
52void fp_send_sig(unsigned long sig, struct task_struct *p, int priv);
53#else
54#define fp_send_sig send_sig
55#define kern_fp_enter fp_enter
56
57extern char fpe_type[];
58#endif
59
60/* kernel function prototypes required */
61void fp_setup(void);
62
63/* external declarations for saved kernel symbols */
64extern void (*kern_fp_enter)(void);
65extern void (*fp_init)(union fp_state *);
66
67/* Original value of fp_enter from kernel before patched by fpe_init. */
68static void (*orig_fp_enter)(void);
69static void (*orig_fp_init)(union fp_state *);
70
71/* forward declarations */
72extern void nwfpe_enter(void);
73
74static int __init fpe_init(void)
75{
76 if (sizeof(FPA11) > sizeof(union fp_state)) {
77 printk(KERN_ERR "nwfpe: bad structure size\n");
78 return -EINVAL;
79 }
80
81 if (sizeof(FPREG) != 12) {
82 printk(KERN_ERR "nwfpe: bad register size\n");
83 return -EINVAL;
84 }
85 if (fpe_type[0] && strcmp(fpe_type, "nwfpe"))
86 return 0;
87
88 /* Display title, version and copyright information. */
89 printk(KERN_WARNING "NetWinder Floating Point Emulator V0.97 ("
90 NWFPE_BITS " precision)\n");
91
92 /* Save pointer to the old FP handler and then patch ourselves in */
93 orig_fp_enter = kern_fp_enter;
94 orig_fp_init = fp_init;
95 kern_fp_enter = nwfpe_enter;
96 fp_init = nwfpe_init_fpa;
97
98 return 0;
99}
100
101static void __exit fpe_exit(void)
102{
103 /* Restore the values we saved earlier. */
104 kern_fp_enter = orig_fp_enter;
105 fp_init = orig_fp_init;
106}
107
108/*
109ScottB: November 4, 1998
110
111Moved this function out of softfloat-specialize into fpmodule.c.
112This effectively isolates all the changes required for integrating with the
113Linux kernel into fpmodule.c. Porting to NetBSD should only require modifying
114fpmodule.c to integrate with the NetBSD kernel (I hope!).
115
116[1/1/99: Not quite true any more unfortunately. There is Linux-specific
117code to access data in user space in some other source files at the
118moment (grep for get_user / put_user calls). --philb]
119
120float_exception_flags is a global variable in SoftFloat.
121
122This function is called by the SoftFloat routines to raise a floating
123point exception. We check the trap enable byte in the FPSR, and raise
124a SIGFPE exception if necessary. If not the relevant bits in the
125cumulative exceptions flag byte are set and we return.
126*/
127
128void float_raise(signed char flags)
129{
130 register unsigned int fpsr, cumulativeTraps;
131
132#ifdef CONFIG_DEBUG_USER
133 printk(KERN_DEBUG
134 "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n",
135 current->comm, current->pid, flags,
136 __builtin_return_address(0), GET_USERREG()[15]);
137#endif
138
139 /* Keep SoftFloat exception flags up to date. */
140 float_exception_flags |= flags;
141
142 /* Read fpsr and initialize the cumulativeTraps. */
143 fpsr = readFPSR();
144 cumulativeTraps = 0;
145
146 /* For each type of exception, the cumulative trap exception bit is only
147 set if the corresponding trap enable bit is not set. */
148 if ((!(fpsr & BIT_IXE)) && (flags & BIT_IXC))
149 cumulativeTraps |= BIT_IXC;
150 if ((!(fpsr & BIT_UFE)) && (flags & BIT_UFC))
151 cumulativeTraps |= BIT_UFC;
152 if ((!(fpsr & BIT_OFE)) && (flags & BIT_OFC))
153 cumulativeTraps |= BIT_OFC;
154 if ((!(fpsr & BIT_DZE)) && (flags & BIT_DZC))
155 cumulativeTraps |= BIT_DZC;
156 if ((!(fpsr & BIT_IOE)) && (flags & BIT_IOC))
157 cumulativeTraps |= BIT_IOC;
158
159 /* Set the cumulative exceptions flags. */
160 if (cumulativeTraps)
161 writeFPSR(fpsr | cumulativeTraps);
162
163 /* Raise an exception if necessary. */
164 if (fpsr & (flags << 16))
165 fp_send_sig(SIGFPE, current, 1);
166}
167
168module_init(fpe_init);
169module_exit(fpe_exit);
170
171MODULE_AUTHOR("Scott Bambrough <scottb@rebel.com>");
172MODULE_DESCRIPTION("NWFPE floating point emulator (" NWFPE_BITS " precision)");
173MODULE_LICENSE("GPL");
diff --git a/arch/arm/nwfpe/fpmodule.h b/arch/arm/nwfpe/fpmodule.h
new file mode 100644
index 000000000000..5c2e8e48544b
--- /dev/null
+++ b/arch/arm/nwfpe/fpmodule.h
@@ -0,0 +1,47 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.com, 1998-1999
4
5 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 27/03/03 Ian Molton Clean up CONFIG_CPU
22*/
23
24#ifndef __FPMODULE_H__
25#define __FPMODULE_H__
26
27#define REG_ORIG_R0 17
28#define REG_CPSR 16
29#define REG_PC 15
30#define REG_LR 14
31#define REG_SP 13
32#define REG_IP 12
33#define REG_FP 11
34#define REG_R10 10
35#define REG_R9 9
36#define REG_R9 9
37#define REG_R8 8
38#define REG_R7 7
39#define REG_R6 6
40#define REG_R5 5
41#define REG_R4 4
42#define REG_R3 3
43#define REG_R2 2
44#define REG_R1 1
45#define REG_R0 0
46
47#endif
diff --git a/arch/arm/nwfpe/fpmodule.inl b/arch/arm/nwfpe/fpmodule.inl
new file mode 100644
index 000000000000..e5f59e9a3022
--- /dev/null
+++ b/arch/arm/nwfpe/fpmodule.inl
@@ -0,0 +1,74 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.COM, 1998,1999
4
5 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22static inline unsigned long readRegister(const unsigned int nReg)
23{
24 /* Note: The CPU thinks it has dealt with the current instruction.
25 As a result the program counter has been advanced to the next
26 instruction, and points 4 bytes beyond the actual instruction
27 that caused the invalid instruction trap to occur. We adjust
28 for this in this routine. LDF/STF instructions with Rn = PC
29 depend on the PC being correct, as they use PC+8 in their
30 address calculations. */
31 unsigned long *userRegisters = GET_USERREG();
32 unsigned int val = userRegisters[nReg];
33 if (REG_PC == nReg)
34 val -= 4;
35 return val;
36}
37
38static inline void
39writeRegister(const unsigned int nReg, const unsigned long val)
40{
41 unsigned long *userRegisters = GET_USERREG();
42 userRegisters[nReg] = val;
43}
44
45static inline unsigned long readCPSR(void)
46{
47 return (readRegister(REG_CPSR));
48}
49
50static inline void writeCPSR(const unsigned long val)
51{
52 writeRegister(REG_CPSR, val);
53}
54
55static inline unsigned long readConditionCodes(void)
56{
57#ifdef __FPEM_TEST__
58 return (0);
59#else
60 return (readCPSR() & CC_MASK);
61#endif
62}
63
64static inline void writeConditionCodes(const unsigned long val)
65{
66 unsigned long *userRegisters = GET_USERREG();
67 unsigned long rval;
68 /*
69 * Operate directly on userRegisters since
70 * the CPSR may be the PC register itself.
71 */
72 rval = userRegisters[REG_CPSR] & ~CC_MASK;
73 userRegisters[REG_CPSR] = rval | (val & CC_MASK);
74}
diff --git a/arch/arm/nwfpe/fpopcode.c b/arch/arm/nwfpe/fpopcode.c
new file mode 100644
index 000000000000..4c9f5703148c
--- /dev/null
+++ b/arch/arm/nwfpe/fpopcode.c
@@ -0,0 +1,90 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.COM, 1998,1999
4
5 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include <linux/config.h>
23#include "fpa11.h"
24#include "softfloat.h"
25#include "fpopcode.h"
26#include "fpsr.h"
27#include "fpmodule.h"
28#include "fpmodule.inl"
29
30#ifdef CONFIG_FPE_NWFPE_XP
31const floatx80 floatx80Constant[] = {
32 {0x0000, 0x0000000000000000ULL}, /* extended 0.0 */
33 {0x3fff, 0x8000000000000000ULL}, /* extended 1.0 */
34 {0x4000, 0x8000000000000000ULL}, /* extended 2.0 */
35 {0x4000, 0xc000000000000000ULL}, /* extended 3.0 */
36 {0x4001, 0x8000000000000000ULL}, /* extended 4.0 */
37 {0x4001, 0xa000000000000000ULL}, /* extended 5.0 */
38 {0x3ffe, 0x8000000000000000ULL}, /* extended 0.5 */
39 {0x4002, 0xa000000000000000ULL} /* extended 10.0 */
40};
41#endif
42
43const float64 float64Constant[] = {
44 0x0000000000000000ULL, /* double 0.0 */
45 0x3ff0000000000000ULL, /* double 1.0 */
46 0x4000000000000000ULL, /* double 2.0 */
47 0x4008000000000000ULL, /* double 3.0 */
48 0x4010000000000000ULL, /* double 4.0 */
49 0x4014000000000000ULL, /* double 5.0 */
50 0x3fe0000000000000ULL, /* double 0.5 */
51 0x4024000000000000ULL /* double 10.0 */
52};
53
54const float32 float32Constant[] = {
55 0x00000000, /* single 0.0 */
56 0x3f800000, /* single 1.0 */
57 0x40000000, /* single 2.0 */
58 0x40400000, /* single 3.0 */
59 0x40800000, /* single 4.0 */
60 0x40a00000, /* single 5.0 */
61 0x3f000000, /* single 0.5 */
62 0x41200000 /* single 10.0 */
63};
64
65/* condition code lookup table
66 index into the table is test code: EQ, NE, ... LT, GT, AL, NV
67 bit position in short is condition code: NZCV */
68static const unsigned short aCC[16] = {
69 0xF0F0, // EQ == Z set
70 0x0F0F, // NE
71 0xCCCC, // CS == C set
72 0x3333, // CC
73 0xFF00, // MI == N set
74 0x00FF, // PL
75 0xAAAA, // VS == V set
76 0x5555, // VC
77 0x0C0C, // HI == C set && Z clear
78 0xF3F3, // LS == C clear || Z set
79 0xAA55, // GE == (N==V)
80 0x55AA, // LT == (N!=V)
81 0x0A05, // GT == (!Z && (N==V))
82 0xF5FA, // LE == (Z || (N!=V))
83 0xFFFF, // AL always
84 0 // NV
85};
86
87unsigned int checkCondition(const unsigned int opcode, const unsigned int ccodes)
88{
89 return (aCC[opcode >> 28] >> (ccodes >> 28)) & 1;
90}
diff --git a/arch/arm/nwfpe/fpopcode.h b/arch/arm/nwfpe/fpopcode.h
new file mode 100644
index 000000000000..8035f4faafbf
--- /dev/null
+++ b/arch/arm/nwfpe/fpopcode.h
@@ -0,0 +1,479 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.COM, 1998,1999
4 (c) Philip Blundell, 2001
5
6 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#ifndef __FPOPCODE_H__
24#define __FPOPCODE_H__
25
26#include <linux/config.h>
27
28/*
29ARM Floating Point Instruction Classes
30| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
31|c o n d|1 1 0 P|U|u|W|L| Rn |v| Fd |0|0|0|1| o f f s e t | CPDT
32|c o n d|1 1 0 P|U|w|W|L| Rn |x| Fd |0|0|1|0| o f f s e t | CPDT (copro 2)
33| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
34|c o n d|1 1 1 0|a|b|c|d|e| Fn |j| Fd |0|0|0|1|f|g|h|0|i| Fm | CPDO
35|c o n d|1 1 1 0|a|b|c|L|e| Fn | Rd |0|0|0|1|f|g|h|1|i| Fm | CPRT
36|c o n d|1 1 1 0|a|b|c|1|e| Fn |1|1|1|1|0|0|0|1|f|g|h|1|i| Fm | comparisons
37| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
38
39CPDT data transfer instructions
40 LDF, STF, LFM (copro 2), SFM (copro 2)
41
42CPDO dyadic arithmetic instructions
43 ADF, MUF, SUF, RSF, DVF, RDF,
44 POW, RPW, RMF, FML, FDV, FRD, POL
45
46CPDO monadic arithmetic instructions
47 MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP,
48 SIN, COS, TAN, ASN, ACS, ATN, URD, NRM
49
50CPRT joint arithmetic/data transfer instructions
51 FIX (arithmetic followed by load/store)
52 FLT (load/store followed by arithmetic)
53 CMF, CNF CMFE, CNFE (comparisons)
54 WFS, RFS (write/read floating point status register)
55 WFC, RFC (write/read floating point control register)
56
57cond condition codes
58P pre/post index bit: 0 = postindex, 1 = preindex
59U up/down bit: 0 = stack grows down, 1 = stack grows up
60W write back bit: 1 = update base register (Rn)
61L load/store bit: 0 = store, 1 = load
62Rn base register
63Rd destination/source register
64Fd floating point destination register
65Fn floating point source register
66Fm floating point source register or floating point constant
67
68uv transfer length (TABLE 1)
69wx register count (TABLE 2)
70abcd arithmetic opcode (TABLES 3 & 4)
71ef destination size (rounding precision) (TABLE 5)
72gh rounding mode (TABLE 6)
73j dyadic/monadic bit: 0 = dyadic, 1 = monadic
74i constant bit: 1 = constant (TABLE 6)
75*/
76
77/*
78TABLE 1
79+-------------------------+---+---+---------+---------+
80| Precision | u | v | FPSR.EP | length |
81+-------------------------+---+---+---------+---------+
82| Single | 0 ü 0 | x | 1 words |
83| Double | 1 ü 1 | x | 2 words |
84| Extended | 1 ü 1 | x | 3 words |
85| Packed decimal | 1 ü 1 | 0 | 3 words |
86| Expanded packed decimal | 1 ü 1 | 1 | 4 words |
87+-------------------------+---+---+---------+---------+
88Note: x = don't care
89*/
90
91/*
92TABLE 2
93+---+---+---------------------------------+
94| w | x | Number of registers to transfer |
95+---+---+---------------------------------+
96| 0 ü 1 | 1 |
97| 1 ü 0 | 2 |
98| 1 ü 1 | 3 |
99| 0 ü 0 | 4 |
100+---+---+---------------------------------+
101*/
102
103/*
104TABLE 3: Dyadic Floating Point Opcodes
105+---+---+---+---+----------+-----------------------+-----------------------+
106| a | b | c | d | Mnemonic | Description | Operation |
107+---+---+---+---+----------+-----------------------+-----------------------+
108| 0 | 0 | 0 | 0 | ADF | Add | Fd := Fn + Fm |
109| 0 | 0 | 0 | 1 | MUF | Multiply | Fd := Fn * Fm |
110| 0 | 0 | 1 | 0 | SUF | Subtract | Fd := Fn - Fm |
111| 0 | 0 | 1 | 1 | RSF | Reverse subtract | Fd := Fm - Fn |
112| 0 | 1 | 0 | 0 | DVF | Divide | Fd := Fn / Fm |
113| 0 | 1 | 0 | 1 | RDF | Reverse divide | Fd := Fm / Fn |
114| 0 | 1 | 1 | 0 | POW | Power | Fd := Fn ^ Fm |
115| 0 | 1 | 1 | 1 | RPW | Reverse power | Fd := Fm ^ Fn |
116| 1 | 0 | 0 | 0 | RMF | Remainder | Fd := IEEE rem(Fn/Fm) |
117| 1 | 0 | 0 | 1 | FML | Fast Multiply | Fd := Fn * Fm |
118| 1 | 0 | 1 | 0 | FDV | Fast Divide | Fd := Fn / Fm |
119| 1 | 0 | 1 | 1 | FRD | Fast reverse divide | Fd := Fm / Fn |
120| 1 | 1 | 0 | 0 | POL | Polar angle (ArcTan2) | Fd := arctan2(Fn,Fm) |
121| 1 | 1 | 0 | 1 | | undefined instruction | trap |
122| 1 | 1 | 1 | 0 | | undefined instruction | trap |
123| 1 | 1 | 1 | 1 | | undefined instruction | trap |
124+---+---+---+---+----------+-----------------------+-----------------------+
125Note: POW, RPW, POL are deprecated, and are available for backwards
126 compatibility only.
127*/
128
129/*
130TABLE 4: Monadic Floating Point Opcodes
131+---+---+---+---+----------+-----------------------+-----------------------+
132| a | b | c | d | Mnemonic | Description | Operation |
133+---+---+---+---+----------+-----------------------+-----------------------+
134| 0 | 0 | 0 | 0 | MVF | Move | Fd := Fm |
135| 0 | 0 | 0 | 1 | MNF | Move negated | Fd := - Fm |
136| 0 | 0 | 1 | 0 | ABS | Absolute value | Fd := abs(Fm) |
137| 0 | 0 | 1 | 1 | RND | Round to integer | Fd := int(Fm) |
138| 0 | 1 | 0 | 0 | SQT | Square root | Fd := sqrt(Fm) |
139| 0 | 1 | 0 | 1 | LOG | Log base 10 | Fd := log10(Fm) |
140| 0 | 1 | 1 | 0 | LGN | Log base e | Fd := ln(Fm) |
141| 0 | 1 | 1 | 1 | EXP | Exponent | Fd := e ^ Fm |
142| 1 | 0 | 0 | 0 | SIN | Sine | Fd := sin(Fm) |
143| 1 | 0 | 0 | 1 | COS | Cosine | Fd := cos(Fm) |
144| 1 | 0 | 1 | 0 | TAN | Tangent | Fd := tan(Fm) |
145| 1 | 0 | 1 | 1 | ASN | Arc Sine | Fd := arcsin(Fm) |
146| 1 | 1 | 0 | 0 | ACS | Arc Cosine | Fd := arccos(Fm) |
147| 1 | 1 | 0 | 1 | ATN | Arc Tangent | Fd := arctan(Fm) |
148| 1 | 1 | 1 | 0 | URD | Unnormalized round | Fd := int(Fm) |
149| 1 | 1 | 1 | 1 | NRM | Normalize | Fd := norm(Fm) |
150+---+---+---+---+----------+-----------------------+-----------------------+
151Note: LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN are deprecated, and are
152 available for backwards compatibility only.
153*/
154
155/*
156TABLE 5
157+-------------------------+---+---+
158| Rounding Precision | e | f |
159+-------------------------+---+---+
160| IEEE Single precision | 0 ü 0 |
161| IEEE Double precision | 0 ü 1 |
162| IEEE Extended precision | 1 ü 0 |
163| undefined (trap) | 1 ü 1 |
164+-------------------------+---+---+
165*/
166
167/*
168TABLE 5
169+---------------------------------+---+---+
170| Rounding Mode | g | h |
171+---------------------------------+---+---+
172| Round to nearest (default) | 0 ü 0 |
173| Round toward plus infinity | 0 ü 1 |
174| Round toward negative infinity | 1 ü 0 |
175| Round toward zero | 1 ü 1 |
176+---------------------------------+---+---+
177*/
178
179/*
180===
181=== Definitions for load and store instructions
182===
183*/
184
185/* bit masks */
186#define BIT_PREINDEX 0x01000000
187#define BIT_UP 0x00800000
188#define BIT_WRITE_BACK 0x00200000
189#define BIT_LOAD 0x00100000
190
191/* masks for load/store */
192#define MASK_CPDT 0x0c000000 /* data processing opcode */
193#define MASK_OFFSET 0x000000ff
194#define MASK_TRANSFER_LENGTH 0x00408000
195#define MASK_REGISTER_COUNT MASK_TRANSFER_LENGTH
196#define MASK_COPROCESSOR 0x00000f00
197
198/* Tests for transfer length */
199#define TRANSFER_SINGLE 0x00000000
200#define TRANSFER_DOUBLE 0x00008000
201#define TRANSFER_EXTENDED 0x00400000
202#define TRANSFER_PACKED MASK_TRANSFER_LENGTH
203
204/* Get the coprocessor number from the opcode. */
205#define getCoprocessorNumber(opcode) ((opcode & MASK_COPROCESSOR) >> 8)
206
207/* Get the offset from the opcode. */
208#define getOffset(opcode) (opcode & MASK_OFFSET)
209
210/* Tests for specific data transfer load/store opcodes. */
211#define TEST_OPCODE(opcode,mask) (((opcode) & (mask)) == (mask))
212
213#define LOAD_OP(opcode) TEST_OPCODE((opcode),MASK_CPDT | BIT_LOAD)
214#define STORE_OP(opcode) ((opcode & (MASK_CPDT | BIT_LOAD)) == MASK_CPDT)
215
216#define LDF_OP(opcode) (LOAD_OP(opcode) && (getCoprocessorNumber(opcode) == 1))
217#define LFM_OP(opcode) (LOAD_OP(opcode) && (getCoprocessorNumber(opcode) == 2))
218#define STF_OP(opcode) (STORE_OP(opcode) && (getCoprocessorNumber(opcode) == 1))
219#define SFM_OP(opcode) (STORE_OP(opcode) && (getCoprocessorNumber(opcode) == 2))
220
221#define PREINDEXED(opcode) ((opcode & BIT_PREINDEX) != 0)
222#define POSTINDEXED(opcode) ((opcode & BIT_PREINDEX) == 0)
223#define BIT_UP_SET(opcode) ((opcode & BIT_UP) != 0)
224#define BIT_UP_CLEAR(opcode) ((opcode & BIT_DOWN) == 0)
225#define WRITE_BACK(opcode) ((opcode & BIT_WRITE_BACK) != 0)
226#define LOAD(opcode) ((opcode & BIT_LOAD) != 0)
227#define STORE(opcode) ((opcode & BIT_LOAD) == 0)
228
229/*
230===
231=== Definitions for arithmetic instructions
232===
233*/
234/* bit masks */
235#define BIT_MONADIC 0x00008000
236#define BIT_CONSTANT 0x00000008
237
238#define CONSTANT_FM(opcode) ((opcode & BIT_CONSTANT) != 0)
239#define MONADIC_INSTRUCTION(opcode) ((opcode & BIT_MONADIC) != 0)
240
241/* instruction identification masks */
242#define MASK_CPDO 0x0e000000 /* arithmetic opcode */
243#define MASK_ARITHMETIC_OPCODE 0x00f08000
244#define MASK_DESTINATION_SIZE 0x00080080
245
246/* dyadic arithmetic opcodes. */
247#define ADF_CODE 0x00000000
248#define MUF_CODE 0x00100000
249#define SUF_CODE 0x00200000
250#define RSF_CODE 0x00300000
251#define DVF_CODE 0x00400000
252#define RDF_CODE 0x00500000
253#define POW_CODE 0x00600000
254#define RPW_CODE 0x00700000
255#define RMF_CODE 0x00800000
256#define FML_CODE 0x00900000
257#define FDV_CODE 0x00a00000
258#define FRD_CODE 0x00b00000
259#define POL_CODE 0x00c00000
260/* 0x00d00000 is an invalid dyadic arithmetic opcode */
261/* 0x00e00000 is an invalid dyadic arithmetic opcode */
262/* 0x00f00000 is an invalid dyadic arithmetic opcode */
263
264/* monadic arithmetic opcodes. */
265#define MVF_CODE 0x00008000
266#define MNF_CODE 0x00108000
267#define ABS_CODE 0x00208000
268#define RND_CODE 0x00308000
269#define SQT_CODE 0x00408000
270#define LOG_CODE 0x00508000
271#define LGN_CODE 0x00608000
272#define EXP_CODE 0x00708000
273#define SIN_CODE 0x00808000
274#define COS_CODE 0x00908000
275#define TAN_CODE 0x00a08000
276#define ASN_CODE 0x00b08000
277#define ACS_CODE 0x00c08000
278#define ATN_CODE 0x00d08000
279#define URD_CODE 0x00e08000
280#define NRM_CODE 0x00f08000
281
282/*
283===
284=== Definitions for register transfer and comparison instructions
285===
286*/
287
288#define MASK_CPRT 0x0e000010 /* register transfer opcode */
289#define MASK_CPRT_CODE 0x00f00000
290#define FLT_CODE 0x00000000
291#define FIX_CODE 0x00100000
292#define WFS_CODE 0x00200000
293#define RFS_CODE 0x00300000
294#define WFC_CODE 0x00400000
295#define RFC_CODE 0x00500000
296#define CMF_CODE 0x00900000
297#define CNF_CODE 0x00b00000
298#define CMFE_CODE 0x00d00000
299#define CNFE_CODE 0x00f00000
300
301/*
302===
303=== Common definitions
304===
305*/
306
307/* register masks */
308#define MASK_Rd 0x0000f000
309#define MASK_Rn 0x000f0000
310#define MASK_Fd 0x00007000
311#define MASK_Fm 0x00000007
312#define MASK_Fn 0x00070000
313
314/* condition code masks */
315#define CC_MASK 0xf0000000
316#define CC_NEGATIVE 0x80000000
317#define CC_ZERO 0x40000000
318#define CC_CARRY 0x20000000
319#define CC_OVERFLOW 0x10000000
320#define CC_EQ 0x00000000
321#define CC_NE 0x10000000
322#define CC_CS 0x20000000
323#define CC_HS CC_CS
324#define CC_CC 0x30000000
325#define CC_LO CC_CC
326#define CC_MI 0x40000000
327#define CC_PL 0x50000000
328#define CC_VS 0x60000000
329#define CC_VC 0x70000000
330#define CC_HI 0x80000000
331#define CC_LS 0x90000000
332#define CC_GE 0xa0000000
333#define CC_LT 0xb0000000
334#define CC_GT 0xc0000000
335#define CC_LE 0xd0000000
336#define CC_AL 0xe0000000
337#define CC_NV 0xf0000000
338
339/* rounding masks/values */
340#define MASK_ROUNDING_MODE 0x00000060
341#define ROUND_TO_NEAREST 0x00000000
342#define ROUND_TO_PLUS_INFINITY 0x00000020
343#define ROUND_TO_MINUS_INFINITY 0x00000040
344#define ROUND_TO_ZERO 0x00000060
345
346#define MASK_ROUNDING_PRECISION 0x00080080
347#define ROUND_SINGLE 0x00000000
348#define ROUND_DOUBLE 0x00000080
349#define ROUND_EXTENDED 0x00080000
350
351/* Get the condition code from the opcode. */
352#define getCondition(opcode) (opcode >> 28)
353
354/* Get the source register from the opcode. */
355#define getRn(opcode) ((opcode & MASK_Rn) >> 16)
356
357/* Get the destination floating point register from the opcode. */
358#define getFd(opcode) ((opcode & MASK_Fd) >> 12)
359
360/* Get the first source floating point register from the opcode. */
361#define getFn(opcode) ((opcode & MASK_Fn) >> 16)
362
363/* Get the second source floating point register from the opcode. */
364#define getFm(opcode) (opcode & MASK_Fm)
365
366/* Get the destination register from the opcode. */
367#define getRd(opcode) ((opcode & MASK_Rd) >> 12)
368
369/* Get the rounding mode from the opcode. */
370#define getRoundingMode(opcode) ((opcode & MASK_ROUNDING_MODE) >> 5)
371
372#ifdef CONFIG_FPE_NWFPE_XP
373static inline const floatx80 getExtendedConstant(const unsigned int nIndex)
374{
375 extern const floatx80 floatx80Constant[];
376 return floatx80Constant[nIndex];
377}
378#endif
379
380static inline const float64 getDoubleConstant(const unsigned int nIndex)
381{
382 extern const float64 float64Constant[];
383 return float64Constant[nIndex];
384}
385
386static inline const float32 getSingleConstant(const unsigned int nIndex)
387{
388 extern const float32 float32Constant[];
389 return float32Constant[nIndex];
390}
391
392static inline unsigned int getTransferLength(const unsigned int opcode)
393{
394 unsigned int nRc;
395
396 switch (opcode & MASK_TRANSFER_LENGTH) {
397 case 0x00000000:
398 nRc = 1;
399 break; /* single precision */
400 case 0x00008000:
401 nRc = 2;
402 break; /* double precision */
403 case 0x00400000:
404 nRc = 3;
405 break; /* extended precision */
406 default:
407 nRc = 0;
408 }
409
410 return (nRc);
411}
412
413static inline unsigned int getRegisterCount(const unsigned int opcode)
414{
415 unsigned int nRc;
416
417 switch (opcode & MASK_REGISTER_COUNT) {
418 case 0x00000000:
419 nRc = 4;
420 break;
421 case 0x00008000:
422 nRc = 1;
423 break;
424 case 0x00400000:
425 nRc = 2;
426 break;
427 case 0x00408000:
428 nRc = 3;
429 break;
430 default:
431 nRc = 0;
432 }
433
434 return (nRc);
435}
436
437static inline unsigned int getRoundingPrecision(const unsigned int opcode)
438{
439 unsigned int nRc;
440
441 switch (opcode & MASK_ROUNDING_PRECISION) {
442 case 0x00000000:
443 nRc = 1;
444 break;
445 case 0x00000080:
446 nRc = 2;
447 break;
448 case 0x00080000:
449 nRc = 3;
450 break;
451 default:
452 nRc = 0;
453 }
454
455 return (nRc);
456}
457
458static inline unsigned int getDestinationSize(const unsigned int opcode)
459{
460 unsigned int nRc;
461
462 switch (opcode & MASK_DESTINATION_SIZE) {
463 case 0x00000000:
464 nRc = typeSingle;
465 break;
466 case 0x00000080:
467 nRc = typeDouble;
468 break;
469 case 0x00080000:
470 nRc = typeExtended;
471 break;
472 default:
473 nRc = typeNone;
474 }
475
476 return (nRc);
477}
478
479#endif
diff --git a/arch/arm/nwfpe/fpsr.h b/arch/arm/nwfpe/fpsr.h
new file mode 100644
index 000000000000..859b300d89fd
--- /dev/null
+++ b/arch/arm/nwfpe/fpsr.h
@@ -0,0 +1,108 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.com, 1998-1999
4
5 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#ifndef __FPSR_H__
23#define __FPSR_H__
24
25/*
26The FPSR is a 32 bit register consisting of 4 parts, each exactly
27one byte.
28
29 SYSTEM ID
30 EXCEPTION TRAP ENABLE BYTE
31 SYSTEM CONTROL BYTE
32 CUMULATIVE EXCEPTION FLAGS BYTE
33
34The FPCR is a 32 bit register consisting of bit flags.
35*/
36
37/* SYSTEM ID
38------------
39Note: the system id byte is read only */
40
41typedef unsigned int FPSR; /* type for floating point status register */
42typedef unsigned int FPCR; /* type for floating point control register */
43
44#define MASK_SYSID 0xff000000
45#define BIT_HARDWARE 0x80000000
46#define FP_EMULATOR 0x01000000 /* System ID for emulator */
47#define FP_ACCELERATOR 0x81000000 /* System ID for FPA11 */
48
49/* EXCEPTION TRAP ENABLE BYTE
50----------------------------- */
51
52#define MASK_TRAP_ENABLE 0x00ff0000
53#define MASK_TRAP_ENABLE_STRICT 0x001f0000
54#define BIT_IXE 0x00100000 /* inexact exception enable */
55#define BIT_UFE 0x00080000 /* underflow exception enable */
56#define BIT_OFE 0x00040000 /* overflow exception enable */
57#define BIT_DZE 0x00020000 /* divide by zero exception enable */
58#define BIT_IOE 0x00010000 /* invalid operation exception enable */
59
60/* SYSTEM CONTROL BYTE
61---------------------- */
62
63#define MASK_SYSTEM_CONTROL 0x0000ff00
64#define MASK_TRAP_STRICT 0x00001f00
65
66#define BIT_AC 0x00001000 /* use alternative C-flag definition
67 for compares */
68#define BIT_EP 0x00000800 /* use expanded packed decimal format */
69#define BIT_SO 0x00000400 /* select synchronous operation of FPA */
70#define BIT_NE 0x00000200 /* NaN exception bit */
71#define BIT_ND 0x00000100 /* no denormalized numbers bit */
72
73/* CUMULATIVE EXCEPTION FLAGS BYTE
74---------------------------------- */
75
76#define MASK_EXCEPTION_FLAGS 0x000000ff
77#define MASK_EXCEPTION_FLAGS_STRICT 0x0000001f
78
79#define BIT_IXC 0x00000010 /* inexact exception flag */
80#define BIT_UFC 0x00000008 /* underflow exception flag */
81#define BIT_OFC 0x00000004 /* overfloat exception flag */
82#define BIT_DZC 0x00000002 /* divide by zero exception flag */
83#define BIT_IOC 0x00000001 /* invalid operation exception flag */
84
85/* Floating Point Control Register
86----------------------------------*/
87
88#define BIT_RU 0x80000000 /* rounded up bit */
89#define BIT_IE 0x10000000 /* inexact bit */
90#define BIT_MO 0x08000000 /* mantissa overflow bit */
91#define BIT_EO 0x04000000 /* exponent overflow bit */
92#define BIT_SB 0x00000800 /* store bounce */
93#define BIT_AB 0x00000400 /* arithmetic bounce */
94#define BIT_RE 0x00000200 /* rounding exception */
95#define BIT_DA 0x00000100 /* disable FPA */
96
97#define MASK_OP 0x00f08010 /* AU operation code */
98#define MASK_PR 0x00080080 /* AU precision */
99#define MASK_S1 0x00070000 /* AU source register 1 */
100#define MASK_S2 0x00000007 /* AU source register 2 */
101#define MASK_DS 0x00007000 /* AU destination register */
102#define MASK_RM 0x00000060 /* AU rounding mode */
103#define MASK_ALU 0x9cfff2ff /* only ALU can write these bits */
104#define MASK_RESET 0x00000d00 /* bits set on reset, all others cleared */
105#define MASK_WFC MASK_RESET
106#define MASK_RFC ~MASK_RESET
107
108#endif
diff --git a/arch/arm/nwfpe/milieu.h b/arch/arm/nwfpe/milieu.h
new file mode 100644
index 000000000000..a3892ab2dca4
--- /dev/null
+++ b/arch/arm/nwfpe/milieu.h
@@ -0,0 +1,48 @@
1
2/*
3===============================================================================
4
5This C header file is part of the SoftFloat IEC/IEEE Floating-point
6Arithmetic Package, Release 2.
7
8Written by John R. Hauser. This work was made possible in part by the
9International Computer Science Institute, located at Suite 600, 1947 Center
10Street, Berkeley, California 94704. Funding was partially provided by the
11National Science Foundation under grant MIP-9311980. The original version
12of this code was written as part of a project to build a fixed-point vector
13processor in collaboration with the University of California at Berkeley,
14overseen by Profs. Nelson Morgan and John Wawrzynek. More information
15is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
16arithmetic/softfloat.html'.
17
18THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
19has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
20TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
21PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
22AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
23
24Derivative works are acceptable, even for commercial purposes, so long as
25(1) they include prominent notice that the work is derivative, and (2) they
26include prominent notice akin to these three paragraphs for those parts of
27this code that are retained.
28
29===============================================================================
30*/
31
32/*
33-------------------------------------------------------------------------------
34Include common integer types and flags.
35-------------------------------------------------------------------------------
36*/
37#include "ARM-gcc.h"
38
39/*
40-------------------------------------------------------------------------------
41Symbolic Boolean literals.
42-------------------------------------------------------------------------------
43*/
44enum {
45 FALSE = 0,
46 TRUE = 1
47};
48
diff --git a/arch/arm/nwfpe/single_cpdo.c b/arch/arm/nwfpe/single_cpdo.c
new file mode 100644
index 000000000000..705808e88d9d
--- /dev/null
+++ b/arch/arm/nwfpe/single_cpdo.c
@@ -0,0 +1,124 @@
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.COM, 1998,1999
4 (c) Philip Blundell, 2001
5
6 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#include "fpa11.h"
24#include "softfloat.h"
25#include "fpopcode.h"
26
27float32 float32_exp(float32 Fm);
28float32 float32_ln(float32 Fm);
29float32 float32_sin(float32 rFm);
30float32 float32_cos(float32 rFm);
31float32 float32_arcsin(float32 rFm);
32float32 float32_arctan(float32 rFm);
33float32 float32_log(float32 rFm);
34float32 float32_tan(float32 rFm);
35float32 float32_arccos(float32 rFm);
36float32 float32_pow(float32 rFn, float32 rFm);
37float32 float32_pol(float32 rFn, float32 rFm);
38
39static float32 float32_rsf(float32 rFn, float32 rFm)
40{
41 return float32_sub(rFm, rFn);
42}
43
44static float32 float32_rdv(float32 rFn, float32 rFm)
45{
46 return float32_div(rFm, rFn);
47}
48
49static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = {
50 [ADF_CODE >> 20] = float32_add,
51 [MUF_CODE >> 20] = float32_mul,
52 [SUF_CODE >> 20] = float32_sub,
53 [RSF_CODE >> 20] = float32_rsf,
54 [DVF_CODE >> 20] = float32_div,
55 [RDF_CODE >> 20] = float32_rdv,
56 [RMF_CODE >> 20] = float32_rem,
57
58 [FML_CODE >> 20] = float32_mul,
59 [FDV_CODE >> 20] = float32_div,
60 [FRD_CODE >> 20] = float32_rdv,
61};
62
63static float32 float32_mvf(float32 rFm)
64{
65 return rFm;
66}
67
68static float32 float32_mnf(float32 rFm)
69{
70 return rFm ^ 0x80000000;
71}
72
73static float32 float32_abs(float32 rFm)
74{
75 return rFm & 0x7fffffff;
76}
77
78static float32 (*const monadic_single[16])(float32 rFm) = {
79 [MVF_CODE >> 20] = float32_mvf,
80 [MNF_CODE >> 20] = float32_mnf,
81 [ABS_CODE >> 20] = float32_abs,
82 [RND_CODE >> 20] = float32_round_to_int,
83 [URD_CODE >> 20] = float32_round_to_int,
84 [SQT_CODE >> 20] = float32_sqrt,
85 [NRM_CODE >> 20] = float32_mvf,
86};
87
88unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd)
89{
90 FPA11 *fpa11 = GET_FPA11();
91 float32 rFm;
92 unsigned int Fm, opc_mask_shift;
93
94 Fm = getFm(opcode);
95 if (CONSTANT_FM(opcode)) {
96 rFm = getSingleConstant(Fm);
97 } else if (fpa11->fType[Fm] == typeSingle) {
98 rFm = fpa11->fpreg[Fm].fSingle;
99 } else {
100 return 0;
101 }
102
103 opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
104 if (!MONADIC_INSTRUCTION(opcode)) {
105 unsigned int Fn = getFn(opcode);
106 float32 rFn;
107
108 if (fpa11->fType[Fn] == typeSingle &&
109 dyadic_single[opc_mask_shift]) {
110 rFn = fpa11->fpreg[Fn].fSingle;
111 rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm);
112 } else {
113 return 0;
114 }
115 } else {
116 if (monadic_single[opc_mask_shift]) {
117 rFd->fSingle = monadic_single[opc_mask_shift](rFm);
118 } else {
119 return 0;
120 }
121 }
122
123 return 1;
124}
diff --git a/arch/arm/nwfpe/softfloat-macros b/arch/arm/nwfpe/softfloat-macros
new file mode 100644
index 000000000000..5469989f2c5e
--- /dev/null
+++ b/arch/arm/nwfpe/softfloat-macros
@@ -0,0 +1,740 @@
1
2/*
3===============================================================================
4
5This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
6Arithmetic Package, Release 2.
7
8Written by John R. Hauser. This work was made possible in part by the
9International Computer Science Institute, located at Suite 600, 1947 Center
10Street, Berkeley, California 94704. Funding was partially provided by the
11National Science Foundation under grant MIP-9311980. The original version
12of this code was written as part of a project to build a fixed-point vector
13processor in collaboration with the University of California at Berkeley,
14overseen by Profs. Nelson Morgan and John Wawrzynek. More information
15is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
16arithmetic/softfloat.html'.
17
18THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
19has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
20TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
21PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
22AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
23
24Derivative works are acceptable, even for commercial purposes, so long as
25(1) they include prominent notice that the work is derivative, and (2) they
26include prominent notice akin to these three paragraphs for those parts of
27this code that are retained.
28
29===============================================================================
30*/
31
32/*
33-------------------------------------------------------------------------------
34Shifts `a' right by the number of bits given in `count'. If any nonzero
35bits are shifted off, they are ``jammed'' into the least significant bit of
36the result by setting the least significant bit to 1. The value of `count'
37can be arbitrarily large; in particular, if `count' is greater than 32, the
38result will be either 0 or 1, depending on whether `a' is zero or nonzero.
39The result is stored in the location pointed to by `zPtr'.
40-------------------------------------------------------------------------------
41*/
42INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
43{
44 bits32 z;
45 if ( count == 0 ) {
46 z = a;
47 }
48 else if ( count < 32 ) {
49 z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 );
50 }
51 else {
52 z = ( a != 0 );
53 }
54 *zPtr = z;
55}
56
57/*
58-------------------------------------------------------------------------------
59Shifts `a' right by the number of bits given in `count'. If any nonzero
60bits are shifted off, they are ``jammed'' into the least significant bit of
61the result by setting the least significant bit to 1. The value of `count'
62can be arbitrarily large; in particular, if `count' is greater than 64, the
63result will be either 0 or 1, depending on whether `a' is zero or nonzero.
64The result is stored in the location pointed to by `zPtr'.
65-------------------------------------------------------------------------------
66*/
67INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr )
68{
69 bits64 z;
70
71 __asm__("@shift64RightJamming -- start");
72 if ( count == 0 ) {
73 z = a;
74 }
75 else if ( count < 64 ) {
76 z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 );
77 }
78 else {
79 z = ( a != 0 );
80 }
81 __asm__("@shift64RightJamming -- end");
82 *zPtr = z;
83}
84
85/*
86-------------------------------------------------------------------------------
87Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
88_plus_ the number of bits given in `count'. The shifted result is at most
8964 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The
90bits shifted off form a second 64-bit result as follows: The _last_ bit
91shifted off is the most-significant bit of the extra result, and the other
9263 bits of the extra result are all zero if and only if _all_but_the_last_
93bits shifted off were all zero. This extra result is stored in the location
94pointed to by `z1Ptr'. The value of `count' can be arbitrarily large.
95 (This routine makes more sense if `a0' and `a1' are considered to form a
96fixed-point value with binary point between `a0' and `a1'. This fixed-point
97value is shifted right by the number of bits given in `count', and the
98integer part of the result is returned at the location pointed to by
99`z0Ptr'. The fractional part of the result may be slightly corrupted as
100described above, and is returned at the location pointed to by `z1Ptr'.)
101-------------------------------------------------------------------------------
102*/
103INLINE void
104 shift64ExtraRightJamming(
105 bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
106{
107 bits64 z0, z1;
108 int8 negCount = ( - count ) & 63;
109
110 if ( count == 0 ) {
111 z1 = a1;
112 z0 = a0;
113 }
114 else if ( count < 64 ) {
115 z1 = ( a0<<negCount ) | ( a1 != 0 );
116 z0 = a0>>count;
117 }
118 else {
119 if ( count == 64 ) {
120 z1 = a0 | ( a1 != 0 );
121 }
122 else {
123 z1 = ( ( a0 | a1 ) != 0 );
124 }
125 z0 = 0;
126 }
127 *z1Ptr = z1;
128 *z0Ptr = z0;
129
130}
131
132/*
133-------------------------------------------------------------------------------
134Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
135number of bits given in `count'. Any bits shifted off are lost. The value
136of `count' can be arbitrarily large; in particular, if `count' is greater
137than 128, the result will be 0. The result is broken into two 64-bit pieces
138which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
139-------------------------------------------------------------------------------
140*/
141INLINE void
142 shift128Right(
143 bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
144{
145 bits64 z0, z1;
146 int8 negCount = ( - count ) & 63;
147
148 if ( count == 0 ) {
149 z1 = a1;
150 z0 = a0;
151 }
152 else if ( count < 64 ) {
153 z1 = ( a0<<negCount ) | ( a1>>count );
154 z0 = a0>>count;
155 }
156 else {
157 z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0;
158 z0 = 0;
159 }
160 *z1Ptr = z1;
161 *z0Ptr = z0;
162
163}
164
165/*
166-------------------------------------------------------------------------------
167Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
168number of bits given in `count'. If any nonzero bits are shifted off, they
169are ``jammed'' into the least significant bit of the result by setting the
170least significant bit to 1. The value of `count' can be arbitrarily large;
171in particular, if `count' is greater than 128, the result will be either 0
172or 1, depending on whether the concatenation of `a0' and `a1' is zero or
173nonzero. The result is broken into two 64-bit pieces which are stored at
174the locations pointed to by `z0Ptr' and `z1Ptr'.
175-------------------------------------------------------------------------------
176*/
177INLINE void
178 shift128RightJamming(
179 bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
180{
181 bits64 z0, z1;
182 int8 negCount = ( - count ) & 63;
183
184 if ( count == 0 ) {
185 z1 = a1;
186 z0 = a0;
187 }
188 else if ( count < 64 ) {
189 z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
190 z0 = a0>>count;
191 }
192 else {
193 if ( count == 64 ) {
194 z1 = a0 | ( a1 != 0 );
195 }
196 else if ( count < 128 ) {
197 z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
198 }
199 else {
200 z1 = ( ( a0 | a1 ) != 0 );
201 }
202 z0 = 0;
203 }
204 *z1Ptr = z1;
205 *z0Ptr = z0;
206
207}
208
209/*
210-------------------------------------------------------------------------------
211Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
212by 64 _plus_ the number of bits given in `count'. The shifted result is
213at most 128 nonzero bits; these are broken into two 64-bit pieces which are
214stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
215off form a third 64-bit result as follows: The _last_ bit shifted off is
216the most-significant bit of the extra result, and the other 63 bits of the
217extra result are all zero if and only if _all_but_the_last_ bits shifted off
218were all zero. This extra result is stored in the location pointed to by
219`z2Ptr'. The value of `count' can be arbitrarily large.
220 (This routine makes more sense if `a0', `a1', and `a2' are considered
221to form a fixed-point value with binary point between `a1' and `a2'. This
222fixed-point value is shifted right by the number of bits given in `count',
223and the integer part of the result is returned at the locations pointed to
224by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
225corrupted as described above, and is returned at the location pointed to by
226`z2Ptr'.)
227-------------------------------------------------------------------------------
228*/
229INLINE void
230 shift128ExtraRightJamming(
231 bits64 a0,
232 bits64 a1,
233 bits64 a2,
234 int16 count,
235 bits64 *z0Ptr,
236 bits64 *z1Ptr,
237 bits64 *z2Ptr
238 )
239{
240 bits64 z0, z1, z2;
241 int8 negCount = ( - count ) & 63;
242
243 if ( count == 0 ) {
244 z2 = a2;
245 z1 = a1;
246 z0 = a0;
247 }
248 else {
249 if ( count < 64 ) {
250 z2 = a1<<negCount;
251 z1 = ( a0<<negCount ) | ( a1>>count );
252 z0 = a0>>count;
253 }
254 else {
255 if ( count == 64 ) {
256 z2 = a1;
257 z1 = a0;
258 }
259 else {
260 a2 |= a1;
261 if ( count < 128 ) {
262 z2 = a0<<negCount;
263 z1 = a0>>( count & 63 );
264 }
265 else {
266 z2 = ( count == 128 ) ? a0 : ( a0 != 0 );
267 z1 = 0;
268 }
269 }
270 z0 = 0;
271 }
272 z2 |= ( a2 != 0 );
273 }
274 *z2Ptr = z2;
275 *z1Ptr = z1;
276 *z0Ptr = z0;
277
278}
279
280/*
281-------------------------------------------------------------------------------
282Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
283number of bits given in `count'. Any bits shifted off are lost. The value
284of `count' must be less than 64. The result is broken into two 64-bit
285pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
286-------------------------------------------------------------------------------
287*/
288INLINE void
289 shortShift128Left(
290 bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
291{
292
293 *z1Ptr = a1<<count;
294 *z0Ptr =
295 ( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 63 ) );
296
297}
298
299/*
300-------------------------------------------------------------------------------
301Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left
302by the number of bits given in `count'. Any bits shifted off are lost.
303The value of `count' must be less than 64. The result is broken into three
30464-bit pieces which are stored at the locations pointed to by `z0Ptr',
305`z1Ptr', and `z2Ptr'.
306-------------------------------------------------------------------------------
307*/
308INLINE void
309 shortShift192Left(
310 bits64 a0,
311 bits64 a1,
312 bits64 a2,
313 int16 count,
314 bits64 *z0Ptr,
315 bits64 *z1Ptr,
316 bits64 *z2Ptr
317 )
318{
319 bits64 z0, z1, z2;
320 int8 negCount;
321
322 z2 = a2<<count;
323 z1 = a1<<count;
324 z0 = a0<<count;
325 if ( 0 < count ) {
326 negCount = ( ( - count ) & 63 );
327 z1 |= a2>>negCount;
328 z0 |= a1>>negCount;
329 }
330 *z2Ptr = z2;
331 *z1Ptr = z1;
332 *z0Ptr = z0;
333
334}
335
336/*
337-------------------------------------------------------------------------------
338Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
339value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so
340any carry out is lost. The result is broken into two 64-bit pieces which
341are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
342-------------------------------------------------------------------------------
343*/
344INLINE void
345 add128(
346 bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
347{
348 bits64 z1;
349
350 z1 = a1 + b1;
351 *z1Ptr = z1;
352 *z0Ptr = a0 + b0 + ( z1 < a1 );
353
354}
355
356/*
357-------------------------------------------------------------------------------
358Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the
359192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
360modulo 2^192, so any carry out is lost. The result is broken into three
36164-bit pieces which are stored at the locations pointed to by `z0Ptr',
362`z1Ptr', and `z2Ptr'.
363-------------------------------------------------------------------------------
364*/
365INLINE void
366 add192(
367 bits64 a0,
368 bits64 a1,
369 bits64 a2,
370 bits64 b0,
371 bits64 b1,
372 bits64 b2,
373 bits64 *z0Ptr,
374 bits64 *z1Ptr,
375 bits64 *z2Ptr
376 )
377{
378 bits64 z0, z1, z2;
379 int8 carry0, carry1;
380
381 z2 = a2 + b2;
382 carry1 = ( z2 < a2 );
383 z1 = a1 + b1;
384 carry0 = ( z1 < a1 );
385 z0 = a0 + b0;
386 z1 += carry1;
387 z0 += ( z1 < carry1 );
388 z0 += carry0;
389 *z2Ptr = z2;
390 *z1Ptr = z1;
391 *z0Ptr = z0;
392
393}
394
395/*
396-------------------------------------------------------------------------------
397Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
398128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
3992^128, so any borrow out (carry out) is lost. The result is broken into two
40064-bit pieces which are stored at the locations pointed to by `z0Ptr' and
401`z1Ptr'.
402-------------------------------------------------------------------------------
403*/
404INLINE void
405 sub128(
406 bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
407{
408
409 *z1Ptr = a1 - b1;
410 *z0Ptr = a0 - b0 - ( a1 < b1 );
411
412}
413
414/*
415-------------------------------------------------------------------------------
416Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'
417from the 192-bit value formed by concatenating `a0', `a1', and `a2'.
418Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The
419result is broken into three 64-bit pieces which are stored at the locations
420pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
421-------------------------------------------------------------------------------
422*/
423INLINE void
424 sub192(
425 bits64 a0,
426 bits64 a1,
427 bits64 a2,
428 bits64 b0,
429 bits64 b1,
430 bits64 b2,
431 bits64 *z0Ptr,
432 bits64 *z1Ptr,
433 bits64 *z2Ptr
434 )
435{
436 bits64 z0, z1, z2;
437 int8 borrow0, borrow1;
438
439 z2 = a2 - b2;
440 borrow1 = ( a2 < b2 );
441 z1 = a1 - b1;
442 borrow0 = ( a1 < b1 );
443 z0 = a0 - b0;
444 z0 -= ( z1 < borrow1 );
445 z1 -= borrow1;
446 z0 -= borrow0;
447 *z2Ptr = z2;
448 *z1Ptr = z1;
449 *z0Ptr = z0;
450
451}
452
453/*
454-------------------------------------------------------------------------------
455Multiplies `a' by `b' to obtain a 128-bit product. The product is broken
456into two 64-bit pieces which are stored at the locations pointed to by
457`z0Ptr' and `z1Ptr'.
458-------------------------------------------------------------------------------
459*/
460INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr )
461{
462 bits32 aHigh, aLow, bHigh, bLow;
463 bits64 z0, zMiddleA, zMiddleB, z1;
464
465 aLow = a;
466 aHigh = a>>32;
467 bLow = b;
468 bHigh = b>>32;
469 z1 = ( (bits64) aLow ) * bLow;
470 zMiddleA = ( (bits64) aLow ) * bHigh;
471 zMiddleB = ( (bits64) aHigh ) * bLow;
472 z0 = ( (bits64) aHigh ) * bHigh;
473 zMiddleA += zMiddleB;
474 z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 );
475 zMiddleA <<= 32;
476 z1 += zMiddleA;
477 z0 += ( z1 < zMiddleA );
478 *z1Ptr = z1;
479 *z0Ptr = z0;
480
481}
482
483/*
484-------------------------------------------------------------------------------
485Multiplies the 128-bit value formed by concatenating `a0' and `a1' by `b' to
486obtain a 192-bit product. The product is broken into three 64-bit pieces
487which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
488`z2Ptr'.
489-------------------------------------------------------------------------------
490*/
491INLINE void
492 mul128By64To192(
493 bits64 a0,
494 bits64 a1,
495 bits64 b,
496 bits64 *z0Ptr,
497 bits64 *z1Ptr,
498 bits64 *z2Ptr
499 )
500{
501 bits64 z0, z1, z2, more1;
502
503 mul64To128( a1, b, &z1, &z2 );
504 mul64To128( a0, b, &z0, &more1 );
505 add128( z0, more1, 0, z1, &z0, &z1 );
506 *z2Ptr = z2;
507 *z1Ptr = z1;
508 *z0Ptr = z0;
509
510}
511
512/*
513-------------------------------------------------------------------------------
514Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the
515128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit
516product. The product is broken into four 64-bit pieces which are stored at
517the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
518-------------------------------------------------------------------------------
519*/
520INLINE void
521 mul128To256(
522 bits64 a0,
523 bits64 a1,
524 bits64 b0,
525 bits64 b1,
526 bits64 *z0Ptr,
527 bits64 *z1Ptr,
528 bits64 *z2Ptr,
529 bits64 *z3Ptr
530 )
531{
532 bits64 z0, z1, z2, z3;
533 bits64 more1, more2;
534
535 mul64To128( a1, b1, &z2, &z3 );
536 mul64To128( a1, b0, &z1, &more2 );
537 add128( z1, more2, 0, z2, &z1, &z2 );
538 mul64To128( a0, b0, &z0, &more1 );
539 add128( z0, more1, 0, z1, &z0, &z1 );
540 mul64To128( a0, b1, &more1, &more2 );
541 add128( more1, more2, 0, z2, &more1, &z2 );
542 add128( z0, z1, 0, more1, &z0, &z1 );
543 *z3Ptr = z3;
544 *z2Ptr = z2;
545 *z1Ptr = z1;
546 *z0Ptr = z0;
547
548}
549
550/*
551-------------------------------------------------------------------------------
552Returns an approximation to the 64-bit integer quotient obtained by dividing
553`b' into the 128-bit value formed by concatenating `a0' and `a1'. The
554divisor `b' must be at least 2^63. If q is the exact quotient truncated
555toward zero, the approximation returned lies between q and q + 2 inclusive.
556If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
557unsigned integer is returned.
558-------------------------------------------------------------------------------
559*/
560static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b )
561{
562 bits64 b0, b1;
563 bits64 rem0, rem1, term0, term1;
564 bits64 z;
565 if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF );
566 b0 = b>>32;
567 z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32;
568 mul64To128( b, z, &term0, &term1 );
569 sub128( a0, a1, term0, term1, &rem0, &rem1 );
570 while ( ( (sbits64) rem0 ) < 0 ) {
571 z -= LIT64( 0x100000000 );
572 b1 = b<<32;
573 add128( rem0, rem1, b0, b1, &rem0, &rem1 );
574 }
575 rem0 = ( rem0<<32 ) | ( rem1>>32 );
576 z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0;
577 return z;
578
579}
580
581/*
582-------------------------------------------------------------------------------
583Returns an approximation to the square root of the 32-bit significand given
584by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
585`aExp' (the least significant bit) is 1, the integer returned approximates
5862^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
587is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
588case, the approximation returned lies strictly within +/-2 of the exact
589value.
590-------------------------------------------------------------------------------
591*/
592static bits32 estimateSqrt32( int16 aExp, bits32 a )
593{
594 static const bits16 sqrtOddAdjustments[] = {
595 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
596 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
597 };
598 static const bits16 sqrtEvenAdjustments[] = {
599 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
600 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
601 };
602 int8 index;
603 bits32 z;
604
605 index = ( a>>27 ) & 15;
606 if ( aExp & 1 ) {
607 z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ];
608 z = ( ( a / z )<<14 ) + ( z<<15 );
609 a >>= 1;
610 }
611 else {
612 z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ];
613 z = a / z + z;
614 z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
615 if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
616 }
617 return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 );
618
619}
620
621/*
622-------------------------------------------------------------------------------
623Returns the number of leading 0 bits before the most-significant 1 bit
624of `a'. If `a' is zero, 32 is returned.
625-------------------------------------------------------------------------------
626*/
627static int8 countLeadingZeros32( bits32 a )
628{
629 static const int8 countLeadingZerosHigh[] = {
630 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
631 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
632 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
633 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
634 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
635 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
636 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
637 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
638 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
639 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
640 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
641 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
642 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
643 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
644 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
645 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
646 };
647 int8 shiftCount;
648
649 shiftCount = 0;
650 if ( a < 0x10000 ) {
651 shiftCount += 16;
652 a <<= 16;
653 }
654 if ( a < 0x1000000 ) {
655 shiftCount += 8;
656 a <<= 8;
657 }
658 shiftCount += countLeadingZerosHigh[ a>>24 ];
659 return shiftCount;
660
661}
662
663/*
664-------------------------------------------------------------------------------
665Returns the number of leading 0 bits before the most-significant 1 bit
666of `a'. If `a' is zero, 64 is returned.
667-------------------------------------------------------------------------------
668*/
669static int8 countLeadingZeros64( bits64 a )
670{
671 int8 shiftCount;
672
673 shiftCount = 0;
674 if ( a < ( (bits64) 1 )<<32 ) {
675 shiftCount += 32;
676 }
677 else {
678 a >>= 32;
679 }
680 shiftCount += countLeadingZeros32( a );
681 return shiftCount;
682
683}
684
685/*
686-------------------------------------------------------------------------------
687Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
688is equal to the 128-bit value formed by concatenating `b0' and `b1'.
689Otherwise, returns 0.
690-------------------------------------------------------------------------------
691*/
692INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
693{
694
695 return ( a0 == b0 ) && ( a1 == b1 );
696
697}
698
699/*
700-------------------------------------------------------------------------------
701Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
702than or equal to the 128-bit value formed by concatenating `b0' and `b1'.
703Otherwise, returns 0.
704-------------------------------------------------------------------------------
705*/
706INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
707{
708
709 return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
710
711}
712
713/*
714-------------------------------------------------------------------------------
715Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
716than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise,
717returns 0.
718-------------------------------------------------------------------------------
719*/
720INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
721{
722
723 return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
724
725}
726
727/*
728-------------------------------------------------------------------------------
729Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is
730not equal to the 128-bit value formed by concatenating `b0' and `b1'.
731Otherwise, returns 0.
732-------------------------------------------------------------------------------
733*/
734INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
735{
736
737 return ( a0 != b0 ) || ( a1 != b1 );
738
739}
740
diff --git a/arch/arm/nwfpe/softfloat-specialize b/arch/arm/nwfpe/softfloat-specialize
new file mode 100644
index 000000000000..acf409144763
--- /dev/null
+++ b/arch/arm/nwfpe/softfloat-specialize
@@ -0,0 +1,366 @@
1
2/*
3===============================================================================
4
5This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
6Arithmetic Package, Release 2.
7
8Written by John R. Hauser. This work was made possible in part by the
9International Computer Science Institute, located at Suite 600, 1947 Center
10Street, Berkeley, California 94704. Funding was partially provided by the
11National Science Foundation under grant MIP-9311980. The original version
12of this code was written as part of a project to build a fixed-point vector
13processor in collaboration with the University of California at Berkeley,
14overseen by Profs. Nelson Morgan and John Wawrzynek. More information
15is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
16arithmetic/softfloat.html'.
17
18THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
19has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
20TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
21PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
22AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
23
24Derivative works are acceptable, even for commercial purposes, so long as
25(1) they include prominent notice that the work is derivative, and (2) they
26include prominent notice akin to these three paragraphs for those parts of
27this code that are retained.
28
29===============================================================================
30*/
31
32/*
33-------------------------------------------------------------------------------
34Underflow tininess-detection mode, statically initialized to default value.
35(The declaration in `softfloat.h' must match the `int8' type here.)
36-------------------------------------------------------------------------------
37*/
38int8 float_detect_tininess = float_tininess_after_rounding;
39
40/*
41-------------------------------------------------------------------------------
42Raises the exceptions specified by `flags'. Floating-point traps can be
43defined here if desired. It is currently not possible for such a trap to
44substitute a result value. If traps are not implemented, this routine
45should be simply `float_exception_flags |= flags;'.
46
47ScottB: November 4, 1998
48Moved this function out of softfloat-specialize into fpmodule.c.
49This effectively isolates all the changes required for integrating with the
50Linux kernel into fpmodule.c. Porting to NetBSD should only require modifying
51fpmodule.c to integrate with the NetBSD kernel (I hope!).
52-------------------------------------------------------------------------------
53void float_raise( int8 flags )
54{
55 float_exception_flags |= flags;
56}
57*/
58
59/*
60-------------------------------------------------------------------------------
61Internal canonical NaN format.
62-------------------------------------------------------------------------------
63*/
64typedef struct {
65 flag sign;
66 bits64 high, low;
67} commonNaNT;
68
69/*
70-------------------------------------------------------------------------------
71The pattern for a default generated single-precision NaN.
72-------------------------------------------------------------------------------
73*/
74#define float32_default_nan 0xFFFFFFFF
75
76/*
77-------------------------------------------------------------------------------
78Returns 1 if the single-precision floating-point value `a' is a NaN;
79otherwise returns 0.
80-------------------------------------------------------------------------------
81*/
82flag float32_is_nan( float32 a )
83{
84
85 return ( 0xFF000000 < (bits32) ( a<<1 ) );
86
87}
88
89/*
90-------------------------------------------------------------------------------
91Returns 1 if the single-precision floating-point value `a' is a signaling
92NaN; otherwise returns 0.
93-------------------------------------------------------------------------------
94*/
95flag float32_is_signaling_nan( float32 a )
96{
97
98 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
99
100}
101
102/*
103-------------------------------------------------------------------------------
104Returns the result of converting the single-precision floating-point NaN
105`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
106exception is raised.
107-------------------------------------------------------------------------------
108*/
109static commonNaNT float32ToCommonNaN( float32 a )
110{
111 commonNaNT z;
112
113 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
114 z.sign = a>>31;
115 z.low = 0;
116 z.high = ( (bits64) a )<<41;
117 return z;
118
119}
120
121/*
122-------------------------------------------------------------------------------
123Returns the result of converting the canonical NaN `a' to the single-
124precision floating-point format.
125-------------------------------------------------------------------------------
126*/
127static float32 commonNaNToFloat32( commonNaNT a )
128{
129
130 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
131
132}
133
134/*
135-------------------------------------------------------------------------------
136Takes two single-precision floating-point values `a' and `b', one of which
137is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
138signaling NaN, the invalid exception is raised.
139-------------------------------------------------------------------------------
140*/
141static float32 propagateFloat32NaN( float32 a, float32 b )
142{
143 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
144
145 aIsNaN = float32_is_nan( a );
146 aIsSignalingNaN = float32_is_signaling_nan( a );
147 bIsNaN = float32_is_nan( b );
148 bIsSignalingNaN = float32_is_signaling_nan( b );
149 a |= 0x00400000;
150 b |= 0x00400000;
151 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
152 if ( aIsNaN ) {
153 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
154 }
155 else {
156 return b;
157 }
158
159}
160
161/*
162-------------------------------------------------------------------------------
163The pattern for a default generated double-precision NaN.
164-------------------------------------------------------------------------------
165*/
166#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
167
168/*
169-------------------------------------------------------------------------------
170Returns 1 if the double-precision floating-point value `a' is a NaN;
171otherwise returns 0.
172-------------------------------------------------------------------------------
173*/
174flag float64_is_nan( float64 a )
175{
176
177 return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
178
179}
180
181/*
182-------------------------------------------------------------------------------
183Returns 1 if the double-precision floating-point value `a' is a signaling
184NaN; otherwise returns 0.
185-------------------------------------------------------------------------------
186*/
187flag float64_is_signaling_nan( float64 a )
188{
189
190 return
191 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
192 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
193
194}
195
196/*
197-------------------------------------------------------------------------------
198Returns the result of converting the double-precision floating-point NaN
199`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
200exception is raised.
201-------------------------------------------------------------------------------
202*/
203static commonNaNT float64ToCommonNaN( float64 a )
204{
205 commonNaNT z;
206
207 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
208 z.sign = a>>63;
209 z.low = 0;
210 z.high = a<<12;
211 return z;
212
213}
214
215/*
216-------------------------------------------------------------------------------
217Returns the result of converting the canonical NaN `a' to the double-
218precision floating-point format.
219-------------------------------------------------------------------------------
220*/
221static float64 commonNaNToFloat64( commonNaNT a )
222{
223
224 return
225 ( ( (bits64) a.sign )<<63 )
226 | LIT64( 0x7FF8000000000000 )
227 | ( a.high>>12 );
228
229}
230
231/*
232-------------------------------------------------------------------------------
233Takes two double-precision floating-point values `a' and `b', one of which
234is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
235signaling NaN, the invalid exception is raised.
236-------------------------------------------------------------------------------
237*/
238static float64 propagateFloat64NaN( float64 a, float64 b )
239{
240 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
241
242 aIsNaN = float64_is_nan( a );
243 aIsSignalingNaN = float64_is_signaling_nan( a );
244 bIsNaN = float64_is_nan( b );
245 bIsSignalingNaN = float64_is_signaling_nan( b );
246 a |= LIT64( 0x0008000000000000 );
247 b |= LIT64( 0x0008000000000000 );
248 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
249 if ( aIsNaN ) {
250 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
251 }
252 else {
253 return b;
254 }
255
256}
257
258#ifdef FLOATX80
259
260/*
261-------------------------------------------------------------------------------
262The pattern for a default generated extended double-precision NaN. The
263`high' and `low' values hold the most- and least-significant bits,
264respectively.
265-------------------------------------------------------------------------------
266*/
267#define floatx80_default_nan_high 0xFFFF
268#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
269
270/*
271-------------------------------------------------------------------------------
272Returns 1 if the extended double-precision floating-point value `a' is a
273NaN; otherwise returns 0.
274-------------------------------------------------------------------------------
275*/
276flag floatx80_is_nan( floatx80 a )
277{
278
279 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
280
281}
282
283/*
284-------------------------------------------------------------------------------
285Returns 1 if the extended double-precision floating-point value `a' is a
286signaling NaN; otherwise returns 0.
287-------------------------------------------------------------------------------
288*/
289flag floatx80_is_signaling_nan( floatx80 a )
290{
291 //register int lr;
292 bits64 aLow;
293
294 //__asm__("mov %0, lr" : : "g" (lr));
295 //fp_printk("floatx80_is_signalling_nan() called from 0x%08x\n",lr);
296 aLow = a.low & ~ LIT64( 0x4000000000000000 );
297 return
298 ( ( a.high & 0x7FFF ) == 0x7FFF )
299 && (bits64) ( aLow<<1 )
300 && ( a.low == aLow );
301
302}
303
304/*
305-------------------------------------------------------------------------------
306Returns the result of converting the extended double-precision floating-
307point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
308invalid exception is raised.
309-------------------------------------------------------------------------------
310*/
311static commonNaNT floatx80ToCommonNaN( floatx80 a )
312{
313 commonNaNT z;
314
315 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
316 z.sign = a.high>>15;
317 z.low = 0;
318 z.high = a.low<<1;
319 return z;
320
321}
322
323/*
324-------------------------------------------------------------------------------
325Returns the result of converting the canonical NaN `a' to the extended
326double-precision floating-point format.
327-------------------------------------------------------------------------------
328*/
329static floatx80 commonNaNToFloatx80( commonNaNT a )
330{
331 floatx80 z;
332
333 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
334 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
335 return z;
336
337}
338
339/*
340-------------------------------------------------------------------------------
341Takes two extended double-precision floating-point values `a' and `b', one
342of which is a NaN, and returns the appropriate NaN result. If either `a' or
343`b' is a signaling NaN, the invalid exception is raised.
344-------------------------------------------------------------------------------
345*/
346static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
347{
348 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
349
350 aIsNaN = floatx80_is_nan( a );
351 aIsSignalingNaN = floatx80_is_signaling_nan( a );
352 bIsNaN = floatx80_is_nan( b );
353 bIsSignalingNaN = floatx80_is_signaling_nan( b );
354 a.low |= LIT64( 0xC000000000000000 );
355 b.low |= LIT64( 0xC000000000000000 );
356 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
357 if ( aIsNaN ) {
358 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
359 }
360 else {
361 return b;
362 }
363
364}
365
366#endif
diff --git a/arch/arm/nwfpe/softfloat.c b/arch/arm/nwfpe/softfloat.c
new file mode 100644
index 000000000000..9d743ae29062
--- /dev/null
+++ b/arch/arm/nwfpe/softfloat.c
@@ -0,0 +1,3443 @@
1/*
2===============================================================================
3
4This C source file is part of the SoftFloat IEC/IEEE Floating-point
5Arithmetic Package, Release 2.
6
7Written by John R. Hauser. This work was made possible in part by the
8International Computer Science Institute, located at Suite 600, 1947 Center
9Street, Berkeley, California 94704. Funding was partially provided by the
10National Science Foundation under grant MIP-9311980. The original version
11of this code was written as part of a project to build a fixed-point vector
12processor in collaboration with the University of California at Berkeley,
13overseen by Profs. Nelson Morgan and John Wawrzynek. More information
14is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
15arithmetic/softfloat.html'.
16
17THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
18has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
19TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
20PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
21AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
22
23Derivative works are acceptable, even for commercial purposes, so long as
24(1) they include prominent notice that the work is derivative, and (2) they
25include prominent notice akin to these three paragraphs for those parts of
26this code that are retained.
27
28===============================================================================
29*/
30
31#include "fpa11.h"
32//#include "milieu.h"
33//#include "softfloat.h"
34
35/*
36-------------------------------------------------------------------------------
37Floating-point rounding mode, extended double-precision rounding precision,
38and exception flags.
39-------------------------------------------------------------------------------
40*/
41int8 float_rounding_mode = float_round_nearest_even;
42int8 floatx80_rounding_precision = 80;
43int8 float_exception_flags;
44
45/*
46-------------------------------------------------------------------------------
47Primitive arithmetic functions, including multi-word arithmetic, and
48division and square root approximations. (Can be specialized to target if
49desired.)
50-------------------------------------------------------------------------------
51*/
52#include "softfloat-macros"
53
54/*
55-------------------------------------------------------------------------------
56Functions and definitions to determine: (1) whether tininess for underflow
57is detected before or after rounding by default, (2) what (if anything)
58happens when exceptions are raised, (3) how signaling NaNs are distinguished
59from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
60are propagated from function inputs to output. These details are target-
61specific.
62-------------------------------------------------------------------------------
63*/
64#include "softfloat-specialize"
65
66/*
67-------------------------------------------------------------------------------
68Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
69and 7, and returns the properly rounded 32-bit integer corresponding to the
70input. If `zSign' is nonzero, the input is negated before being converted
71to an integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point
72input is simply rounded to an integer, with the inexact exception raised if
73the input cannot be represented exactly as an integer. If the fixed-point
74input is too large, however, the invalid exception is raised and the largest
75positive or negative integer is returned.
76-------------------------------------------------------------------------------
77*/
78static int32 roundAndPackInt32( flag zSign, bits64 absZ )
79{
80 int8 roundingMode;
81 flag roundNearestEven;
82 int8 roundIncrement, roundBits;
83 int32 z;
84
85 roundingMode = float_rounding_mode;
86 roundNearestEven = ( roundingMode == float_round_nearest_even );
87 roundIncrement = 0x40;
88 if ( ! roundNearestEven ) {
89 if ( roundingMode == float_round_to_zero ) {
90 roundIncrement = 0;
91 }
92 else {
93 roundIncrement = 0x7F;
94 if ( zSign ) {
95 if ( roundingMode == float_round_up ) roundIncrement = 0;
96 }
97 else {
98 if ( roundingMode == float_round_down ) roundIncrement = 0;
99 }
100 }
101 }
102 roundBits = absZ & 0x7F;
103 absZ = ( absZ + roundIncrement )>>7;
104 absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
105 z = absZ;
106 if ( zSign ) z = - z;
107 if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
108 float_exception_flags |= float_flag_invalid;
109 return zSign ? 0x80000000 : 0x7FFFFFFF;
110 }
111 if ( roundBits ) float_exception_flags |= float_flag_inexact;
112 return z;
113
114}
115
116/*
117-------------------------------------------------------------------------------
118Returns the fraction bits of the single-precision floating-point value `a'.
119-------------------------------------------------------------------------------
120*/
121INLINE bits32 extractFloat32Frac( float32 a )
122{
123
124 return a & 0x007FFFFF;
125
126}
127
128/*
129-------------------------------------------------------------------------------
130Returns the exponent bits of the single-precision floating-point value `a'.
131-------------------------------------------------------------------------------
132*/
133INLINE int16 extractFloat32Exp( float32 a )
134{
135
136 return ( a>>23 ) & 0xFF;
137
138}
139
140/*
141-------------------------------------------------------------------------------
142Returns the sign bit of the single-precision floating-point value `a'.
143-------------------------------------------------------------------------------
144*/
145#if 0 /* in softfloat.h */
146INLINE flag extractFloat32Sign( float32 a )
147{
148
149 return a>>31;
150
151}
152#endif
153
154/*
155-------------------------------------------------------------------------------
156Normalizes the subnormal single-precision floating-point value represented
157by the denormalized significand `aSig'. The normalized exponent and
158significand are stored at the locations pointed to by `zExpPtr' and
159`zSigPtr', respectively.
160-------------------------------------------------------------------------------
161*/
162static void
163 normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr )
164{
165 int8 shiftCount;
166
167 shiftCount = countLeadingZeros32( aSig ) - 8;
168 *zSigPtr = aSig<<shiftCount;
169 *zExpPtr = 1 - shiftCount;
170
171}
172
173/*
174-------------------------------------------------------------------------------
175Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
176single-precision floating-point value, returning the result. After being
177shifted into the proper positions, the three fields are simply added
178together to form the result. This means that any integer portion of `zSig'
179will be added into the exponent. Since a properly normalized significand
180will have an integer portion equal to 1, the `zExp' input should be 1 less
181than the desired result exponent whenever `zSig' is a complete, normalized
182significand.
183-------------------------------------------------------------------------------
184*/
185INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig )
186{
187#if 0
188 float32 f;
189 __asm__("@ packFloat32 \n\
190 mov %0, %1, asl #31 \n\
191 orr %0, %2, asl #23 \n\
192 orr %0, %3"
193 : /* no outputs */
194 : "g" (f), "g" (zSign), "g" (zExp), "g" (zSig)
195 : "cc");
196 return f;
197#else
198 return ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig;
199#endif
200}
201
202/*
203-------------------------------------------------------------------------------
204Takes an abstract floating-point value having sign `zSign', exponent `zExp',
205and significand `zSig', and returns the proper single-precision floating-
206point value corresponding to the abstract input. Ordinarily, the abstract
207value is simply rounded and packed into the single-precision format, with
208the inexact exception raised if the abstract input cannot be represented
209exactly. If the abstract value is too large, however, the overflow and
210inexact exceptions are raised and an infinity or maximal finite value is
211returned. If the abstract value is too small, the input value is rounded to
212a subnormal number, and the underflow and inexact exceptions are raised if
213the abstract input cannot be represented exactly as a subnormal single-
214precision floating-point number.
215 The input significand `zSig' has its binary point between bits 30
216and 29, which is 7 bits to the left of the usual location. This shifted
217significand must be normalized or smaller. If `zSig' is not normalized,
218`zExp' must be 0; in that case, the result returned is a subnormal number,
219and it must not require rounding. In the usual case that `zSig' is
220normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
221The handling of underflow and overflow follows the IEC/IEEE Standard for
222Binary Floating-point Arithmetic.
223-------------------------------------------------------------------------------
224*/
225static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
226{
227 int8 roundingMode;
228 flag roundNearestEven;
229 int8 roundIncrement, roundBits;
230 flag isTiny;
231
232 roundingMode = float_rounding_mode;
233 roundNearestEven = ( roundingMode == float_round_nearest_even );
234 roundIncrement = 0x40;
235 if ( ! roundNearestEven ) {
236 if ( roundingMode == float_round_to_zero ) {
237 roundIncrement = 0;
238 }
239 else {
240 roundIncrement = 0x7F;
241 if ( zSign ) {
242 if ( roundingMode == float_round_up ) roundIncrement = 0;
243 }
244 else {
245 if ( roundingMode == float_round_down ) roundIncrement = 0;
246 }
247 }
248 }
249 roundBits = zSig & 0x7F;
250 if ( 0xFD <= (bits16) zExp ) {
251 if ( ( 0xFD < zExp )
252 || ( ( zExp == 0xFD )
253 && ( (sbits32) ( zSig + roundIncrement ) < 0 ) )
254 ) {
255 float_raise( float_flag_overflow | float_flag_inexact );
256 return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 );
257 }
258 if ( zExp < 0 ) {
259 isTiny =
260 ( float_detect_tininess == float_tininess_before_rounding )
261 || ( zExp < -1 )
262 || ( zSig + roundIncrement < 0x80000000 );
263 shift32RightJamming( zSig, - zExp, &zSig );
264 zExp = 0;
265 roundBits = zSig & 0x7F;
266 if ( isTiny && roundBits ) float_raise( float_flag_underflow );
267 }
268 }
269 if ( roundBits ) float_exception_flags |= float_flag_inexact;
270 zSig = ( zSig + roundIncrement )>>7;
271 zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
272 if ( zSig == 0 ) zExp = 0;
273 return packFloat32( zSign, zExp, zSig );
274
275}
276
277/*
278-------------------------------------------------------------------------------
279Takes an abstract floating-point value having sign `zSign', exponent `zExp',
280and significand `zSig', and returns the proper single-precision floating-
281point value corresponding to the abstract input. This routine is just like
282`roundAndPackFloat32' except that `zSig' does not have to be normalized in
283any way. In all cases, `zExp' must be 1 less than the ``true'' floating-
284point exponent.
285-------------------------------------------------------------------------------
286*/
287static float32
288 normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
289{
290 int8 shiftCount;
291
292 shiftCount = countLeadingZeros32( zSig ) - 1;
293 return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<<shiftCount );
294
295}
296
297/*
298-------------------------------------------------------------------------------
299Returns the fraction bits of the double-precision floating-point value `a'.
300-------------------------------------------------------------------------------
301*/
302INLINE bits64 extractFloat64Frac( float64 a )
303{
304
305 return a & LIT64( 0x000FFFFFFFFFFFFF );
306
307}
308
309/*
310-------------------------------------------------------------------------------
311Returns the exponent bits of the double-precision floating-point value `a'.
312-------------------------------------------------------------------------------
313*/
314INLINE int16 extractFloat64Exp( float64 a )
315{
316
317 return ( a>>52 ) & 0x7FF;
318
319}
320
321/*
322-------------------------------------------------------------------------------
323Returns the sign bit of the double-precision floating-point value `a'.
324-------------------------------------------------------------------------------
325*/
326#if 0 /* in softfloat.h */
327INLINE flag extractFloat64Sign( float64 a )
328{
329
330 return a>>63;
331
332}
333#endif
334
335/*
336-------------------------------------------------------------------------------
337Normalizes the subnormal double-precision floating-point value represented
338by the denormalized significand `aSig'. The normalized exponent and
339significand are stored at the locations pointed to by `zExpPtr' and
340`zSigPtr', respectively.
341-------------------------------------------------------------------------------
342*/
343static void
344 normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr )
345{
346 int8 shiftCount;
347
348 shiftCount = countLeadingZeros64( aSig ) - 11;
349 *zSigPtr = aSig<<shiftCount;
350 *zExpPtr = 1 - shiftCount;
351
352}
353
354/*
355-------------------------------------------------------------------------------
356Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
357double-precision floating-point value, returning the result. After being
358shifted into the proper positions, the three fields are simply added
359together to form the result. This means that any integer portion of `zSig'
360will be added into the exponent. Since a properly normalized significand
361will have an integer portion equal to 1, the `zExp' input should be 1 less
362than the desired result exponent whenever `zSig' is a complete, normalized
363significand.
364-------------------------------------------------------------------------------
365*/
366INLINE float64 packFloat64( flag zSign, int16 zExp, bits64 zSig )
367{
368
369 return ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<52 ) + zSig;
370
371}
372
373/*
374-------------------------------------------------------------------------------
375Takes an abstract floating-point value having sign `zSign', exponent `zExp',
376and significand `zSig', and returns the proper double-precision floating-
377point value corresponding to the abstract input. Ordinarily, the abstract
378value is simply rounded and packed into the double-precision format, with
379the inexact exception raised if the abstract input cannot be represented
380exactly. If the abstract value is too large, however, the overflow and
381inexact exceptions are raised and an infinity or maximal finite value is
382returned. If the abstract value is too small, the input value is rounded to
383a subnormal number, and the underflow and inexact exceptions are raised if
384the abstract input cannot be represented exactly as a subnormal double-
385precision floating-point number.
386 The input significand `zSig' has its binary point between bits 62
387and 61, which is 10 bits to the left of the usual location. This shifted
388significand must be normalized or smaller. If `zSig' is not normalized,
389`zExp' must be 0; in that case, the result returned is a subnormal number,
390and it must not require rounding. In the usual case that `zSig' is
391normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
392The handling of underflow and overflow follows the IEC/IEEE Standard for
393Binary Floating-point Arithmetic.
394-------------------------------------------------------------------------------
395*/
396static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
397{
398 int8 roundingMode;
399 flag roundNearestEven;
400 int16 roundIncrement, roundBits;
401 flag isTiny;
402
403 roundingMode = float_rounding_mode;
404 roundNearestEven = ( roundingMode == float_round_nearest_even );
405 roundIncrement = 0x200;
406 if ( ! roundNearestEven ) {
407 if ( roundingMode == float_round_to_zero ) {
408 roundIncrement = 0;
409 }
410 else {
411 roundIncrement = 0x3FF;
412 if ( zSign ) {
413 if ( roundingMode == float_round_up ) roundIncrement = 0;
414 }
415 else {
416 if ( roundingMode == float_round_down ) roundIncrement = 0;
417 }
418 }
419 }
420 roundBits = zSig & 0x3FF;
421 if ( 0x7FD <= (bits16) zExp ) {
422 if ( ( 0x7FD < zExp )
423 || ( ( zExp == 0x7FD )
424 && ( (sbits64) ( zSig + roundIncrement ) < 0 ) )
425 ) {
426 //register int lr = __builtin_return_address(0);
427 //printk("roundAndPackFloat64 called from 0x%08x\n",lr);
428 float_raise( float_flag_overflow | float_flag_inexact );
429 return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 );
430 }
431 if ( zExp < 0 ) {
432 isTiny =
433 ( float_detect_tininess == float_tininess_before_rounding )
434 || ( zExp < -1 )
435 || ( zSig + roundIncrement < LIT64( 0x8000000000000000 ) );
436 shift64RightJamming( zSig, - zExp, &zSig );
437 zExp = 0;
438 roundBits = zSig & 0x3FF;
439 if ( isTiny && roundBits ) float_raise( float_flag_underflow );
440 }
441 }
442 if ( roundBits ) float_exception_flags |= float_flag_inexact;
443 zSig = ( zSig + roundIncrement )>>10;
444 zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven );
445 if ( zSig == 0 ) zExp = 0;
446 return packFloat64( zSign, zExp, zSig );
447
448}
449
450/*
451-------------------------------------------------------------------------------
452Takes an abstract floating-point value having sign `zSign', exponent `zExp',
453and significand `zSig', and returns the proper double-precision floating-
454point value corresponding to the abstract input. This routine is just like
455`roundAndPackFloat64' except that `zSig' does not have to be normalized in
456any way. In all cases, `zExp' must be 1 less than the ``true'' floating-
457point exponent.
458-------------------------------------------------------------------------------
459*/
460static float64
461 normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
462{
463 int8 shiftCount;
464
465 shiftCount = countLeadingZeros64( zSig ) - 1;
466 return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<<shiftCount );
467
468}
469
470#ifdef FLOATX80
471
472/*
473-------------------------------------------------------------------------------
474Returns the fraction bits of the extended double-precision floating-point
475value `a'.
476-------------------------------------------------------------------------------
477*/
478INLINE bits64 extractFloatx80Frac( floatx80 a )
479{
480
481 return a.low;
482
483}
484
485/*
486-------------------------------------------------------------------------------
487Returns the exponent bits of the extended double-precision floating-point
488value `a'.
489-------------------------------------------------------------------------------
490*/
491INLINE int32 extractFloatx80Exp( floatx80 a )
492{
493
494 return a.high & 0x7FFF;
495
496}
497
498/*
499-------------------------------------------------------------------------------
500Returns the sign bit of the extended double-precision floating-point value
501`a'.
502-------------------------------------------------------------------------------
503*/
504INLINE flag extractFloatx80Sign( floatx80 a )
505{
506
507 return a.high>>15;
508
509}
510
511/*
512-------------------------------------------------------------------------------
513Normalizes the subnormal extended double-precision floating-point value
514represented by the denormalized significand `aSig'. The normalized exponent
515and significand are stored at the locations pointed to by `zExpPtr' and
516`zSigPtr', respectively.
517-------------------------------------------------------------------------------
518*/
519static void
520 normalizeFloatx80Subnormal( bits64 aSig, int32 *zExpPtr, bits64 *zSigPtr )
521{
522 int8 shiftCount;
523
524 shiftCount = countLeadingZeros64( aSig );
525 *zSigPtr = aSig<<shiftCount;
526 *zExpPtr = 1 - shiftCount;
527
528}
529
530/*
531-------------------------------------------------------------------------------
532Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
533extended double-precision floating-point value, returning the result.
534-------------------------------------------------------------------------------
535*/
536INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig )
537{
538 floatx80 z;
539
540 z.low = zSig;
541 z.high = ( ( (bits16) zSign )<<15 ) + zExp;
542 return z;
543
544}
545
546/*
547-------------------------------------------------------------------------------
548Takes an abstract floating-point value having sign `zSign', exponent `zExp',
549and extended significand formed by the concatenation of `zSig0' and `zSig1',
550and returns the proper extended double-precision floating-point value
551corresponding to the abstract input. Ordinarily, the abstract value is
552rounded and packed into the extended double-precision format, with the
553inexact exception raised if the abstract input cannot be represented
554exactly. If the abstract value is too large, however, the overflow and
555inexact exceptions are raised and an infinity or maximal finite value is
556returned. If the abstract value is too small, the input value is rounded to
557a subnormal number, and the underflow and inexact exceptions are raised if
558the abstract input cannot be represented exactly as a subnormal extended
559double-precision floating-point number.
560 If `roundingPrecision' is 32 or 64, the result is rounded to the same
561number of bits as single or double precision, respectively. Otherwise, the
562result is rounded to the full precision of the extended double-precision
563format.
564 The input significand must be normalized or smaller. If the input
565significand is not normalized, `zExp' must be 0; in that case, the result
566returned is a subnormal number, and it must not require rounding. The
567handling of underflow and overflow follows the IEC/IEEE Standard for Binary
568Floating-point Arithmetic.
569-------------------------------------------------------------------------------
570*/
571static floatx80
572 roundAndPackFloatx80(
573 int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
574 )
575{
576 int8 roundingMode;
577 flag roundNearestEven, increment, isTiny;
578 int64 roundIncrement, roundMask, roundBits;
579
580 roundingMode = float_rounding_mode;
581 roundNearestEven = ( roundingMode == float_round_nearest_even );
582 if ( roundingPrecision == 80 ) goto precision80;
583 if ( roundingPrecision == 64 ) {
584 roundIncrement = LIT64( 0x0000000000000400 );
585 roundMask = LIT64( 0x00000000000007FF );
586 }
587 else if ( roundingPrecision == 32 ) {
588 roundIncrement = LIT64( 0x0000008000000000 );
589 roundMask = LIT64( 0x000000FFFFFFFFFF );
590 }
591 else {
592 goto precision80;
593 }
594 zSig0 |= ( zSig1 != 0 );
595 if ( ! roundNearestEven ) {
596 if ( roundingMode == float_round_to_zero ) {
597 roundIncrement = 0;
598 }
599 else {
600 roundIncrement = roundMask;
601 if ( zSign ) {
602 if ( roundingMode == float_round_up ) roundIncrement = 0;
603 }
604 else {
605 if ( roundingMode == float_round_down ) roundIncrement = 0;
606 }
607 }
608 }
609 roundBits = zSig0 & roundMask;
610 if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
611 if ( ( 0x7FFE < zExp )
612 || ( ( zExp == 0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) )
613 ) {
614 goto overflow;
615 }
616 if ( zExp <= 0 ) {
617 isTiny =
618 ( float_detect_tininess == float_tininess_before_rounding )
619 || ( zExp < 0 )
620 || ( zSig0 <= zSig0 + roundIncrement );
621 shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
622 zExp = 0;
623 roundBits = zSig0 & roundMask;
624 if ( isTiny && roundBits ) float_raise( float_flag_underflow );
625 if ( roundBits ) float_exception_flags |= float_flag_inexact;
626 zSig0 += roundIncrement;
627 if ( (sbits64) zSig0 < 0 ) zExp = 1;
628 roundIncrement = roundMask + 1;
629 if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
630 roundMask |= roundIncrement;
631 }
632 zSig0 &= ~ roundMask;
633 return packFloatx80( zSign, zExp, zSig0 );
634 }
635 }
636 if ( roundBits ) float_exception_flags |= float_flag_inexact;
637 zSig0 += roundIncrement;
638 if ( zSig0 < roundIncrement ) {
639 ++zExp;
640 zSig0 = LIT64( 0x8000000000000000 );
641 }
642 roundIncrement = roundMask + 1;
643 if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
644 roundMask |= roundIncrement;
645 }
646 zSig0 &= ~ roundMask;
647 if ( zSig0 == 0 ) zExp = 0;
648 return packFloatx80( zSign, zExp, zSig0 );
649 precision80:
650 increment = ( (sbits64) zSig1 < 0 );
651 if ( ! roundNearestEven ) {
652 if ( roundingMode == float_round_to_zero ) {
653 increment = 0;
654 }
655 else {
656 if ( zSign ) {
657 increment = ( roundingMode == float_round_down ) && zSig1;
658 }
659 else {
660 increment = ( roundingMode == float_round_up ) && zSig1;
661 }
662 }
663 }
664 if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
665 if ( ( 0x7FFE < zExp )
666 || ( ( zExp == 0x7FFE )
667 && ( zSig0 == LIT64( 0xFFFFFFFFFFFFFFFF ) )
668 && increment
669 )
670 ) {
671 roundMask = 0;
672 overflow:
673 float_raise( float_flag_overflow | float_flag_inexact );
674 if ( ( roundingMode == float_round_to_zero )
675 || ( zSign && ( roundingMode == float_round_up ) )
676 || ( ! zSign && ( roundingMode == float_round_down ) )
677 ) {
678 return packFloatx80( zSign, 0x7FFE, ~ roundMask );
679 }
680 return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
681 }
682 if ( zExp <= 0 ) {
683 isTiny =
684 ( float_detect_tininess == float_tininess_before_rounding )
685 || ( zExp < 0 )
686 || ! increment
687 || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) );
688 shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
689 zExp = 0;
690 if ( isTiny && zSig1 ) float_raise( float_flag_underflow );
691 if ( zSig1 ) float_exception_flags |= float_flag_inexact;
692 if ( roundNearestEven ) {
693 increment = ( (sbits64) zSig1 < 0 );
694 }
695 else {
696 if ( zSign ) {
697 increment = ( roundingMode == float_round_down ) && zSig1;
698 }
699 else {
700 increment = ( roundingMode == float_round_up ) && zSig1;
701 }
702 }
703 if ( increment ) {
704 ++zSig0;
705 zSig0 &= ~ ( ( zSig1 + zSig1 == 0 ) & roundNearestEven );
706 if ( (sbits64) zSig0 < 0 ) zExp = 1;
707 }
708 return packFloatx80( zSign, zExp, zSig0 );
709 }
710 }
711 if ( zSig1 ) float_exception_flags |= float_flag_inexact;
712 if ( increment ) {
713 ++zSig0;
714 if ( zSig0 == 0 ) {
715 ++zExp;
716 zSig0 = LIT64( 0x8000000000000000 );
717 }
718 else {
719 zSig0 &= ~ ( ( zSig1 + zSig1 == 0 ) & roundNearestEven );
720 }
721 }
722 else {
723 if ( zSig0 == 0 ) zExp = 0;
724 }
725
726 return packFloatx80( zSign, zExp, zSig0 );
727}
728
729/*
730-------------------------------------------------------------------------------
731Takes an abstract floating-point value having sign `zSign', exponent
732`zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
733and returns the proper extended double-precision floating-point value
734corresponding to the abstract input. This routine is just like
735`roundAndPackFloatx80' except that the input significand does not have to be
736normalized.
737-------------------------------------------------------------------------------
738*/
739static floatx80
740 normalizeRoundAndPackFloatx80(
741 int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
742 )
743{
744 int8 shiftCount;
745
746 if ( zSig0 == 0 ) {
747 zSig0 = zSig1;
748 zSig1 = 0;
749 zExp -= 64;
750 }
751 shiftCount = countLeadingZeros64( zSig0 );
752 shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
753 zExp -= shiftCount;
754 return
755 roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 );
756
757}
758
759#endif
760
761/*
762-------------------------------------------------------------------------------
763Returns the result of converting the 32-bit two's complement integer `a' to
764the single-precision floating-point format. The conversion is performed
765according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
766-------------------------------------------------------------------------------
767*/
768float32 int32_to_float32( int32 a )
769{
770 flag zSign;
771
772 if ( a == 0 ) return 0;
773 if ( a == 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
774 zSign = ( a < 0 );
775 return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a );
776
777}
778
779/*
780-------------------------------------------------------------------------------
781Returns the result of converting the 32-bit two's complement integer `a' to
782the double-precision floating-point format. The conversion is performed
783according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
784-------------------------------------------------------------------------------
785*/
786float64 int32_to_float64( int32 a )
787{
788 flag aSign;
789 uint32 absA;
790 int8 shiftCount;
791 bits64 zSig;
792
793 if ( a == 0 ) return 0;
794 aSign = ( a < 0 );
795 absA = aSign ? - a : a;
796 shiftCount = countLeadingZeros32( absA ) + 21;
797 zSig = absA;
798 return packFloat64( aSign, 0x432 - shiftCount, zSig<<shiftCount );
799
800}
801
802#ifdef FLOATX80
803
804/*
805-------------------------------------------------------------------------------
806Returns the result of converting the 32-bit two's complement integer `a'
807to the extended double-precision floating-point format. The conversion
808is performed according to the IEC/IEEE Standard for Binary Floating-point
809Arithmetic.
810-------------------------------------------------------------------------------
811*/
812floatx80 int32_to_floatx80( int32 a )
813{
814 flag zSign;
815 uint32 absA;
816 int8 shiftCount;
817 bits64 zSig;
818
819 if ( a == 0 ) return packFloatx80( 0, 0, 0 );
820 zSign = ( a < 0 );
821 absA = zSign ? - a : a;
822 shiftCount = countLeadingZeros32( absA ) + 32;
823 zSig = absA;
824 return packFloatx80( zSign, 0x403E - shiftCount, zSig<<shiftCount );
825
826}
827
828#endif
829
830/*
831-------------------------------------------------------------------------------
832Returns the result of converting the single-precision floating-point value
833`a' to the 32-bit two's complement integer format. The conversion is
834performed according to the IEC/IEEE Standard for Binary Floating-point
835Arithmetic---which means in particular that the conversion is rounded
836according to the current rounding mode. If `a' is a NaN, the largest
837positive integer is returned. Otherwise, if the conversion overflows, the
838largest integer with the same sign as `a' is returned.
839-------------------------------------------------------------------------------
840*/
841int32 float32_to_int32( float32 a )
842{
843 flag aSign;
844 int16 aExp, shiftCount;
845 bits32 aSig;
846 bits64 zSig;
847
848 aSig = extractFloat32Frac( a );
849 aExp = extractFloat32Exp( a );
850 aSign = extractFloat32Sign( a );
851 if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
852 if ( aExp ) aSig |= 0x00800000;
853 shiftCount = 0xAF - aExp;
854 zSig = aSig;
855 zSig <<= 32;
856 if ( 0 < shiftCount ) shift64RightJamming( zSig, shiftCount, &zSig );
857 return roundAndPackInt32( aSign, zSig );
858
859}
860
861/*
862-------------------------------------------------------------------------------
863Returns the result of converting the single-precision floating-point value
864`a' to the 32-bit two's complement integer format. The conversion is
865performed according to the IEC/IEEE Standard for Binary Floating-point
866Arithmetic, except that the conversion is always rounded toward zero. If
867`a' is a NaN, the largest positive integer is returned. Otherwise, if the
868conversion overflows, the largest integer with the same sign as `a' is
869returned.
870-------------------------------------------------------------------------------
871*/
872int32 float32_to_int32_round_to_zero( float32 a )
873{
874 flag aSign;
875 int16 aExp, shiftCount;
876 bits32 aSig;
877 int32 z;
878
879 aSig = extractFloat32Frac( a );
880 aExp = extractFloat32Exp( a );
881 aSign = extractFloat32Sign( a );
882 shiftCount = aExp - 0x9E;
883 if ( 0 <= shiftCount ) {
884 if ( a == 0xCF000000 ) return 0x80000000;
885 float_raise( float_flag_invalid );
886 if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF;
887 return 0x80000000;
888 }
889 else if ( aExp <= 0x7E ) {
890 if ( aExp | aSig ) float_exception_flags |= float_flag_inexact;
891 return 0;
892 }
893 aSig = ( aSig | 0x00800000 )<<8;
894 z = aSig>>( - shiftCount );
895 if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
896 float_exception_flags |= float_flag_inexact;
897 }
898 return aSign ? - z : z;
899
900}
901
902/*
903-------------------------------------------------------------------------------
904Returns the result of converting the single-precision floating-point value
905`a' to the double-precision floating-point format. The conversion is
906performed according to the IEC/IEEE Standard for Binary Floating-point
907Arithmetic.
908-------------------------------------------------------------------------------
909*/
910float64 float32_to_float64( float32 a )
911{
912 flag aSign;
913 int16 aExp;
914 bits32 aSig;
915
916 aSig = extractFloat32Frac( a );
917 aExp = extractFloat32Exp( a );
918 aSign = extractFloat32Sign( a );
919 if ( aExp == 0xFF ) {
920 if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) );
921 return packFloat64( aSign, 0x7FF, 0 );
922 }
923 if ( aExp == 0 ) {
924 if ( aSig == 0 ) return packFloat64( aSign, 0, 0 );
925 normalizeFloat32Subnormal( aSig, &aExp, &aSig );
926 --aExp;
927 }
928 return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 );
929
930}
931
932#ifdef FLOATX80
933
934/*
935-------------------------------------------------------------------------------
936Returns the result of converting the single-precision floating-point value
937`a' to the extended double-precision floating-point format. The conversion
938is performed according to the IEC/IEEE Standard for Binary Floating-point
939Arithmetic.
940-------------------------------------------------------------------------------
941*/
942floatx80 float32_to_floatx80( float32 a )
943{
944 flag aSign;
945 int16 aExp;
946 bits32 aSig;
947
948 aSig = extractFloat32Frac( a );
949 aExp = extractFloat32Exp( a );
950 aSign = extractFloat32Sign( a );
951 if ( aExp == 0xFF ) {
952 if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) );
953 return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
954 }
955 if ( aExp == 0 ) {
956 if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
957 normalizeFloat32Subnormal( aSig, &aExp, &aSig );
958 }
959 aSig |= 0x00800000;
960 return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 );
961
962}
963
964#endif
965
966/*
967-------------------------------------------------------------------------------
968Rounds the single-precision floating-point value `a' to an integer, and
969returns the result as a single-precision floating-point value. The
970operation is performed according to the IEC/IEEE Standard for Binary
971Floating-point Arithmetic.
972-------------------------------------------------------------------------------
973*/
974float32 float32_round_to_int( float32 a )
975{
976 flag aSign;
977 int16 aExp;
978 bits32 lastBitMask, roundBitsMask;
979 int8 roundingMode;
980 float32 z;
981
982 aExp = extractFloat32Exp( a );
983 if ( 0x96 <= aExp ) {
984 if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) {
985 return propagateFloat32NaN( a, a );
986 }
987 return a;
988 }
989 if ( aExp <= 0x7E ) {
990 if ( (bits32) ( a<<1 ) == 0 ) return a;
991 float_exception_flags |= float_flag_inexact;
992 aSign = extractFloat32Sign( a );
993 switch ( float_rounding_mode ) {
994 case float_round_nearest_even:
995 if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
996 return packFloat32( aSign, 0x7F, 0 );
997 }
998 break;
999 case float_round_down:
1000 return aSign ? 0xBF800000 : 0;
1001 case float_round_up:
1002 return aSign ? 0x80000000 : 0x3F800000;
1003 }
1004 return packFloat32( aSign, 0, 0 );
1005 }
1006 lastBitMask = 1;
1007 lastBitMask <<= 0x96 - aExp;
1008 roundBitsMask = lastBitMask - 1;
1009 z = a;
1010 roundingMode = float_rounding_mode;
1011 if ( roundingMode == float_round_nearest_even ) {
1012 z += lastBitMask>>1;
1013 if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
1014 }
1015 else if ( roundingMode != float_round_to_zero ) {
1016 if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) {
1017 z += roundBitsMask;
1018 }
1019 }
1020 z &= ~ roundBitsMask;
1021 if ( z != a ) float_exception_flags |= float_flag_inexact;
1022 return z;
1023
1024}
1025
1026/*
1027-------------------------------------------------------------------------------
1028Returns the result of adding the absolute values of the single-precision
1029floating-point values `a' and `b'. If `zSign' is true, the sum is negated
1030before being returned. `zSign' is ignored if the result is a NaN. The
1031addition is performed according to the IEC/IEEE Standard for Binary
1032Floating-point Arithmetic.
1033-------------------------------------------------------------------------------
1034*/
1035static float32 addFloat32Sigs( float32 a, float32 b, flag zSign )
1036{
1037 int16 aExp, bExp, zExp;
1038 bits32 aSig, bSig, zSig;
1039 int16 expDiff;
1040
1041 aSig = extractFloat32Frac( a );
1042 aExp = extractFloat32Exp( a );
1043 bSig = extractFloat32Frac( b );
1044 bExp = extractFloat32Exp( b );
1045 expDiff = aExp - bExp;
1046 aSig <<= 6;
1047 bSig <<= 6;
1048 if ( 0 < expDiff ) {
1049 if ( aExp == 0xFF ) {
1050 if ( aSig ) return propagateFloat32NaN( a, b );
1051 return a;
1052 }
1053 if ( bExp == 0 ) {
1054 --expDiff;
1055 }
1056 else {
1057 bSig |= 0x20000000;
1058 }
1059 shift32RightJamming( bSig, expDiff, &bSig );
1060 zExp = aExp;
1061 }
1062 else if ( expDiff < 0 ) {
1063 if ( bExp == 0xFF ) {
1064 if ( bSig ) return propagateFloat32NaN( a, b );
1065 return packFloat32( zSign, 0xFF, 0 );
1066 }
1067 if ( aExp == 0 ) {
1068 ++expDiff;
1069 }
1070 else {
1071 aSig |= 0x20000000;
1072 }
1073 shift32RightJamming( aSig, - expDiff, &aSig );
1074 zExp = bExp;
1075 }
1076 else {
1077 if ( aExp == 0xFF ) {
1078 if ( aSig | bSig ) return propagateFloat32NaN( a, b );
1079 return a;
1080 }
1081 if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 );
1082 zSig = 0x40000000 + aSig + bSig;
1083 zExp = aExp;
1084 goto roundAndPack;
1085 }
1086 aSig |= 0x20000000;
1087 zSig = ( aSig + bSig )<<1;
1088 --zExp;
1089 if ( (sbits32) zSig < 0 ) {
1090 zSig = aSig + bSig;
1091 ++zExp;
1092 }
1093 roundAndPack:
1094 return roundAndPackFloat32( zSign, zExp, zSig );
1095
1096}
1097
1098/*
1099-------------------------------------------------------------------------------
1100Returns the result of subtracting the absolute values of the single-
1101precision floating-point values `a' and `b'. If `zSign' is true, the
1102difference is negated before being returned. `zSign' is ignored if the
1103result is a NaN. The subtraction is performed according to the IEC/IEEE
1104Standard for Binary Floating-point Arithmetic.
1105-------------------------------------------------------------------------------
1106*/
1107static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
1108{
1109 int16 aExp, bExp, zExp;
1110 bits32 aSig, bSig, zSig;
1111 int16 expDiff;
1112
1113 aSig = extractFloat32Frac( a );
1114 aExp = extractFloat32Exp( a );
1115 bSig = extractFloat32Frac( b );
1116 bExp = extractFloat32Exp( b );
1117 expDiff = aExp - bExp;
1118 aSig <<= 7;
1119 bSig <<= 7;
1120 if ( 0 < expDiff ) goto aExpBigger;
1121 if ( expDiff < 0 ) goto bExpBigger;
1122 if ( aExp == 0xFF ) {
1123 if ( aSig | bSig ) return propagateFloat32NaN( a, b );
1124 float_raise( float_flag_invalid );
1125 return float32_default_nan;
1126 }
1127 if ( aExp == 0 ) {
1128 aExp = 1;
1129 bExp = 1;
1130 }
1131 if ( bSig < aSig ) goto aBigger;
1132 if ( aSig < bSig ) goto bBigger;
1133 return packFloat32( float_rounding_mode == float_round_down, 0, 0 );
1134 bExpBigger:
1135 if ( bExp == 0xFF ) {
1136 if ( bSig ) return propagateFloat32NaN( a, b );
1137 return packFloat32( zSign ^ 1, 0xFF, 0 );
1138 }
1139 if ( aExp == 0 ) {
1140 ++expDiff;
1141 }
1142 else {
1143 aSig |= 0x40000000;
1144 }
1145 shift32RightJamming( aSig, - expDiff, &aSig );
1146 bSig |= 0x40000000;
1147 bBigger:
1148 zSig = bSig - aSig;
1149 zExp = bExp;
1150 zSign ^= 1;
1151 goto normalizeRoundAndPack;
1152 aExpBigger:
1153 if ( aExp == 0xFF ) {
1154 if ( aSig ) return propagateFloat32NaN( a, b );
1155 return a;
1156 }
1157 if ( bExp == 0 ) {
1158 --expDiff;
1159 }
1160 else {
1161 bSig |= 0x40000000;
1162 }
1163 shift32RightJamming( bSig, expDiff, &bSig );
1164 aSig |= 0x40000000;
1165 aBigger:
1166 zSig = aSig - bSig;
1167 zExp = aExp;
1168 normalizeRoundAndPack:
1169 --zExp;
1170 return normalizeRoundAndPackFloat32( zSign, zExp, zSig );
1171
1172}
1173
1174/*
1175-------------------------------------------------------------------------------
1176Returns the result of adding the single-precision floating-point values `a'
1177and `b'. The operation is performed according to the IEC/IEEE Standard for
1178Binary Floating-point Arithmetic.
1179-------------------------------------------------------------------------------
1180*/
1181float32 float32_add( float32 a, float32 b )
1182{
1183 flag aSign, bSign;
1184
1185 aSign = extractFloat32Sign( a );
1186 bSign = extractFloat32Sign( b );
1187 if ( aSign == bSign ) {
1188 return addFloat32Sigs( a, b, aSign );
1189 }
1190 else {
1191 return subFloat32Sigs( a, b, aSign );
1192 }
1193
1194}
1195
1196/*
1197-------------------------------------------------------------------------------
1198Returns the result of subtracting the single-precision floating-point values
1199`a' and `b'. The operation is performed according to the IEC/IEEE Standard
1200for Binary Floating-point Arithmetic.
1201-------------------------------------------------------------------------------
1202*/
1203float32 float32_sub( float32 a, float32 b )
1204{
1205 flag aSign, bSign;
1206
1207 aSign = extractFloat32Sign( a );
1208 bSign = extractFloat32Sign( b );
1209 if ( aSign == bSign ) {
1210 return subFloat32Sigs( a, b, aSign );
1211 }
1212 else {
1213 return addFloat32Sigs( a, b, aSign );
1214 }
1215
1216}
1217
1218/*
1219-------------------------------------------------------------------------------
1220Returns the result of multiplying the single-precision floating-point values
1221`a' and `b'. The operation is performed according to the IEC/IEEE Standard
1222for Binary Floating-point Arithmetic.
1223-------------------------------------------------------------------------------
1224*/
1225float32 float32_mul( float32 a, float32 b )
1226{
1227 flag aSign, bSign, zSign;
1228 int16 aExp, bExp, zExp;
1229 bits32 aSig, bSig;
1230 bits64 zSig64;
1231 bits32 zSig;
1232
1233 aSig = extractFloat32Frac( a );
1234 aExp = extractFloat32Exp( a );
1235 aSign = extractFloat32Sign( a );
1236 bSig = extractFloat32Frac( b );
1237 bExp = extractFloat32Exp( b );
1238 bSign = extractFloat32Sign( b );
1239 zSign = aSign ^ bSign;
1240 if ( aExp == 0xFF ) {
1241 if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
1242 return propagateFloat32NaN( a, b );
1243 }
1244 if ( ( bExp | bSig ) == 0 ) {
1245 float_raise( float_flag_invalid );
1246 return float32_default_nan;
1247 }
1248 return packFloat32( zSign, 0xFF, 0 );
1249 }
1250 if ( bExp == 0xFF ) {
1251 if ( bSig ) return propagateFloat32NaN( a, b );
1252 if ( ( aExp | aSig ) == 0 ) {
1253 float_raise( float_flag_invalid );
1254 return float32_default_nan;
1255 }
1256 return packFloat32( zSign, 0xFF, 0 );
1257 }
1258 if ( aExp == 0 ) {
1259 if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
1260 normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1261 }
1262 if ( bExp == 0 ) {
1263 if ( bSig == 0 ) return packFloat32( zSign, 0, 0 );
1264 normalizeFloat32Subnormal( bSig, &bExp, &bSig );
1265 }
1266 zExp = aExp + bExp - 0x7F;
1267 aSig = ( aSig | 0x00800000 )<<7;
1268 bSig = ( bSig | 0x00800000 )<<8;
1269 shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 );
1270 zSig = zSig64;
1271 if ( 0 <= (sbits32) ( zSig<<1 ) ) {
1272 zSig <<= 1;
1273 --zExp;
1274 }
1275 return roundAndPackFloat32( zSign, zExp, zSig );
1276
1277}
1278
1279/*
1280-------------------------------------------------------------------------------
1281Returns the result of dividing the single-precision floating-point value `a'
1282by the corresponding value `b'. The operation is performed according to the
1283IEC/IEEE Standard for Binary Floating-point Arithmetic.
1284-------------------------------------------------------------------------------
1285*/
1286float32 float32_div( float32 a, float32 b )
1287{
1288 flag aSign, bSign, zSign;
1289 int16 aExp, bExp, zExp;
1290 bits32 aSig, bSig, zSig;
1291
1292 aSig = extractFloat32Frac( a );
1293 aExp = extractFloat32Exp( a );
1294 aSign = extractFloat32Sign( a );
1295 bSig = extractFloat32Frac( b );
1296 bExp = extractFloat32Exp( b );
1297 bSign = extractFloat32Sign( b );
1298 zSign = aSign ^ bSign;
1299 if ( aExp == 0xFF ) {
1300 if ( aSig ) return propagateFloat32NaN( a, b );
1301 if ( bExp == 0xFF ) {
1302 if ( bSig ) return propagateFloat32NaN( a, b );
1303 float_raise( float_flag_invalid );
1304 return float32_default_nan;
1305 }
1306 return packFloat32( zSign, 0xFF, 0 );
1307 }
1308 if ( bExp == 0xFF ) {
1309 if ( bSig ) return propagateFloat32NaN( a, b );
1310 return packFloat32( zSign, 0, 0 );
1311 }
1312 if ( bExp == 0 ) {
1313 if ( bSig == 0 ) {
1314 if ( ( aExp | aSig ) == 0 ) {
1315 float_raise( float_flag_invalid );
1316 return float32_default_nan;
1317 }
1318 float_raise( float_flag_divbyzero );
1319 return packFloat32( zSign, 0xFF, 0 );
1320 }
1321 normalizeFloat32Subnormal( bSig, &bExp, &bSig );
1322 }
1323 if ( aExp == 0 ) {
1324 if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
1325 normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1326 }
1327 zExp = aExp - bExp + 0x7D;
1328 aSig = ( aSig | 0x00800000 )<<7;
1329 bSig = ( bSig | 0x00800000 )<<8;
1330 if ( bSig <= ( aSig + aSig ) ) {
1331 aSig >>= 1;
1332 ++zExp;
1333 }
1334 zSig = ( ( (bits64) aSig )<<32 ) / bSig;
1335 if ( ( zSig & 0x3F ) == 0 ) {
1336 zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 );
1337 }
1338 return roundAndPackFloat32( zSign, zExp, zSig );
1339
1340}
1341
1342/*
1343-------------------------------------------------------------------------------
1344Returns the remainder of the single-precision floating-point value `a'
1345with respect to the corresponding value `b'. The operation is performed
1346according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
1347-------------------------------------------------------------------------------
1348*/
1349float32 float32_rem( float32 a, float32 b )
1350{
1351 flag aSign, bSign, zSign;
1352 int16 aExp, bExp, expDiff;
1353 bits32 aSig, bSig;
1354 bits32 q;
1355 bits64 aSig64, bSig64, q64;
1356 bits32 alternateASig;
1357 sbits32 sigMean;
1358
1359 aSig = extractFloat32Frac( a );
1360 aExp = extractFloat32Exp( a );
1361 aSign = extractFloat32Sign( a );
1362 bSig = extractFloat32Frac( b );
1363 bExp = extractFloat32Exp( b );
1364 bSign = extractFloat32Sign( b );
1365 if ( aExp == 0xFF ) {
1366 if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
1367 return propagateFloat32NaN( a, b );
1368 }
1369 float_raise( float_flag_invalid );
1370 return float32_default_nan;
1371 }
1372 if ( bExp == 0xFF ) {
1373 if ( bSig ) return propagateFloat32NaN( a, b );
1374 return a;
1375 }
1376 if ( bExp == 0 ) {
1377 if ( bSig == 0 ) {
1378 float_raise( float_flag_invalid );
1379 return float32_default_nan;
1380 }
1381 normalizeFloat32Subnormal( bSig, &bExp, &bSig );
1382 }
1383 if ( aExp == 0 ) {
1384 if ( aSig == 0 ) return a;
1385 normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1386 }
1387 expDiff = aExp - bExp;
1388 aSig |= 0x00800000;
1389 bSig |= 0x00800000;
1390 if ( expDiff < 32 ) {
1391 aSig <<= 8;
1392 bSig <<= 8;
1393 if ( expDiff < 0 ) {
1394 if ( expDiff < -1 ) return a;
1395 aSig >>= 1;
1396 }
1397 q = ( bSig <= aSig );
1398 if ( q ) aSig -= bSig;
1399 if ( 0 < expDiff ) {
1400 q = ( ( (bits64) aSig )<<32 ) / bSig;
1401 q >>= 32 - expDiff;
1402 bSig >>= 2;
1403 aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
1404 }
1405 else {
1406 aSig >>= 2;
1407 bSig >>= 2;
1408 }
1409 }
1410 else {
1411 if ( bSig <= aSig ) aSig -= bSig;
1412 aSig64 = ( (bits64) aSig )<<40;
1413 bSig64 = ( (bits64) bSig )<<40;
1414 expDiff -= 64;
1415 while ( 0 < expDiff ) {
1416 q64 = estimateDiv128To64( aSig64, 0, bSig64 );
1417 q64 = ( 2 < q64 ) ? q64 - 2 : 0;
1418 aSig64 = - ( ( bSig * q64 )<<38 );
1419 expDiff -= 62;
1420 }
1421 expDiff += 64;
1422 q64 = estimateDiv128To64( aSig64, 0, bSig64 );
1423 q64 = ( 2 < q64 ) ? q64 - 2 : 0;
1424 q = q64>>( 64 - expDiff );
1425 bSig <<= 6;
1426 aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q;
1427 }
1428 do {
1429 alternateASig = aSig;
1430 ++q;
1431 aSig -= bSig;
1432 } while ( 0 <= (sbits32) aSig );
1433 sigMean = aSig + alternateASig;
1434 if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
1435 aSig = alternateASig;
1436 }
1437 zSign = ( (sbits32) aSig < 0 );
1438 if ( zSign ) aSig = - aSig;
1439 return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig );
1440
1441}
1442
1443/*
1444-------------------------------------------------------------------------------
1445Returns the square root of the single-precision floating-point value `a'.
1446The operation is performed according to the IEC/IEEE Standard for Binary
1447Floating-point Arithmetic.
1448-------------------------------------------------------------------------------
1449*/
1450float32 float32_sqrt( float32 a )
1451{
1452 flag aSign;
1453 int16 aExp, zExp;
1454 bits32 aSig, zSig;
1455 bits64 rem, term;
1456
1457 aSig = extractFloat32Frac( a );
1458 aExp = extractFloat32Exp( a );
1459 aSign = extractFloat32Sign( a );
1460 if ( aExp == 0xFF ) {
1461 if ( aSig ) return propagateFloat32NaN( a, 0 );
1462 if ( ! aSign ) return a;
1463 float_raise( float_flag_invalid );
1464 return float32_default_nan;
1465 }
1466 if ( aSign ) {
1467 if ( ( aExp | aSig ) == 0 ) return a;
1468 float_raise( float_flag_invalid );
1469 return float32_default_nan;
1470 }
1471 if ( aExp == 0 ) {
1472 if ( aSig == 0 ) return 0;
1473 normalizeFloat32Subnormal( aSig, &aExp, &aSig );
1474 }
1475 zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E;
1476 aSig = ( aSig | 0x00800000 )<<8;
1477 zSig = estimateSqrt32( aExp, aSig ) + 2;
1478 if ( ( zSig & 0x7F ) <= 5 ) {
1479 if ( zSig < 2 ) {
1480 zSig = 0xFFFFFFFF;
1481 }
1482 else {
1483 aSig >>= aExp & 1;
1484 term = ( (bits64) zSig ) * zSig;
1485 rem = ( ( (bits64) aSig )<<32 ) - term;
1486 while ( (sbits64) rem < 0 ) {
1487 --zSig;
1488 rem += ( ( (bits64) zSig )<<1 ) | 1;
1489 }
1490 zSig |= ( rem != 0 );
1491 }
1492 }
1493 shift32RightJamming( zSig, 1, &zSig );
1494 return roundAndPackFloat32( 0, zExp, zSig );
1495
1496}
1497
1498/*
1499-------------------------------------------------------------------------------
1500Returns 1 if the single-precision floating-point value `a' is equal to the
1501corresponding value `b', and 0 otherwise. The comparison is performed
1502according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
1503-------------------------------------------------------------------------------
1504*/
1505flag float32_eq( float32 a, float32 b )
1506{
1507
1508 if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
1509 || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
1510 ) {
1511 if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
1512 float_raise( float_flag_invalid );
1513 }
1514 return 0;
1515 }
1516 return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
1517
1518}
1519
1520/*
1521-------------------------------------------------------------------------------
1522Returns 1 if the single-precision floating-point value `a' is less than or
1523equal to the corresponding value `b', and 0 otherwise. The comparison is
1524performed according to the IEC/IEEE Standard for Binary Floating-point
1525Arithmetic.
1526-------------------------------------------------------------------------------
1527*/
1528flag float32_le( float32 a, float32 b )
1529{
1530 flag aSign, bSign;
1531
1532 if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
1533 || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
1534 ) {
1535 float_raise( float_flag_invalid );
1536 return 0;
1537 }
1538 aSign = extractFloat32Sign( a );
1539 bSign = extractFloat32Sign( b );
1540 if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
1541 return ( a == b ) || ( aSign ^ ( a < b ) );
1542
1543}
1544
1545/*
1546-------------------------------------------------------------------------------
1547Returns 1 if the single-precision floating-point value `a' is less than
1548the corresponding value `b', and 0 otherwise. The comparison is performed
1549according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
1550-------------------------------------------------------------------------------
1551*/
1552flag float32_lt( float32 a, float32 b )
1553{
1554 flag aSign, bSign;
1555
1556 if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
1557 || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
1558 ) {
1559 float_raise( float_flag_invalid );
1560 return 0;
1561 }
1562 aSign = extractFloat32Sign( a );
1563 bSign = extractFloat32Sign( b );
1564 if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
1565 return ( a != b ) && ( aSign ^ ( a < b ) );
1566
1567}
1568
1569/*
1570-------------------------------------------------------------------------------
1571Returns 1 if the single-precision floating-point value `a' is equal to the
1572corresponding value `b', and 0 otherwise. The invalid exception is raised
1573if either operand is a NaN. Otherwise, the comparison is performed
1574according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
1575-------------------------------------------------------------------------------
1576*/
1577flag float32_eq_signaling( float32 a, float32 b )
1578{
1579
1580 if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
1581 || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
1582 ) {
1583 float_raise( float_flag_invalid );
1584 return 0;
1585 }
1586 return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
1587
1588}
1589
1590/*
1591-------------------------------------------------------------------------------
1592Returns 1 if the single-precision floating-point value `a' is less than or
1593equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
1594cause an exception. Otherwise, the comparison is performed according to the
1595IEC/IEEE Standard for Binary Floating-point Arithmetic.
1596-------------------------------------------------------------------------------
1597*/
1598flag float32_le_quiet( float32 a, float32 b )
1599{
1600 flag aSign, bSign;
1601 //int16 aExp, bExp;
1602
1603 if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
1604 || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
1605 ) {
1606 if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
1607 float_raise( float_flag_invalid );
1608 }
1609 return 0;
1610 }
1611 aSign = extractFloat32Sign( a );
1612 bSign = extractFloat32Sign( b );
1613 if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
1614 return ( a == b ) || ( aSign ^ ( a < b ) );
1615
1616}
1617
1618/*
1619-------------------------------------------------------------------------------
1620Returns 1 if the single-precision floating-point value `a' is less than
1621the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
1622exception. Otherwise, the comparison is performed according to the IEC/IEEE
1623Standard for Binary Floating-point Arithmetic.
1624-------------------------------------------------------------------------------
1625*/
1626flag float32_lt_quiet( float32 a, float32 b )
1627{
1628 flag aSign, bSign;
1629
1630 if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
1631 || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
1632 ) {
1633 if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
1634 float_raise( float_flag_invalid );
1635 }
1636 return 0;
1637 }
1638 aSign = extractFloat32Sign( a );
1639 bSign = extractFloat32Sign( b );
1640 if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
1641 return ( a != b ) && ( aSign ^ ( a < b ) );
1642
1643}
1644
1645/*
1646-------------------------------------------------------------------------------
1647Returns the result of converting the double-precision floating-point value
1648`a' to the 32-bit two's complement integer format. The conversion is
1649performed according to the IEC/IEEE Standard for Binary Floating-point
1650Arithmetic---which means in particular that the conversion is rounded
1651according to the current rounding mode. If `a' is a NaN, the largest
1652positive integer is returned. Otherwise, if the conversion overflows, the
1653largest integer with the same sign as `a' is returned.
1654-------------------------------------------------------------------------------
1655*/
1656int32 float64_to_int32( float64 a )
1657{
1658 flag aSign;
1659 int16 aExp, shiftCount;
1660 bits64 aSig;
1661
1662 aSig = extractFloat64Frac( a );
1663 aExp = extractFloat64Exp( a );
1664 aSign = extractFloat64Sign( a );
1665 if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
1666 if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
1667 shiftCount = 0x42C - aExp;
1668 if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
1669 return roundAndPackInt32( aSign, aSig );
1670
1671}
1672
1673/*
1674-------------------------------------------------------------------------------
1675Returns the result of converting the double-precision floating-point value
1676`a' to the 32-bit two's complement integer format. The conversion is
1677performed according to the IEC/IEEE Standard for Binary Floating-point
1678Arithmetic, except that the conversion is always rounded toward zero. If
1679`a' is a NaN, the largest positive integer is returned. Otherwise, if the
1680conversion overflows, the largest integer with the same sign as `a' is
1681returned.
1682-------------------------------------------------------------------------------
1683*/
1684int32 float64_to_int32_round_to_zero( float64 a )
1685{
1686 flag aSign;
1687 int16 aExp, shiftCount;
1688 bits64 aSig, savedASig;
1689 int32 z;
1690
1691 aSig = extractFloat64Frac( a );
1692 aExp = extractFloat64Exp( a );
1693 aSign = extractFloat64Sign( a );
1694 shiftCount = 0x433 - aExp;
1695 if ( shiftCount < 21 ) {
1696 if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
1697 goto invalid;
1698 }
1699 else if ( 52 < shiftCount ) {
1700 if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
1701 return 0;
1702 }
1703 aSig |= LIT64( 0x0010000000000000 );
1704 savedASig = aSig;
1705 aSig >>= shiftCount;
1706 z = aSig;
1707 if ( aSign ) z = - z;
1708 if ( ( z < 0 ) ^ aSign ) {
1709 invalid:
1710 float_exception_flags |= float_flag_invalid;
1711 return aSign ? 0x80000000 : 0x7FFFFFFF;
1712 }
1713 if ( ( aSig<<shiftCount ) != savedASig ) {
1714 float_exception_flags |= float_flag_inexact;
1715 }
1716 return z;
1717
1718}
1719
1720/*
1721-------------------------------------------------------------------------------
1722Returns the result of converting the double-precision floating-point value
1723`a' to the 32-bit two's complement unsigned integer format. The conversion
1724is performed according to the IEC/IEEE Standard for Binary Floating-point
1725Arithmetic---which means in particular that the conversion is rounded
1726according to the current rounding mode. If `a' is a NaN, the largest
1727positive integer is returned. Otherwise, if the conversion overflows, the
1728largest positive integer is returned.
1729-------------------------------------------------------------------------------
1730*/
1731int32 float64_to_uint32( float64 a )
1732{
1733 flag aSign;
1734 int16 aExp, shiftCount;
1735 bits64 aSig;
1736
1737 aSig = extractFloat64Frac( a );
1738 aExp = extractFloat64Exp( a );
1739 aSign = 0; //extractFloat64Sign( a );
1740 //if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
1741 if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
1742 shiftCount = 0x42C - aExp;
1743 if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
1744 return roundAndPackInt32( aSign, aSig );
1745}
1746
1747/*
1748-------------------------------------------------------------------------------
1749Returns the result of converting the double-precision floating-point value
1750`a' to the 32-bit two's complement integer format. The conversion is
1751performed according to the IEC/IEEE Standard for Binary Floating-point
1752Arithmetic, except that the conversion is always rounded toward zero. If
1753`a' is a NaN, the largest positive integer is returned. Otherwise, if the
1754conversion overflows, the largest positive integer is returned.
1755-------------------------------------------------------------------------------
1756*/
1757int32 float64_to_uint32_round_to_zero( float64 a )
1758{
1759 flag aSign;
1760 int16 aExp, shiftCount;
1761 bits64 aSig, savedASig;
1762 int32 z;
1763
1764 aSig = extractFloat64Frac( a );
1765 aExp = extractFloat64Exp( a );
1766 aSign = extractFloat64Sign( a );
1767 shiftCount = 0x433 - aExp;
1768 if ( shiftCount < 21 ) {
1769 if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
1770 goto invalid;
1771 }
1772 else if ( 52 < shiftCount ) {
1773 if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
1774 return 0;
1775 }
1776 aSig |= LIT64( 0x0010000000000000 );
1777 savedASig = aSig;
1778 aSig >>= shiftCount;
1779 z = aSig;
1780 if ( aSign ) z = - z;
1781 if ( ( z < 0 ) ^ aSign ) {
1782 invalid:
1783 float_exception_flags |= float_flag_invalid;
1784 return aSign ? 0x80000000 : 0x7FFFFFFF;
1785 }
1786 if ( ( aSig<<shiftCount ) != savedASig ) {
1787 float_exception_flags |= float_flag_inexact;
1788 }
1789 return z;
1790}
1791
1792/*
1793-------------------------------------------------------------------------------
1794Returns the result of converting the double-precision floating-point value
1795`a' to the single-precision floating-point format. The conversion is
1796performed according to the IEC/IEEE Standard for Binary Floating-point
1797Arithmetic.
1798-------------------------------------------------------------------------------
1799*/
1800float32 float64_to_float32( float64 a )
1801{
1802 flag aSign;
1803 int16 aExp;
1804 bits64 aSig;
1805 bits32 zSig;
1806
1807 aSig = extractFloat64Frac( a );
1808 aExp = extractFloat64Exp( a );
1809 aSign = extractFloat64Sign( a );
1810 if ( aExp == 0x7FF ) {
1811 if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) );
1812 return packFloat32( aSign, 0xFF, 0 );
1813 }
1814 shift64RightJamming( aSig, 22, &aSig );
1815 zSig = aSig;
1816 if ( aExp || zSig ) {
1817 zSig |= 0x40000000;
1818 aExp -= 0x381;
1819 }
1820 return roundAndPackFloat32( aSign, aExp, zSig );
1821
1822}
1823
1824#ifdef FLOATX80
1825
1826/*
1827-------------------------------------------------------------------------------
1828Returns the result of converting the double-precision floating-point value
1829`a' to the extended double-precision floating-point format. The conversion
1830is performed according to the IEC/IEEE Standard for Binary Floating-point
1831Arithmetic.
1832-------------------------------------------------------------------------------
1833*/
1834floatx80 float64_to_floatx80( float64 a )
1835{
1836 flag aSign;
1837 int16 aExp;
1838 bits64 aSig;
1839
1840 aSig = extractFloat64Frac( a );
1841 aExp = extractFloat64Exp( a );
1842 aSign = extractFloat64Sign( a );
1843 if ( aExp == 0x7FF ) {
1844 if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) );
1845 return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
1846 }
1847 if ( aExp == 0 ) {
1848 if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
1849 normalizeFloat64Subnormal( aSig, &aExp, &aSig );
1850 }
1851 return
1852 packFloatx80(
1853 aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 );
1854
1855}
1856
1857#endif
1858
1859/*
1860-------------------------------------------------------------------------------
1861Rounds the double-precision floating-point value `a' to an integer, and
1862returns the result as a double-precision floating-point value. The
1863operation is performed according to the IEC/IEEE Standard for Binary
1864Floating-point Arithmetic.
1865-------------------------------------------------------------------------------
1866*/
1867float64 float64_round_to_int( float64 a )
1868{
1869 flag aSign;
1870 int16 aExp;
1871 bits64 lastBitMask, roundBitsMask;
1872 int8 roundingMode;
1873 float64 z;
1874
1875 aExp = extractFloat64Exp( a );
1876 if ( 0x433 <= aExp ) {
1877 if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) {
1878 return propagateFloat64NaN( a, a );
1879 }
1880 return a;
1881 }
1882 if ( aExp <= 0x3FE ) {
1883 if ( (bits64) ( a<<1 ) == 0 ) return a;
1884 float_exception_flags |= float_flag_inexact;
1885 aSign = extractFloat64Sign( a );
1886 switch ( float_rounding_mode ) {
1887 case float_round_nearest_even:
1888 if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) {
1889 return packFloat64( aSign, 0x3FF, 0 );
1890 }
1891 break;
1892 case float_round_down:
1893 return aSign ? LIT64( 0xBFF0000000000000 ) : 0;
1894 case float_round_up:
1895 return
1896 aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 );
1897 }
1898 return packFloat64( aSign, 0, 0 );
1899 }
1900 lastBitMask = 1;
1901 lastBitMask <<= 0x433 - aExp;
1902 roundBitsMask = lastBitMask - 1;
1903 z = a;
1904 roundingMode = float_rounding_mode;
1905 if ( roundingMode == float_round_nearest_even ) {
1906 z += lastBitMask>>1;
1907 if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
1908 }
1909 else if ( roundingMode != float_round_to_zero ) {
1910 if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) {
1911 z += roundBitsMask;
1912 }
1913 }
1914 z &= ~ roundBitsMask;
1915 if ( z != a ) float_exception_flags |= float_flag_inexact;
1916 return z;
1917
1918}
1919
1920/*
1921-------------------------------------------------------------------------------
1922Returns the result of adding the absolute values of the double-precision
1923floating-point values `a' and `b'. If `zSign' is true, the sum is negated
1924before being returned. `zSign' is ignored if the result is a NaN. The
1925addition is performed according to the IEC/IEEE Standard for Binary
1926Floating-point Arithmetic.
1927-------------------------------------------------------------------------------
1928*/
1929static float64 addFloat64Sigs( float64 a, float64 b, flag zSign )
1930{
1931 int16 aExp, bExp, zExp;
1932 bits64 aSig, bSig, zSig;
1933 int16 expDiff;
1934
1935 aSig = extractFloat64Frac( a );
1936 aExp = extractFloat64Exp( a );
1937 bSig = extractFloat64Frac( b );
1938 bExp = extractFloat64Exp( b );
1939 expDiff = aExp - bExp;
1940 aSig <<= 9;
1941 bSig <<= 9;
1942 if ( 0 < expDiff ) {
1943 if ( aExp == 0x7FF ) {
1944 if ( aSig ) return propagateFloat64NaN( a, b );
1945 return a;
1946 }
1947 if ( bExp == 0 ) {
1948 --expDiff;
1949 }
1950 else {
1951 bSig |= LIT64( 0x2000000000000000 );
1952 }
1953 shift64RightJamming( bSig, expDiff, &bSig );
1954 zExp = aExp;
1955 }
1956 else if ( expDiff < 0 ) {
1957 if ( bExp == 0x7FF ) {
1958 if ( bSig ) return propagateFloat64NaN( a, b );
1959 return packFloat64( zSign, 0x7FF, 0 );
1960 }
1961 if ( aExp == 0 ) {
1962 ++expDiff;
1963 }
1964 else {
1965 aSig |= LIT64( 0x2000000000000000 );
1966 }
1967 shift64RightJamming( aSig, - expDiff, &aSig );
1968 zExp = bExp;
1969 }
1970 else {
1971 if ( aExp == 0x7FF ) {
1972 if ( aSig | bSig ) return propagateFloat64NaN( a, b );
1973 return a;
1974 }
1975 if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 );
1976 zSig = LIT64( 0x4000000000000000 ) + aSig + bSig;
1977 zExp = aExp;
1978 goto roundAndPack;
1979 }
1980 aSig |= LIT64( 0x2000000000000000 );
1981 zSig = ( aSig + bSig )<<1;
1982 --zExp;
1983 if ( (sbits64) zSig < 0 ) {
1984 zSig = aSig + bSig;
1985 ++zExp;
1986 }
1987 roundAndPack:
1988 return roundAndPackFloat64( zSign, zExp, zSig );
1989
1990}
1991
1992/*
1993-------------------------------------------------------------------------------
1994Returns the result of subtracting the absolute values of the double-
1995precision floating-point values `a' and `b'. If `zSign' is true, the
1996difference is negated before being returned. `zSign' is ignored if the
1997result is a NaN. The subtraction is performed according to the IEC/IEEE
1998Standard for Binary Floating-point Arithmetic.
1999-------------------------------------------------------------------------------
2000*/
2001static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
2002{
2003 int16 aExp, bExp, zExp;
2004 bits64 aSig, bSig, zSig;
2005 int16 expDiff;
2006
2007 aSig = extractFloat64Frac( a );
2008 aExp = extractFloat64Exp( a );
2009 bSig = extractFloat64Frac( b );
2010 bExp = extractFloat64Exp( b );
2011 expDiff = aExp - bExp;
2012 aSig <<= 10;
2013 bSig <<= 10;
2014 if ( 0 < expDiff ) goto aExpBigger;
2015 if ( expDiff < 0 ) goto bExpBigger;
2016 if ( aExp == 0x7FF ) {
2017 if ( aSig | bSig ) return propagateFloat64NaN( a, b );
2018 float_raise( float_flag_invalid );
2019 return float64_default_nan;
2020 }
2021 if ( aExp == 0 ) {
2022 aExp = 1;
2023 bExp = 1;
2024 }
2025 if ( bSig < aSig ) goto aBigger;
2026 if ( aSig < bSig ) goto bBigger;
2027 return packFloat64( float_rounding_mode == float_round_down, 0, 0 );
2028 bExpBigger:
2029 if ( bExp == 0x7FF ) {
2030 if ( bSig ) return propagateFloat64NaN( a, b );
2031 return packFloat64( zSign ^ 1, 0x7FF, 0 );
2032 }
2033 if ( aExp == 0 ) {
2034 ++expDiff;
2035 }
2036 else {
2037 aSig |= LIT64( 0x4000000000000000 );
2038 }
2039 shift64RightJamming( aSig, - expDiff, &aSig );
2040 bSig |= LIT64( 0x4000000000000000 );
2041 bBigger:
2042 zSig = bSig - aSig;
2043 zExp = bExp;
2044 zSign ^= 1;
2045 goto normalizeRoundAndPack;
2046 aExpBigger:
2047 if ( aExp == 0x7FF ) {
2048 if ( aSig ) return propagateFloat64NaN( a, b );
2049 return a;
2050 }
2051 if ( bExp == 0 ) {
2052 --expDiff;
2053 }
2054 else {
2055 bSig |= LIT64( 0x4000000000000000 );
2056 }
2057 shift64RightJamming( bSig, expDiff, &bSig );
2058 aSig |= LIT64( 0x4000000000000000 );
2059 aBigger:
2060 zSig = aSig - bSig;
2061 zExp = aExp;
2062 normalizeRoundAndPack:
2063 --zExp;
2064 return normalizeRoundAndPackFloat64( zSign, zExp, zSig );
2065
2066}
2067
2068/*
2069-------------------------------------------------------------------------------
2070Returns the result of adding the double-precision floating-point values `a'
2071and `b'. The operation is performed according to the IEC/IEEE Standard for
2072Binary Floating-point Arithmetic.
2073-------------------------------------------------------------------------------
2074*/
2075float64 float64_add( float64 a, float64 b )
2076{
2077 flag aSign, bSign;
2078
2079 aSign = extractFloat64Sign( a );
2080 bSign = extractFloat64Sign( b );
2081 if ( aSign == bSign ) {
2082 return addFloat64Sigs( a, b, aSign );
2083 }
2084 else {
2085 return subFloat64Sigs( a, b, aSign );
2086 }
2087
2088}
2089
2090/*
2091-------------------------------------------------------------------------------
2092Returns the result of subtracting the double-precision floating-point values
2093`a' and `b'. The operation is performed according to the IEC/IEEE Standard
2094for Binary Floating-point Arithmetic.
2095-------------------------------------------------------------------------------
2096*/
2097float64 float64_sub( float64 a, float64 b )
2098{
2099 flag aSign, bSign;
2100
2101 aSign = extractFloat64Sign( a );
2102 bSign = extractFloat64Sign( b );
2103 if ( aSign == bSign ) {
2104 return subFloat64Sigs( a, b, aSign );
2105 }
2106 else {
2107 return addFloat64Sigs( a, b, aSign );
2108 }
2109
2110}
2111
2112/*
2113-------------------------------------------------------------------------------
2114Returns the result of multiplying the double-precision floating-point values
2115`a' and `b'. The operation is performed according to the IEC/IEEE Standard
2116for Binary Floating-point Arithmetic.
2117-------------------------------------------------------------------------------
2118*/
2119float64 float64_mul( float64 a, float64 b )
2120{
2121 flag aSign, bSign, zSign;
2122 int16 aExp, bExp, zExp;
2123 bits64 aSig, bSig, zSig0, zSig1;
2124
2125 aSig = extractFloat64Frac( a );
2126 aExp = extractFloat64Exp( a );
2127 aSign = extractFloat64Sign( a );
2128 bSig = extractFloat64Frac( b );
2129 bExp = extractFloat64Exp( b );
2130 bSign = extractFloat64Sign( b );
2131 zSign = aSign ^ bSign;
2132 if ( aExp == 0x7FF ) {
2133 if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
2134 return propagateFloat64NaN( a, b );
2135 }
2136 if ( ( bExp | bSig ) == 0 ) {
2137 float_raise( float_flag_invalid );
2138 return float64_default_nan;
2139 }
2140 return packFloat64( zSign, 0x7FF, 0 );
2141 }
2142 if ( bExp == 0x7FF ) {
2143 if ( bSig ) return propagateFloat64NaN( a, b );
2144 if ( ( aExp | aSig ) == 0 ) {
2145 float_raise( float_flag_invalid );
2146 return float64_default_nan;
2147 }
2148 return packFloat64( zSign, 0x7FF, 0 );
2149 }
2150 if ( aExp == 0 ) {
2151 if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
2152 normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2153 }
2154 if ( bExp == 0 ) {
2155 if ( bSig == 0 ) return packFloat64( zSign, 0, 0 );
2156 normalizeFloat64Subnormal( bSig, &bExp, &bSig );
2157 }
2158 zExp = aExp + bExp - 0x3FF;
2159 aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
2160 bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
2161 mul64To128( aSig, bSig, &zSig0, &zSig1 );
2162 zSig0 |= ( zSig1 != 0 );
2163 if ( 0 <= (sbits64) ( zSig0<<1 ) ) {
2164 zSig0 <<= 1;
2165 --zExp;
2166 }
2167 return roundAndPackFloat64( zSign, zExp, zSig0 );
2168
2169}
2170
2171/*
2172-------------------------------------------------------------------------------
2173Returns the result of dividing the double-precision floating-point value `a'
2174by the corresponding value `b'. The operation is performed according to
2175the IEC/IEEE Standard for Binary Floating-point Arithmetic.
2176-------------------------------------------------------------------------------
2177*/
2178float64 float64_div( float64 a, float64 b )
2179{
2180 flag aSign, bSign, zSign;
2181 int16 aExp, bExp, zExp;
2182 bits64 aSig, bSig, zSig;
2183 bits64 rem0, rem1;
2184 bits64 term0, term1;
2185
2186 aSig = extractFloat64Frac( a );
2187 aExp = extractFloat64Exp( a );
2188 aSign = extractFloat64Sign( a );
2189 bSig = extractFloat64Frac( b );
2190 bExp = extractFloat64Exp( b );
2191 bSign = extractFloat64Sign( b );
2192 zSign = aSign ^ bSign;
2193 if ( aExp == 0x7FF ) {
2194 if ( aSig ) return propagateFloat64NaN( a, b );
2195 if ( bExp == 0x7FF ) {
2196 if ( bSig ) return propagateFloat64NaN( a, b );
2197 float_raise( float_flag_invalid );
2198 return float64_default_nan;
2199 }
2200 return packFloat64( zSign, 0x7FF, 0 );
2201 }
2202 if ( bExp == 0x7FF ) {
2203 if ( bSig ) return propagateFloat64NaN( a, b );
2204 return packFloat64( zSign, 0, 0 );
2205 }
2206 if ( bExp == 0 ) {
2207 if ( bSig == 0 ) {
2208 if ( ( aExp | aSig ) == 0 ) {
2209 float_raise( float_flag_invalid );
2210 return float64_default_nan;
2211 }
2212 float_raise( float_flag_divbyzero );
2213 return packFloat64( zSign, 0x7FF, 0 );
2214 }
2215 normalizeFloat64Subnormal( bSig, &bExp, &bSig );
2216 }
2217 if ( aExp == 0 ) {
2218 if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
2219 normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2220 }
2221 zExp = aExp - bExp + 0x3FD;
2222 aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
2223 bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
2224 if ( bSig <= ( aSig + aSig ) ) {
2225 aSig >>= 1;
2226 ++zExp;
2227 }
2228 zSig = estimateDiv128To64( aSig, 0, bSig );
2229 if ( ( zSig & 0x1FF ) <= 2 ) {
2230 mul64To128( bSig, zSig, &term0, &term1 );
2231 sub128( aSig, 0, term0, term1, &rem0, &rem1 );
2232 while ( (sbits64) rem0 < 0 ) {
2233 --zSig;
2234 add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
2235 }
2236 zSig |= ( rem1 != 0 );
2237 }
2238 return roundAndPackFloat64( zSign, zExp, zSig );
2239
2240}
2241
2242/*
2243-------------------------------------------------------------------------------
2244Returns the remainder of the double-precision floating-point value `a'
2245with respect to the corresponding value `b'. The operation is performed
2246according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
2247-------------------------------------------------------------------------------
2248*/
2249float64 float64_rem( float64 a, float64 b )
2250{
2251 flag aSign, bSign, zSign;
2252 int16 aExp, bExp, expDiff;
2253 bits64 aSig, bSig;
2254 bits64 q, alternateASig;
2255 sbits64 sigMean;
2256
2257 aSig = extractFloat64Frac( a );
2258 aExp = extractFloat64Exp( a );
2259 aSign = extractFloat64Sign( a );
2260 bSig = extractFloat64Frac( b );
2261 bExp = extractFloat64Exp( b );
2262 bSign = extractFloat64Sign( b );
2263 if ( aExp == 0x7FF ) {
2264 if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
2265 return propagateFloat64NaN( a, b );
2266 }
2267 float_raise( float_flag_invalid );
2268 return float64_default_nan;
2269 }
2270 if ( bExp == 0x7FF ) {
2271 if ( bSig ) return propagateFloat64NaN( a, b );
2272 return a;
2273 }
2274 if ( bExp == 0 ) {
2275 if ( bSig == 0 ) {
2276 float_raise( float_flag_invalid );
2277 return float64_default_nan;
2278 }
2279 normalizeFloat64Subnormal( bSig, &bExp, &bSig );
2280 }
2281 if ( aExp == 0 ) {
2282 if ( aSig == 0 ) return a;
2283 normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2284 }
2285 expDiff = aExp - bExp;
2286 aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11;
2287 bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
2288 if ( expDiff < 0 ) {
2289 if ( expDiff < -1 ) return a;
2290 aSig >>= 1;
2291 }
2292 q = ( bSig <= aSig );
2293 if ( q ) aSig -= bSig;
2294 expDiff -= 64;
2295 while ( 0 < expDiff ) {
2296 q = estimateDiv128To64( aSig, 0, bSig );
2297 q = ( 2 < q ) ? q - 2 : 0;
2298 aSig = - ( ( bSig>>2 ) * q );
2299 expDiff -= 62;
2300 }
2301 expDiff += 64;
2302 if ( 0 < expDiff ) {
2303 q = estimateDiv128To64( aSig, 0, bSig );
2304 q = ( 2 < q ) ? q - 2 : 0;
2305 q >>= 64 - expDiff;
2306 bSig >>= 2;
2307 aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
2308 }
2309 else {
2310 aSig >>= 2;
2311 bSig >>= 2;
2312 }
2313 do {
2314 alternateASig = aSig;
2315 ++q;
2316 aSig -= bSig;
2317 } while ( 0 <= (sbits64) aSig );
2318 sigMean = aSig + alternateASig;
2319 if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
2320 aSig = alternateASig;
2321 }
2322 zSign = ( (sbits64) aSig < 0 );
2323 if ( zSign ) aSig = - aSig;
2324 return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig );
2325
2326}
2327
2328/*
2329-------------------------------------------------------------------------------
2330Returns the square root of the double-precision floating-point value `a'.
2331The operation is performed according to the IEC/IEEE Standard for Binary
2332Floating-point Arithmetic.
2333-------------------------------------------------------------------------------
2334*/
2335float64 float64_sqrt( float64 a )
2336{
2337 flag aSign;
2338 int16 aExp, zExp;
2339 bits64 aSig, zSig;
2340 bits64 rem0, rem1, term0, term1; //, shiftedRem;
2341 //float64 z;
2342
2343 aSig = extractFloat64Frac( a );
2344 aExp = extractFloat64Exp( a );
2345 aSign = extractFloat64Sign( a );
2346 if ( aExp == 0x7FF ) {
2347 if ( aSig ) return propagateFloat64NaN( a, a );
2348 if ( ! aSign ) return a;
2349 float_raise( float_flag_invalid );
2350 return float64_default_nan;
2351 }
2352 if ( aSign ) {
2353 if ( ( aExp | aSig ) == 0 ) return a;
2354 float_raise( float_flag_invalid );
2355 return float64_default_nan;
2356 }
2357 if ( aExp == 0 ) {
2358 if ( aSig == 0 ) return 0;
2359 normalizeFloat64Subnormal( aSig, &aExp, &aSig );
2360 }
2361 zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE;
2362 aSig |= LIT64( 0x0010000000000000 );
2363 zSig = estimateSqrt32( aExp, aSig>>21 );
2364 zSig <<= 31;
2365 aSig <<= 9 - ( aExp & 1 );
2366 zSig = estimateDiv128To64( aSig, 0, zSig ) + zSig + 2;
2367 if ( ( zSig & 0x3FF ) <= 5 ) {
2368 if ( zSig < 2 ) {
2369 zSig = LIT64( 0xFFFFFFFFFFFFFFFF );
2370 }
2371 else {
2372 aSig <<= 2;
2373 mul64To128( zSig, zSig, &term0, &term1 );
2374 sub128( aSig, 0, term0, term1, &rem0, &rem1 );
2375 while ( (sbits64) rem0 < 0 ) {
2376 --zSig;
2377 shortShift128Left( 0, zSig, 1, &term0, &term1 );
2378 term1 |= 1;
2379 add128( rem0, rem1, term0, term1, &rem0, &rem1 );
2380 }
2381 zSig |= ( ( rem0 | rem1 ) != 0 );
2382 }
2383 }
2384 shift64RightJamming( zSig, 1, &zSig );
2385 return roundAndPackFloat64( 0, zExp, zSig );
2386
2387}
2388
2389/*
2390-------------------------------------------------------------------------------
2391Returns 1 if the double-precision floating-point value `a' is equal to the
2392corresponding value `b', and 0 otherwise. The comparison is performed
2393according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
2394-------------------------------------------------------------------------------
2395*/
2396flag float64_eq( float64 a, float64 b )
2397{
2398
2399 if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
2400 || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
2401 ) {
2402 if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
2403 float_raise( float_flag_invalid );
2404 }
2405 return 0;
2406 }
2407 return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
2408
2409}
2410
2411/*
2412-------------------------------------------------------------------------------
2413Returns 1 if the double-precision floating-point value `a' is less than or
2414equal to the corresponding value `b', and 0 otherwise. The comparison is
2415performed according to the IEC/IEEE Standard for Binary Floating-point
2416Arithmetic.
2417-------------------------------------------------------------------------------
2418*/
2419flag float64_le( float64 a, float64 b )
2420{
2421 flag aSign, bSign;
2422
2423 if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
2424 || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
2425 ) {
2426 float_raise( float_flag_invalid );
2427 return 0;
2428 }
2429 aSign = extractFloat64Sign( a );
2430 bSign = extractFloat64Sign( b );
2431 if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
2432 return ( a == b ) || ( aSign ^ ( a < b ) );
2433
2434}
2435
2436/*
2437-------------------------------------------------------------------------------
2438Returns 1 if the double-precision floating-point value `a' is less than
2439the corresponding value `b', and 0 otherwise. The comparison is performed
2440according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
2441-------------------------------------------------------------------------------
2442*/
2443flag float64_lt( float64 a, float64 b )
2444{
2445 flag aSign, bSign;
2446
2447 if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
2448 || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
2449 ) {
2450 float_raise( float_flag_invalid );
2451 return 0;
2452 }
2453 aSign = extractFloat64Sign( a );
2454 bSign = extractFloat64Sign( b );
2455 if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
2456 return ( a != b ) && ( aSign ^ ( a < b ) );
2457
2458}
2459
2460/*
2461-------------------------------------------------------------------------------
2462Returns 1 if the double-precision floating-point value `a' is equal to the
2463corresponding value `b', and 0 otherwise. The invalid exception is raised
2464if either operand is a NaN. Otherwise, the comparison is performed
2465according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
2466-------------------------------------------------------------------------------
2467*/
2468flag float64_eq_signaling( float64 a, float64 b )
2469{
2470
2471 if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
2472 || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
2473 ) {
2474 float_raise( float_flag_invalid );
2475 return 0;
2476 }
2477 return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
2478
2479}
2480
2481/*
2482-------------------------------------------------------------------------------
2483Returns 1 if the double-precision floating-point value `a' is less than or
2484equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
2485cause an exception. Otherwise, the comparison is performed according to the
2486IEC/IEEE Standard for Binary Floating-point Arithmetic.
2487-------------------------------------------------------------------------------
2488*/
2489flag float64_le_quiet( float64 a, float64 b )
2490{
2491 flag aSign, bSign;
2492 //int16 aExp, bExp;
2493
2494 if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
2495 || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
2496 ) {
2497 if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
2498 float_raise( float_flag_invalid );
2499 }
2500 return 0;
2501 }
2502 aSign = extractFloat64Sign( a );
2503 bSign = extractFloat64Sign( b );
2504 if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
2505 return ( a == b ) || ( aSign ^ ( a < b ) );
2506
2507}
2508
2509/*
2510-------------------------------------------------------------------------------
2511Returns 1 if the double-precision floating-point value `a' is less than
2512the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
2513exception. Otherwise, the comparison is performed according to the IEC/IEEE
2514Standard for Binary Floating-point Arithmetic.
2515-------------------------------------------------------------------------------
2516*/
2517flag float64_lt_quiet( float64 a, float64 b )
2518{
2519 flag aSign, bSign;
2520
2521 if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
2522 || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
2523 ) {
2524 if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
2525 float_raise( float_flag_invalid );
2526 }
2527 return 0;
2528 }
2529 aSign = extractFloat64Sign( a );
2530 bSign = extractFloat64Sign( b );
2531 if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
2532 return ( a != b ) && ( aSign ^ ( a < b ) );
2533
2534}
2535
2536#ifdef FLOATX80
2537
2538/*
2539-------------------------------------------------------------------------------
2540Returns the result of converting the extended double-precision floating-
2541point value `a' to the 32-bit two's complement integer format. The
2542conversion is performed according to the IEC/IEEE Standard for Binary
2543Floating-point Arithmetic---which means in particular that the conversion
2544is rounded according to the current rounding mode. If `a' is a NaN, the
2545largest positive integer is returned. Otherwise, if the conversion
2546overflows, the largest integer with the same sign as `a' is returned.
2547-------------------------------------------------------------------------------
2548*/
2549int32 floatx80_to_int32( floatx80 a )
2550{
2551 flag aSign;
2552 int32 aExp, shiftCount;
2553 bits64 aSig;
2554
2555 aSig = extractFloatx80Frac( a );
2556 aExp = extractFloatx80Exp( a );
2557 aSign = extractFloatx80Sign( a );
2558 if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
2559 shiftCount = 0x4037 - aExp;
2560 if ( shiftCount <= 0 ) shiftCount = 1;
2561 shift64RightJamming( aSig, shiftCount, &aSig );
2562 return roundAndPackInt32( aSign, aSig );
2563
2564}
2565
2566/*
2567-------------------------------------------------------------------------------
2568Returns the result of converting the extended double-precision floating-
2569point value `a' to the 32-bit two's complement integer format. The
2570conversion is performed according to the IEC/IEEE Standard for Binary
2571Floating-point Arithmetic, except that the conversion is always rounded
2572toward zero. If `a' is a NaN, the largest positive integer is returned.
2573Otherwise, if the conversion overflows, the largest integer with the same
2574sign as `a' is returned.
2575-------------------------------------------------------------------------------
2576*/
2577int32 floatx80_to_int32_round_to_zero( floatx80 a )
2578{
2579 flag aSign;
2580 int32 aExp, shiftCount;
2581 bits64 aSig, savedASig;
2582 int32 z;
2583
2584 aSig = extractFloatx80Frac( a );
2585 aExp = extractFloatx80Exp( a );
2586 aSign = extractFloatx80Sign( a );
2587 shiftCount = 0x403E - aExp;
2588 if ( shiftCount < 32 ) {
2589 if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
2590 goto invalid;
2591 }
2592 else if ( 63 < shiftCount ) {
2593 if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
2594 return 0;
2595 }
2596 savedASig = aSig;
2597 aSig >>= shiftCount;
2598 z = aSig;
2599 if ( aSign ) z = - z;
2600 if ( ( z < 0 ) ^ aSign ) {
2601 invalid:
2602 float_exception_flags |= float_flag_invalid;
2603 return aSign ? 0x80000000 : 0x7FFFFFFF;
2604 }
2605 if ( ( aSig<<shiftCount ) != savedASig ) {
2606 float_exception_flags |= float_flag_inexact;
2607 }
2608 return z;
2609
2610}
2611
2612/*
2613-------------------------------------------------------------------------------
2614Returns the result of converting the extended double-precision floating-
2615point value `a' to the single-precision floating-point format. The
2616conversion is performed according to the IEC/IEEE Standard for Binary
2617Floating-point Arithmetic.
2618-------------------------------------------------------------------------------
2619*/
2620float32 floatx80_to_float32( floatx80 a )
2621{
2622 flag aSign;
2623 int32 aExp;
2624 bits64 aSig;
2625
2626 aSig = extractFloatx80Frac( a );
2627 aExp = extractFloatx80Exp( a );
2628 aSign = extractFloatx80Sign( a );
2629 if ( aExp == 0x7FFF ) {
2630 if ( (bits64) ( aSig<<1 ) ) {
2631 return commonNaNToFloat32( floatx80ToCommonNaN( a ) );
2632 }
2633 return packFloat32( aSign, 0xFF, 0 );
2634 }
2635 shift64RightJamming( aSig, 33, &aSig );
2636 if ( aExp || aSig ) aExp -= 0x3F81;
2637 return roundAndPackFloat32( aSign, aExp, aSig );
2638
2639}
2640
2641/*
2642-------------------------------------------------------------------------------
2643Returns the result of converting the extended double-precision floating-
2644point value `a' to the double-precision floating-point format. The
2645conversion is performed according to the IEC/IEEE Standard for Binary
2646Floating-point Arithmetic.
2647-------------------------------------------------------------------------------
2648*/
2649float64 floatx80_to_float64( floatx80 a )
2650{
2651 flag aSign;
2652 int32 aExp;
2653 bits64 aSig, zSig;
2654
2655 aSig = extractFloatx80Frac( a );
2656 aExp = extractFloatx80Exp( a );
2657 aSign = extractFloatx80Sign( a );
2658 if ( aExp == 0x7FFF ) {
2659 if ( (bits64) ( aSig<<1 ) ) {
2660 return commonNaNToFloat64( floatx80ToCommonNaN( a ) );
2661 }
2662 return packFloat64( aSign, 0x7FF, 0 );
2663 }
2664 shift64RightJamming( aSig, 1, &zSig );
2665 if ( aExp || aSig ) aExp -= 0x3C01;
2666 return roundAndPackFloat64( aSign, aExp, zSig );
2667
2668}
2669
2670/*
2671-------------------------------------------------------------------------------
2672Rounds the extended double-precision floating-point value `a' to an integer,
2673and returns the result as an extended quadruple-precision floating-point
2674value. The operation is performed according to the IEC/IEEE Standard for
2675Binary Floating-point Arithmetic.
2676-------------------------------------------------------------------------------
2677*/
2678floatx80 floatx80_round_to_int( floatx80 a )
2679{
2680 flag aSign;
2681 int32 aExp;
2682 bits64 lastBitMask, roundBitsMask;
2683 int8 roundingMode;
2684 floatx80 z;
2685
2686 aExp = extractFloatx80Exp( a );
2687 if ( 0x403E <= aExp ) {
2688 if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) {
2689 return propagateFloatx80NaN( a, a );
2690 }
2691 return a;
2692 }
2693 if ( aExp <= 0x3FFE ) {
2694 if ( ( aExp == 0 )
2695 && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
2696 return a;
2697 }
2698 float_exception_flags |= float_flag_inexact;
2699 aSign = extractFloatx80Sign( a );
2700 switch ( float_rounding_mode ) {
2701 case float_round_nearest_even:
2702 if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 )
2703 ) {
2704 return
2705 packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
2706 }
2707 break;
2708 case float_round_down:
2709 return
2710 aSign ?
2711 packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) )
2712 : packFloatx80( 0, 0, 0 );
2713 case float_round_up:
2714 return
2715 aSign ? packFloatx80( 1, 0, 0 )
2716 : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) );
2717 }
2718 return packFloatx80( aSign, 0, 0 );
2719 }
2720 lastBitMask = 1;
2721 lastBitMask <<= 0x403E - aExp;
2722 roundBitsMask = lastBitMask - 1;
2723 z = a;
2724 roundingMode = float_rounding_mode;
2725 if ( roundingMode == float_round_nearest_even ) {
2726 z.low += lastBitMask>>1;
2727 if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
2728 }
2729 else if ( roundingMode != float_round_to_zero ) {
2730 if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) {
2731 z.low += roundBitsMask;
2732 }
2733 }
2734 z.low &= ~ roundBitsMask;
2735 if ( z.low == 0 ) {
2736 ++z.high;
2737 z.low = LIT64( 0x8000000000000000 );
2738 }
2739 if ( z.low != a.low ) float_exception_flags |= float_flag_inexact;
2740 return z;
2741
2742}
2743
2744/*
2745-------------------------------------------------------------------------------
2746Returns the result of adding the absolute values of the extended double-
2747precision floating-point values `a' and `b'. If `zSign' is true, the sum is
2748negated before being returned. `zSign' is ignored if the result is a NaN.
2749The addition is performed according to the IEC/IEEE Standard for Binary
2750Floating-point Arithmetic.
2751-------------------------------------------------------------------------------
2752*/
2753static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
2754{
2755 int32 aExp, bExp, zExp;
2756 bits64 aSig, bSig, zSig0, zSig1;
2757 int32 expDiff;
2758
2759 aSig = extractFloatx80Frac( a );
2760 aExp = extractFloatx80Exp( a );
2761 bSig = extractFloatx80Frac( b );
2762 bExp = extractFloatx80Exp( b );
2763 expDiff = aExp - bExp;
2764 if ( 0 < expDiff ) {
2765 if ( aExp == 0x7FFF ) {
2766 if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
2767 return a;
2768 }
2769 if ( bExp == 0 ) --expDiff;
2770 shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
2771 zExp = aExp;
2772 }
2773 else if ( expDiff < 0 ) {
2774 if ( bExp == 0x7FFF ) {
2775 if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
2776 return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
2777 }
2778 if ( aExp == 0 ) ++expDiff;
2779 shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
2780 zExp = bExp;
2781 }
2782 else {
2783 if ( aExp == 0x7FFF ) {
2784 if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
2785 return propagateFloatx80NaN( a, b );
2786 }
2787 return a;
2788 }
2789 zSig1 = 0;
2790 zSig0 = aSig + bSig;
2791 if ( aExp == 0 ) {
2792 normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 );
2793 goto roundAndPack;
2794 }
2795 zExp = aExp;
2796 goto shiftRight1;
2797 }
2798
2799 zSig0 = aSig + bSig;
2800
2801 if ( (sbits64) zSig0 < 0 ) goto roundAndPack;
2802 shiftRight1:
2803 shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 );
2804 zSig0 |= LIT64( 0x8000000000000000 );
2805 ++zExp;
2806 roundAndPack:
2807 return
2808 roundAndPackFloatx80(
2809 floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
2810
2811}
2812
2813/*
2814-------------------------------------------------------------------------------
2815Returns the result of subtracting the absolute values of the extended
2816double-precision floating-point values `a' and `b'. If `zSign' is true,
2817the difference is negated before being returned. `zSign' is ignored if the
2818result is a NaN. The subtraction is performed according to the IEC/IEEE
2819Standard for Binary Floating-point Arithmetic.
2820-------------------------------------------------------------------------------
2821*/
2822static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
2823{
2824 int32 aExp, bExp, zExp;
2825 bits64 aSig, bSig, zSig0, zSig1;
2826 int32 expDiff;
2827 floatx80 z;
2828
2829 aSig = extractFloatx80Frac( a );
2830 aExp = extractFloatx80Exp( a );
2831 bSig = extractFloatx80Frac( b );
2832 bExp = extractFloatx80Exp( b );
2833 expDiff = aExp - bExp;
2834 if ( 0 < expDiff ) goto aExpBigger;
2835 if ( expDiff < 0 ) goto bExpBigger;
2836 if ( aExp == 0x7FFF ) {
2837 if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
2838 return propagateFloatx80NaN( a, b );
2839 }
2840 float_raise( float_flag_invalid );
2841 z.low = floatx80_default_nan_low;
2842 z.high = floatx80_default_nan_high;
2843 return z;
2844 }
2845 if ( aExp == 0 ) {
2846 aExp = 1;
2847 bExp = 1;
2848 }
2849 zSig1 = 0;
2850 if ( bSig < aSig ) goto aBigger;
2851 if ( aSig < bSig ) goto bBigger;
2852 return packFloatx80( float_rounding_mode == float_round_down, 0, 0 );
2853 bExpBigger:
2854 if ( bExp == 0x7FFF ) {
2855 if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
2856 return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) );
2857 }
2858 if ( aExp == 0 ) ++expDiff;
2859 shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
2860 bBigger:
2861 sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 );
2862 zExp = bExp;
2863 zSign ^= 1;
2864 goto normalizeRoundAndPack;
2865 aExpBigger:
2866 if ( aExp == 0x7FFF ) {
2867 if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
2868 return a;
2869 }
2870 if ( bExp == 0 ) --expDiff;
2871 shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
2872 aBigger:
2873 sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 );
2874 zExp = aExp;
2875 normalizeRoundAndPack:
2876 return
2877 normalizeRoundAndPackFloatx80(
2878 floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
2879
2880}
2881
2882/*
2883-------------------------------------------------------------------------------
2884Returns the result of adding the extended double-precision floating-point
2885values `a' and `b'. The operation is performed according to the IEC/IEEE
2886Standard for Binary Floating-point Arithmetic.
2887-------------------------------------------------------------------------------
2888*/
2889floatx80 floatx80_add( floatx80 a, floatx80 b )
2890{
2891 flag aSign, bSign;
2892
2893 aSign = extractFloatx80Sign( a );
2894 bSign = extractFloatx80Sign( b );
2895 if ( aSign == bSign ) {
2896 return addFloatx80Sigs( a, b, aSign );
2897 }
2898 else {
2899 return subFloatx80Sigs( a, b, aSign );
2900 }
2901
2902}
2903
2904/*
2905-------------------------------------------------------------------------------
2906Returns the result of subtracting the extended double-precision floating-
2907point values `a' and `b'. The operation is performed according to the
2908IEC/IEEE Standard for Binary Floating-point Arithmetic.
2909-------------------------------------------------------------------------------
2910*/
2911floatx80 floatx80_sub( floatx80 a, floatx80 b )
2912{
2913 flag aSign, bSign;
2914
2915 aSign = extractFloatx80Sign( a );
2916 bSign = extractFloatx80Sign( b );
2917 if ( aSign == bSign ) {
2918 return subFloatx80Sigs( a, b, aSign );
2919 }
2920 else {
2921 return addFloatx80Sigs( a, b, aSign );
2922 }
2923
2924}
2925
2926/*
2927-------------------------------------------------------------------------------
2928Returns the result of multiplying the extended double-precision floating-
2929point values `a' and `b'. The operation is performed according to the
2930IEC/IEEE Standard for Binary Floating-point Arithmetic.
2931-------------------------------------------------------------------------------
2932*/
2933floatx80 floatx80_mul( floatx80 a, floatx80 b )
2934{
2935 flag aSign, bSign, zSign;
2936 int32 aExp, bExp, zExp;
2937 bits64 aSig, bSig, zSig0, zSig1;
2938 floatx80 z;
2939
2940 aSig = extractFloatx80Frac( a );
2941 aExp = extractFloatx80Exp( a );
2942 aSign = extractFloatx80Sign( a );
2943 bSig = extractFloatx80Frac( b );
2944 bExp = extractFloatx80Exp( b );
2945 bSign = extractFloatx80Sign( b );
2946 zSign = aSign ^ bSign;
2947 if ( aExp == 0x7FFF ) {
2948 if ( (bits64) ( aSig<<1 )
2949 || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
2950 return propagateFloatx80NaN( a, b );
2951 }
2952 if ( ( bExp | bSig ) == 0 ) goto invalid;
2953 return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
2954 }
2955 if ( bExp == 0x7FFF ) {
2956 if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
2957 if ( ( aExp | aSig ) == 0 ) {
2958 invalid:
2959 float_raise( float_flag_invalid );
2960 z.low = floatx80_default_nan_low;
2961 z.high = floatx80_default_nan_high;
2962 return z;
2963 }
2964 return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
2965 }
2966 if ( aExp == 0 ) {
2967 if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
2968 normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
2969 }
2970 if ( bExp == 0 ) {
2971 if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 );
2972 normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
2973 }
2974 zExp = aExp + bExp - 0x3FFE;
2975 mul64To128( aSig, bSig, &zSig0, &zSig1 );
2976 if ( 0 < (sbits64) zSig0 ) {
2977 shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
2978 --zExp;
2979 }
2980 return
2981 roundAndPackFloatx80(
2982 floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
2983
2984}
2985
2986/*
2987-------------------------------------------------------------------------------
2988Returns the result of dividing the extended double-precision floating-point
2989value `a' by the corresponding value `b'. The operation is performed
2990according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
2991-------------------------------------------------------------------------------
2992*/
2993floatx80 floatx80_div( floatx80 a, floatx80 b )
2994{
2995 flag aSign, bSign, zSign;
2996 int32 aExp, bExp, zExp;
2997 bits64 aSig, bSig, zSig0, zSig1;
2998 bits64 rem0, rem1, rem2, term0, term1, term2;
2999 floatx80 z;
3000
3001 aSig = extractFloatx80Frac( a );
3002 aExp = extractFloatx80Exp( a );
3003 aSign = extractFloatx80Sign( a );
3004 bSig = extractFloatx80Frac( b );
3005 bExp = extractFloatx80Exp( b );
3006 bSign = extractFloatx80Sign( b );
3007 zSign = aSign ^ bSign;
3008 if ( aExp == 0x7FFF ) {
3009 if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
3010 if ( bExp == 0x7FFF ) {
3011 if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
3012 goto invalid;
3013 }
3014 return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
3015 }
3016 if ( bExp == 0x7FFF ) {
3017 if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
3018 return packFloatx80( zSign, 0, 0 );
3019 }
3020 if ( bExp == 0 ) {
3021 if ( bSig == 0 ) {
3022 if ( ( aExp | aSig ) == 0 ) {
3023 invalid:
3024 float_raise( float_flag_invalid );
3025 z.low = floatx80_default_nan_low;
3026 z.high = floatx80_default_nan_high;
3027 return z;
3028 }
3029 float_raise( float_flag_divbyzero );
3030 return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
3031 }
3032 normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
3033 }
3034 if ( aExp == 0 ) {
3035 if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
3036 normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
3037 }
3038 zExp = aExp - bExp + 0x3FFE;
3039 rem1 = 0;
3040 if ( bSig <= aSig ) {
3041 shift128Right( aSig, 0, 1, &aSig, &rem1 );
3042 ++zExp;
3043 }
3044 zSig0 = estimateDiv128To64( aSig, rem1, bSig );
3045 mul64To128( bSig, zSig0, &term0, &term1 );
3046 sub128( aSig, rem1, term0, term1, &rem0, &rem1 );
3047 while ( (sbits64) rem0 < 0 ) {
3048 --zSig0;
3049 add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
3050 }
3051 zSig1 = estimateDiv128To64( rem1, 0, bSig );
3052 if ( (bits64) ( zSig1<<1 ) <= 8 ) {
3053 mul64To128( bSig, zSig1, &term1, &term2 );
3054 sub128( rem1, 0, term1, term2, &rem1, &rem2 );
3055 while ( (sbits64) rem1 < 0 ) {
3056 --zSig1;
3057 add128( rem1, rem2, 0, bSig, &rem1, &rem2 );
3058 }
3059 zSig1 |= ( ( rem1 | rem2 ) != 0 );
3060 }
3061 return
3062 roundAndPackFloatx80(
3063 floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
3064
3065}
3066
3067/*
3068-------------------------------------------------------------------------------
3069Returns the remainder of the extended double-precision floating-point value
3070`a' with respect to the corresponding value `b'. The operation is performed
3071according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
3072-------------------------------------------------------------------------------
3073*/
3074floatx80 floatx80_rem( floatx80 a, floatx80 b )
3075{
3076 flag aSign, bSign, zSign;
3077 int32 aExp, bExp, expDiff;
3078 bits64 aSig0, aSig1, bSig;
3079 bits64 q, term0, term1, alternateASig0, alternateASig1;
3080 floatx80 z;
3081
3082 aSig0 = extractFloatx80Frac( a );
3083 aExp = extractFloatx80Exp( a );
3084 aSign = extractFloatx80Sign( a );
3085 bSig = extractFloatx80Frac( b );
3086 bExp = extractFloatx80Exp( b );
3087 bSign = extractFloatx80Sign( b );
3088 if ( aExp == 0x7FFF ) {
3089 if ( (bits64) ( aSig0<<1 )
3090 || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
3091 return propagateFloatx80NaN( a, b );
3092 }
3093 goto invalid;
3094 }
3095 if ( bExp == 0x7FFF ) {
3096 if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
3097 return a;
3098 }
3099 if ( bExp == 0 ) {
3100 if ( bSig == 0 ) {
3101 invalid:
3102 float_raise( float_flag_invalid );
3103 z.low = floatx80_default_nan_low;
3104 z.high = floatx80_default_nan_high;
3105 return z;
3106 }
3107 normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
3108 }
3109 if ( aExp == 0 ) {
3110 if ( (bits64) ( aSig0<<1 ) == 0 ) return a;
3111 normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
3112 }
3113 bSig |= LIT64( 0x8000000000000000 );
3114 zSign = aSign;
3115 expDiff = aExp - bExp;
3116 aSig1 = 0;
3117 if ( expDiff < 0 ) {
3118 if ( expDiff < -1 ) return a;
3119 shift128Right( aSig0, 0, 1, &aSig0, &aSig1 );
3120 expDiff = 0;
3121 }
3122 q = ( bSig <= aSig0 );
3123 if ( q ) aSig0 -= bSig;
3124 expDiff -= 64;
3125 while ( 0 < expDiff ) {
3126 q = estimateDiv128To64( aSig0, aSig1, bSig );
3127 q = ( 2 < q ) ? q - 2 : 0;
3128 mul64To128( bSig, q, &term0, &term1 );
3129 sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
3130 shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 );
3131 expDiff -= 62;
3132 }
3133 expDiff += 64;
3134 if ( 0 < expDiff ) {
3135 q = estimateDiv128To64( aSig0, aSig1, bSig );
3136 q = ( 2 < q ) ? q - 2 : 0;
3137 q >>= 64 - expDiff;
3138 mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 );
3139 sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
3140 shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 );
3141 while ( le128( term0, term1, aSig0, aSig1 ) ) {
3142 ++q;
3143 sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
3144 }
3145 }
3146 else {
3147 term1 = 0;
3148 term0 = bSig;
3149 }
3150 sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 );
3151 if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 )
3152 || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 )
3153 && ( q & 1 ) )
3154 ) {
3155 aSig0 = alternateASig0;
3156 aSig1 = alternateASig1;
3157 zSign = ! zSign;
3158 }
3159 return
3160 normalizeRoundAndPackFloatx80(
3161 80, zSign, bExp + expDiff, aSig0, aSig1 );
3162
3163}
3164
3165/*
3166-------------------------------------------------------------------------------
3167Returns the square root of the extended double-precision floating-point
3168value `a'. The operation is performed according to the IEC/IEEE Standard
3169for Binary Floating-point Arithmetic.
3170-------------------------------------------------------------------------------
3171*/
3172floatx80 floatx80_sqrt( floatx80 a )
3173{
3174 flag aSign;
3175 int32 aExp, zExp;
3176 bits64 aSig0, aSig1, zSig0, zSig1;
3177 bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
3178 bits64 shiftedRem0, shiftedRem1;
3179 floatx80 z;
3180
3181 aSig0 = extractFloatx80Frac( a );
3182 aExp = extractFloatx80Exp( a );
3183 aSign = extractFloatx80Sign( a );
3184 if ( aExp == 0x7FFF ) {
3185 if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a );
3186 if ( ! aSign ) return a;
3187 goto invalid;
3188 }
3189 if ( aSign ) {
3190 if ( ( aExp | aSig0 ) == 0 ) return a;
3191 invalid:
3192 float_raise( float_flag_invalid );
3193 z.low = floatx80_default_nan_low;
3194 z.high = floatx80_default_nan_high;
3195 return z;
3196 }
3197 if ( aExp == 0 ) {
3198 if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 );
3199 normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
3200 }
3201 zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF;
3202 zSig0 = estimateSqrt32( aExp, aSig0>>32 );
3203 zSig0 <<= 31;
3204 aSig1 = 0;
3205 shift128Right( aSig0, 0, ( aExp & 1 ) + 2, &aSig0, &aSig1 );
3206 zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0 ) + zSig0 + 4;
3207 if ( 0 <= (sbits64) zSig0 ) zSig0 = LIT64( 0xFFFFFFFFFFFFFFFF );
3208 shortShift128Left( aSig0, aSig1, 2, &aSig0, &aSig1 );
3209 mul64To128( zSig0, zSig0, &term0, &term1 );
3210 sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
3211 while ( (sbits64) rem0 < 0 ) {
3212 --zSig0;
3213 shortShift128Left( 0, zSig0, 1, &term0, &term1 );
3214 term1 |= 1;
3215 add128( rem0, rem1, term0, term1, &rem0, &rem1 );
3216 }
3217 shortShift128Left( rem0, rem1, 63, &shiftedRem0, &shiftedRem1 );
3218 zSig1 = estimateDiv128To64( shiftedRem0, shiftedRem1, zSig0 );
3219 if ( (bits64) ( zSig1<<1 ) <= 10 ) {
3220 if ( zSig1 == 0 ) zSig1 = 1;
3221 mul64To128( zSig0, zSig1, &term1, &term2 );
3222 shortShift128Left( term1, term2, 1, &term1, &term2 );
3223 sub128( rem1, 0, term1, term2, &rem1, &rem2 );
3224 mul64To128( zSig1, zSig1, &term2, &term3 );
3225 sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
3226 while ( (sbits64) rem1 < 0 ) {
3227 --zSig1;
3228 shortShift192Left( 0, zSig0, zSig1, 1, &term1, &term2, &term3 );
3229 term3 |= 1;
3230 add192(
3231 rem1, rem2, rem3, term1, term2, term3, &rem1, &rem2, &rem3 );
3232 }
3233 zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
3234 }
3235 return
3236 roundAndPackFloatx80(
3237 floatx80_rounding_precision, 0, zExp, zSig0, zSig1 );
3238
3239}
3240
3241/*
3242-------------------------------------------------------------------------------
3243Returns 1 if the extended double-precision floating-point value `a' is
3244equal to the corresponding value `b', and 0 otherwise. The comparison is
3245performed according to the IEC/IEEE Standard for Binary Floating-point
3246Arithmetic.
3247-------------------------------------------------------------------------------
3248*/
3249flag floatx80_eq( floatx80 a, floatx80 b )
3250{
3251
3252 if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
3253 && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3254 || ( ( extractFloatx80Exp( b ) == 0x7FFF )
3255 && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3256 ) {
3257 if ( floatx80_is_signaling_nan( a )
3258 || floatx80_is_signaling_nan( b ) ) {
3259 float_raise( float_flag_invalid );
3260 }
3261 return 0;
3262 }
3263 return
3264 ( a.low == b.low )
3265 && ( ( a.high == b.high )
3266 || ( ( a.low == 0 )
3267 && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
3268 );
3269
3270}
3271
3272/*
3273-------------------------------------------------------------------------------
3274Returns 1 if the extended double-precision floating-point value `a' is
3275less than or equal to the corresponding value `b', and 0 otherwise. The
3276comparison is performed according to the IEC/IEEE Standard for Binary
3277Floating-point Arithmetic.
3278-------------------------------------------------------------------------------
3279*/
3280flag floatx80_le( floatx80 a, floatx80 b )
3281{
3282 flag aSign, bSign;
3283
3284 if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
3285 && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3286 || ( ( extractFloatx80Exp( b ) == 0x7FFF )
3287 && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3288 ) {
3289 float_raise( float_flag_invalid );
3290 return 0;
3291 }
3292 aSign = extractFloatx80Sign( a );
3293 bSign = extractFloatx80Sign( b );
3294 if ( aSign != bSign ) {
3295 return
3296 aSign
3297 || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
3298 == 0 );
3299 }
3300 return
3301 aSign ? le128( b.high, b.low, a.high, a.low )
3302 : le128( a.high, a.low, b.high, b.low );
3303
3304}
3305
3306/*
3307-------------------------------------------------------------------------------
3308Returns 1 if the extended double-precision floating-point value `a' is
3309less than the corresponding value `b', and 0 otherwise. The comparison
3310is performed according to the IEC/IEEE Standard for Binary Floating-point
3311Arithmetic.
3312-------------------------------------------------------------------------------
3313*/
3314flag floatx80_lt( floatx80 a, floatx80 b )
3315{
3316 flag aSign, bSign;
3317
3318 if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
3319 && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3320 || ( ( extractFloatx80Exp( b ) == 0x7FFF )
3321 && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3322 ) {
3323 float_raise( float_flag_invalid );
3324 return 0;
3325 }
3326 aSign = extractFloatx80Sign( a );
3327 bSign = extractFloatx80Sign( b );
3328 if ( aSign != bSign ) {
3329 return
3330 aSign
3331 && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
3332 != 0 );
3333 }
3334 return
3335 aSign ? lt128( b.high, b.low, a.high, a.low )
3336 : lt128( a.high, a.low, b.high, b.low );
3337
3338}
3339
3340/*
3341-------------------------------------------------------------------------------
3342Returns 1 if the extended double-precision floating-point value `a' is equal
3343to the corresponding value `b', and 0 otherwise. The invalid exception is
3344raised if either operand is a NaN. Otherwise, the comparison is performed
3345according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
3346-------------------------------------------------------------------------------
3347*/
3348flag floatx80_eq_signaling( floatx80 a, floatx80 b )
3349{
3350
3351 if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
3352 && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3353 || ( ( extractFloatx80Exp( b ) == 0x7FFF )
3354 && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3355 ) {
3356 float_raise( float_flag_invalid );
3357 return 0;
3358 }
3359 return
3360 ( a.low == b.low )
3361 && ( ( a.high == b.high )
3362 || ( ( a.low == 0 )
3363 && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
3364 );
3365
3366}
3367
3368/*
3369-------------------------------------------------------------------------------
3370Returns 1 if the extended double-precision floating-point value `a' is less
3371than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs
3372do not cause an exception. Otherwise, the comparison is performed according
3373to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
3374-------------------------------------------------------------------------------
3375*/
3376flag floatx80_le_quiet( floatx80 a, floatx80 b )
3377{
3378 flag aSign, bSign;
3379
3380 if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
3381 && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3382 || ( ( extractFloatx80Exp( b ) == 0x7FFF )
3383 && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3384 ) {
3385 if ( floatx80_is_signaling_nan( a )
3386 || floatx80_is_signaling_nan( b ) ) {
3387 float_raise( float_flag_invalid );
3388 }
3389 return 0;
3390 }
3391 aSign = extractFloatx80Sign( a );
3392 bSign = extractFloatx80Sign( b );
3393 if ( aSign != bSign ) {
3394 return
3395 aSign
3396 || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
3397 == 0 );
3398 }
3399 return
3400 aSign ? le128( b.high, b.low, a.high, a.low )
3401 : le128( a.high, a.low, b.high, b.low );
3402
3403}
3404
3405/*
3406-------------------------------------------------------------------------------
3407Returns 1 if the extended double-precision floating-point value `a' is less
3408than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause
3409an exception. Otherwise, the comparison is performed according to the
3410IEC/IEEE Standard for Binary Floating-point Arithmetic.
3411-------------------------------------------------------------------------------
3412*/
3413flag floatx80_lt_quiet( floatx80 a, floatx80 b )
3414{
3415 flag aSign, bSign;
3416
3417 if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
3418 && (bits64) ( extractFloatx80Frac( a )<<1 ) )
3419 || ( ( extractFloatx80Exp( b ) == 0x7FFF )
3420 && (bits64) ( extractFloatx80Frac( b )<<1 ) )
3421 ) {
3422 if ( floatx80_is_signaling_nan( a )
3423 || floatx80_is_signaling_nan( b ) ) {
3424 float_raise( float_flag_invalid );
3425 }
3426 return 0;
3427 }
3428 aSign = extractFloatx80Sign( a );
3429 bSign = extractFloatx80Sign( b );
3430 if ( aSign != bSign ) {
3431 return
3432 aSign
3433 && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
3434 != 0 );
3435 }
3436 return
3437 aSign ? lt128( b.high, b.low, a.high, a.low )
3438 : lt128( a.high, a.low, b.high, b.low );
3439
3440}
3441
3442#endif
3443
diff --git a/arch/arm/nwfpe/softfloat.h b/arch/arm/nwfpe/softfloat.h
new file mode 100644
index 000000000000..1e1743173899
--- /dev/null
+++ b/arch/arm/nwfpe/softfloat.h
@@ -0,0 +1,278 @@
1
2/*
3===============================================================================
4
5This C header file is part of the SoftFloat IEC/IEEE Floating-point
6Arithmetic Package, Release 2.
7
8Written by John R. Hauser. This work was made possible in part by the
9International Computer Science Institute, located at Suite 600, 1947 Center
10Street, Berkeley, California 94704. Funding was partially provided by the
11National Science Foundation under grant MIP-9311980. The original version
12of this code was written as part of a project to build a fixed-point vector
13processor in collaboration with the University of California at Berkeley,
14overseen by Profs. Nelson Morgan and John Wawrzynek. More information
15is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
16arithmetic/softfloat.html'.
17
18THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
19has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
20TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
21PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
22AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
23
24Derivative works are acceptable, even for commercial purposes, so long as
25(1) they include prominent notice that the work is derivative, and (2) they
26include prominent notice akin to these three paragraphs for those parts of
27this code that are retained.
28
29===============================================================================
30*/
31
32#ifndef __SOFTFLOAT_H__
33#define __SOFTFLOAT_H__
34
35#include <linux/config.h>
36
37/*
38-------------------------------------------------------------------------------
39The macro `FLOATX80' must be defined to enable the extended double-precision
40floating-point format `floatx80'. If this macro is not defined, the
41`floatx80' type will not be defined, and none of the functions that either
42input or output the `floatx80' type will be defined.
43-------------------------------------------------------------------------------
44*/
45#ifdef CONFIG_FPE_NWFPE_XP
46#define FLOATX80
47#endif
48
49/*
50-------------------------------------------------------------------------------
51Software IEC/IEEE floating-point types.
52-------------------------------------------------------------------------------
53*/
54typedef unsigned long int float32;
55typedef unsigned long long float64;
56typedef struct {
57 unsigned short high;
58 unsigned long long low;
59} floatx80;
60
61/*
62-------------------------------------------------------------------------------
63Software IEC/IEEE floating-point underflow tininess-detection mode.
64-------------------------------------------------------------------------------
65*/
66extern signed char float_detect_tininess;
67enum {
68 float_tininess_after_rounding = 0,
69 float_tininess_before_rounding = 1
70};
71
72/*
73-------------------------------------------------------------------------------
74Software IEC/IEEE floating-point rounding mode.
75-------------------------------------------------------------------------------
76*/
77extern signed char float_rounding_mode;
78enum {
79 float_round_nearest_even = 0,
80 float_round_to_zero = 1,
81 float_round_down = 2,
82 float_round_up = 3
83};
84
85/*
86-------------------------------------------------------------------------------
87Software IEC/IEEE floating-point exception flags.
88-------------------------------------------------------------------------------
89extern signed char float_exception_flags;
90enum {
91 float_flag_inexact = 1,
92 float_flag_underflow = 2,
93 float_flag_overflow = 4,
94 float_flag_divbyzero = 8,
95 float_flag_invalid = 16
96};
97
98ScottB: November 4, 1998
99Changed the enumeration to match the bit order in the FPA11.
100*/
101
102extern signed char float_exception_flags;
103enum {
104 float_flag_invalid = 1,
105 float_flag_divbyzero = 2,
106 float_flag_overflow = 4,
107 float_flag_underflow = 8,
108 float_flag_inexact = 16
109};
110
111/*
112-------------------------------------------------------------------------------
113Routine to raise any or all of the software IEC/IEEE floating-point
114exception flags.
115-------------------------------------------------------------------------------
116*/
117void float_raise( signed char );
118
119/*
120-------------------------------------------------------------------------------
121Software IEC/IEEE integer-to-floating-point conversion routines.
122-------------------------------------------------------------------------------
123*/
124float32 int32_to_float32( signed int );
125float64 int32_to_float64( signed int );
126#ifdef FLOATX80
127floatx80 int32_to_floatx80( signed int );
128#endif
129
130/*
131-------------------------------------------------------------------------------
132Software IEC/IEEE single-precision conversion routines.
133-------------------------------------------------------------------------------
134*/
135signed int float32_to_int32( float32 );
136signed int float32_to_int32_round_to_zero( float32 );
137float64 float32_to_float64( float32 );
138#ifdef FLOATX80
139floatx80 float32_to_floatx80( float32 );
140#endif
141
142/*
143-------------------------------------------------------------------------------
144Software IEC/IEEE single-precision operations.
145-------------------------------------------------------------------------------
146*/
147float32 float32_round_to_int( float32 );
148float32 float32_add( float32, float32 );
149float32 float32_sub( float32, float32 );
150float32 float32_mul( float32, float32 );
151float32 float32_div( float32, float32 );
152float32 float32_rem( float32, float32 );
153float32 float32_sqrt( float32 );
154char float32_eq( float32, float32 );
155char float32_le( float32, float32 );
156char float32_lt( float32, float32 );
157char float32_eq_signaling( float32, float32 );
158char float32_le_quiet( float32, float32 );
159char float32_lt_quiet( float32, float32 );
160char float32_is_signaling_nan( float32 );
161
162/*
163-------------------------------------------------------------------------------
164Software IEC/IEEE double-precision conversion routines.
165-------------------------------------------------------------------------------
166*/
167signed int float64_to_int32( float64 );
168signed int float64_to_int32_round_to_zero( float64 );
169float32 float64_to_float32( float64 );
170#ifdef FLOATX80
171floatx80 float64_to_floatx80( float64 );
172#endif
173
174/*
175-------------------------------------------------------------------------------
176Software IEC/IEEE double-precision operations.
177-------------------------------------------------------------------------------
178*/
179float64 float64_round_to_int( float64 );
180float64 float64_add( float64, float64 );
181float64 float64_sub( float64, float64 );
182float64 float64_mul( float64, float64 );
183float64 float64_div( float64, float64 );
184float64 float64_rem( float64, float64 );
185float64 float64_sqrt( float64 );
186char float64_eq( float64, float64 );
187char float64_le( float64, float64 );
188char float64_lt( float64, float64 );
189char float64_eq_signaling( float64, float64 );
190char float64_le_quiet( float64, float64 );
191char float64_lt_quiet( float64, float64 );
192char float64_is_signaling_nan( float64 );
193
194#ifdef FLOATX80
195
196/*
197-------------------------------------------------------------------------------
198Software IEC/IEEE extended double-precision conversion routines.
199-------------------------------------------------------------------------------
200*/
201signed int floatx80_to_int32( floatx80 );
202signed int floatx80_to_int32_round_to_zero( floatx80 );
203float32 floatx80_to_float32( floatx80 );
204float64 floatx80_to_float64( floatx80 );
205
206/*
207-------------------------------------------------------------------------------
208Software IEC/IEEE extended double-precision rounding precision. Valid
209values are 32, 64, and 80.
210-------------------------------------------------------------------------------
211*/
212extern signed char floatx80_rounding_precision;
213
214/*
215-------------------------------------------------------------------------------
216Software IEC/IEEE extended double-precision operations.
217-------------------------------------------------------------------------------
218*/
219floatx80 floatx80_round_to_int( floatx80 );
220floatx80 floatx80_add( floatx80, floatx80 );
221floatx80 floatx80_sub( floatx80, floatx80 );
222floatx80 floatx80_mul( floatx80, floatx80 );
223floatx80 floatx80_div( floatx80, floatx80 );
224floatx80 floatx80_rem( floatx80, floatx80 );
225floatx80 floatx80_sqrt( floatx80 );
226char floatx80_eq( floatx80, floatx80 );
227char floatx80_le( floatx80, floatx80 );
228char floatx80_lt( floatx80, floatx80 );
229char floatx80_eq_signaling( floatx80, floatx80 );
230char floatx80_le_quiet( floatx80, floatx80 );
231char floatx80_lt_quiet( floatx80, floatx80 );
232char floatx80_is_signaling_nan( floatx80 );
233
234#endif
235
236static inline flag extractFloat32Sign(float32 a)
237{
238 return a >> 31;
239}
240
241static inline flag float32_eq_nocheck(float32 a, float32 b)
242{
243 return (a == b) || ((bits32) ((a | b) << 1) == 0);
244}
245
246static inline flag float32_lt_nocheck(float32 a, float32 b)
247{
248 flag aSign, bSign;
249
250 aSign = extractFloat32Sign(a);
251 bSign = extractFloat32Sign(b);
252 if (aSign != bSign)
253 return aSign && ((bits32) ((a | b) << 1) != 0);
254 return (a != b) && (aSign ^ (a < b));
255}
256
257static inline flag extractFloat64Sign(float64 a)
258{
259 return a >> 63;
260}
261
262static inline flag float64_eq_nocheck(float64 a, float64 b)
263{
264 return (a == b) || ((bits64) ((a | b) << 1) == 0);
265}
266
267static inline flag float64_lt_nocheck(float64 a, float64 b)
268{
269 flag aSign, bSign;
270
271 aSign = extractFloat64Sign(a);
272 bSign = extractFloat64Sign(b);
273 if (aSign != bSign)
274 return aSign && ((bits64) ((a | b) << 1) != 0);
275 return (a != b) && (aSign ^ (a < b));
276}
277
278#endif