Oh GACK! src-clean doesn't quite work that easily since cleandist rebuilds the
[unix-history] / contrib / FAQ / programs / fp-emu / fpem.tar
CommitLineData
a6d13d53
GCI
1fpemul/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 40755 \0 0 \0 0 \0 0 5462553466 10470\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/control_w.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 6533 5462320154 12735\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
2 * control_w.h
3 *
4 *
5 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
6 * Vic 3163, Australia.
7 * E-mail apm233m@vaxc.cc.monash.edu.au
8 * All rights reserved.
9 *
10 * This copyright notice covers the redistribution and use of the
11 * FPU emulator developed by W. Metzenthen. It covers only its use
12 * in the 386BSD operating system. Any other use is not permitted
13 * under this copyright.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must include information specifying
21 * that source code for the emulator is freely available and include
22 * either:
23 * a) an offer to provide the source code for a nominal distribution
24 * fee, or
25 * b) list at least two alternative methods whereby the source
26 * can be obtained, e.g. a publically accessible bulletin board
27 * and an anonymous ftp site from which the software can be
28 * downloaded.
29 * 3. All advertising materials specifically mentioning features or use of
30 * this emulator must acknowledge that it was developed by W. Metzenthen.
31 * 4. The name of W. Metzenthen may not be used to endorse or promote
32 * products derived from this software without specific prior written
33 * permission.
34 *
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
36 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
37 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
38 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
39 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
40 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
41 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
42 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
43 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 *
46 */
47
48#ifndef _CONTROLW_H_
49#define _CONTROLW_H_
50
51#ifdef LOCORE
52#define _Const_(x) $/**/x
53#else
54#define _Const_(x) x
55#endif
56
57#define CW_RC _Const_(0x0C00) /* rounding control */
58#define CW_PC _Const_(0x0300) /* precision control */
59
60#define CW_Precision Const_(0x0020) /* loss of precision mask */
61#define CW_Underflow Const_(0x0010) /* underflow mask */
62#define CW_Overflow Const_(0x0008) /* overflow mask */
63#define CW_ZeroDiv Const_(0x0004) /* divide by zero mask */
64#define CW_Denormal Const_(0x0002) /* denormalized operand mask */
65#define CW_Invalid Const_(0x0001) /* invalid operation mask */
66
67#define CW_Exceptions _Const_(0x003f) /* all masks */
68
69#define RC_RND _Const_(0x0000)
70#define RC_DOWN _Const_(0x0400)
71#define RC_UP _Const_(0x0800)
72#define RC_CHOP _Const_(0x0C00)
73
74/* p 15-5: Precision control bits affect only the following:
75 ADD, SUB(R), MUL, DIV(R), and SQRT */
76#define PR_24_BITS _Const_(0x000)
77#define PR_53_BITS _Const_(0x200)
78#define PR_64_BITS _Const_(0x300)
79/* FULL_PRECISION simulates all exceptions masked */
80#define FULL_PRECISION (PR_64_BITS | RC_RND | 0x3f)
81
82#endif /* _CONTROLW_H_ */
83\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/fpu_entry.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 41015 5462541274 12757\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
84 * fpu_entry.c
85 *
86 * The entry function for wm-FPU-emu
87 *
88 *
89 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
90 * Vic 3163, Australia.
91 * E-mail apm233m@vaxc.cc.monash.edu.au
92 * All rights reserved.
93 *
94 * This copyright notice covers the redistribution and use of the
95 * FPU emulator developed by W. Metzenthen. It covers only its use
96 * in the 386BSD operating system. Any other use is not permitted
97 * under this copyright.
98 *
99 * Redistribution and use in source and binary forms, with or without
100 * modification, are permitted provided that the following conditions
101 * are met:
102 * 1. Redistributions of source code must retain the above copyright
103 * notice, this list of conditions and the following disclaimer.
104 * 2. Redistributions in binary form must include information specifying
105 * that source code for the emulator is freely available and include
106 * either:
107 * a) an offer to provide the source code for a nominal distribution
108 * fee, or
109 * b) list at least two alternative methods whereby the source
110 * can be obtained, e.g. a publically accessible bulletin board
111 * and an anonymous ftp site from which the software can be
112 * downloaded.
113 * 3. All advertising materials specifically mentioning features or use of
114 * this emulator must acknowledge that it was developed by W. Metzenthen.
115 * 4. The name of W. Metzenthen may not be used to endorse or promote
116 * products derived from this software without specific prior written
117 * permission.
118 *
119 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
120 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
121 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
122 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
123 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
124 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
125 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
126 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
127 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
128 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
129 *
130 *
131 * The purpose of the copyright is to ensure that the covered software
132 * remains freely available to everyone. It is felt to be necessary to
133 * try and prevent the software being taken by unscrupulous people and
134 * (perhaps after modification) being copyrighted or otherwise
135 * restricted and being made no longer freely available. There are a
136 * number of examples of corporations hijacking ideas and trying to
137 * sue the pants of lesser financed entities who try to subsequently
138 * use the ideas.
139 *
140 * If the software were placed in the public domain then there would
141 * be no protection at all. By claiming a copyright it puts at least a
142 * strong moral pressure on the greedy to restrain themselves and
143 * behave ethically. And let's not be naive, we are all subject to the
144 * emotion of greed to some extent...
145 *
146 * Up until now, the software has been covered by the GNU copyleft.
147 * That copyright mechanism has problems for operating systems which
148 * are not themselves covered by the GNU copyleft. Hence I have
149 * decided to allow the covered software to be used with 386BSD under
150 * restrictions which are meant to be broadly similar, but not
151 * identical, to those which already cover the 386BSD operating
152 * system.
153 *
154 * The software, in its form for the Linux operating system, remains
155 * available under the terms of the GNU copyleft.
156 *
157 * W. Metzenthen June 1993.
158 */
159
160/*---------------------------------------------------------------------------+
161 | Note: |
162 | The file contains code which accesses user memory. |
163 | Emulator static data may change when user memory is accessed, due to |
164 | other processes using the emulator while swapping is in progress. |
165 +---------------------------------------------------------------------------*/
166
167/*---------------------------------------------------------------------------+
168 | math_emulate() is the sole entry point for wm-FPU-emu |
169 +---------------------------------------------------------------------------*/
170
171
172#include "param.h"
173#include "systm.h"
174#include "proc.h"
175#include "machine/cpu.h"
176#include "machine/pcb.h"
177
178#include "fpu_emu.h"
179#include "fpu_system.h"
180#include "exception.h"
181#include "control_w.h"
182#include "status_w.h"
183
184
185#define __BAD__ Un_impl /* Not implemented */
186
187#define FPU_LOOKAHEAD 1 /* For performance boost */
188
189#if FPU_LOOKAHEAD != 0 /* I think thet we have to limit the */
190#define LOOKAHEAD_LIMIT 7 /* Max number of lookahead instructions*/
191#endif /* Or else a prog consisting of a million */
192 /* fnops will spend all its time in kernel*/
193
194#ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by
195 * default. */
196
197/* WARNING: These codes are not documented by Intel in their 80486 manual
198 and may not work on FPU clones or later Intel FPUs. */
199
200/* Changes to support the un-doc codes provided by Linus Torvalds. */
201
202#define _d9_d8_ fstp_i /* unofficial code (19) */
203#define _dc_d0_ fcom_st /* unofficial code (14) */
204#define _dc_d8_ fcompst /* unofficial code (1c) */
205#define _dd_c8_ fxch_i /* unofficial code (0d) */
206#define _de_d0_ fcompst /* unofficial code (16) */
207#define _df_c0_ ffreep /* unofficial code (07) ffree + pop */
208#define _df_c8_ fxch_i /* unofficial code (0f) */
209#define _df_d0_ fstp_i /* unofficial code (17) */
210#define _df_d8_ fstp_i /* unofficial code (1f) */
211
212static FUNC st_instr_table[64] = {
213 fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, _df_c0_,
214 fmul__, fxch_i, __BAD__, __BAD__, fmul_i, _dd_c8_, fmulp_, _df_c8_,
215 fcom_st, fp_nop, __BAD__, __BAD__, _dc_d0_, fst_i_, _de_d0_, _df_d0_,
216 fcompst, _d9_d8_, __BAD__, __BAD__, _dc_d8_, fstp_i, fcompp, _df_d8_,
217 fsub__, fp_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
218 fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
219 fdiv__, trig_a, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
220 fdivr_, trig_b, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
221};
222#else /* Support only documented FPU op-codes */
223
224static FUNC st_instr_table[64] = {
225 fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, __BAD__,
226 fmul__, fxch_i, __BAD__, __BAD__, fmul_i, __BAD__, fmulp_, __BAD__,
227 fcom_st, fp_nop, __BAD__, __BAD__, __BAD__, fst_i_, __BAD__, __BAD__,
228 fcompst, __BAD__, __BAD__, __BAD__, __BAD__, fstp_i, fcompp, __BAD__,
229 fsub__, fp_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
230 fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
231 fdiv__, trig_a, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
232 fdivr_, trig_b, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
233};
234#endif /* NO_UNDOC_CODE */
235
236
237#define _NONE_ 0 /* Take no special action */
238#define _REG0_ 1 /* Need to check for not empty st(0) */
239#define _REGI_ 2 /* Need to check for not empty st(0) and
240 * st(rm) */
241#define _REGi_ 0 /* Uses st(rm) */
242#define _PUSH_ 3 /* Need to check for space to push onto stack */
243#define _null_ 4 /* Function illegal or not implemented */
244#define _REGIi 5 /* Uses st(0) and st(rm), result to st(rm) */
245#define _REGIp 6 /* Uses st(0) and st(rm), result to st(rm)
246 * then pop */
247#define _REGIc 0 /* Compare st(0) and st(rm) */
248#define _REGIn 0 /* Uses st(0) and st(rm), but handle checks
249 * later */
250
251#ifndef NO_UNDOC_CODE
252
253/* Un-documented FPU op-codes supported by default. (see above) */
254
255static unsigned char type_table[64] = {
256 _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _REGi_,
257 _REGI_, _REGIn, _null_, _null_, _REGIi, _REGI_, _REGIp, _REGI_,
258 _REGIc, _NONE_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
259 _REGIc, _REG0_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
260 _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
261 _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
262 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
263 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
264};
265#else /* Support only documented FPU op-codes */
266
267static unsigned char type_table[64] = {
268 _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _null_,
269 _REGI_, _REGIn, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
270 _REGIc, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_,
271 _REGIc, _null_, _null_, _null_, _null_, _REG0_, _REGIc, _null_,
272 _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
273 _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
274 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
275 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
276};
277#endif /* NO_UNDOC_CODE */
278
279/* Be careful when using any of these global variables...
280 they might change if swapping is triggered */
281unsigned char FPU_rm;
282char FPU_st0_tag;
283FPU_REG *FPU_st0_ptr;
284
285#ifdef PARANOID
286char emulating = 0;
287#endif /* PARANOID */
288
289#define bswapw(x) __asm__("xchgb %%al,%%ah":"=a" (x):"0" ((short)x))
290#define math_abort(signo) \
291 FPU_EIP = FPU_ORIG_EIP;REENTRANT_CHECK(OFF);return(signo);
292
293int
294math_emulate(struct trapframe * tframe)
295{
296
297 unsigned char FPU_modrm;
298 unsigned short code;
299#ifdef LOOKAHEAD_LIMIT
300 int lookahead_limit = LOOKAHEAD_LIMIT;
301#endif
302#ifdef PARANOID
303 if (emulating) {
304 printf("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
305 }
306 REENTRANT_CHECK(ON);
307#endif /* PARANOID */
308
309 if ((((struct pcb *) curproc->p_addr)->pcb_flags & FP_SOFTFP) == 0) {
310 finit();
311 ((struct pcb *) curproc->p_addr)->pcb_flags |= FP_SOFTFP;
312 }
313 FPU_info = tframe;
314 FPU_ORIG_EIP = FPU_EIP; /* --pink-- */
315
316 if (FPU_CS != 0x001f) {
317 printf("math_emulate: %x : %x\n", FPU_CS, FPU_EIP);
318 panic("FPU emulation in kernel");
319 }
320#ifdef notyet
321 /* We cannot handle emulation in v86-mode */
322 if (FPU_EFLAGS & 0x00020000) {
323 FPU_ORIG_EIP = FPU_EIP;
324 math_abort(FPU_info, SIGILL);
325 }
326#endif
327
328 FPU_lookahead = FPU_LOOKAHEAD;
329#if notnow /* I dont know that much of traceing. Is it right? --pink-- */
330 if (curproc->p_flag & STRC)
331 FPU_lookahead = 0;
332#endif
333
334do_another_FPU_instruction:
335
336 REENTRANT_CHECK(OFF);
337 code = fuword((u_int *) FPU_EIP);
338 REENTRANT_CHECK(ON);
339 if ((code & 0xff) == 0x9b) { /* fwait */
340 if (status_word & SW_Summary)
341 goto do_the_FPU_interrupt;
342 else {
343 FPU_EIP++;
344 goto FPU_instruction_done;
345 }
346 }
347 if (status_word & SW_Summary) {
348 /* Ignore the error for now if the current instruction is a
349 * no-wait control instruction */
350 /* The 80486 manual contradicts itself on this topic, so I use
351 * the following list of such instructions until I can check
352 * on a real 80486: fninit, fnstenv, fnsave, fnstsw, fnstenv,
353 * fnclex. */
354 if (!((((code & 0xf803) == 0xe003) || /* fnclex, fninit,
355 * fnstsw */
356 (((code & 0x3003) == 0x3001) && /* fnsave, fnstcw,
357 * fnstenv, fnstsw */
358 ((code & 0xc000) != 0xc000))))) {
359 /* This is a guess about what a real FPU might do to
360 * this bit: */
361/* status_word &= ~SW_Summary; ****/
362
363 /* We need to simulate the action of the kernel to FPU
364 * interrupts here. Currently, the "real FPU" part of
365 * the kernel (0.99.10) clears the exception flags,
366 * sets the registers to empty, and passes information
367 * back to the interrupted process via the cs selector
368 * and operand selector, so we do the same. */
369 do_the_FPU_interrupt:
370 cs_selector &= 0xffff0000;
371 cs_selector |= (status_word & ~SW_Top) | ((top & 7) << SW_Top_Shift);
372 operand_selector = tag_word();
373 status_word = 0;
374 top = 0;
375 {
376 int r;
377 for (r = 0; r < 8; r++) {
378 regs[r].tag = TW_Empty;
379 }
380 }
381 REENTRANT_CHECK(OFF);
382 math_abort(SIGFPE);
383 }
384 }
385 FPU_entry_eip = FPU_ORIG_EIP = FPU_EIP;
386
387 if ((code & 0xff) == 0x66) { /* size prefix */
388 FPU_EIP++;
389 REENTRANT_CHECK(OFF);
390 code = fuword((u_int *) FPU_EIP);
391 REENTRANT_CHECK(ON);
392 }
393 FPU_EIP += 2;
394
395 FPU_modrm = code >> 8;
396 FPU_rm = FPU_modrm & 7;
397
398 if (FPU_modrm < 0300) {
399 /* All of these instructions use the mod/rm byte to get a data
400 * address */
401 get_address(FPU_modrm);
402 if (!(code & 1)) {
403 unsigned short status1 = status_word;
404 FPU_st0_ptr = &st(0);
405 FPU_st0_tag = FPU_st0_ptr->tag;
406
407 /* Stack underflow has priority */
408 if (NOT_EMPTY_0) {
409 switch ((code >> 1) & 3) {
410 case 0:
411 reg_load_single();
412 break;
413 case 1:
414 reg_load_int32();
415 break;
416 case 2:
417 reg_load_double();
418 break;
419 case 3:
420 reg_load_int16();
421 break;
422 }
423
424 /* No more access to user memory, it is safe
425 * to use static data now */
426 FPU_st0_ptr = &st(0);
427 FPU_st0_tag = FPU_st0_ptr->tag;
428
429 /* NaN operands have the next priority. */
430 /* We have to delay looking at st(0) until
431 * after loading the data, because that data
432 * might contain an SNaN */
433 if ((FPU_st0_tag == TW_NaN) ||
434 (FPU_loaded_data.tag == TW_NaN)) {
435 /* Restore the status word; we might
436 * have loaded a denormal. */
437 status_word = status1;
438 if ((FPU_modrm & 0x30) == 0x10) {
439 /* fcom or fcomp */
440 EXCEPTION(EX_Invalid);
441 setcc(SW_C3 | SW_C2 | SW_C0);
442 if (FPU_modrm & 0x08)
443 pop(); /* fcomp, so we pop. */
444 } else
445 real_2op_NaN(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr);
446 goto reg_mem_instr_done;
447 }
448 switch ((FPU_modrm >> 3) & 7) {
449 case 0: /* fadd */
450 reg_add(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word);
451 break;
452 case 1: /* fmul */
453 reg_mul(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word);
454 break;
455 case 2: /* fcom */
456 compare_st_data();
457 break;
458 case 3: /* fcomp */
459 compare_st_data();
460 pop();
461 break;
462 case 4: /* fsub */
463 reg_sub(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word);
464 break;
465 case 5: /* fsubr */
466 reg_sub(&FPU_loaded_data, FPU_st0_ptr, FPU_st0_ptr, control_word);
467 break;
468 case 6: /* fdiv */
469 reg_div(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word);
470 break;
471 case 7: /* fdivr */
472 if (FPU_st0_tag == TW_Zero)
473 status_word = status1; /* Undo any denorm tag,
474 * zero-divide has
475 * priority. */
476 reg_div(&FPU_loaded_data, FPU_st0_ptr, FPU_st0_ptr, control_word);
477 break;
478 }
479 } else {
480 if ((FPU_modrm & 0x30) == 0x10) {
481 /* The instruction is fcom or fcomp */
482 EXCEPTION(EX_StackUnder);
483 setcc(SW_C3 | SW_C2 | SW_C0);
484 if (FPU_modrm & 0x08)
485 pop(); /* fcomp, Empty or not,
486 * we pop. */
487 } else
488 stack_underflow();
489 }
490 } else {
491 load_store_instr(((FPU_modrm & 0x38) | (code & 6)) >> 1);
492 }
493
494reg_mem_instr_done:
495
496 data_operand_offset = (unsigned long) FPU_data_address;
497 } else {
498 /* None of these instructions access user memory */
499 unsigned char instr_index = (FPU_modrm & 0x38) | (code & 7);
500
501 FPU_st0_ptr = &st(0);
502 FPU_st0_tag = FPU_st0_ptr->tag;
503 switch (type_table[(int) instr_index]) {
504 case _NONE_: /* also _REGIc: _REGIn */
505 break;
506 case _REG0_:
507 if (!NOT_EMPTY_0) {
508 stack_underflow();
509 goto FPU_instruction_done;
510 }
511 break;
512 case _REGIi:
513 if (!NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm)) {
514 stack_underflow_i(FPU_rm);
515 goto FPU_instruction_done;
516 }
517 break;
518 case _REGIp:
519 if (!NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm)) {
520 stack_underflow_i(FPU_rm);
521 pop();
522 goto FPU_instruction_done;
523 }
524 break;
525 case _REGI_:
526 if (!NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm)) {
527 stack_underflow();
528 goto FPU_instruction_done;
529 }
530 break;
531 case _PUSH_: /* Only used by the fld st(i) instruction */
532 break;
533 case _null_:
534 Un_impl();
535 goto FPU_instruction_done;
536 default:
537 EXCEPTION(EX_INTERNAL | 0x111);
538 goto FPU_instruction_done;
539 }
540 (*st_instr_table[(int) instr_index]) ();
541 }
542
543FPU_instruction_done:
544
545 ip_offset = FPU_entry_eip;
546 bswapw(code);
547 *(1 + (unsigned short *) &cs_selector) = code & 0x7ff;
548
549#ifdef DEBUG
550 REENTRANT_CHECK(OFF);
551 emu_printall();
552 REENTRANT_CHECK(ON);
553#endif /* DEBUG */
554#ifdef LOOKAHEAD_LIMIT
555if (--lookahead_limit)
556#endif
557 if (FPU_lookahead) {
558 unsigned char next;
559
560 /* (This test should generate no machine code) */
561 while (1) {
562 REENTRANT_CHECK(OFF);
563 next = fubyte((u_char *) FPU_EIP);
564 REENTRANT_CHECK(ON);
565 if (((next & 0xf8) == 0xd8) || (next == 0x9b)) { /* fwait */
566 goto do_another_FPU_instruction;
567 } else
568 if (next == 0x66) { /* size prefix */
569 REENTRANT_CHECK(OFF);
570 next = fubyte((u_char *) (FPU_EIP + 1));
571 REENTRANT_CHECK(ON);
572 if ((next & 0xf8) == 0xd8) {
573 FPU_EIP++;
574 goto do_another_FPU_instruction;
575 }
576 }
577 break;
578 }
579 }
580 REENTRANT_CHECK(OFF);
581 return (0); /* --pink-- */
582}
583\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/errors.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 35403 5462512042 12253\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
584 * errors.c
585 *
586 * The error handling functions for wm-FPU-emu
587 *
588 *
589 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
590 * Vic 3163, Australia.
591 * E-mail apm233m@vaxc.cc.monash.edu.au
592 * All rights reserved.
593 *
594 * This copyright notice covers the redistribution and use of the
595 * FPU emulator developed by W. Metzenthen. It covers only its use
596 * in the 386BSD operating system. Any other use is not permitted
597 * under this copyright.
598 *
599 * Redistribution and use in source and binary forms, with or without
600 * modification, are permitted provided that the following conditions
601 * are met:
602 * 1. Redistributions of source code must retain the above copyright
603 * notice, this list of conditions and the following disclaimer.
604 * 2. Redistributions in binary form must include information specifying
605 * that source code for the emulator is freely available and include
606 * either:
607 * a) an offer to provide the source code for a nominal distribution
608 * fee, or
609 * b) list at least two alternative methods whereby the source
610 * can be obtained, e.g. a publically accessible bulletin board
611 * and an anonymous ftp site from which the software can be
612 * downloaded.
613 * 3. All advertising materials specifically mentioning features or use of
614 * this emulator must acknowledge that it was developed by W. Metzenthen.
615 * 4. The name of W. Metzenthen may not be used to endorse or promote
616 * products derived from this software without specific prior written
617 * permission.
618 *
619 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
620 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
621 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
622 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
623 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
624 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
625 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
626 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
627 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
628 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
629 *
630 */
631
632/*---------------------------------------------------------------------------+
633 | Note: |
634 | The file contains code which accesses user memory. |
635 | Emulator static data may change when user memory is accessed, due to |
636 | other processes using the emulator while swapping is in progress. |
637 +---------------------------------------------------------------------------*/
638
639
640
641
642
643#include "param.h"
644#include "proc.h"
645#include "machine/cpu.h"
646#include "machine/pcb.h"
647
648#include "fpu_emu.h"
649#include "fpu_system.h"
650#include "exception.h"
651#include "status_w.h"
652#include "control_w.h"
653#include "reg_constant.h"
654#include "version.h"
655
656/* */
657#undef PRINT_MESSAGES
658/* */
659
660
661void
662Un_impl(void)
663{
664 unsigned char byte1, FPU_modrm;
665
666 REENTRANT_CHECK(OFF);
667 byte1 = fubyte((unsigned char *) FPU_ORIG_EIP);
668 FPU_modrm = fubyte(1 + (unsigned char *) FPU_ORIG_EIP);
669
670 printf("Unimplemented FPU Opcode at eip=%p : %02x ",
671 FPU_ORIG_EIP, byte1);
672
673 if (FPU_modrm >= 0300)
674 printf("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
675 else
676 printf("/%d\n", (FPU_modrm >> 3) & 7);
677 REENTRANT_CHECK(ON);
678
679 EXCEPTION(EX_Invalid);
680
681}
682
683
684
685
686void
687emu_printall()
688{
689 int i;
690 static char *tag_desc[] = {"Valid", "Zero", "ERROR", "ERROR",
691 "DeNorm", "Inf", "NaN", "Empty"};
692 unsigned char byte1, FPU_modrm;
693
694 REENTRANT_CHECK(OFF);
695 byte1 = fubyte((unsigned char *) FPU_ORIG_EIP);
696 FPU_modrm = fubyte(1 + (unsigned char *) FPU_ORIG_EIP);
697
698#ifdef DEBUGGING
699 if (status_word & SW_Backward)
700 printf("SW: backward compatibility\n");
701 if (status_word & SW_C3)
702 printf("SW: condition bit 3\n");
703 if (status_word & SW_C2)
704 printf("SW: condition bit 2\n");
705 if (status_word & SW_C1)
706 printf("SW: condition bit 1\n");
707 if (status_word & SW_C0)
708 printf("SW: condition bit 0\n");
709 if (status_word & SW_Summary)
710 printf("SW: exception summary\n");
711 if (status_word & SW_Stack_Fault)
712 printf("SW: stack fault\n");
713 if (status_word & SW_Precision)
714 printf("SW: loss of precision\n");
715 if (status_word & SW_Underflow)
716 printf("SW: underflow\n");
717 if (status_word & SW_Overflow)
718 printf("SW: overflow\n");
719 if (status_word & SW_Zero_Div)
720 printf("SW: divide by zero\n");
721 if (status_word & SW_Denorm_Op)
722 printf("SW: denormalized operand\n");
723 if (status_word & SW_Invalid)
724 printf("SW: invalid operation\n");
725#endif /* DEBUGGING */
726
727 status_word = status_word & ~SW_Top;
728 status_word |= (top & 7) << SW_Top_Shift;
729
730 printf("At %p: %02x ", FPU_ORIG_EIP, byte1);
731 if (FPU_modrm >= 0300)
732 printf("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
733 else
734 printf("/%d, mod=%d rm=%d\n",
735 (FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7);
736
737 printf(" SW: b=%d st=%d es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n",
738 status_word & 0x8000 ? 1 : 0, /* busy */
739 (status_word & 0x3800) >> 11, /* stack top pointer */
740 status_word & 0x80 ? 1 : 0, /* Error summary status */
741 status_word & 0x40 ? 1 : 0, /* Stack flag */
742 status_word & SW_C3 ? 1 : 0, status_word & SW_C2 ? 1 : 0, /* cc */
743 status_word & SW_C1 ? 1 : 0, status_word & SW_C0 ? 1 : 0, /* cc */
744 status_word & SW_Precision ? 1 : 0, status_word & SW_Underflow ? 1 : 0,
745 status_word & SW_Overflow ? 1 : 0, status_word & SW_Zero_Div ? 1 : 0,
746 status_word & SW_Denorm_Op ? 1 : 0, status_word & SW_Invalid ? 1 : 0);
747
748 printf(" CW: ic=%d rc=%d%d pc=%d%d iem=%d ef=%d%d%d%d%d%d\n",
749 control_word & 0x1000 ? 1 : 0,
750 (control_word & 0x800) >> 11, (control_word & 0x400) >> 10,
751 (control_word & 0x200) >> 9, (control_word & 0x100) >> 8,
752 control_word & 0x80 ? 1 : 0,
753 control_word & SW_Precision ? 1 : 0, control_word & SW_Underflow ? 1 : 0,
754 control_word & SW_Overflow ? 1 : 0, control_word & SW_Zero_Div ? 1 : 0,
755 control_word & SW_Denorm_Op ? 1 : 0, control_word & SW_Invalid ? 1 : 0);
756
757 for (i = 0; i < 8; i++) {
758 FPU_REG *r = &st(i);
759 switch (r->tag) {
760 case TW_Empty:
761 continue;
762 break;
763 case TW_Zero:
764 printf("st(%d) %c .0000 0000 0000 0000 ",
765 i, r->sign ? '-' : '+');
766 break;
767 case TW_Valid:
768 case TW_NaN:
769 case TW_Denormal:
770 case TW_Infinity:
771 printf("st(%d) %c .%04x %04x %04x %04x e%+-6d ", i,
772 r->sign ? '-' : '+',
773 (long) (r->sigh >> 16),
774 (long) (r->sigh & 0xFFFF),
775 (long) (r->sigl >> 16),
776 (long) (r->sigl & 0xFFFF),
777 r->exp - EXP_BIAS + 1);
778 break;
779 default:
780 printf("Whoops! Error in errors.c ");
781 break;
782 }
783 printf("%s\n", tag_desc[(int) (unsigned) r->tag]);
784 }
785
786 printf("[data] %c .%04x %04x %04x %04x e%+-6d ",
787 FPU_loaded_data.sign ? '-' : '+',
788 (long) (FPU_loaded_data.sigh >> 16),
789 (long) (FPU_loaded_data.sigh & 0xFFFF),
790 (long) (FPU_loaded_data.sigl >> 16),
791 (long) (FPU_loaded_data.sigl & 0xFFFF),
792 FPU_loaded_data.exp - EXP_BIAS + 1);
793 printf("%s\n", tag_desc[(int) (unsigned) FPU_loaded_data.tag]);
794 REENTRANT_CHECK(ON);
795
796}
797
798static struct {
799 int type;
800 char *name;
801} exception_names[] = {
802 {
803 EX_StackOver, "stack overflow"
804 },
805 {
806 EX_StackUnder, "stack underflow"
807 },
808 {
809 EX_Precision, "loss of precision"
810 },
811 {
812 EX_Underflow, "underflow"
813 },
814 {
815 EX_Overflow, "overflow"
816 },
817 {
818 EX_ZeroDiv, "divide by zero"
819 },
820 {
821 EX_Denormal, "denormalized operand"
822 },
823 {
824 EX_Invalid, "invalid operation"
825 },
826 {
827 EX_INTERNAL, "INTERNAL BUG in " FPU_VERSION
828 },
829 {
830 0, NULL
831 }
832};
833/*
834 EX_INTERNAL is always given with a code which indicates where the
835 error was detected.
836
837 Internal error types:
838 0x14 in e14.c
839 0x1nn in a *.c file:
840 0x101 in reg_add_sub.c
841 0x102 in reg_mul.c
842 0x103 in poly_sin.c
843 0x104 in poly_tan.c
844 0x105 in reg_mul.c
845 0x106 in reg_mov.c
846 0x107 in fpu_trig.c
847 0x108 in reg_compare.c
848 0x109 in reg_compare.c
849 0x110 in reg_add_sub.c
850 0x111 in interface.c
851 0x112 in fpu_trig.c
852 0x113 in reg_add_sub.c
853 0x114 in reg_ld_str.c
854 0x115 in fpu_trig.c
855 0x116 in fpu_trig.c
856 0x117 in fpu_trig.c
857 0x118 in fpu_trig.c
858 0x119 in fpu_trig.c
859 0x120 in poly_atan.c
860 0x121 in reg_compare.c
861 0x122 in reg_compare.c
862 0x123 in reg_compare.c
863 0x2nn in an *.s file:
864 0x201 in reg_u_add.S
865 0x202 in reg_u_div.S
866 0x203 in reg_u_div.S
867 0x204 in reg_u_div.S
868 0x205 in reg_u_mul.S
869 0x206 in reg_u_sub.S
870 0x207 in wm_sqrt.S
871 0x208 in reg_div.S
872 0x209 in reg_u_sub.S
873 0x210 in reg_u_sub.S
874 0x211 in reg_u_sub.S
875 0x212 in reg_u_sub.S
876 0x213 in wm_sqrt.S
877 0x214 in wm_sqrt.S
878 0x215 in wm_sqrt.S
879 0x216 in reg_round.S
880 0x217 in reg_round.S
881 0x218 in reg_round.S
882 */
883
884void
885exception(int n)
886{
887 int i, int_type;
888
889 int_type = 0; /* Needed only to stop compiler warnings */
890 if (n & EX_INTERNAL) {
891 int_type = n - EX_INTERNAL;
892 n = EX_INTERNAL;
893 /* Set lots of exception bits! */
894 status_word |= (SW_Exc_Mask | SW_Summary | FPU_BUSY);
895 } else {
896 /* Extract only the bits which we use to set the status word */
897 n &= (SW_Exc_Mask);
898 /* Set the corresponding exception bit */
899 status_word |= n;
900 if (status_word & ~control_word & CW_Exceptions)
901 status_word |= SW_Summary;
902 if (n & (SW_Stack_Fault | EX_Precision)) {
903 if (!(n & SW_C1))
904 /* This bit distinguishes over- from underflow
905 * for a stack fault, and roundup from
906 * round-down for precision loss. */
907 status_word &= ~SW_C1;
908 }
909 }
910
911 REENTRANT_CHECK(OFF);
912 if ((~control_word & n & CW_Exceptions) || (n == EX_INTERNAL)) {
913#ifdef PRINT_MESSAGES
914 /* My message from the sponsor */
915 printf(FPU_VERSION " " __DATE__ " (C) W. Metzenthen.\n");
916#endif /* PRINT_MESSAGES */
917
918 /* Get a name string for error reporting */
919 for (i = 0; exception_names[i].type; i++)
920 if ((exception_names[i].type & n) == exception_names[i].type)
921 break;
922
923 if (exception_names[i].type) {
924#ifdef PRINT_MESSAGES
925 printf("FP Exception: %s!\n", exception_names[i].name);
926#endif /* PRINT_MESSAGES */
927 } else
928 printf("FP emulator: Unknown Exception: 0x%04x!\n", n);
929
930 if (n == EX_INTERNAL) {
931 printf("FP emulator: Internal error type 0x%04x\n", int_type);
932 emu_printall();
933 }
934#ifdef PRINT_MESSAGES
935 else
936 emu_printall();
937#endif /* PRINT_MESSAGES */
938
939 /* The 80486 generates an interrupt on the next non-control
940 * FPU instruction. So we need some means of flagging it. We
941 * use the ES (Error Summary) bit for this, assuming that this
942 * is the way a real FPU does it (until I can check it out),
943 * if not, then some method such as the following kludge might
944 * be needed. */
945/* regs[0].tag |= TW_FPU_Interrupt; */
946 }
947 REENTRANT_CHECK(ON);
948
949#ifdef __DEBUG__
950 math_abort(SIGFPE);
951#endif /* __DEBUG__ */
952
953}
954
955
956/* Real operation attempted on two operands, one a NaN */
957void
958real_2op_NaN(FPU_REG * a, FPU_REG * b, FPU_REG * dest)
959{
960 FPU_REG *x;
961 int signalling;
962
963 x = a;
964 if (a->tag == TW_NaN) {
965 if (b->tag == TW_NaN) {
966 signalling = !(a->sigh & b->sigh & 0x40000000);
967 /* find the "larger" */
968 if (*(long long *) &(a->sigl) < *(long long *) &(b->sigl))
969 x = b;
970 } else {
971 /* return the quiet version of the NaN in a */
972 signalling = !(a->sigh & 0x40000000);
973 }
974 } else
975#ifdef PARANOID
976 if (b->tag == TW_NaN)
977#endif /* PARANOID */
978 {
979 signalling = !(b->sigh & 0x40000000);
980 x = b;
981 }
982#ifdef PARANOID
983 else {
984 signalling = 0;
985 EXCEPTION(EX_INTERNAL | 0x113);
986 x = &CONST_QNaN;
987 }
988#endif /* PARANOID */
989
990 if (!signalling) {
991 if (!(x->sigh & 0x80000000)) /* pseudo-NaN ? */
992 x = &CONST_QNaN;
993 reg_move(x, dest);
994 return;
995 }
996 if (control_word & CW_Invalid) {
997 /* The masked response */
998 if (!(x->sigh & 0x80000000)) /* pseudo-NaN ? */
999 x = &CONST_QNaN;
1000 reg_move(x, dest);
1001 /* ensure a Quiet NaN */
1002 dest->sigh |= 0x40000000;
1003 }
1004 EXCEPTION(EX_Invalid);
1005
1006 return;
1007}
1008/* Invalid arith operation on Valid registers */
1009void
1010arith_invalid(FPU_REG * dest)
1011{
1012
1013 if (control_word & CW_Invalid) {
1014 /* The masked response */
1015 reg_move(&CONST_QNaN, dest);
1016 }
1017 EXCEPTION(EX_Invalid);
1018
1019 return;
1020
1021}
1022
1023
1024/* Divide a finite number by zero */
1025void
1026divide_by_zero(int sign, FPU_REG * dest)
1027{
1028
1029 if (control_word & CW_ZeroDiv) {
1030 /* The masked response */
1031 reg_move(&CONST_INF, dest);
1032 dest->sign = (unsigned char) sign;
1033 }
1034 EXCEPTION(EX_ZeroDiv);
1035
1036 return;
1037
1038}
1039
1040
1041/* This may be called often, so keep it lean */
1042void
1043set_precision_flag_up(void)
1044{
1045 if (control_word & CW_Precision)
1046 status_word |= (SW_Precision | SW_C1); /* The masked response */
1047 else
1048 exception(EX_Precision | SW_C1);
1049
1050}
1051
1052
1053/* This may be called often, so keep it lean */
1054void
1055set_precision_flag_down(void)
1056{
1057 if (control_word & CW_Precision) { /* The masked response */
1058 status_word &= ~SW_C1;
1059 status_word |= SW_Precision;
1060 } else
1061 exception(EX_Precision);
1062}
1063
1064
1065int
1066denormal_operand(void)
1067{
1068 if (control_word & CW_Denormal) { /* The masked response */
1069 status_word |= SW_Denorm_Op;
1070 return 0;
1071 } else {
1072 exception(EX_Denormal);
1073 return 1;
1074 }
1075}
1076
1077
1078void
1079arith_overflow(FPU_REG * dest)
1080{
1081
1082 if (control_word & CW_Overflow) {
1083 char sign;
1084 /* The masked response */
1085/* **** The response here depends upon the rounding mode */
1086 sign = dest->sign;
1087 reg_move(&CONST_INF, dest);
1088 dest->sign = sign;
1089 } else {
1090 /* Subtract the magic number from the exponent */
1091 dest->exp -= (3 * (1 << 13));
1092 }
1093
1094 /* By definition, precision is lost. It appears that the roundup bit
1095 * (C1) is also set by convention. */
1096 EXCEPTION(EX_Overflow | EX_Precision | SW_C1);
1097
1098 return;
1099
1100}
1101
1102
1103void
1104arith_underflow(FPU_REG * dest)
1105{
1106
1107 if (control_word & CW_Underflow) {
1108 /* The masked response */
1109 if (dest->exp <= EXP_UNDER - 63)
1110 reg_move(&CONST_Z, dest);
1111 } else {
1112 /* Add the magic number to the exponent */
1113 dest->exp += (3 * (1 << 13));
1114 }
1115
1116 EXCEPTION(EX_Underflow);
1117
1118 return;
1119}
1120
1121
1122void
1123stack_overflow(void)
1124{
1125
1126 if (control_word & CW_Invalid) {
1127 /* The masked response */
1128 top--;
1129 reg_move(&CONST_QNaN, FPU_st0_ptr = &st(0));
1130 }
1131 EXCEPTION(EX_StackOver);
1132
1133 return;
1134
1135}
1136
1137
1138void
1139stack_underflow(void)
1140{
1141
1142 if (control_word & CW_Invalid) {
1143 /* The masked response */
1144 reg_move(&CONST_QNaN, FPU_st0_ptr);
1145 }
1146 EXCEPTION(EX_StackUnder);
1147
1148 return;
1149
1150}
1151
1152
1153void
1154stack_underflow_i(int i)
1155{
1156
1157 if (control_word & CW_Invalid) {
1158 /* The masked response */
1159 reg_move(&CONST_QNaN, &(st(i)));
1160 }
1161 EXCEPTION(EX_StackUnder);
1162
1163 return;
1164
1165}
1166
1167
1168void
1169stack_underflow_pop(int i)
1170{
1171
1172 if (control_word & CW_Invalid) {
1173 /* The masked response */
1174 reg_move(&CONST_QNaN, &(st(i)));
1175 pop();
1176 }
1177 EXCEPTION(EX_StackUnder);
1178
1179 return;
1180
1181}
1182\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/exception.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 6530 5462320155 12723\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
1183 * exception.h
1184 *
1185 *
1186 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
1187 * Vic 3163, Australia.
1188 * E-mail apm233m@vaxc.cc.monash.edu.au
1189 * All rights reserved.
1190 *
1191 * This copyright notice covers the redistribution and use of the
1192 * FPU emulator developed by W. Metzenthen. It covers only its use
1193 * in the 386BSD operating system. Any other use is not permitted
1194 * under this copyright.
1195 *
1196 * Redistribution and use in source and binary forms, with or without
1197 * modification, are permitted provided that the following conditions
1198 * are met:
1199 * 1. Redistributions of source code must retain the above copyright
1200 * notice, this list of conditions and the following disclaimer.
1201 * 2. Redistributions in binary form must include information specifying
1202 * that source code for the emulator is freely available and include
1203 * either:
1204 * a) an offer to provide the source code for a nominal distribution
1205 * fee, or
1206 * b) list at least two alternative methods whereby the source
1207 * can be obtained, e.g. a publically accessible bulletin board
1208 * and an anonymous ftp site from which the software can be
1209 * downloaded.
1210 * 3. All advertising materials specifically mentioning features or use of
1211 * this emulator must acknowledge that it was developed by W. Metzenthen.
1212 * 4. The name of W. Metzenthen may not be used to endorse or promote
1213 * products derived from this software without specific prior written
1214 * permission.
1215 *
1216 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1217 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
1218 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
1219 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1220 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1221 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1222 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1223 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1224 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1225 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1226 *
1227 */
1228
1229#ifndef _EXCEPTION_H_
1230#define _EXCEPTION_H_
1231
1232
1233#ifdef LOCORE
1234#define Const_(x) $/**/x
1235#else
1236#define Const_(x) x
1237#endif
1238
1239#ifndef SW_C1
1240#include "fpu_emu.h"
1241#endif /* SW_C1 */
1242
1243#define FPU_BUSY Const_(0x8000) /* FPU busy bit (8087 compatibility) */
1244#define EX_ErrorSummary Const_(0x0080) /* Error summary status */
1245/* Special exceptions: */
1246#define EX_INTERNAL Const_(0x8000) /* Internal error in wm-FPU-emu */
1247#define EX_StackOver Const_(0x0041|SW_C1) /* stack overflow */
1248#define EX_StackUnder Const_(0x0041) /* stack underflow */
1249/* Exception flags: */
1250#define EX_Precision Const_(0x0020) /* loss of precision */
1251#define EX_Underflow Const_(0x0010) /* underflow */
1252#define EX_Overflow Const_(0x0008) /* overflow */
1253#define EX_ZeroDiv Const_(0x0004) /* divide by zero */
1254#define EX_Denormal Const_(0x0002) /* denormalized operand */
1255#define EX_Invalid Const_(0x0001) /* invalid operation */
1256
1257
1258#ifndef LOCORE
1259
1260#ifdef DEBUG
1261#define EXCEPTION(x) { printf("exception in %s at line %d\n", \
1262 __FILE__, __LINE__); exception(x); }
1263#else
1264#define EXCEPTION(x) exception(x)
1265#endif
1266
1267#endif /* LOCORE */
1268
1269#endif /* _EXCEPTION_H_ */
1270\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/fpu_arith.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 11436 5462511711 12722\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
1271 * fpu_arith.c
1272 *
1273 * Code to implement the FPU register/register arithmetic instructions
1274 *
1275 *
1276 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
1277 * Vic 3163, Australia.
1278 * E-mail apm233m@vaxc.cc.monash.edu.au
1279 * All rights reserved.
1280 *
1281 * This copyright notice covers the redistribution and use of the
1282 * FPU emulator developed by W. Metzenthen. It covers only its use
1283 * in the 386BSD operating system. Any other use is not permitted
1284 * under this copyright.
1285 *
1286 * Redistribution and use in source and binary forms, with or without
1287 * modification, are permitted provided that the following conditions
1288 * are met:
1289 * 1. Redistributions of source code must retain the above copyright
1290 * notice, this list of conditions and the following disclaimer.
1291 * 2. Redistributions in binary form must include information specifying
1292 * that source code for the emulator is freely available and include
1293 * either:
1294 * a) an offer to provide the source code for a nominal distribution
1295 * fee, or
1296 * b) list at least two alternative methods whereby the source
1297 * can be obtained, e.g. a publically accessible bulletin board
1298 * and an anonymous ftp site from which the software can be
1299 * downloaded.
1300 * 3. All advertising materials specifically mentioning features or use of
1301 * this emulator must acknowledge that it was developed by W. Metzenthen.
1302 * 4. The name of W. Metzenthen may not be used to endorse or promote
1303 * products derived from this software without specific prior written
1304 * permission.
1305 *
1306 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1307 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
1308 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
1309 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1310 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1311 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1312 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1313 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1314 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1315 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1316 *
1317 */
1318
1319
1320
1321
1322#include "param.h"
1323#include "proc.h"
1324#include "machine/cpu.h"
1325#include "machine/pcb.h"
1326
1327#include "fpu_emu.h"
1328#include "fpu_system.h"
1329#include "control_w.h"
1330
1331
1332void
1333fadd__()
1334{
1335 /* fadd st,st(i) */
1336 reg_add(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word);
1337}
1338
1339
1340void
1341fmul__()
1342{
1343 /* fmul st,st(i) */
1344 reg_mul(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word);
1345}
1346
1347
1348
1349void
1350fsub__()
1351{
1352 /* fsub st,st(i) */
1353 reg_sub(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word);
1354}
1355
1356
1357void
1358fsubr_()
1359{
1360 /* fsubr st,st(i) */
1361 reg_sub(&st(FPU_rm), FPU_st0_ptr, FPU_st0_ptr, control_word);
1362}
1363
1364
1365void
1366fdiv__()
1367{
1368 /* fdiv st,st(i) */
1369 reg_div(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word);
1370}
1371
1372
1373void
1374fdivr_()
1375{
1376 /* fdivr st,st(i) */
1377 reg_div(&st(FPU_rm), FPU_st0_ptr, FPU_st0_ptr, control_word);
1378}
1379
1380
1381
1382void
1383fadd_i()
1384{
1385 /* fadd st(i),st */
1386 reg_add(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word);
1387}
1388
1389
1390void
1391fmul_i()
1392{
1393 /* fmul st(i),st */
1394 reg_mul(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word);
1395}
1396
1397
1398void
1399fsubri()
1400{
1401 /* fsubr st(i),st */
1402 /* This is the sense of the 80486 manual reg_sub(&st(FPU_rm),
1403 * FPU_st0_ptr, &st(FPU_rm), control_word); */
1404 reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word);
1405}
1406
1407
1408void
1409fsub_i()
1410{
1411 /* fsub st(i),st */
1412 /* This is the sense of the 80486 manual reg_sub(FPU_st0_ptr,
1413 * &st(FPU_rm), &st(FPU_rm), control_word); */
1414 reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word);
1415}
1416
1417
1418void
1419fdivri()
1420{
1421 /* fdivr st(i),st */
1422 reg_div(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word);
1423}
1424
1425
1426void
1427fdiv_i()
1428{
1429 /* fdiv st(i),st */
1430 reg_div(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word);
1431}
1432
1433
1434
1435void
1436faddp_()
1437{
1438 /* faddp st(i),st */
1439 reg_add(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word);
1440 pop();
1441}
1442
1443
1444void
1445fmulp_()
1446{
1447 /* fmulp st(i),st */
1448 reg_mul(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word);
1449 pop();
1450}
1451
1452
1453
1454void
1455fsubrp()
1456{
1457 /* fsubrp st(i),st */
1458 /* This is the sense of the 80486 manual reg_sub(&st(FPU_rm),
1459 * FPU_st0_ptr, &st(FPU_rm), control_word); */
1460 reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word);
1461 pop();
1462}
1463
1464
1465void
1466fsubp_()
1467{
1468 /* fsubp st(i),st */
1469 /* This is the sense of the 80486 manual reg_sub(FPU_st0_ptr,
1470 * &st(FPU_rm), &st(FPU_rm), control_word); */
1471 reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word);
1472 pop();
1473}
1474
1475
1476void
1477fdivrp()
1478{
1479 /* fdivrp st(i),st */
1480 reg_div(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word);
1481 pop();
1482}
1483
1484
1485void
1486fdivp_()
1487{
1488 /* fdivp st(i),st */
1489 reg_div(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word);
1490 pop();
1491}
1492\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/fpu_asm.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 24 \0 5157 5462320155 12410\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0staff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
1493 * fpu_asm.h
1494 *
1495 *
1496 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
1497 * Vic 3163, Australia.
1498 * E-mail apm233m@vaxc.cc.monash.edu.au
1499 * All rights reserved.
1500 *
1501 * This copyright notice covers the redistribution and use of the
1502 * FPU emulator developed by W. Metzenthen. It covers only its use
1503 * in the 386BSD operating system. Any other use is not permitted
1504 * under this copyright.
1505 *
1506 * Redistribution and use in source and binary forms, with or without
1507 * modification, are permitted provided that the following conditions
1508 * are met:
1509 * 1. Redistributions of source code must retain the above copyright
1510 * notice, this list of conditions and the following disclaimer.
1511 * 2. Redistributions in binary form must include information specifying
1512 * that source code for the emulator is freely available and include
1513 * either:
1514 * a) an offer to provide the source code for a nominal distribution
1515 * fee, or
1516 * b) list at least two alternative methods whereby the source
1517 * can be obtained, e.g. a publically accessible bulletin board
1518 * and an anonymous ftp site from which the software can be
1519 * downloaded.
1520 * 3. All advertising materials specifically mentioning features or use of
1521 * this emulator must acknowledge that it was developed by W. Metzenthen.
1522 * 4. The name of W. Metzenthen may not be used to endorse or promote
1523 * products derived from this software without specific prior written
1524 * permission.
1525 *
1526 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1527 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
1528 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
1529 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1530 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1531 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1532 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1533 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1534 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1535 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1536 *
1537 */
1538
1539#ifndef _FPU_ASM_H_
1540#define _FPU_ASM_H_
1541
1542#include "fpu_emu.h"
1543
1544#define EXCEPTION _exception
1545
1546
1547#define PARAM1 8(%ebp)
1548#define PARAM2 12(%ebp)
1549#define PARAM3 16(%ebp)
1550#define PARAM4 20(%ebp)
1551
1552#define SIGL_OFFSET 8
1553#define SIGN(x) (x)
1554#define TAG(x) 1(x)
1555#define EXP(x) 4(x)
1556#define SIG(x) SIGL_OFFSET/**/(x)
1557#define SIGL(x) SIGL_OFFSET/**/(x)
1558#define SIGH(x) 12(x)
1559
1560#endif /* _FPU_ASM_H_ */
1561\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/fpu_aux.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 11274 5462512021 12403\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
1562 * fpu_aux.c
1563 *
1564 * Code to implement some of the FPU auxiliary instructions.
1565 *
1566 *
1567 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
1568 * Vic 3163, Australia.
1569 * E-mail apm233m@vaxc.cc.monash.edu.au
1570 * All rights reserved.
1571 *
1572 * This copyright notice covers the redistribution and use of the
1573 * FPU emulator developed by W. Metzenthen. It covers only its use
1574 * in the 386BSD operating system. Any other use is not permitted
1575 * under this copyright.
1576 *
1577 * Redistribution and use in source and binary forms, with or without
1578 * modification, are permitted provided that the following conditions
1579 * are met:
1580 * 1. Redistributions of source code must retain the above copyright
1581 * notice, this list of conditions and the following disclaimer.
1582 * 2. Redistributions in binary form must include information specifying
1583 * that source code for the emulator is freely available and include
1584 * either:
1585 * a) an offer to provide the source code for a nominal distribution
1586 * fee, or
1587 * b) list at least two alternative methods whereby the source
1588 * can be obtained, e.g. a publically accessible bulletin board
1589 * and an anonymous ftp site from which the software can be
1590 * downloaded.
1591 * 3. All advertising materials specifically mentioning features or use of
1592 * this emulator must acknowledge that it was developed by W. Metzenthen.
1593 * 4. The name of W. Metzenthen may not be used to endorse or promote
1594 * products derived from this software without specific prior written
1595 * permission.
1596 *
1597 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1598 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
1599 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
1600 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1601 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1602 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1603 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1604 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1605 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1606 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1607 *
1608 */
1609
1610
1611#include "param.h"
1612#include "proc.h"
1613#include "machine/cpu.h"
1614#include "machine/pcb.h"
1615
1616#include "fpu_emu.h"
1617#include "fpu_system.h"
1618#include "exception.h"
1619#include "status_w.h"
1620
1621
1622
1623void
1624fclex(void)
1625{
1626 status_word &= ~(SW_Backward | SW_Summary | SW_Stack_Fault | SW_Precision |
1627 SW_Underflow | SW_Overflow | SW_Zero_Div | SW_Denorm_Op |
1628 SW_Invalid);
1629 FPU_entry_eip = ip_offset; /* We want no net effect */
1630}
1631/* Needs to be externally visible */
1632void
1633finit()
1634{
1635 int r;
1636 control_word = 0x037f;
1637 status_word = 0;
1638 top = 0; /* We don't keep top in the status word
1639 * internally. */
1640 for (r = 0; r < 8; r++) {
1641 regs[r].tag = TW_Empty;
1642 }
1643 FPU_entry_eip = ip_offset = 0;
1644}
1645
1646static FUNC finit_table[] = {
1647 Un_impl, Un_impl, fclex, finit, Un_impl, Un_impl, Un_impl, Un_impl
1648};
1649
1650void
1651finit_()
1652{
1653 (finit_table[FPU_rm]) ();
1654}
1655
1656
1657static void
1658fstsw_ax(void)
1659{
1660
1661 status_word &= ~SW_Top;
1662 status_word |= (top & 7) << SW_Top_Shift;
1663
1664 *(short *) &FPU_EAX = status_word;
1665
1666}
1667
1668static FUNC fstsw_table[] = {
1669 fstsw_ax, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl
1670};
1671
1672void
1673fstsw_()
1674{
1675 (fstsw_table[FPU_rm]) ();
1676}
1677
1678
1679
1680static void
1681fnop(void)
1682{
1683}
1684
1685FUNC fp_nop_table[] = {
1686 fnop, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl
1687};
1688
1689void
1690fp_nop()
1691{
1692 (fp_nop_table[FPU_rm]) ();
1693}
1694
1695
1696void
1697fld_i_()
1698{
1699 FPU_REG *st_new_ptr;
1700
1701 if (STACK_OVERFLOW) {
1702 stack_overflow();
1703 return;
1704 }
1705 /* fld st(i) */
1706 if (NOT_EMPTY(FPU_rm)) {
1707 reg_move(&st(FPU_rm), st_new_ptr);
1708 push();
1709 } else {
1710 if (control_word & EX_Invalid) {
1711 /* The masked response */
1712 push();
1713 stack_underflow();
1714 } else
1715 EXCEPTION(EX_StackUnder);
1716 }
1717
1718}
1719
1720
1721void
1722fxch_i()
1723{
1724 /* fxch st(i) */
1725 FPU_REG t;
1726 register FPU_REG *sti_ptr = &st(FPU_rm);
1727
1728 if (FPU_st0_tag == TW_Empty) {
1729 if (sti_ptr->tag == TW_Empty) {
1730 stack_underflow();
1731 stack_underflow_i(FPU_rm);
1732 return;
1733 }
1734 reg_move(sti_ptr, FPU_st0_ptr);
1735 stack_underflow_i(FPU_rm);
1736 return;
1737 }
1738 if (sti_ptr->tag == TW_Empty) {
1739 reg_move(FPU_st0_ptr, sti_ptr);
1740 stack_underflow();
1741 return;
1742 }
1743 reg_move(FPU_st0_ptr, &t);
1744 reg_move(sti_ptr, FPU_st0_ptr);
1745 reg_move(&t, sti_ptr);
1746}
1747
1748
1749void
1750ffree_()
1751{
1752 /* ffree st(i) */
1753 st(FPU_rm).tag = TW_Empty;
1754}
1755
1756
1757void
1758ffreep()
1759{
1760 /* ffree st(i) + pop - unofficial code */
1761 st(FPU_rm).tag = TW_Empty;
1762 pop();
1763}
1764
1765
1766void
1767fst_i_()
1768{
1769 /* fst st(i) */
1770 reg_move(FPU_st0_ptr, &st(FPU_rm));
1771}
1772
1773
1774void
1775fstp_i()
1776{
1777 /* fstp st(i) */
1778 reg_move(FPU_st0_ptr, &st(FPU_rm));
1779 pop();
1780}
1781\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/fpu_etc.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 10162 5462320157 12363\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
1782 * fpu_etc.c
1783 *
1784 * Implement a few FPU instructions.
1785 *
1786 *
1787 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
1788 * Vic 3163, Australia.
1789 * E-mail apm233m@vaxc.cc.monash.edu.au
1790 * All rights reserved.
1791 *
1792 * This copyright notice covers the redistribution and use of the
1793 * FPU emulator developed by W. Metzenthen. It covers only its use
1794 * in the 386BSD operating system. Any other use is not permitted
1795 * under this copyright.
1796 *
1797 * Redistribution and use in source and binary forms, with or without
1798 * modification, are permitted provided that the following conditions
1799 * are met:
1800 * 1. Redistributions of source code must retain the above copyright
1801 * notice, this list of conditions and the following disclaimer.
1802 * 2. Redistributions in binary form must include information specifying
1803 * that source code for the emulator is freely available and include
1804 * either:
1805 * a) an offer to provide the source code for a nominal distribution
1806 * fee, or
1807 * b) list at least two alternative methods whereby the source
1808 * can be obtained, e.g. a publically accessible bulletin board
1809 * and an anonymous ftp site from which the software can be
1810 * downloaded.
1811 * 3. All advertising materials specifically mentioning features or use of
1812 * this emulator must acknowledge that it was developed by W. Metzenthen.
1813 * 4. The name of W. Metzenthen may not be used to endorse or promote
1814 * products derived from this software without specific prior written
1815 * permission.
1816 *
1817 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1818 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
1819 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
1820 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1821 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1822 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1823 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1824 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1825 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1826 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1827 *
1828 */
1829
1830#include "param.h"
1831#include "proc.h"
1832#include "machine/cpu.h"
1833#include "machine/pcb.h"
1834
1835#include "fpu_emu.h"
1836#include "fpu_system.h"
1837#include "exception.h"
1838#include "status_w.h"
1839#include "reg_constant.h"
1840
1841
1842static void
1843fchs(void)
1844{
1845 if (NOT_EMPTY_0) {
1846 FPU_st0_ptr->sign ^= SIGN_POS ^ SIGN_NEG;
1847 status_word &= ~SW_C1;
1848 } else
1849 stack_underflow();
1850}
1851
1852static void
1853fabs(void)
1854{
1855 if (FPU_st0_tag ^ TW_Empty) {
1856 FPU_st0_ptr->sign = SIGN_POS;
1857 status_word &= ~SW_C1;
1858 } else
1859 stack_underflow();
1860}
1861
1862
1863static void
1864ftst_(void)
1865{
1866 switch (FPU_st0_tag) {
1867 case TW_Zero:
1868 setcc(SW_C3);
1869 break;
1870 case TW_Valid:
1871
1872#ifdef DENORM_OPERAND
1873 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
1874 return;
1875#endif /* DENORM_OPERAND */
1876
1877 if (FPU_st0_ptr->sign == SIGN_POS)
1878 setcc(0);
1879 else
1880 setcc(SW_C0);
1881 break;
1882 case TW_NaN:
1883 setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */
1884 EXCEPTION(EX_Invalid);
1885 break;
1886 case TW_Infinity:
1887 if (FPU_st0_ptr->sign == SIGN_POS)
1888 setcc(0);
1889 else
1890 setcc(SW_C0);
1891 EXCEPTION(EX_Invalid);
1892 break;
1893 case TW_Empty:
1894 setcc(SW_C0 | SW_C2 | SW_C3);
1895 EXCEPTION(EX_StackUnder);
1896 break;
1897 default:
1898 setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */
1899 EXCEPTION(EX_INTERNAL | 0x14);
1900 break;
1901 }
1902}
1903
1904static void
1905fxam(void)
1906{
1907 int c = 0;
1908 switch (FPU_st0_tag) {
1909 case TW_Empty:
1910 c = SW_C3 | SW_C0;
1911 break;
1912 case TW_Zero:
1913 c = SW_C3;
1914 break;
1915 case TW_Valid:
1916 /* This will need to be changed if TW_Denormal is ever used. */
1917 if (FPU_st0_ptr->exp <= EXP_UNDER)
1918 c = SW_C2 | SW_C3; /* Denormal */
1919 else
1920 c = SW_C3;
1921 break;
1922 case TW_NaN:
1923 c = SW_C0;
1924 break;
1925 case TW_Infinity:
1926 c = SW_C2 | SW_C0;
1927 break;
1928 }
1929 if (FPU_st0_ptr->sign == SIGN_NEG)
1930 c |= SW_C1;
1931 setcc(c);
1932}
1933
1934static FUNC fp_etc_table[] = {
1935 fchs, fabs, Un_impl, Un_impl, ftst_, fxam, Un_impl, Un_impl
1936};
1937
1938void
1939fp_etc()
1940{
1941 (fp_etc_table[FPU_rm]) ();
1942}
1943\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/fpu_system.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 24 \0 6377 5462534357 13174\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0staff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
1944 * fpu_system.h
1945 *
1946 *
1947 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
1948 * Vic 3163, Australia.
1949 * E-mail apm233m@vaxc.cc.monash.edu.au
1950 * All rights reserved.
1951 *
1952 * This copyright notice covers the redistribution and use of the
1953 * FPU emulator developed by W. Metzenthen. It covers only its use
1954 * in the 386BSD operating system. Any other use is not permitted
1955 * under this copyright.
1956 *
1957 * Redistribution and use in source and binary forms, with or without
1958 * modification, are permitted provided that the following conditions
1959 * are met:
1960 * 1. Redistributions of source code must retain the above copyright
1961 * notice, this list of conditions and the following disclaimer.
1962 * 2. Redistributions in binary form must include information specifying
1963 * that source code for the emulator is freely available and include
1964 * either:
1965 * a) an offer to provide the source code for a nominal distribution
1966 * fee, or
1967 * b) list at least two alternative methods whereby the source
1968 * can be obtained, e.g. a publically accessible bulletin board
1969 * and an anonymous ftp site from which the software can be
1970 * downloaded.
1971 * 3. All advertising materials specifically mentioning features or use of
1972 * this emulator must acknowledge that it was developed by W. Metzenthen.
1973 * 4. The name of W. Metzenthen may not be used to endorse or promote
1974 * products derived from this software without specific prior written
1975 * permission.
1976 *
1977 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1978 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
1979 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
1980 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1981 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1982 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1983 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1984 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1985 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1986 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1987 *
1988 */
1989
1990
1991#ifndef _FPU_SYSTEM_H
1992#define _FPU_SYSTEM_H
1993
1994/* system dependent definitions */
1995
1996/*
1997#include <linux/sched.h>
1998#include <linux/kernel.h>
1999*/
2000
2001#define I387 (*(union i387_union *)&(((struct pcb *)curproc->p_addr)->pcb_savefpu))
2002#define FPU_info (I387.soft.frame)
2003
2004#define FPU_CS (*(unsigned short *) &(FPU_info->tf_cs))
2005#define FPU_DS (*(unsigned short *) &(FPU_info->tf_ds))
2006#define FPU_EAX (FPU_info->tf_eax)
2007#define FPU_EFLAGS (FPU_info->tf_eflags)
2008#define FPU_EIP (FPU_info->tf_eip)
2009/*#define FPU_ORIG_EIP (FPU_info->___orig_eip) */
2010/*#define FPU_ORIG_EIP (FPU_info->tf_isp)*/
2011#define FPU_ORIG_EIP (I387.soft.orig_eip)
2012
2013#define FPU_lookahead (I387.soft.lookahead)
2014#define FPU_entry_eip (I387.soft.entry_eip)
2015
2016#define status_word (I387.soft.swd)
2017#define control_word (I387.soft.cwd)
2018#define regs (I387.soft.regs)
2019#define top (I387.soft.top)
2020
2021#define ip_offset (I387.soft.fip)
2022#define cs_selector (I387.soft.fcs)
2023#define data_operand_offset (I387.soft.foo)
2024#define operand_selector (I387.soft.fos)
2025
2026#endif
2027\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/README\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 24 \0 27206 5462277677 11530\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0staff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
2028 * wm-FPU-emu an FPU emulator for 80386 and 80486SX microprocessors.
2029 *
2030 *
2031 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
2032 * Vic 3163, Australia.
2033 * E-mail apm233m@vaxc.cc.monash.edu.au
2034 * All rights reserved.
2035 *
2036 * This copyright notice covers the redistribution and use of the
2037 * FPU emulator developed by W. Metzenthen. It covers only its use
2038 * in the 386BSD operating system. Any other use is not permitted
2039 * under this copyright.
2040 *
2041 * Redistribution and use in source and binary forms, with or without
2042 * modification, are permitted provided that the following conditions
2043 * are met:
2044 * 1. Redistributions of source code must retain the above copyright
2045 * notice, this list of conditions and the following disclaimer.
2046 * 2. Redistributions in binary form must include information specifying
2047 * that source code for the emulator is freely available and include
2048 * either:
2049 * a) an offer to provide the source code for a nominal distribution
2050 * fee, or
2051 * b) list at least two alternative methods whereby the source
2052 * can be obtained, e.g. a publically accessible bulletin board
2053 * and an anonymous ftp site from which the software can be
2054 * downloaded.
2055 * 3. All advertising materials specifically mentioning features or use of
2056 * this emulator must acknowledge that it was developed by W. Metzenthen.
2057 * 4. The name of W. Metzenthen may not be used to endorse or promote
2058 * products derived from this software without specific prior written
2059 * permission.
2060 *
2061 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
2062 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
2063 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
2064 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2065 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2066 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2067 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2068 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2069 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2070 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2071 *
2072 */
2073
2074wm-FPU-emu is an FPU emulator for Linux. It is derived from wm-emu387
2075which is my 80387 emulator for djgpp (gcc under msdos); wm-emu387 was
2076in turn based upon emu387 which was written by DJ Delorie for djgpp.
2077The interface to the Linux kernel is based upon the original Linux
2078math emulator by Linus Torvalds.
2079
2080My target FPU for wm-FPU-emu is that described in the Intel486
2081Programmer's Reference Manual (1992 edition). Numerous facets of the
2082functioning of the FPU are not well covered in the Reference Manual;
2083in the absence of clear details I have made guesses about the most
2084reasonable behaviour. Recently, this situation has improved because
2085I now have some access to the results produced by a real 80486 FPU.
2086
2087wm-FPU-emu does not implement all of the behaviour of the 80486 FPU.
2088See "Limitations" later in this file for a partial list of some
2089differences. I believe that the missing features are never used by
2090normal C or FORTRAN programs.
2091
2092
2093Please report bugs, etc to me at:
2094 apm233m@vaxc.cc.monash.edu.au
2095
2096
2097--Bill Metzenthen
2098 May 1993
2099
2100
2101----------------------- Internals of wm-FPU-emu -----------------------
2102
2103Numeric algorithms:
2104(1) Add, subtract, and multiply. Nothing remarkable in these.
2105(2) Divide has been tuned to get reasonable performance. The algorithm
2106 is not the obvious one which most people seem to use, but is designed
2107 to take advantage of the characteristics of the 80386. I expect that
2108 it has been invented many times before I discovered it, but I have not
2109 seen it. It is based upon one of those ideas which one carries around
2110 for years without ever bothering to check it out.
2111(3) The sqrt function has been tuned to get good performance. It is based
2112 upon Newton's classic method. Performance was improved by capitalizing
2113 upon the properties of Newton's method, and the code is once again
2114 structured taking account of the 80386 characteristics.
2115(4) The trig, log, and exp functions are based in each case upon quasi-
2116 "optimal" polynomial approximations. My definition of "optimal" was
2117 based upon getting good accuracy with reasonable speed.
2118
2119The code of the emulator is complicated slightly by the need to
2120account for a limited form of re-entrancy. Normally, the emulator will
2121emulate each FPU instruction to completion without interruption.
2122However, it may happen that when the emulator is accessing the user
2123memory space, swapping may be needed. In this case the emulator may be
2124temporarily suspended while disk i/o takes place. During this time
2125another process may use the emulator, thereby changing some static
2126variables (eg FPU_st0_ptr, etc). The code which accesses user memory
2127is confined to five files:
2128 fpu_entry.c
2129 reg_ld_str.c
2130 load_store.c
2131 get_address.c
2132 errors.c
2133
2134----------------------- Limitations of wm-FPU-emu -----------------------
2135
2136There are a number of differences between the current wm-FPU-emu
2137(version beta 1.4) and the 80486 FPU (apart from bugs). Some of the
2138more important differences are listed below:
2139
2140All internal computations are performed at 64 bit or higher precision
2141and rounded etc as required by the PC bits of the FPU control word.
2142Under the crt0 version for Linux current at March 1993, the FPU PC
2143bits specify 53 bits precision.
2144
2145The precision flag (PE of the FPU status word) and the Roundup flag
2146(C1 of the status word) are now partially implemented. Does anyone
2147write code which uses these features?
2148
2149The functions which load/store the FPU state are partially implemented,
2150but the implementation should be sufficient for handling FPU errors etc
2151in 32 bit protected mode.
2152
2153The implementation of the exception mechanism is flawed for unmasked
2154interrupts.
2155
2156Detection of certain conditions, such as denormal operands, is not yet
2157complete.
2158
2159----------------------- Performance of wm-FPU-emu -----------------------
2160
2161Speed.
2162-----
2163
2164The speed of floating point computation with the emulator will depend
2165upon instruction mix. Relative performance is best for the instructions
2166which require most computation. The simple instructions are adversely
2167affected by the fpu instruction trap overhead.
2168
2169
2170Timing: Some simple timing tests have been made on the emulator functions.
2171The times include load/store instructions. All times are in microseconds
2172measured on a 33MHz 386 with 64k cache. The Turbo C tests were under
2173ms-dos, the next two columns are for emulators running with the djgpp
2174ms-dos extender. The final column is for wm-FPU-emu in Linux 0.97,
2175using libm4.0 (hard).
2176
2177function Turbo C djgpp 1.06 WM-emu387 wm-FPU-emu
2178
2179 + 60.5 154.8 76.5 139.4
2180 - 61.1-65.5 157.3-160.8 76.2-79.5 142.9-144.7
2181 * 71.0 190.8 79.6 146.6
2182 / 61.2-75.0 261.4-266.9 75.3-91.6 142.2-158.1
2183
2184 sin() 310.8 4692.0 319.0 398.5
2185 cos() 284.4 4855.2 308.0 388.7
2186 tan() 495.0 8807.1 394.9 504.7
2187 atan() 328.9 4866.4 601.1 419.5-491.9
2188
2189 sqrt() 128.7 crashed 145.2 227.0
2190 log() 413.1-419.1 5103.4-5354.21 254.7-282.2 409.4-437.1
2191 exp() 479.1 6619.2 469.1 850.8
2192
2193
2194The performance under Linux is improved by the use of look-ahead code.
2195The following results show the improvement which is obtained under
2196Linux due to the look-ahead code. Also given are the times for the
2197original Linux emulator with the 4.1 'soft' lib.
2198
2199 [ Linus' note: I changed look-ahead to be the default under linux, as
2200 there was no reason not to use it after I had edited it to be
2201 disabled during tracing ]
2202
2203 wm-FPU-emu w original w
2204 look-ahead 'soft' lib
2205 + 106.4 190.2
2206 - 108.6-111.6 192.4-216.2
2207 * 113.4 193.1
2208 / 108.8-124.4 700.1-706.2
2209
2210 sin() 390.5 2642.0
2211 cos() 381.5 2767.4
2212 tan() 496.5 3153.3
2213 atan() 367.2-435.5 2439.4-3396.8
2214
2215 sqrt() 195.1 4732.5
2216 log() 358.0-387.5 3359.2-3390.3
2217 exp() 619.3 4046.4
2218
2219
2220These figures are now somewhat out-of-date. The emulator has become
2221progressively slower for most functions as more of the 80486 features
2222have been implemented.
2223
2224
2225----------------------- Accuracy of wm-FPU-emu -----------------------
2226
2227
2228Accuracy: The following table gives the accuracy of the sqrt(), trig
2229and log functions. Each function was tested at about 400 points. Ideal
2230results would be 64 bits. The reduced accuracy of cos() and tan() for
2231arguments greater than pi/4 can be thought of as being due to the
2232precision of the argument x; e.g. an argument of pi/2-(1e-10) which is
2233accurate to 64 bits can result in a relative accuracy in cos() of about
223464 + log2(cos(x)) = 31 bits. Results for the Turbo C emulator are given
2235in the last column.
2236
2237
2238Function Tested x range Worst result (bits) Turbo C
2239
2240sqrt(x) 1 .. 2 64.1 63.2
2241atan(x) 1e-10 .. 200 62.6 62.8
2242cos(x) 0 .. pi/2-(1e-10) 63.2 (x <= pi/4) 62.4
2243 35.2 (x = pi/2-(1e-10)) 31.9
2244sin(x) 1e-10 .. pi/2 63.0 62.8
2245tan(x) 1e-10 .. pi/2-(1e-10) 62.4 (x <= pi/4) 62.1
2246 35.2 (x = pi/2-(1e-10)) 31.9
2247exp(x) 0 .. 1 63.1 62.9
2248log(x) 1+1e-6 .. 2 62.4 62.1
2249
2250
2251As of version 1.3 of the emulator, the accuracy of the basic
2252arithmetic has been improved (by a small fraction of a bit). Care has
2253been taken to ensure full accuracy of the rounding of the basic
2254arithmetic functions (+,-,*,/,and fsqrt), and they all now produce
2255results which are exact to the 64th bit (unless there are any bugs
2256left). To ensure this, it was necessary to effectively get information
2257of up to about 128 bits precision. The emulator now passes the
2258"paranoia" tests (compiled with gcc 2.3.3) for 'float' variables (24
2259bit precision numbers) when precision control is set to 24, 53 or 64
2260bits, and for 'double' variables (53 bit precision numbers) when
2261precision control is set to 53 bits (a properly performing FPU cannot
2262pass the 'paranoia' tests for 'double' variables when precision
2263control is set to 64 bits).
2264
2265------------------------- Contributors -------------------------------
2266
2267A number of people have contributed to the development of the
2268emulator, often by just reporting bugs, sometimes with a suggested
2269fix, and a few kind people have provided me with access in one way or
2270another to an 80486 machine. Contributors include (to those people who
2271I have forgotten, please excuse me):
2272
2273Linus Torvalds
2274Tommy.Thorn@daimi.aau.dk
2275Andrew.Tridgell@anu.edu.au
2276Nick Holloway alfie@dcs.warwick.ac.uk
2277Hermano Moura moura@dcs.gla.ac.uk
2278Jon Jagger J.Jagger@scp.ac.uk
2279Lennart Benschop
2280Brian Gallew geek+@CMU.EDU
2281Thomas Staniszewski ts3v+@andrew.cmu.edu
2282Martin Howell mph@plasma.apana.org.au
2283M Saggaf alsaggaf@athena.mit.edu
2284Peter Barker PETER@socpsy.sci.fau.edu
2285tom@vlsivie.tuwien.ac.at
2286Dan Russel russed@rpi.edu
2287Daniel Carosone danielce@ee.mu.oz.au
2288cae@jpmorgan.com
2289Hamish Coleman t933093@minyos.xx.rmit.oz.au
2290
2291...and numerous others who responded to my request for help with
2292a real 80486.
2293
2294\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/fpu_trig.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 76162 5462320160 12563\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
2295 * fpu_trig.c
2296 *
2297 * Implementation of the FPU "transcendental" functions.
2298 *
2299 *
2300 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
2301 * Vic 3163, Australia.
2302 * E-mail apm233m@vaxc.cc.monash.edu.au
2303 * All rights reserved.
2304 *
2305 * This copyright notice covers the redistribution and use of the
2306 * FPU emulator developed by W. Metzenthen. It covers only its use
2307 * in the 386BSD operating system. Any other use is not permitted
2308 * under this copyright.
2309 *
2310 * Redistribution and use in source and binary forms, with or without
2311 * modification, are permitted provided that the following conditions
2312 * are met:
2313 * 1. Redistributions of source code must retain the above copyright
2314 * notice, this list of conditions and the following disclaimer.
2315 * 2. Redistributions in binary form must include information specifying
2316 * that source code for the emulator is freely available and include
2317 * either:
2318 * a) an offer to provide the source code for a nominal distribution
2319 * fee, or
2320 * b) list at least two alternative methods whereby the source
2321 * can be obtained, e.g. a publically accessible bulletin board
2322 * and an anonymous ftp site from which the software can be
2323 * downloaded.
2324 * 3. All advertising materials specifically mentioning features or use of
2325 * this emulator must acknowledge that it was developed by W. Metzenthen.
2326 * 4. The name of W. Metzenthen may not be used to endorse or promote
2327 * products derived from this software without specific prior written
2328 * permission.
2329 *
2330 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
2331 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
2332 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
2333 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2334 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2335 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2336 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2337 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2338 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2339 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2340 *
2341 */
2342
2343
2344#include "param.h"
2345#include "proc.h"
2346#include "machine/cpu.h"
2347#include "machine/pcb.h"
2348
2349#include "fpu_emu.h"
2350#include "fpu_system.h"
2351#include "exception.h"
2352#include "status_w.h"
2353#include "reg_constant.h"
2354#include "control_w.h"
2355
2356static int
2357trig_arg(FPU_REG * X)
2358{
2359 FPU_REG tmp, quot;
2360 int rv;
2361 long long q;
2362 int old_cw = control_word;
2363
2364 control_word &= ~CW_RC;
2365 control_word |= RC_CHOP;
2366
2367 reg_move(X, &quot);
2368 reg_div(&quot, &CONST_PI2, &quot, FULL_PRECISION);
2369
2370 reg_move(&quot, &tmp);
2371 round_to_int(&tmp);
2372 if (tmp.sigh & 0x80000000)
2373 return -1; /* |Arg| is >= 2^63 */
2374 tmp.exp = EXP_BIAS + 63;
2375 q = *(long long *) &(tmp.sigl);
2376 normalize(&tmp);
2377
2378 reg_sub(&quot, &tmp, X, FULL_PRECISION);
2379 rv = q & 7;
2380
2381 control_word = old_cw;
2382 return rv;;
2383}
2384
2385
2386/* Convert a long to register */
2387void
2388convert_l2reg(long *arg, FPU_REG * dest)
2389{
2390 long num = *arg;
2391
2392 if (num == 0) {
2393 reg_move(&CONST_Z, dest);
2394 return;
2395 }
2396 if (num > 0)
2397 dest->sign = SIGN_POS;
2398 else {
2399 num = -num;
2400 dest->sign = SIGN_NEG;
2401 }
2402
2403 dest->sigh = num;
2404 dest->sigl = 0;
2405 dest->exp = EXP_BIAS + 31;
2406 dest->tag = TW_Valid;
2407 normalize(dest);
2408}
2409
2410
2411static void
2412single_arg_error(void)
2413{
2414 switch (FPU_st0_tag) {
2415 case TW_NaN:
2416 if (!(FPU_st0_ptr->sigh & 0x40000000)) { /* Signaling ? */
2417 EXCEPTION(EX_Invalid);
2418 /* Convert to a QNaN */
2419 FPU_st0_ptr->sigh |= 0x40000000;
2420 }
2421 break; /* return with a NaN in st(0) */
2422 case TW_Empty:
2423 stack_underflow(); /* Puts a QNaN in st(0) */
2424 break;
2425#ifdef PARANOID
2426 default:
2427 EXCEPTION(EX_INTERNAL | 0x0112);
2428#endif /* PARANOID */
2429 }
2430}
2431
2432
2433/*---------------------------------------------------------------------------*/
2434
2435static void
2436f2xm1(void)
2437{
2438 switch (FPU_st0_tag) {
2439 case TW_Valid:
2440 {
2441 FPU_REG rv, tmp;
2442
2443#ifdef DENORM_OPERAND
2444 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
2445 return;
2446#endif /* DENORM_OPERAND */
2447
2448 if (FPU_st0_ptr->sign == SIGN_POS) {
2449 /* poly_2xm1(x) requires 0 < x < 1. */
2450 if (poly_2xm1(FPU_st0_ptr, &rv))
2451 return; /* error */
2452 reg_mul(&rv, FPU_st0_ptr, FPU_st0_ptr, FULL_PRECISION);
2453 } else {
2454/* **** Should change poly_2xm1() to at least handle numbers near 0 */
2455 /* poly_2xm1(x) doesn't handle negative
2456 * numbers. */
2457 /* So we compute (poly_2xm1(x+1)-1)/2, for -1
2458 * < x < 0 */
2459 reg_add(FPU_st0_ptr, &CONST_1, &tmp, FULL_PRECISION);
2460 poly_2xm1(&tmp, &rv);
2461 reg_mul(&rv, &tmp, &tmp, FULL_PRECISION);
2462 reg_sub(&tmp, &CONST_1, FPU_st0_ptr, FULL_PRECISION);
2463 FPU_st0_ptr->exp--;
2464 if (FPU_st0_ptr->exp <= EXP_UNDER)
2465 arith_underflow(FPU_st0_ptr);
2466 }
2467 return;
2468 }
2469 case TW_Zero:
2470 return;
2471 case TW_Infinity:
2472 if (FPU_st0_ptr->sign == SIGN_NEG) {
2473 /* -infinity gives -1 (p16-10) */
2474 reg_move(&CONST_1, FPU_st0_ptr);
2475 FPU_st0_ptr->sign = SIGN_NEG;
2476 }
2477 return;
2478 default:
2479 single_arg_error();
2480 }
2481}
2482
2483static void
2484fptan(void)
2485{
2486 FPU_REG *st_new_ptr;
2487 int q;
2488 char arg_sign = FPU_st0_ptr->sign;
2489
2490 if (STACK_OVERFLOW) {
2491 stack_overflow();
2492 return;
2493 }
2494 switch (FPU_st0_tag) {
2495 case TW_Valid:
2496
2497#ifdef DENORM_OPERAND
2498 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
2499 return;
2500#endif /* DENORM_OPERAND */
2501
2502 FPU_st0_ptr->sign = SIGN_POS;
2503 if ((q = trig_arg(FPU_st0_ptr)) != -1) {
2504 if (q & 1)
2505 reg_sub(&CONST_1, FPU_st0_ptr, FPU_st0_ptr, FULL_PRECISION);
2506
2507 poly_tan(FPU_st0_ptr, FPU_st0_ptr);
2508
2509 FPU_st0_ptr->sign = (q & 1) ^ arg_sign;
2510
2511 if (FPU_st0_ptr->exp <= EXP_UNDER)
2512 arith_underflow(FPU_st0_ptr);
2513
2514 push();
2515 reg_move(&CONST_1, FPU_st0_ptr);
2516 setcc(0);
2517 } else {
2518 /* Operand is out of range */
2519 setcc(SW_C2);
2520 FPU_st0_ptr->sign = arg_sign; /* restore st(0) */
2521 return;
2522 }
2523 break;
2524 case TW_Infinity:
2525 /* Operand is out of range */
2526 setcc(SW_C2);
2527 FPU_st0_ptr->sign = arg_sign; /* restore st(0) */
2528 return;
2529 case TW_Zero:
2530 push();
2531 reg_move(&CONST_1, FPU_st0_ptr);
2532 setcc(0);
2533 break;
2534 default:
2535 single_arg_error();
2536 break;
2537 }
2538}
2539
2540
2541static void
2542fxtract(void)
2543{
2544 FPU_REG *st_new_ptr;
2545 register FPU_REG *st1_ptr = FPU_st0_ptr; /* anticipate */
2546
2547 if (STACK_OVERFLOW) {
2548 stack_overflow();
2549 return;
2550 }
2551 if (!(FPU_st0_tag ^ TW_Valid)) {
2552 long e;
2553
2554#ifdef DENORM_OPERAND
2555 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
2556 return;
2557#endif /* DENORM_OPERAND */
2558
2559 push();
2560 reg_move(st1_ptr, FPU_st0_ptr);
2561 FPU_st0_ptr->exp = EXP_BIAS;
2562 e = st1_ptr->exp - EXP_BIAS;
2563 convert_l2reg(&e, st1_ptr);
2564 return;
2565 } else
2566 if (FPU_st0_tag == TW_Zero) {
2567 char sign = FPU_st0_ptr->sign;
2568 divide_by_zero(SIGN_NEG, FPU_st0_ptr);
2569 push();
2570 reg_move(&CONST_Z, FPU_st0_ptr);
2571 FPU_st0_ptr->sign = sign;
2572 return;
2573 } else
2574 if (FPU_st0_tag == TW_Infinity) {
2575 char sign = FPU_st0_ptr->sign;
2576 FPU_st0_ptr->sign = SIGN_POS;
2577 push();
2578 reg_move(&CONST_INF, FPU_st0_ptr);
2579 FPU_st0_ptr->sign = sign;
2580 return;
2581 } else
2582 if (FPU_st0_tag == TW_NaN) {
2583 if (!(FPU_st0_ptr->sigh & 0x40000000)) { /* Signaling ? */
2584 EXCEPTION(EX_Invalid);
2585 /* Convert to a QNaN */
2586 FPU_st0_ptr->sigh |= 0x40000000;
2587 }
2588 push();
2589 reg_move(st1_ptr, FPU_st0_ptr);
2590 return;
2591 } else
2592 if (FPU_st0_tag == TW_Empty) {
2593 /* Is this the correct
2594 * behaviour? */
2595 if (control_word & EX_Invalid) {
2596 stack_underflow();
2597 push();
2598 stack_underflow();
2599 } else
2600 EXCEPTION(EX_StackUnder);
2601 }
2602#ifdef PARANOID
2603 else
2604 EXCEPTION(EX_INTERNAL | 0x119);
2605#endif /* PARANOID */
2606}
2607
2608
2609static void
2610fdecstp(void)
2611{
2612 top--; /* FPU_st0_ptr will be fixed in math_emulate()
2613 * before the next instr */
2614}
2615
2616static void
2617fincstp(void)
2618{
2619 top++; /* FPU_st0_ptr will be fixed in math_emulate()
2620 * before the next instr */
2621}
2622
2623
2624static void
2625fsqrt_(void)
2626{
2627 if (!(FPU_st0_tag ^ TW_Valid)) {
2628 int expon;
2629
2630 if (FPU_st0_ptr->sign == SIGN_NEG) {
2631 arith_invalid(FPU_st0_ptr); /* sqrt(negative) is
2632 * invalid */
2633 return;
2634 }
2635#ifdef DENORM_OPERAND
2636 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
2637 return;
2638#endif /* DENORM_OPERAND */
2639
2640 expon = FPU_st0_ptr->exp - EXP_BIAS;
2641 FPU_st0_ptr->exp = EXP_BIAS + (expon & 1); /* make st(0) in [1.0
2642 * .. 4.0) */
2643
2644 wm_sqrt(FPU_st0_ptr, control_word); /* Do the computation */
2645
2646 FPU_st0_ptr->exp += expon >> 1;
2647 FPU_st0_ptr->sign = SIGN_POS;
2648 } else
2649 if (FPU_st0_tag == TW_Zero)
2650 return;
2651 else
2652 if (FPU_st0_tag == TW_Infinity) {
2653 if (FPU_st0_ptr->sign == SIGN_NEG)
2654 arith_invalid(FPU_st0_ptr); /* sqrt(-Infinity) is
2655 * invalid */
2656 return;
2657 } else {
2658 single_arg_error();
2659 return;
2660 }
2661
2662}
2663
2664
2665static void
2666frndint_(void)
2667{
2668 if (!(FPU_st0_tag ^ TW_Valid)) {
2669 if (FPU_st0_ptr->exp > EXP_BIAS + 63)
2670 return;
2671
2672#ifdef DENORM_OPERAND
2673 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
2674 return;
2675#endif /* DENORM_OPERAND */
2676
2677 round_to_int(FPU_st0_ptr); /* Fortunately, this can't
2678 * overflow to 2^64 */
2679 FPU_st0_ptr->exp = EXP_BIAS + 63;
2680 normalize(FPU_st0_ptr);
2681 return;
2682 } else
2683 if ((FPU_st0_tag == TW_Zero) || (FPU_st0_tag == TW_Infinity))
2684 return;
2685 else
2686 single_arg_error();
2687}
2688
2689
2690static void
2691fsin(void)
2692{
2693 char arg_sign = FPU_st0_ptr->sign;
2694
2695 if (FPU_st0_tag == TW_Valid) {
2696 int q;
2697 FPU_st0_ptr->sign = SIGN_POS;
2698
2699#ifdef DENORM_OPERAND
2700 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
2701 return;
2702#endif /* DENORM_OPERAND */
2703
2704 if ((q = trig_arg(FPU_st0_ptr)) != -1) {
2705 FPU_REG rv;
2706
2707 if (q & 1)
2708 reg_sub(&CONST_1, FPU_st0_ptr, FPU_st0_ptr, FULL_PRECISION);
2709
2710 poly_sine(FPU_st0_ptr, &rv);
2711
2712 setcc(0);
2713 if (q & 2)
2714 rv.sign ^= SIGN_POS ^ SIGN_NEG;
2715 rv.sign ^= arg_sign;
2716 reg_move(&rv, FPU_st0_ptr);
2717
2718 if (FPU_st0_ptr->exp <= EXP_UNDER)
2719 arith_underflow(FPU_st0_ptr);
2720
2721 set_precision_flag_up(); /* We do not really know
2722 * if up or down */
2723
2724 return;
2725 } else {
2726 /* Operand is out of range */
2727 setcc(SW_C2);
2728 FPU_st0_ptr->sign = arg_sign; /* restore st(0) */
2729 return;
2730 }
2731 } else
2732 if (FPU_st0_tag == TW_Zero) {
2733 setcc(0);
2734 return;
2735 } else
2736 if (FPU_st0_tag == TW_Infinity) {
2737 /* Operand is out of range */
2738 setcc(SW_C2);
2739 FPU_st0_ptr->sign = arg_sign; /* restore st(0) */
2740 return;
2741 } else
2742 single_arg_error();
2743}
2744
2745
2746static int
2747f_cos(FPU_REG * arg)
2748{
2749 char arg_sign = arg->sign;
2750
2751 if (arg->tag == TW_Valid) {
2752 int q;
2753
2754#ifdef DENORM_OPERAND
2755 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
2756 return 1;
2757#endif /* DENORM_OPERAND */
2758
2759 arg->sign = SIGN_POS;
2760 if ((q = trig_arg(arg)) != -1) {
2761 FPU_REG rv;
2762
2763 if (!(q & 1))
2764 reg_sub(&CONST_1, arg, arg, FULL_PRECISION);
2765
2766 poly_sine(arg, &rv);
2767
2768 setcc(0);
2769 if ((q + 1) & 2)
2770 rv.sign ^= SIGN_POS ^ SIGN_NEG;
2771 reg_move(&rv, arg);
2772
2773 set_precision_flag_up(); /* We do not really know
2774 * if up or down */
2775
2776 return 0;
2777 } else {
2778 /* Operand is out of range */
2779 setcc(SW_C2);
2780 arg->sign = arg_sign; /* restore st(0) */
2781 return 1;
2782 }
2783 } else
2784 if (arg->tag == TW_Zero) {
2785 reg_move(&CONST_1, arg);
2786 setcc(0);
2787 return 0;
2788 } else
2789 if (FPU_st0_tag == TW_Infinity) {
2790 /* Operand is out of range */
2791 setcc(SW_C2);
2792 arg->sign = arg_sign; /* restore st(0) */
2793 return 1;
2794 } else {
2795 single_arg_error(); /* requires arg ==
2796 * &st(0) */
2797 return 1;
2798 }
2799}
2800
2801
2802static void
2803fcos(void)
2804{
2805 f_cos(FPU_st0_ptr);
2806}
2807
2808
2809static void
2810fsincos(void)
2811{
2812 FPU_REG *st_new_ptr;
2813 FPU_REG arg;
2814
2815 if (STACK_OVERFLOW) {
2816 stack_overflow();
2817 return;
2818 }
2819 reg_move(FPU_st0_ptr, &arg);
2820 if (!f_cos(&arg)) {
2821 fsin();
2822 push();
2823 reg_move(&arg, FPU_st0_ptr);
2824 }
2825}
2826
2827
2828/*---------------------------------------------------------------------------*/
2829/* The following all require two arguments: st(0) and st(1) */
2830
2831/* remainder of st(0) / st(1) */
2832/* Assumes that st(0) and st(1) are both TW_Valid */
2833static void
2834fprem_kernel(int round)
2835{
2836 FPU_REG *st1_ptr = &st(1);
2837 char st1_tag = st1_ptr->tag;
2838
2839 if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) {
2840 FPU_REG tmp;
2841 int old_cw = control_word;
2842 int expdif = FPU_st0_ptr->exp - (st1_ptr)->exp;
2843
2844#ifdef DENORM_OPERAND
2845 if (((FPU_st0_ptr->exp <= EXP_UNDER) ||
2846 (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()))
2847 return;
2848#endif /* DENORM_OPERAND */
2849
2850 control_word &= ~CW_RC;
2851 control_word |= round;
2852
2853 if (expdif < 64) {
2854 /* This should be the most common case */
2855 long long q;
2856 int c = 0;
2857
2858 reg_div(FPU_st0_ptr, st1_ptr, &tmp, FULL_PRECISION);
2859
2860 round_to_int(&tmp); /* Fortunately, this can't
2861 * overflow to 2^64 */
2862 tmp.exp = EXP_BIAS + 63;
2863 q = *(long long *) &(tmp.sigl);
2864 normalize(&tmp);
2865
2866 reg_mul(st1_ptr, &tmp, &tmp, FULL_PRECISION);
2867 reg_sub(FPU_st0_ptr, &tmp, FPU_st0_ptr, FULL_PRECISION);
2868
2869 if (q & 4)
2870 c |= SW_C3;
2871 if (q & 2)
2872 c |= SW_C1;
2873 if (q & 1)
2874 c |= SW_C0;
2875
2876 setcc(c);
2877 } else {
2878 /* There is a large exponent difference ( >= 64 ) */
2879 int N_exp;
2880
2881 reg_div(FPU_st0_ptr, st1_ptr, &tmp, FULL_PRECISION);
2882 /* N is 'a number between 32 and 63' (p26-113) */
2883 N_exp = (tmp.exp & 31) + 32;
2884 tmp.exp = EXP_BIAS + N_exp;
2885
2886 round_to_int(&tmp); /* Fortunately, this can't
2887 * overflow to 2^64 */
2888 tmp.exp = EXP_BIAS + 63;
2889 normalize(&tmp);
2890
2891 tmp.exp = EXP_BIAS + expdif - N_exp;
2892
2893 reg_mul(st1_ptr, &tmp, &tmp, FULL_PRECISION);
2894 reg_sub(FPU_st0_ptr, &tmp, FPU_st0_ptr, FULL_PRECISION);
2895
2896 setcc(SW_C2);
2897 }
2898 control_word = old_cw;
2899
2900 if (FPU_st0_ptr->exp <= EXP_UNDER)
2901 arith_underflow(FPU_st0_ptr);
2902 return;
2903 } else
2904 if ((FPU_st0_tag == TW_Empty) | (st1_tag == TW_Empty)) {
2905 stack_underflow();
2906 return;
2907 } else
2908 if (FPU_st0_tag == TW_Zero) {
2909 if (st1_tag == TW_Valid) {
2910
2911#ifdef DENORM_OPERAND
2912 if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand()))
2913 return;
2914#endif /* DENORM_OPERAND */
2915
2916 setcc(0);
2917 return;
2918 } else
2919 if (st1_tag == TW_Zero) {
2920 arith_invalid(FPU_st0_ptr);
2921 return;
2922 }
2923 /* fprem(?,0) always invalid */
2924 else
2925 if (st1_tag == TW_Infinity) {
2926 setcc(0);
2927 return;
2928 }
2929 } else
2930 if (FPU_st0_tag == TW_Valid) {
2931 if (st1_tag == TW_Zero) {
2932 arith_invalid(FPU_st0_ptr); /* fprem(Valid,Zero) is
2933 * invalid */
2934 return;
2935 } else
2936 if (st1_tag != TW_NaN) {
2937#ifdef DENORM_OPERAND
2938 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
2939 return;
2940#endif /* DENORM_OPERAND */
2941
2942 if (st1_tag == TW_Infinity) {
2943 /* fprem(Valid,
2944 * Infinity)
2945 * is o.k. */
2946 setcc(0);
2947 return;
2948 }
2949 }
2950 } else
2951 if (FPU_st0_tag == TW_Infinity) {
2952 if (st1_tag != TW_NaN) {
2953 arith_invalid(FPU_st0_ptr); /* fprem(Infinity,?) is
2954 * invalid */
2955 return;
2956 }
2957 }
2958 /* One of the registers must contain a NaN is we got here. */
2959
2960#ifdef PARANOID
2961 if ((FPU_st0_tag != TW_NaN) && (st1_tag != TW_NaN))
2962 EXCEPTION(EX_INTERNAL | 0x118);
2963#endif /* PARANOID */
2964
2965 real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr);
2966
2967}
2968
2969
2970/* ST(1) <- ST(1) * log ST; pop ST */
2971static void
2972fyl2x(void)
2973{
2974 FPU_REG *st1_ptr = &st(1);
2975 char st1_tag = st1_ptr->tag;
2976
2977 if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) {
2978 if (FPU_st0_ptr->sign == SIGN_POS) {
2979 int saved_control, saved_status;
2980
2981#ifdef DENORM_OPERAND
2982 if (((FPU_st0_ptr->exp <= EXP_UNDER) ||
2983 (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()))
2984 return;
2985#endif /* DENORM_OPERAND */
2986
2987 /* We use the general purpose arithmetic, so we need
2988 * to save these. */
2989 saved_status = status_word;
2990 saved_control = control_word;
2991 control_word = FULL_PRECISION;
2992
2993 poly_l2(FPU_st0_ptr, FPU_st0_ptr);
2994
2995 /* Enough of the basic arithmetic is done now */
2996 control_word = saved_control;
2997 status_word = saved_status;
2998
2999 /* Let the multiply set the flags */
3000 reg_mul(FPU_st0_ptr, st1_ptr, st1_ptr, FULL_PRECISION);
3001
3002 pop();
3003 FPU_st0_ptr = &st(0);
3004 } else {
3005 /* negative */
3006 pop();
3007 FPU_st0_ptr = &st(0);
3008 arith_invalid(FPU_st0_ptr); /* st(0) cannot be
3009 * negative */
3010 return;
3011 }
3012 } else
3013 if ((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty)) {
3014 stack_underflow_pop(1);
3015 return;
3016 } else
3017 if ((FPU_st0_tag == TW_NaN) || (st1_tag == TW_NaN)) {
3018 real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr);
3019 pop();
3020 return;
3021 } else
3022 if ((FPU_st0_tag <= TW_Zero) && (st1_tag <= TW_Zero)) {
3023 /* one of the args is zero, the other
3024 * valid, or both zero */
3025 if (FPU_st0_tag == TW_Zero) {
3026 pop();
3027 FPU_st0_ptr = &st(0);
3028 if (FPU_st0_ptr->tag == TW_Zero)
3029 arith_invalid(FPU_st0_ptr); /* Both args zero is
3030 * invalid */
3031#ifdef PECULIAR_486
3032 /* This case is not
3033 * specifically covered in the
3034 * manual, but divide-by-zero
3035 * would seem to be the best
3036 * response. However, a real
3037 * 80486 does it this way... */
3038 else
3039 if (FPU_st0_ptr->tag == TW_Infinity) {
3040 reg_move(&CONST_INF, FPU_st0_ptr);
3041 return;
3042 }
3043#endif /* PECULIAR_486 */
3044 else
3045 divide_by_zero(st1_ptr->sign ^ SIGN_NEG ^ SIGN_POS, FPU_st0_ptr);
3046 return;
3047 } else {
3048 /* st(1) contains zero, st(0)
3049 * valid <> 0 */
3050 /* Zero is the valid answer */
3051 char sign = st1_ptr->sign;
3052
3053#ifdef DENORM_OPERAND
3054 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3055 return;
3056#endif /* DENORM_OPERAND */
3057 if (FPU_st0_ptr->sign == SIGN_NEG) {
3058 pop();
3059 FPU_st0_ptr = &st(0);
3060 arith_invalid(FPU_st0_ptr); /* log(negative) */
3061 return;
3062 }
3063 if (FPU_st0_ptr->exp < EXP_BIAS)
3064 sign ^= SIGN_NEG ^ SIGN_POS;
3065 pop();
3066 FPU_st0_ptr = &st(0);
3067 reg_move(&CONST_Z, FPU_st0_ptr);
3068 FPU_st0_ptr->sign = sign;
3069 return;
3070 }
3071 }
3072 /* One or both arg must be an infinity */
3073 else
3074 if (FPU_st0_tag == TW_Infinity) {
3075 if ((FPU_st0_ptr->sign == SIGN_NEG) || (st1_tag == TW_Zero)) {
3076 pop();
3077 FPU_st0_ptr = &st(0);
3078 arith_invalid(FPU_st0_ptr); /* log(-infinity) or
3079 * 0*log(infinity) */
3080 return;
3081 } else {
3082 char sign = st1_ptr->sign;
3083
3084#ifdef DENORM_OPERAND
3085 if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3086 return;
3087#endif /* DENORM_OPERAND */
3088
3089 pop();
3090 FPU_st0_ptr = &st(0);
3091 reg_move(&CONST_INF, FPU_st0_ptr);
3092 FPU_st0_ptr->sign = sign;
3093 return;
3094 }
3095 }
3096 /* st(1) must be infinity here */
3097 else
3098 if ((FPU_st0_tag == TW_Valid) && (FPU_st0_ptr->sign == SIGN_POS)) {
3099 if (FPU_st0_ptr->exp >= EXP_BIAS) {
3100 if ((FPU_st0_ptr->exp == EXP_BIAS) &&
3101 (FPU_st0_ptr->sigh == 0x80000000) &&
3102 (FPU_st0_ptr->sigl == 0)) {
3103 /* st(0
3104 * )
3105 * hold
3106 * s
3107 * 1.0 */
3108 pop();
3109 FPU_st0_ptr = &st(0);
3110 arith_invalid(FPU_st0_ptr); /* infinity*log(1) */
3111 return;
3112 }
3113 /* st(0) is
3114 * positive
3115 * and > 1.0 */
3116 pop();
3117 } else {
3118 /* st(0) is
3119 * positive
3120 * and < 1.0 */
3121
3122#ifdef DENORM_OPERAND
3123 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3124 return;
3125#endif /* DENORM_OPERAND */
3126
3127 st1_ptr->sign ^= SIGN_NEG;
3128 pop();
3129 }
3130 return;
3131 } else {
3132 /* st(0) must be zero
3133 * or negative */
3134 if (FPU_st0_ptr->tag == TW_Zero) {
3135 pop();
3136 FPU_st0_ptr = st1_ptr;
3137 st1_ptr->sign ^= SIGN_NEG ^ SIGN_POS;
3138 /* This should
3139 * be invalid,
3140 * but a real
3141 * 80486 is
3142 * happy with
3143 * it. */
3144#ifndef PECULIAR_486
3145 divide_by_zero(st1_ptr->sign, FPU_st0_ptr);
3146#endif /* PECULIAR_486 */
3147 } else {
3148 pop();
3149 FPU_st0_ptr = st1_ptr;
3150 arith_invalid(FPU_st0_ptr); /* log(negative) */
3151 }
3152 return;
3153 }
3154}
3155
3156
3157static void
3158fpatan(void)
3159{
3160 FPU_REG *st1_ptr = &st(1);
3161 char st1_tag = st1_ptr->tag;
3162
3163 if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) {
3164 int saved_control, saved_status;
3165 FPU_REG sum;
3166 int quadrant = st1_ptr->sign | ((FPU_st0_ptr->sign) << 1);
3167
3168#ifdef DENORM_OPERAND
3169 if (((FPU_st0_ptr->exp <= EXP_UNDER) ||
3170 (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()))
3171 return;
3172#endif /* DENORM_OPERAND */
3173
3174 /* We use the general purpose arithmetic so we need to save
3175 * these. */
3176 saved_status = status_word;
3177 saved_control = control_word;
3178 control_word = FULL_PRECISION;
3179
3180 st1_ptr->sign = FPU_st0_ptr->sign = SIGN_POS;
3181 if (compare(st1_ptr) == COMP_A_lt_B) {
3182 quadrant |= 4;
3183 reg_div(FPU_st0_ptr, st1_ptr, &sum, FULL_PRECISION);
3184 } else
3185 reg_div(st1_ptr, FPU_st0_ptr, &sum, FULL_PRECISION);
3186
3187 poly_atan(&sum);
3188
3189 if (quadrant & 4) {
3190 reg_sub(&CONST_PI2, &sum, &sum, FULL_PRECISION);
3191 }
3192 if (quadrant & 2) {
3193 reg_sub(&CONST_PI, &sum, &sum, FULL_PRECISION);
3194 }
3195 if (quadrant & 1)
3196 sum.sign ^= SIGN_POS ^ SIGN_NEG;
3197
3198 /* All of the basic arithmetic is done now */
3199 control_word = saved_control;
3200 status_word = saved_status;
3201
3202 reg_move(&sum, st1_ptr);
3203 } else
3204 if ((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty)) {
3205 stack_underflow_pop(1);
3206 return;
3207 } else
3208 if ((FPU_st0_tag == TW_NaN) || (st1_tag == TW_NaN)) {
3209 real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr);
3210 pop();
3211 return;
3212 } else
3213 if ((FPU_st0_tag == TW_Infinity) || (st1_tag == TW_Infinity)) {
3214 char sign = st1_ptr->sign;
3215 if (FPU_st0_tag == TW_Infinity) {
3216 if (st1_tag == TW_Infinity) {
3217 if (FPU_st0_ptr->sign == SIGN_POS) {
3218 reg_move(&CONST_PI4, st1_ptr);
3219 } else
3220 reg_add(&CONST_PI4, &CONST_PI2, st1_ptr, FULL_PRECISION);
3221 } else {
3222
3223#ifdef DENORM_OPERAND
3224 if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3225 return;
3226#endif /* DENORM_OPERAND */
3227
3228 if (FPU_st0_ptr->sign == SIGN_POS) {
3229 reg_move(&CONST_Z, st1_ptr);
3230 pop();
3231 return;
3232 } else
3233 reg_move(&CONST_PI, st1_ptr);
3234 }
3235 } else {
3236 /* st(1) is infinity, st(0)
3237 * not infinity */
3238#ifdef DENORM_OPERAND
3239 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3240 return;
3241#endif /* DENORM_OPERAND */
3242
3243 reg_move(&CONST_PI2, st1_ptr);
3244 }
3245 st1_ptr->sign = sign;
3246 } else
3247 if (st1_tag == TW_Zero) {
3248 /* st(0) must be valid or zero */
3249 char sign = st1_ptr->sign;
3250
3251#ifdef DENORM_OPERAND
3252 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3253 return;
3254#endif /* DENORM_OPERAND */
3255
3256 if (FPU_st0_ptr->sign == SIGN_POS) {
3257 reg_move(&CONST_Z, st1_ptr);
3258 pop();
3259 return;
3260 } else
3261 reg_move(&CONST_PI, st1_ptr);
3262 st1_ptr->sign = sign;
3263 } else
3264 if (FPU_st0_tag == TW_Zero) {
3265 /* st(1) must be
3266 * TW_Valid here */
3267 char sign = st1_ptr->sign;
3268
3269#ifdef DENORM_OPERAND
3270 if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3271 return;
3272#endif /* DENORM_OPERAND */
3273
3274 reg_move(&CONST_PI2, st1_ptr);
3275 st1_ptr->sign = sign;
3276 }
3277#ifdef PARANOID
3278 else
3279 EXCEPTION(EX_INTERNAL | 0x220);
3280#endif /* PARANOID */
3281
3282 pop();
3283 set_precision_flag_up();/* We do not really know if up or down */
3284}
3285
3286
3287static void
3288fprem(void)
3289{
3290 fprem_kernel(RC_CHOP);
3291}
3292
3293
3294static void
3295fprem1(void)
3296{
3297 fprem_kernel(RC_RND);
3298}
3299
3300
3301static void
3302fyl2xp1(void)
3303{
3304 FPU_REG *st1_ptr = &st(1);
3305 char st1_tag = st1_ptr->tag;
3306
3307 if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) {
3308 int saved_control, saved_status;
3309
3310#ifdef DENORM_OPERAND
3311 if (((FPU_st0_ptr->exp <= EXP_UNDER) ||
3312 (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()))
3313 return;
3314#endif /* DENORM_OPERAND */
3315
3316 /* We use the general purpose arithmetic so we need to save
3317 * these. */
3318 saved_status = status_word;
3319 saved_control = control_word;
3320 control_word = FULL_PRECISION;
3321
3322 if (poly_l2p1(FPU_st0_ptr, FPU_st0_ptr)) {
3323 arith_invalid(st1_ptr); /* poly_l2p1() returned
3324 * invalid */
3325 pop();
3326 return;
3327 }
3328 /* Enough of the basic arithmetic is done now */
3329 control_word = saved_control;
3330 status_word = saved_status;
3331
3332 /* Let the multiply set the flags */
3333 reg_mul(FPU_st0_ptr, st1_ptr, st1_ptr, FULL_PRECISION);
3334
3335 pop();
3336 } else
3337 if ((FPU_st0_tag == TW_Empty) | (st1_tag == TW_Empty)) {
3338 stack_underflow_pop(1);
3339 return;
3340 } else
3341 if (FPU_st0_tag == TW_Zero) {
3342 if (st1_tag <= TW_Zero) {
3343
3344#ifdef DENORM_OPERAND
3345 if ((st1_tag == TW_Valid) && (st1_ptr->exp <= EXP_UNDER) &&
3346 (denormal_operand()))
3347 return;
3348#endif /* DENORM_OPERAND */
3349
3350 st1_ptr->sign ^= FPU_st0_ptr->sign;
3351 reg_move(FPU_st0_ptr, st1_ptr);
3352 } else
3353 if (st1_tag == TW_Infinity) {
3354 arith_invalid(st1_ptr); /* Infinity*log(1) */
3355 pop();
3356 return;
3357 } else
3358 if (st1_tag == TW_NaN) {
3359 real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr);
3360 pop();
3361 return;
3362 }
3363#ifdef PARANOID
3364 else {
3365 EXCEPTION(EX_INTERNAL | 0x116);
3366 return;
3367 }
3368#endif /* PARANOID */
3369 pop();
3370 return;
3371 } else
3372 if (FPU_st0_tag == TW_Valid) {
3373 if (st1_tag == TW_Zero) {
3374 if (FPU_st0_ptr->sign == SIGN_NEG) {
3375 if (FPU_st0_ptr->exp >= EXP_BIAS) {
3376 /* st(0) holds
3377 * <= -1.0 */
3378 arith_invalid(st1_ptr); /* infinity*log(1) */
3379 pop();
3380 return;
3381 }
3382#ifdef DENORM_OPERAND
3383 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3384 return;
3385#endif /* DENORM_OPERAND */
3386 st1_ptr->sign ^= SIGN_POS ^ SIGN_NEG;
3387 pop();
3388 return;
3389 }
3390#ifdef DENORM_OPERAND
3391 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3392 return;
3393#endif /* DENORM_OPERAND */
3394 pop();
3395 return;
3396 }
3397 if (st1_tag == TW_Infinity) {
3398 if (FPU_st0_ptr->sign == SIGN_NEG) {
3399 if ((FPU_st0_ptr->exp >= EXP_BIAS) &&
3400 !((FPU_st0_ptr->sigh == 0x80000000) &&
3401 (FPU_st0_ptr->sigl == 0))) {
3402 /* st(0) holds
3403 * < -1.0 */
3404 arith_invalid(st1_ptr);
3405 pop();
3406 return;
3407 }
3408#ifdef DENORM_OPERAND
3409 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3410 return;
3411#endif /* DENORM_OPERAND */
3412 st1_ptr->sign ^= SIGN_POS ^ SIGN_NEG;
3413 pop();
3414 return;
3415 }
3416#ifdef DENORM_OPERAND
3417 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3418 return;
3419#endif /* DENORM_OPERAND */
3420 pop();
3421 return;
3422 }
3423 if (st1_tag == TW_NaN) {
3424 real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr);
3425 pop();
3426 return;
3427 }
3428 } else
3429 if (FPU_st0_tag == TW_NaN) {
3430 real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr);
3431 pop();
3432 return;
3433 } else
3434 if (FPU_st0_tag == TW_Infinity) {
3435 if (st1_tag == TW_NaN) {
3436 real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr);
3437 pop();
3438 return;
3439 } else
3440 if ((FPU_st0_ptr->sign == SIGN_NEG) ||
3441 (st1_tag == TW_Zero)) {
3442 arith_invalid(st1_ptr); /* log(infinity) */
3443 pop();
3444 return;
3445 }
3446 /* st(1) must be valid
3447 * here. */
3448
3449#ifdef DENORM_OPERAND
3450 if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3451 return;
3452#endif /* DENORM_OPERAND */
3453
3454 /* The Manual says
3455 * that log(Infinity)
3456 * is invalid, but a
3457 * real 80486 sensibly
3458 * says that it is
3459 * o.k. */
3460 {
3461 char sign = st1_ptr->sign;
3462 reg_move(&CONST_INF, st1_ptr);
3463 st1_ptr->sign = sign;
3464 }
3465 pop();
3466 return;
3467 }
3468#ifdef PARANOID
3469 else {
3470 EXCEPTION(EX_INTERNAL | 0x117);
3471 }
3472#endif /* PARANOID */
3473}
3474
3475
3476static void
3477fscale(void)
3478{
3479 FPU_REG *st1_ptr = &st(1);
3480 char st1_tag = st1_ptr->tag;
3481 int old_cw = control_word;
3482
3483 if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) {
3484 long scale;
3485 FPU_REG tmp;
3486
3487#ifdef DENORM_OPERAND
3488 if (((FPU_st0_ptr->exp <= EXP_UNDER) ||
3489 (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()))
3490 return;
3491#endif /* DENORM_OPERAND */
3492
3493 if (st1_ptr->exp > EXP_BIAS + 30) {
3494 /* 2^31 is far too large, would require 2^(2^30) or
3495 * 2^(-2^30) */
3496 char sign;
3497
3498 if (st1_ptr->sign == SIGN_POS) {
3499 EXCEPTION(EX_Overflow);
3500 sign = FPU_st0_ptr->sign;
3501 reg_move(&CONST_INF, FPU_st0_ptr);
3502 FPU_st0_ptr->sign = sign;
3503 } else {
3504 EXCEPTION(EX_Underflow);
3505 sign = FPU_st0_ptr->sign;
3506 reg_move(&CONST_Z, FPU_st0_ptr);
3507 FPU_st0_ptr->sign = sign;
3508 }
3509 return;
3510 }
3511 control_word &= ~CW_RC;
3512 control_word |= RC_CHOP;
3513 reg_move(st1_ptr, &tmp);
3514 round_to_int(&tmp); /* This can never overflow here */
3515 control_word = old_cw;
3516 scale = st1_ptr->sign ? -tmp.sigl : tmp.sigl;
3517 scale += FPU_st0_ptr->exp;
3518 FPU_st0_ptr->exp = scale;
3519
3520 /* Use round_reg() to properly detect under/overflow etc */
3521 round_reg(FPU_st0_ptr, 0, control_word);
3522
3523 return;
3524 } else
3525 if (FPU_st0_tag == TW_Valid) {
3526 if (st1_tag == TW_Zero) {
3527
3528#ifdef DENORM_OPERAND
3529 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3530 return;
3531#endif /* DENORM_OPERAND */
3532
3533 return;
3534 }
3535 if (st1_tag == TW_Infinity) {
3536 char sign = st1_ptr->sign;
3537
3538#ifdef DENORM_OPERAND
3539 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3540 return;
3541#endif /* DENORM_OPERAND */
3542
3543 if (sign == SIGN_POS) {
3544 reg_move(&CONST_INF, FPU_st0_ptr);
3545 } else
3546 reg_move(&CONST_Z, FPU_st0_ptr);
3547 FPU_st0_ptr->sign = sign;
3548 return;
3549 }
3550 if (st1_tag == TW_NaN) {
3551 real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr);
3552 return;
3553 }
3554 } else
3555 if (FPU_st0_tag == TW_Zero) {
3556 if (st1_tag == TW_Valid) {
3557
3558#ifdef DENORM_OPERAND
3559 if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3560 return;
3561#endif /* DENORM_OPERAND */
3562
3563 return;
3564 } else
3565 if (st1_tag == TW_Zero) {
3566 return;
3567 } else
3568 if (st1_tag == TW_Infinity) {
3569 if (st1_ptr->sign == SIGN_NEG)
3570 return;
3571 else {
3572 arith_invalid(FPU_st0_ptr); /* Zero scaled by
3573 * +Infinity */
3574 return;
3575 }
3576 } else
3577 if (st1_tag == TW_NaN) {
3578 real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr);
3579 return;
3580 }
3581 } else
3582 if (FPU_st0_tag == TW_Infinity) {
3583 if (st1_tag == TW_Valid) {
3584
3585#ifdef DENORM_OPERAND
3586 if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand()))
3587 return;
3588#endif /* DENORM_OPERAND */
3589
3590 return;
3591 }
3592 if (((st1_tag == TW_Infinity) && (st1_ptr->sign == SIGN_POS))
3593 || (st1_tag == TW_Zero))
3594 return;
3595 else
3596 if (st1_tag == TW_Infinity) {
3597 arith_invalid(FPU_st0_ptr); /* Infinity scaled by
3598 * -Infinity */
3599 return;
3600 } else
3601 if (st1_tag == TW_NaN) {
3602 real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr);
3603 return;
3604 }
3605 } else
3606 if (FPU_st0_tag == TW_NaN) {
3607 if (st1_tag != TW_Empty) {
3608 real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr);
3609 return;
3610 }
3611 }
3612#ifdef PARANOID
3613 if (!((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty))) {
3614 EXCEPTION(EX_INTERNAL | 0x115);
3615 return;
3616 }
3617#endif
3618
3619 /* At least one of st(0), st(1) must be empty */
3620 stack_underflow();
3621
3622}
3623
3624
3625/*---------------------------------------------------------------------------*/
3626
3627static FUNC trig_table_a[] = {
3628 f2xm1, fyl2x, fptan, fpatan, fxtract, fprem1, fdecstp, fincstp
3629};
3630
3631void
3632trig_a(void)
3633{
3634 (trig_table_a[FPU_rm]) ();
3635}
3636
3637
3638static FUNC trig_table_b[] =
3639{
3640 fprem, fyl2xp1, fsqrt_, fsincos, frndint_, fscale, fsin, fcos
3641};
3642
3643void
3644trig_b(void)
3645{
3646 (trig_table_b[FPU_rm]) ();
3647}
3648\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/get_address.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 13050 5462320160 13213\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
3649 * get_address.c
3650 *
3651 * Get the effective address from an FPU instruction.
3652 *
3653 *
3654 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
3655 * Vic 3163, Australia.
3656 * E-mail apm233m@vaxc.cc.monash.edu.au
3657 * All rights reserved.
3658 *
3659 * This copyright notice covers the redistribution and use of the
3660 * FPU emulator developed by W. Metzenthen. It covers only its use
3661 * in the 386BSD operating system. Any other use is not permitted
3662 * under this copyright.
3663 *
3664 * Redistribution and use in source and binary forms, with or without
3665 * modification, are permitted provided that the following conditions
3666 * are met:
3667 * 1. Redistributions of source code must retain the above copyright
3668 * notice, this list of conditions and the following disclaimer.
3669 * 2. Redistributions in binary form must include information specifying
3670 * that source code for the emulator is freely available and include
3671 * either:
3672 * a) an offer to provide the source code for a nominal distribution
3673 * fee, or
3674 * b) list at least two alternative methods whereby the source
3675 * can be obtained, e.g. a publically accessible bulletin board
3676 * and an anonymous ftp site from which the software can be
3677 * downloaded.
3678 * 3. All advertising materials specifically mentioning features or use of
3679 * this emulator must acknowledge that it was developed by W. Metzenthen.
3680 * 4. The name of W. Metzenthen may not be used to endorse or promote
3681 * products derived from this software without specific prior written
3682 * permission.
3683 *
3684 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
3685 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
3686 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
3687 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
3688 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3689 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3690 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3691 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3692 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3693 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3694 *
3695 */
3696
3697/*---------------------------------------------------------------------------+
3698 | Note: |
3699 | The file contains code which accesses user memory. |
3700 | Emulator static data may change when user memory is accessed, due to |
3701 | other processes using the emulator while swapping is in progress. |
3702 +---------------------------------------------------------------------------*/
3703
3704#include "param.h"
3705#include "proc.h"
3706#include "systm.h"
3707#include "machine/cpu.h"
3708#include "machine/pcb.h"
3709#include "machine/reg.h"
3710
3711#include "fpu_emu.h"
3712#include "fpu_system.h"
3713#include "exception.h"
3714
3715static int reg_offset[] = {
3716tEAX, tECX, tEDX, tEBX, tESP, tEBP, tESI, tEDI};
3717#define REG_(x) (*(((int*)FPU_info) + reg_offset[(x)]))
3718
3719void *FPU_data_address;
3720
3721
3722/* Decode the SIB byte. This function assumes mod != 0 */
3723static void *
3724sib(int mod)
3725{
3726 unsigned char ss, index, base;
3727 long offset;
3728
3729 REENTRANT_CHECK(OFF);
3730 base = fubyte((char *) FPU_EIP); /* The SIB byte */
3731 REENTRANT_CHECK(ON);
3732 FPU_EIP++;
3733 ss = base >> 6;
3734 index = (base >> 3) & 7;
3735 base &= 7;
3736
3737 if ((mod == 0) && (base == 5))
3738 offset = 0; /* No base register */
3739 else
3740 offset = REG_(base);
3741
3742 if (index == 4) {
3743 /* No index register */
3744 /* A non-zero ss is illegal */
3745 if (ss)
3746 EXCEPTION(EX_Invalid);
3747 } else {
3748 offset += (REG_(index)) << ss;
3749 }
3750
3751 if (mod == 1) {
3752 /* 8 bit signed displacement */
3753 REENTRANT_CHECK(OFF);
3754 offset += (signed char) fubyte((char *) FPU_EIP);
3755 REENTRANT_CHECK(ON);
3756 FPU_EIP++;
3757 } else
3758 if (mod == 2 || base == 5) { /* The second condition also
3759 * has mod==0 */
3760 /* 32 bit displacment */
3761 REENTRANT_CHECK(OFF);
3762 offset += (signed) fuword((unsigned long *) FPU_EIP);
3763 REENTRANT_CHECK(ON);
3764 FPU_EIP += 4;
3765 }
3766 return (void *) offset;
3767}
3768
3769
3770/*
3771 MOD R/M byte: MOD == 3 has a special use for the FPU
3772 SIB byte used iff R/M = 100b
3773
3774 7 6 5 4 3 2 1 0
3775 ..... ......... .........
3776 MOD OPCODE(2) R/M
3777
3778
3779 SIB byte
3780
3781 7 6 5 4 3 2 1 0
3782 ..... ......... .........
3783 SS INDEX BASE
3784
3785*/
3786
3787void
3788get_address(unsigned char FPU_modrm)
3789{
3790 unsigned char mod;
3791 long *cpu_reg_ptr;
3792 int offset = 0; /* Initialized just to stop compiler warnings. */
3793
3794 mod = (FPU_modrm >> 6) & 3;
3795
3796 if (FPU_rm == 4 && mod != 3) {
3797 FPU_data_address = sib(mod);
3798 return;
3799 }
3800 cpu_reg_ptr = (long *) &REG_(FPU_rm);
3801 switch (mod) {
3802 case 0:
3803 if (FPU_rm == 5) {
3804 /* Special case: disp32 */
3805 REENTRANT_CHECK(OFF);
3806 offset = fuword((unsigned long *) FPU_EIP);
3807 REENTRANT_CHECK(ON);
3808 FPU_EIP += 4;
3809 FPU_data_address = (void *) offset;
3810 return;
3811 } else {
3812 FPU_data_address = (void *) *cpu_reg_ptr; /* Just return the
3813 * contents of the cpu
3814 * register */
3815 return;
3816 }
3817 case 1:
3818 /* 8 bit signed displacement */
3819 REENTRANT_CHECK(OFF);
3820 offset = (signed char) fubyte((char *) FPU_EIP);
3821 REENTRANT_CHECK(ON);
3822 FPU_EIP++;
3823 break;
3824 case 2:
3825 /* 32 bit displacement */
3826 REENTRANT_CHECK(OFF);
3827 offset = (signed) fuword((unsigned long *) FPU_EIP);
3828 REENTRANT_CHECK(ON);
3829 FPU_EIP += 4;
3830 break;
3831 case 3:
3832 /* Not legal for the FPU */
3833 EXCEPTION(EX_Invalid);
3834 }
3835
3836 FPU_data_address = offset + (char *) *cpu_reg_ptr;
3837}
3838\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/load_store.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 20476 5462501712 13100\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
3839 * load_store.c
3840 *
3841 * This file contains most of the code to interpret the FPU instructions
3842 * which load and store from user memory.
3843 *
3844 *
3845 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
3846 * Vic 3163, Australia.
3847 * E-mail apm233m@vaxc.cc.monash.edu.au
3848 * All rights reserved.
3849 *
3850 * This copyright notice covers the redistribution and use of the
3851 * FPU emulator developed by W. Metzenthen. It covers only its use
3852 * in the 386BSD operating system. Any other use is not permitted
3853 * under this copyright.
3854 *
3855 * Redistribution and use in source and binary forms, with or without
3856 * modification, are permitted provided that the following conditions
3857 * are met:
3858 * 1. Redistributions of source code must retain the above copyright
3859 * notice, this list of conditions and the following disclaimer.
3860 * 2. Redistributions in binary form must include information specifying
3861 * that source code for the emulator is freely available and include
3862 * either:
3863 * a) an offer to provide the source code for a nominal distribution
3864 * fee, or
3865 * b) list at least two alternative methods whereby the source
3866 * can be obtained, e.g. a publically accessible bulletin board
3867 * and an anonymous ftp site from which the software can be
3868 * downloaded.
3869 * 3. All advertising materials specifically mentioning features or use of
3870 * this emulator must acknowledge that it was developed by W. Metzenthen.
3871 * 4. The name of W. Metzenthen may not be used to endorse or promote
3872 * products derived from this software without specific prior written
3873 * permission.
3874 *
3875 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
3876 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
3877 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
3878 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
3879 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3880 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3881 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3882 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3883 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3884 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3885 *
3886 */
3887
3888/*---------------------------------------------------------------------------+
3889 | Note: |
3890 | The file contains code which accesses user memory. |
3891 | Emulator static data may change when user memory is accessed, due to |
3892 | other processes using the emulator while swapping is in progress. |
3893 +---------------------------------------------------------------------------*/
3894
3895#include "param.h"
3896#include "proc.h"
3897#include "systm.h"
3898#include "machine/cpu.h"
3899#include "machine/pcb.h"
3900
3901#include "fpu_emu.h"
3902#include "fpu_system.h"
3903#include "exception.h"
3904#include "status_w.h"
3905
3906
3907#define _NONE_ 0 /* FPU_st0_ptr etc not needed */
3908#define _REG0_ 1 /* Will be storing st(0) */
3909#define _PUSH_ 3 /* Need to check for space to push onto stack */
3910#define _null_ 4 /* Function illegal or not implemented */
3911
3912#define pop_0() { pop_ptr->tag = TW_Empty; top++; }
3913
3914
3915static unsigned char type_table[32] = {
3916 _PUSH_, _PUSH_, _PUSH_, _PUSH_,
3917 _null_, _null_, _null_, _null_,
3918 _REG0_, _REG0_, _REG0_, _REG0_,
3919 _REG0_, _REG0_, _REG0_, _REG0_,
3920 _NONE_, _null_, _NONE_, _PUSH_,
3921 _NONE_, _PUSH_, _null_, _PUSH_,
3922 _NONE_, _null_, _NONE_, _REG0_,
3923 _NONE_, _REG0_, _NONE_, _REG0_
3924};
3925
3926void
3927load_store_instr(char type)
3928{
3929 FPU_REG *pop_ptr; /* We need a version of FPU_st0_ptr which
3930 * won't change. */
3931
3932 pop_ptr = NULL; /* Initialized just to stop compiler warnings. */
3933
3934
3935 switch (type_table[(int) (unsigned) type]) {
3936 case _NONE_:
3937 break;
3938 case _REG0_:
3939 pop_ptr = &st(0); /* Some of these instructions pop
3940 * after storing */
3941
3942 FPU_st0_ptr = pop_ptr; /* Set the global variables. */
3943 FPU_st0_tag = FPU_st0_ptr->tag;
3944 break;
3945 case _PUSH_:
3946 {
3947 pop_ptr = &st(-1);
3948 if (pop_ptr->tag != TW_Empty) {
3949 stack_overflow();
3950 return;
3951 }
3952 top--;
3953 }
3954 break;
3955 case _null_:
3956 return Un_impl();
3957#ifdef PARANOID
3958 default:
3959 return EXCEPTION(EX_INTERNAL);
3960#endif /* PARANOID */
3961 }
3962
3963 switch (type) {
3964 case 000: /* fld m32real */
3965 reg_load_single();
3966 setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */
3967 reg_move(&FPU_loaded_data, pop_ptr);
3968 break;
3969 case 001: /* fild m32int */
3970 reg_load_int32();
3971 setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */
3972 reg_move(&FPU_loaded_data, pop_ptr);
3973 break;
3974 case 002: /* fld m64real */
3975 reg_load_double();
3976 setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */
3977 reg_move(&FPU_loaded_data, pop_ptr);
3978 break;
3979 case 003: /* fild m16int */
3980 reg_load_int16();
3981 setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */
3982 reg_move(&FPU_loaded_data, pop_ptr);
3983 break;
3984 case 010: /* fst m32real */
3985 reg_store_single();
3986 break;
3987 case 011: /* fist m32int */
3988 reg_store_int32();
3989 break;
3990 case 012: /* fst m64real */
3991 reg_store_double();
3992 break;
3993 case 013: /* fist m16int */
3994 reg_store_int16();
3995 break;
3996 case 014: /* fstp m32real */
3997 if (reg_store_single())
3998 pop_0();/* pop only if the number was actually stored
3999 * (see the 80486 manual p16-28) */
4000 break;
4001 case 015: /* fistp m32int */
4002 if (reg_store_int32())
4003 pop_0();/* pop only if the number was actually stored
4004 * (see the 80486 manual p16-28) */
4005 break;
4006 case 016: /* fstp m64real */
4007 if (reg_store_double())
4008 pop_0();/* pop only if the number was actually stored
4009 * (see the 80486 manual p16-28) */
4010 break;
4011 case 017: /* fistp m16int */
4012 if (reg_store_int16())
4013 pop_0();/* pop only if the number was actually stored
4014 * (see the 80486 manual p16-28) */
4015 break;
4016 case 020: /* fldenv m14/28byte */
4017 fldenv();
4018 break;
4019 case 022: /* frstor m94/108byte */
4020 frstor();
4021 break;
4022 case 023: /* fbld m80dec */
4023 reg_load_bcd();
4024 setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */
4025 reg_move(&FPU_loaded_data, pop_ptr);
4026 break;
4027 case 024: /* fldcw */
4028 REENTRANT_CHECK(OFF);
4029 control_word = fuword((unsigned short *) FPU_data_address);
4030 REENTRANT_CHECK(ON);
4031#ifdef NO_UNDERFLOW_TRAP
4032 if (!(control_word & EX_Underflow)) {
4033 control_word |= EX_Underflow;
4034 }
4035#endif
4036 FPU_data_address = (void *) data_operand_offset; /* We want no net effect */
4037 FPU_entry_eip = ip_offset; /* We want no net effect */
4038 break;
4039 case 025: /* fld m80real */
4040 reg_load_extended();
4041 setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */
4042 reg_move(&FPU_loaded_data, pop_ptr);
4043 break;
4044 case 027: /* fild m64int */
4045 reg_load_int64();
4046 setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */
4047 reg_move(&FPU_loaded_data, pop_ptr);
4048 break;
4049 case 030: /* fstenv m14/28byte */
4050 fstenv();
4051 FPU_data_address = (void *) data_operand_offset; /* We want no net effect */
4052 FPU_entry_eip = ip_offset; /* We want no net effect */
4053 break;
4054 case 032: /* fsave */
4055 fsave();
4056 FPU_data_address = (void *) data_operand_offset; /* We want no net effect */
4057 FPU_entry_eip = ip_offset; /* We want no net effect */
4058 break;
4059 case 033: /* fbstp m80dec */
4060 if (reg_store_bcd())
4061 pop_0();/* pop only if the number was actually stored
4062 * (see the 80486 manual p16-28) */
4063 break;
4064 case 034: /* fstcw m16int */
4065 REENTRANT_CHECK(OFF);
4066/* verify_area(VERIFY_WRITE, FPU_data_address, 2);*/
4067 suword( (short *) FPU_data_address,control_word);
4068 REENTRANT_CHECK(ON);
4069 FPU_data_address = (void *) data_operand_offset; /* We want no net effect */
4070 FPU_entry_eip = ip_offset; /* We want no net effect */
4071 break;
4072 case 035: /* fstp m80real */
4073 if (reg_store_extended())
4074 pop_0();/* pop only if the number was actually stored
4075 * (see the 80486 manual p16-28) */
4076 break;
4077 case 036: /* fstsw m2byte */
4078 status_word &= ~SW_Top;
4079 status_word |= (top & 7) << SW_Top_Shift;
4080 REENTRANT_CHECK(OFF);
4081/* verify_area(VERIFY_WRITE, FPU_data_address, 2);*/
4082 suword( (short *) FPU_data_address,status_word);
4083 REENTRANT_CHECK(ON);
4084 FPU_data_address = (void *) data_operand_offset; /* We want no net effect */
4085 FPU_entry_eip = ip_offset; /* We want no net effect */
4086 break;
4087 case 037: /* fistp m64int */
4088 if (reg_store_int64())
4089 pop_0();/* pop only if the number was actually stored
4090 * (see the 80486 manual p16-28) */
4091 break;
4092 }
4093}
4094\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/math_emu.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 1331 5462505406 12522\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#ifndef _MATH_EMU_H
4095#define _MATH_EMU_H
4096
4097struct fpu_reg {
4098 char sign;
4099 char tag;
4100 long exp;
4101 u_long sigl;
4102 u_long sigh;
4103};
4104
4105union i387_union {
4106 struct i387_hard_struct {
4107 long cwd;
4108 long swd;
4109 long twd;
4110 long fip;
4111 long fcs;
4112 long foo;
4113 long fos;
4114 long st_space[20]; /* 8*10 bytes for each FP-reg = 80
4115 * bytes */
4116 } hard;
4117 struct i387_soft_struct {
4118 long cwd;
4119 long swd;
4120 long twd;
4121 long fip;
4122 long fcs;
4123 long foo;
4124 long fos;
4125 long top;
4126 struct fpu_reg regs[8]; /* 8*16 bytes for each FP-reg = 128
4127 * bytes */
4128 unsigned char lookahead;
4129 struct trapframe *frame;
4130 unsigned long entry_eip;
4131 int orig_eip;
4132 } soft;
4133};
4134#endif
4135\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/poly_2xm1.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 10352 5462473734 12603\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
4136 * poly_2xm1.c
4137 *
4138 * Function to compute 2^x-1 by a polynomial approximation.
4139 *
4140 *
4141 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
4142 * Vic 3163, Australia.
4143 * E-mail apm233m@vaxc.cc.monash.edu.au
4144 * All rights reserved.
4145 *
4146 * This copyright notice covers the redistribution and use of the
4147 * FPU emulator developed by W. Metzenthen. It covers only its use
4148 * in the 386BSD operating system. Any other use is not permitted
4149 * under this copyright.
4150 *
4151 * Redistribution and use in source and binary forms, with or without
4152 * modification, are permitted provided that the following conditions
4153 * are met:
4154 * 1. Redistributions of source code must retain the above copyright
4155 * notice, this list of conditions and the following disclaimer.
4156 * 2. Redistributions in binary form must include information specifying
4157 * that source code for the emulator is freely available and include
4158 * either:
4159 * a) an offer to provide the source code for a nominal distribution
4160 * fee, or
4161 * b) list at least two alternative methods whereby the source
4162 * can be obtained, e.g. a publically accessible bulletin board
4163 * and an anonymous ftp site from which the software can be
4164 * downloaded.
4165 * 3. All advertising materials specifically mentioning features or use of
4166 * this emulator must acknowledge that it was developed by W. Metzenthen.
4167 * 4. The name of W. Metzenthen may not be used to endorse or promote
4168 * products derived from this software without specific prior written
4169 * permission.
4170 *
4171 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
4172 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
4173 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
4174 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4175 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
4176 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
4177 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
4178 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4179 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
4180 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4181 *
4182 */
4183
4184#include "exception.h"
4185#include "reg_constant.h"
4186#include "fpu_emu.h"
4187
4188
4189
4190#define HIPOWER 13
4191static unsigned short lterms[HIPOWER][4] =
4192{
4193 {0x79b5, 0xd1cf, 0x17f7, 0xb172},
4194 {0x1b56, 0x058b, 0x7bff, 0x3d7f},
4195 {0x8bb0, 0x8250, 0x846b, 0x0e35},
4196 {0xbc65, 0xf747, 0x556d, 0x0276},
4197 {0x17cb, 0x9e39, 0x61ff, 0x0057},
4198 {0xe018, 0x9776, 0x1848, 0x000a},
4199 {0x66f2, 0xff30, 0xffe5, 0x0000},
4200 {0x682f, 0xffb6, 0x162b, 0x0000},
4201 {0xb7ca, 0x2956, 0x01b5, 0x0000},
4202 {0xcd3e, 0x4817, 0x001e, 0x0000},
4203 {0xb7e2, 0xecbe, 0x0001, 0x0000},
4204 {0x0ed5, 0x1a27, 0x0000, 0x0000},
4205 {0x101d, 0x0222, 0x0000, 0x0000},
4206};
4207
4208
4209/*--- poly_2xm1() -----------------------------------------------------------+
4210 | |
4211 +---------------------------------------------------------------------------*/
4212int
4213poly_2xm1(FPU_REG * arg, FPU_REG * result)
4214{
4215 short exponent;
4216 long long Xll;
4217 FPU_REG accum;
4218
4219
4220 exponent = arg->exp - EXP_BIAS;
4221
4222 if (arg->tag == TW_Zero) {
4223 /* Return 0.0 */
4224 reg_move(&CONST_Z, result);
4225 return 0;
4226 }
4227 if (exponent >= 0) { /* Can't hack a number >= 1.0 */
4228 arith_invalid(result); /* Number too large */
4229 return 1;
4230 }
4231 if (arg->sign != SIGN_POS) { /* Can't hack a number < 0.0 */
4232 arith_invalid(result); /* Number negative */
4233 return 1;
4234 }
4235 if (exponent < -64) {
4236 reg_move(&CONST_LN2, result);
4237 return 0;
4238 }
4239 *(unsigned *) &Xll = arg->sigl;
4240 *(((unsigned *) &Xll) + 1) = arg->sigh;
4241 if (exponent < -1) {
4242 /* shift the argument right by the required places */
4243 if (shrx(&Xll, -1 - exponent) >= (unsigned)0x80000000)
4244 Xll++; /* round up */
4245 }
4246 *(short *) &(accum.sign) = 0; /* will be a valid positive nr with
4247 * expon = 0 */
4248 accum.exp = 0;
4249
4250 /* Do the basic fixed point polynomial evaluation */
4251 polynomial((unsigned *) &accum.sigl, (unsigned *) &Xll, lterms, HIPOWER - 1);
4252
4253 /* Convert to 64 bit signed-compatible */
4254 accum.exp += EXP_BIAS - 1;
4255
4256 reg_move(&accum, result);
4257
4258 normalize(result);
4259
4260 return 0;
4261
4262}
4263\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/Changelog\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 2477 5462534134 12400\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0This file contains the changes made to W. Metzenthem's 387 FPU
4264emulator to make it work under NetBSD.
4265
4266a, Changes to make it compile:
4267
4268 1 - Changed the #include's to get the appropriate .h files.
4269 2 - Renamed .S to .s, to satisfy the kernel Makefile.
4270 3 - Changed the C++ style // comments to /* */
4271 4 - Changed the FPU_ORIG_EIP macro. A letter from bde included
4272 in the package suggested using tf_isp for using instead
4273 of the linux __orig_eip. This later turned out to interfere
4274 with the user stack, so i created a separate variable, stored
4275 in the i387_union.
4276 5 - Changed the get_fs_.. put_fs_.. fns to fubyte,fuword,subyte,
4277 suword.
4278 6 - Removed the verify_area fns. I don't really know what they do,
4279 i suppose they verify access to memory. The sufu routines
4280 should do this.
4281
4282b, Changes to make it work:
4283
4284 1 - Made math_emulate() to return 0 when successful, so trap() won't
4285 try to generate a signal.
4286 2 - Changed the size of the save87 struct in /sys/arch/i387/include/
4287 npx.h to accomodate the i387_union.
4288
4289d, Other changes:
4290
4291 1 - Removed obsolate and/or linux specific stuff.
4292 2 - Changed the RE_ENTRANT_CHECK_[ON|OFF] macro to
4293 REENTRANT_CHECK([ON|OFF]) so indent can grok it.
4294 3 - Re-indented to Berkeley style.
4295 4 - Limited max no of lookaheads. LOOKAHEAD_LIMIT in fpu_entry.c
4296
4297
4298 Szabolcs Szigeti (pink@fsz.bme.hu)
4299\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/poly_atan.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 16553 5462473734 12750\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
4300 * p_atan.c
4301 *
4302 * Compute the tan of a FPU_REG, using a polynomial approximation.
4303 *
4304 *
4305 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
4306 * Vic 3163, Australia.
4307 * E-mail apm233m@vaxc.cc.monash.edu.au
4308 * All rights reserved.
4309 *
4310 * This copyright notice covers the redistribution and use of the
4311 * FPU emulator developed by W. Metzenthen. It covers only its use
4312 * in the 386BSD operating system. Any other use is not permitted
4313 * under this copyright.
4314 *
4315 * Redistribution and use in source and binary forms, with or without
4316 * modification, are permitted provided that the following conditions
4317 * are met:
4318 * 1. Redistributions of source code must retain the above copyright
4319 * notice, this list of conditions and the following disclaimer.
4320 * 2. Redistributions in binary form must include information specifying
4321 * that source code for the emulator is freely available and include
4322 * either:
4323 * a) an offer to provide the source code for a nominal distribution
4324 * fee, or
4325 * b) list at least two alternative methods whereby the source
4326 * can be obtained, e.g. a publically accessible bulletin board
4327 * and an anonymous ftp site from which the software can be
4328 * downloaded.
4329 * 3. All advertising materials specifically mentioning features or use of
4330 * this emulator must acknowledge that it was developed by W. Metzenthen.
4331 * 4. The name of W. Metzenthen may not be used to endorse or promote
4332 * products derived from this software without specific prior written
4333 * permission.
4334 *
4335 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
4336 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
4337 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
4338 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4339 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
4340 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
4341 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
4342 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4343 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
4344 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4345 *
4346 */
4347
4348#include "exception.h"
4349#include "reg_constant.h"
4350#include "fpu_emu.h"
4351#include "control_w.h"
4352
4353
4354#define HIPOWERon 6 /* odd poly, negative terms */
4355static unsigned oddnegterms[HIPOWERon][2] =
4356{
4357 {0x00000000, 0x00000000}, /* for + 1.0 */
4358 {0x763b6f3d, 0x1adc4428},
4359 {0x20f0630b, 0x0502909d},
4360 {0x4e825578, 0x0198ce38},
4361 {0x22b7cb87, 0x008da6e3},
4362 {0x9b30ca03, 0x00239c79}
4363};
4364#define HIPOWERop 6 /* odd poly, positive terms */
4365static unsigned oddplterms[HIPOWERop][2] =
4366{
4367 {0xa6f67cb8, 0x94d910bd},
4368 {0xa02ffab4, 0x0a43cb45},
4369 {0x04265e6b, 0x02bf5655},
4370 {0x0a728914, 0x00f280f7},
4371 {0x6d640e01, 0x004d6556},
4372 {0xf1dd2dbf, 0x000a530a}
4373};
4374
4375
4376static unsigned denomterm[2] =
4377{0xfc4bd208, 0xea2e6612};
4378
4379
4380
4381/*--- poly_atan() -----------------------------------------------------------+
4382 | |
4383 +---------------------------------------------------------------------------*/
4384void
4385poly_atan(FPU_REG * arg)
4386{
4387 char recursions = 0;
4388 short exponent;
4389 FPU_REG odd_poly, even_poly, pos_poly, neg_poly;
4390 FPU_REG argSq;
4391 long long arg_signif, argSqSq;
4392
4393
4394#ifdef PARANOID
4395 if (arg->sign != 0) { /* Can't hack a number < 0.0 */
4396 arith_invalid(arg);
4397 return;
4398 } /* Need a positive number */
4399#endif /* PARANOID */
4400
4401 exponent = arg->exp - EXP_BIAS;
4402
4403 if (arg->tag == TW_Zero) {
4404 /* Return 0.0 */
4405 reg_move(&CONST_Z, arg);
4406 return;
4407 }
4408 if (exponent >= -2) {
4409 /* argument is in the range [0.25 .. 1.0] */
4410 if (exponent >= 0) {
4411#ifdef PARANOID
4412 if ((exponent == 0) &&
4413 (arg->sigl == 0) && (arg->sigh == 0x80000000))
4414#endif /* PARANOID */
4415 {
4416 reg_move(&CONST_PI4, arg);
4417 return;
4418 }
4419#ifdef PARANOID
4420 EXCEPTION(EX_INTERNAL | 0x104); /* There must be a logic
4421 * error */
4422#endif /* PARANOID */
4423 }
4424 /* If the argument is greater than sqrt(2)-1 (=0.414213562...) */
4425 /* convert the argument by an identity for atan */
4426 if ((exponent >= -1) || (arg->sigh > 0xd413ccd0)) {
4427 FPU_REG numerator, denom;
4428
4429 recursions++;
4430
4431 arg_signif = *(long long *) &(arg->sigl);
4432 if (exponent < -1) {
4433 if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000)
4434 arg_signif++; /* round up */
4435 }
4436 *(long long *) &(numerator.sigl) = -arg_signif;
4437 numerator.exp = EXP_BIAS - 1;
4438 normalize(&numerator); /* 1 - arg */
4439
4440 arg_signif = *(long long *) &(arg->sigl);
4441 if (shrx(&arg_signif, -exponent) >= (unsigned)0x80000000)
4442 arg_signif++; /* round up */
4443 *(long long *) &(denom.sigl) = arg_signif;
4444 denom.sigh |= 0x80000000; /* 1 + arg */
4445
4446 arg->exp = numerator.exp;
4447 reg_u_div(&numerator, &denom, arg, FULL_PRECISION);
4448
4449 exponent = arg->exp - EXP_BIAS;
4450 }
4451 }
4452 *(long long *) &arg_signif = *(long long *) &(arg->sigl);
4453
4454#ifdef PARANOID
4455 /* This must always be true */
4456 if (exponent >= -1) {
4457 EXCEPTION(EX_INTERNAL | 0x120); /* There must be a logic error */
4458 }
4459#endif /* PARANOID */
4460
4461 /* shift the argument right by the required places */
4462 if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000)
4463 arg_signif++; /* round up */
4464
4465 /* Now have arg_signif with binary point at the left .1xxxxxxxx */
4466 mul64(&arg_signif, &arg_signif, (long long *) (&argSq.sigl));
4467 mul64((long long *) (&argSq.sigl), (long long *) (&argSq.sigl), &argSqSq);
4468
4469 /* will be a valid positive nr with expon = 0 */
4470 *(short *) &(pos_poly.sign) = 0;
4471 pos_poly.exp = EXP_BIAS;
4472
4473 /* Do the basic fixed point polynomial evaluation */
4474 polynomial(&pos_poly.sigl, (unsigned *) &argSqSq,
4475 (unsigned short (*)[4]) oddplterms, HIPOWERop - 1);
4476 mul64((long long *) (&argSq.sigl), (long long *) (&pos_poly.sigl),
4477 (long long *) (&pos_poly.sigl));
4478
4479 /* will be a valid positive nr with expon = 0 */
4480 *(short *) &(neg_poly.sign) = 0;
4481 neg_poly.exp = EXP_BIAS;
4482
4483 /* Do the basic fixed point polynomial evaluation */
4484 polynomial(&neg_poly.sigl, (unsigned *) &argSqSq,
4485 (unsigned short (*)[4]) oddnegterms, HIPOWERon - 1);
4486
4487 /* Subtract the mantissas */
4488 *((long long *) (&pos_poly.sigl)) -= *((long long *) (&neg_poly.sigl));
4489
4490 reg_move(&pos_poly, &odd_poly);
4491 poly_add_1(&odd_poly);
4492
4493 /* The complete odd polynomial */
4494 reg_u_mul(&odd_poly, arg, &odd_poly, FULL_PRECISION);
4495
4496 /* will be a valid positive nr with expon = 0 */
4497 *(short *) &(even_poly.sign) = 0;
4498
4499 mul64((long long *) (&argSq.sigl),
4500 (long long *) (&denomterm), (long long *) (&even_poly.sigl));
4501
4502 poly_add_1(&even_poly);
4503
4504 reg_div(&odd_poly, &even_poly, arg, FULL_PRECISION);
4505
4506 if (recursions)
4507 reg_sub(&CONST_PI4, arg, arg, FULL_PRECISION);
4508}
4509
4510
4511/* The argument to this function must be polynomial() compatible,
4512 i.e. have an exponent (not checked) of EXP_BIAS-1 but need not
4513 be normalized.
4514 This function adds 1.0 to the (assumed positive) argument. */
4515void
4516poly_add_1(FPU_REG * src)
4517{
4518/* Rounding in a consistent direction produces better results
4519 for the use of this function in poly_atan. Simple truncation
4520 is used here instead of round-to-nearest. */
4521
4522#ifdef OBSOLETE
4523 char round = (src->sigl & 3) == 3;
4524#endif /* OBSOLETE */
4525
4526 shrx(&src->sigl, 1);
4527
4528#ifdef OBSOLETE
4529 if (round)
4530 (*(long long *) &src->sigl)++; /* Round to even */
4531#endif /* OBSOLETE */
4532
4533 src->sigh |= 0x80000000;
4534
4535 src->exp = EXP_BIAS;
4536
4537}
4538\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/poly_l2.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 24 \0 21727 5462320163 12351\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0staff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
4539 * poly_l2.c
4540 *
4541 * Compute the base 2 log of a FPU_REG, using a polynomial approximation.
4542 *
4543 *
4544 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
4545 * Vic 3163, Australia.
4546 * E-mail apm233m@vaxc.cc.monash.edu.au
4547 * All rights reserved.
4548 *
4549 * This copyright notice covers the redistribution and use of the
4550 * FPU emulator developed by W. Metzenthen. It covers only its use
4551 * in the 386BSD operating system. Any other use is not permitted
4552 * under this copyright.
4553 *
4554 * Redistribution and use in source and binary forms, with or without
4555 * modification, are permitted provided that the following conditions
4556 * are met:
4557 * 1. Redistributions of source code must retain the above copyright
4558 * notice, this list of conditions and the following disclaimer.
4559 * 2. Redistributions in binary form must include information specifying
4560 * that source code for the emulator is freely available and include
4561 * either:
4562 * a) an offer to provide the source code for a nominal distribution
4563 * fee, or
4564 * b) list at least two alternative methods whereby the source
4565 * can be obtained, e.g. a publically accessible bulletin board
4566 * and an anonymous ftp site from which the software can be
4567 * downloaded.
4568 * 3. All advertising materials specifically mentioning features or use of
4569 * this emulator must acknowledge that it was developed by W. Metzenthen.
4570 * 4. The name of W. Metzenthen may not be used to endorse or promote
4571 * products derived from this software without specific prior written
4572 * permission.
4573 *
4574 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
4575 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
4576 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
4577 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4578 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
4579 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
4580 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
4581 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4582 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
4583 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4584 *
4585 */
4586
4587
4588#include "exception.h"
4589#include "reg_constant.h"
4590#include "fpu_emu.h"
4591#include "control_w.h"
4592
4593
4594
4595#define HIPOWER 9
4596static unsigned short lterms[HIPOWER][4] =
4597{
4598 /* Ideal computation with these coeffs gives about 64.6 bit rel
4599 * accuracy. */
4600 {0xe177, 0xb82f, 0x7652, 0x7154},
4601 {0xee0f, 0xe80f, 0x2770, 0x7b1c},
4602 {0x0fc0, 0xbe87, 0xb143, 0x49dd},
4603 {0x78b9, 0xdadd, 0xec54, 0x34c2},
4604 {0x003a, 0x5de9, 0x628b, 0x2909},
4605 {0x5588, 0xed16, 0x4abf, 0x2193},
4606 {0xb461, 0x85f7, 0x347a, 0x1c6a},
4607 {0x0975, 0x87b3, 0xd5bf, 0x1876},
4608 {0xe85c, 0xcec9, 0x84e7, 0x187d}
4609};
4610
4611
4612
4613
4614/*--- poly_l2() -------------------------------------------------------------+
4615 | Base 2 logarithm by a polynomial approximation. |
4616 +---------------------------------------------------------------------------*/
4617void
4618poly_l2(FPU_REG * arg, FPU_REG * result)
4619{
4620 short exponent;
4621 char zero; /* flag for an Xx == 0 */
4622 unsigned short bits, shift;
4623 long long Xsq;
4624 FPU_REG accum, denom, num, Xx;
4625
4626
4627 exponent = arg->exp - EXP_BIAS;
4628
4629 accum.tag = TW_Valid; /* set the tags to Valid */
4630
4631 if (arg->sigh > (unsigned) 0xb504f334) {
4632 /* This is good enough for the computation of the polynomial
4633 * sum, but actually results in a loss of precision for the
4634 * computation of Xx. This will matter only if exponent
4635 * becomes zero. */
4636 exponent++;
4637 accum.sign = 1; /* sign to negative */
4638 num.exp = EXP_BIAS; /* needed to prevent errors in div
4639 * routine */
4640 reg_u_div(&CONST_1, arg, &num, FULL_PRECISION);
4641 } else {
4642 accum.sign = 0; /* set the sign to positive */
4643 num.sigl = arg->sigl; /* copy the mantissa */
4644 num.sigh = arg->sigh;
4645 }
4646
4647
4648 /* shift num left, lose the ms bit */
4649 num.sigh <<= 1;
4650 if (num.sigl & 0x80000000)
4651 num.sigh |= 1;
4652 num.sigl <<= 1;
4653
4654 denom.sigl = num.sigl;
4655 denom.sigh = num.sigh;
4656 poly_div4((long long *) &(denom.sigl));
4657 denom.sigh += 0x80000000; /* set the msb */
4658 Xx.exp = EXP_BIAS; /* needed to prevent errors in div routine */
4659 reg_u_div(&num, &denom, &Xx, FULL_PRECISION);
4660
4661 zero = !(Xx.sigh | Xx.sigl);
4662
4663 mul64((long long *) &Xx.sigl, (long long *) &Xx.sigl, &Xsq);
4664 poly_div16(&Xsq);
4665
4666 accum.exp = -1; /* exponent of accum */
4667
4668 /* Do the basic fixed point polynomial evaluation */
4669 polynomial((unsigned *) &accum.sigl, (unsigned *) &Xsq, lterms, HIPOWER - 1);
4670
4671 if (!exponent) {
4672 /* If the exponent is zero, then we would lose precision by
4673 * sticking to fixed point computation here */
4674 /* We need to re-compute Xx because of loss of precision. */
4675 FPU_REG lXx;
4676 char sign;
4677
4678 sign = accum.sign;
4679 accum.sign = 0;
4680
4681 /* make accum compatible and normalize */
4682 accum.exp = EXP_BIAS + accum.exp;
4683 normalize(&accum);
4684
4685 if (zero) {
4686 reg_move(&CONST_Z, result);
4687 } else {
4688 /* we need to re-compute lXx to better accuracy */
4689 num.tag = TW_Valid; /* set the tags to Vaild */
4690 num.sign = 0; /* set the sign to positive */
4691 num.exp = EXP_BIAS - 1;
4692 if (sign) {
4693 /* The argument is of the form 1-x */
4694 /* Use 1-1/(1-x) = x/(1-x) */
4695 *((long long *) &num.sigl) = -*((long long *) &(arg->sigl));
4696 normalize(&num);
4697 reg_div(&num, arg, &num, FULL_PRECISION);
4698 } else {
4699 normalize(&num);
4700 }
4701
4702 denom.tag = TW_Valid; /* set the tags to Valid */
4703 denom.sign = SIGN_POS; /* set the sign to positive */
4704 denom.exp = EXP_BIAS;
4705
4706 reg_div(&num, &denom, &lXx, FULL_PRECISION);
4707
4708 reg_u_mul(&lXx, &accum, &accum, FULL_PRECISION);
4709
4710 reg_u_add(&lXx, &accum, result, FULL_PRECISION);
4711
4712 normalize(result);
4713 }
4714
4715 result->sign = sign;
4716 return;
4717 }
4718 mul64((long long *) &accum.sigl,
4719 (long long *) &Xx.sigl, (long long *) &accum.sigl);
4720
4721 *((long long *) (&accum.sigl)) += *((long long *) (&Xx.sigl));
4722
4723 if (Xx.sigh > accum.sigh) {
4724 /* There was an overflow */
4725
4726 poly_div2((long long *) &accum.sigl);
4727 accum.sigh |= 0x80000000;
4728 accum.exp++;
4729 }
4730 /* When we add the exponent to the accum result later, we will require
4731 * that their signs are the same. Here we ensure that this is so. */
4732 if (exponent && ((exponent < 0) ^ (accum.sign))) {
4733 /* signs are different */
4734
4735 accum.sign = !accum.sign;
4736
4737 /* An exceptional case is when accum is zero */
4738 if (accum.sigl | accum.sigh) {
4739 /* find 1-accum */
4740 /* Shift to get exponent == 0 */
4741 if (accum.exp < 0) {
4742 poly_div2((long long *) &accum.sigl);
4743 accum.exp++;
4744 }
4745 /* Just negate, but throw away the sign */
4746 *((long long *) &(accum.sigl)) = -*((long long *) &(accum.sigl));
4747 if (exponent < 0)
4748 exponent++;
4749 else
4750 exponent--;
4751 }
4752 }
4753 shift = exponent >= 0 ? exponent : -exponent;
4754 bits = 0;
4755 if (shift) {
4756 if (accum.exp) {
4757 accum.exp++;
4758 poly_div2((long long *) &accum.sigl);
4759 }
4760 while (shift) {
4761 poly_div2((long long *) &accum.sigl);
4762 if (shift & 1)
4763 accum.sigh |= 0x80000000;
4764 shift >>= 1;
4765 bits++;
4766 }
4767 }
4768 /* Convert to 64 bit signed-compatible */
4769 accum.exp += bits + EXP_BIAS - 1;
4770
4771 reg_move(&accum, result);
4772 normalize(result);
4773
4774 return;
4775}
4776
4777
4778/*--- poly_l2p1() -----------------------------------------------------------+
4779 | Base 2 logarithm by a polynomial approximation. |
4780 | log2(x+1) |
4781 +---------------------------------------------------------------------------*/
4782int
4783poly_l2p1(FPU_REG * arg, FPU_REG * result)
4784{
4785 char sign = 0;
4786 long long Xsq;
4787 FPU_REG arg_pl1, denom, accum, local_arg, poly_arg;
4788
4789
4790 sign = arg->sign;
4791
4792 reg_add(arg, &CONST_1, &arg_pl1, FULL_PRECISION);
4793
4794 if ((arg_pl1.sign) | (arg_pl1.tag)) { /* We need a valid positive
4795 * number! */
4796 return 1;
4797 }
4798 reg_add(&CONST_1, &arg_pl1, &denom, FULL_PRECISION);
4799 reg_div(arg, &denom, &local_arg, FULL_PRECISION);
4800 local_arg.sign = 0; /* Make the sign positive */
4801
4802 /* Now we need to check that |local_arg| is less than 3-2*sqrt(2) =
4803 * 0.17157.. = .0xafb0ccc0 * 2^-2 */
4804
4805 if (local_arg.exp >= EXP_BIAS - 3) {
4806 if ((local_arg.exp > EXP_BIAS - 3) ||
4807 (local_arg.sigh > (unsigned) 0xafb0ccc0)) {
4808 /* The argument is large */
4809 poly_l2(&arg_pl1, result);
4810 return 0;
4811 }
4812 }
4813 /* Make a copy of local_arg */
4814 reg_move(&local_arg, &poly_arg);
4815
4816 /* Get poly_arg bits aligned as required */
4817 shrx((unsigned *) &(poly_arg.sigl), -(poly_arg.exp - EXP_BIAS + 3));
4818
4819 mul64((long long *) &(poly_arg.sigl), (long long *) &(poly_arg.sigl), &Xsq);
4820 poly_div16(&Xsq);
4821
4822 /* Do the basic fixed point polynomial evaluation */
4823 polynomial(&(accum.sigl), (unsigned *) &Xsq, lterms, HIPOWER - 1);
4824
4825 accum.tag = TW_Valid; /* set the tags to Valid */
4826 accum.sign = SIGN_POS; /* and make accum positive */
4827
4828 /* make accum compatible and normalize */
4829 accum.exp = EXP_BIAS - 1;
4830 normalize(&accum);
4831
4832 reg_u_mul(&local_arg, &accum, &accum, FULL_PRECISION);
4833
4834 reg_u_add(&local_arg, &accum, result, FULL_PRECISION);
4835
4836 /* Multiply the result by 2 */
4837 result->exp++;
4838
4839 result->sign = sign;
4840
4841 return 0;
4842}
4843\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/poly_sin.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 13632 5462473735 12612\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
4844 * poly_sin.c
4845 *
4846 * Computation of an approximation of the sin function by a polynomial
4847 *
4848 *
4849 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
4850 * Vic 3163, Australia.
4851 * E-mail apm233m@vaxc.cc.monash.edu.au
4852 * All rights reserved.
4853 *
4854 * This copyright notice covers the redistribution and use of the
4855 * FPU emulator developed by W. Metzenthen. It covers only its use
4856 * in the 386BSD operating system. Any other use is not permitted
4857 * under this copyright.
4858 *
4859 * Redistribution and use in source and binary forms, with or without
4860 * modification, are permitted provided that the following conditions
4861 * are met:
4862 * 1. Redistributions of source code must retain the above copyright
4863 * notice, this list of conditions and the following disclaimer.
4864 * 2. Redistributions in binary form must include information specifying
4865 * that source code for the emulator is freely available and include
4866 * either:
4867 * a) an offer to provide the source code for a nominal distribution
4868 * fee, or
4869 * b) list at least two alternative methods whereby the source
4870 * can be obtained, e.g. a publically accessible bulletin board
4871 * and an anonymous ftp site from which the software can be
4872 * downloaded.
4873 * 3. All advertising materials specifically mentioning features or use of
4874 * this emulator must acknowledge that it was developed by W. Metzenthen.
4875 * 4. The name of W. Metzenthen may not be used to endorse or promote
4876 * products derived from this software without specific prior written
4877 * permission.
4878 *
4879 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
4880 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
4881 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
4882 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4883 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
4884 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
4885 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
4886 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4887 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
4888 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4889 *
4890 */
4891
4892
4893#include "exception.h"
4894#include "reg_constant.h"
4895#include "fpu_emu.h"
4896#include "control_w.h"
4897
4898
4899#define HIPOWER 5
4900static unsigned short lterms[HIPOWER][4] =
4901{
4902 {0x846a, 0x42d1, 0xb544, 0x921f},
4903 {0xe110, 0x75aa, 0xbc67, 0x1466},
4904 {0x503d, 0xa43f, 0x83c1, 0x000a},
4905 {0x8f9d, 0x7a19, 0x00f4, 0x0000},
4906 {0xda03, 0x06aa, 0x0000, 0x0000},
4907};
4908
4909static unsigned short negterms[HIPOWER][4] =
4910{
4911 {0x95ed, 0x2df2, 0xe731, 0xa55d},
4912 {0xd159, 0xe62b, 0xd2cc, 0x0132},
4913 {0x6342, 0xe9fb, 0x3c60, 0x0000},
4914 {0x6256, 0xdf5a, 0x0002, 0x0000},
4915 {0xf279, 0x000b, 0x0000, 0x0000},
4916};
4917
4918
4919/*--- poly_sine() -----------------------------------------------------------+
4920 | |
4921 +---------------------------------------------------------------------------*/
4922void
4923poly_sine(FPU_REG * arg, FPU_REG * result)
4924{
4925 short exponent;
4926 FPU_REG Xx, Xx2, Xx4, accum, negaccum;
4927
4928
4929 exponent = arg->exp - EXP_BIAS;
4930
4931 if (arg->tag == TW_Zero) {
4932 /* Return 0.0 */
4933 reg_move(&CONST_Z, result);
4934 return;
4935 }
4936#ifdef PARANOID
4937 if (arg->sign != 0) { /* Can't hack a number < 0.0 */
4938 EXCEPTION(EX_Invalid);
4939 reg_move(&CONST_QNaN, result);
4940 return;
4941 }
4942 if (exponent >= 0) { /* Can't hack a number > 1.0 */
4943 if ((exponent == 0) && (arg->sigl == 0) && (arg->sigh == 0x80000000)) {
4944 reg_move(&CONST_1, result);
4945 return;
4946 }
4947 EXCEPTION(EX_Invalid);
4948 reg_move(&CONST_QNaN, result);
4949 return;
4950 }
4951#endif /* PARANOID */
4952
4953 Xx.sigl = arg->sigl;
4954 Xx.sigh = arg->sigh;
4955 if (exponent < -1) {
4956 /* shift the argument right by the required places */
4957 if (shrx(&(Xx.sigl), -1 - exponent) >= (unsigned)0x80000000)
4958 (*((long long *) (&(Xx.sigl))))++; /* round up */
4959 }
4960 mul64((long long *) &(Xx.sigl), (long long *) &(Xx.sigl),
4961 (long long *) &(Xx2.sigl));
4962 mul64((long long *) &(Xx2.sigl), (long long *) &(Xx2.sigl),
4963 (long long *) &(Xx4.sigl));
4964
4965 /* will be a valid positive nr with expon = 0 */
4966 *(short *) &(accum.sign) = 0;
4967 accum.exp = 0;
4968
4969 /* Do the basic fixed point polynomial evaluation */
4970 polynomial(&(accum.sigl), &(Xx4.sigl), lterms, HIPOWER - 1);
4971
4972 /* will be a valid positive nr with expon = 0 */
4973 *(short *) &(negaccum.sign) = 0;
4974 negaccum.exp = 0;
4975
4976 /* Do the basic fixed point polynomial evaluation */
4977 polynomial(&(negaccum.sigl), &(Xx4.sigl), negterms, HIPOWER - 1);
4978 mul64((long long *) &(Xx2.sigl), (long long *) &(negaccum.sigl),
4979 (long long *) &(negaccum.sigl));
4980
4981 /* Subtract the mantissas */
4982 *((long long *) (&(accum.sigl))) -= *((long long *) (&(negaccum.sigl)));
4983
4984 /* Convert to 64 bit signed-compatible */
4985 accum.exp = EXP_BIAS - 1 + accum.exp;
4986
4987 *(short *) &(result->sign) = *(short *) &(accum.sign);
4988 result->exp = accum.exp;
4989 result->sigl = accum.sigl;
4990 result->sigh = accum.sigh;
4991
4992 normalize(result);
4993
4994 reg_mul(result, arg, result, FULL_PRECISION);
4995 reg_u_add(result, arg, result, FULL_PRECISION);
4996
4997 /* A small overflow may be possible... but an illegal result. */
4998 if (result->exp >= EXP_BIAS) {
4999 if ((result->exp > EXP_BIAS) /* Larger or equal 2.0 */
5000 ||(result->sigl > 1) /* Larger than 1.0+msb */
5001 ||(result->sigh != 0x80000000) /* Much > 1.0 */
5002 ) {
5003#ifdef DEBUGGING
5004 RE_ENTRANT_CHECK_OFF
5005 printk("\nEXP=%d, MS=%08x, LS=%08x\n", result->exp,
5006 result->sigh, result->sigl);
5007 RE_ENTRANT_CHECK_ON
5008#endif /* DEBUGGING */
5009 EXCEPTION(EX_INTERNAL | 0x103);
5010 }
5011#ifdef DEBUGGING
5012 RE_ENTRANT_CHECK_OFF
5013 printk("\n***CORRECTING ILLEGAL RESULT*** in poly_sin() computation\n");
5014 printk("EXP=%d, MS=%08x, LS=%08x\n", result->exp,
5015 result->sigh, result->sigl);
5016 RE_ENTRANT_CHECK_ON
5017#endif /* DEBUGGING */
5018
5019 result->sigl = 0; /* Truncate the result to 1.00 */
5020 }
5021}
5022\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/poly_tan.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 16221 5462473735 12600\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
5023 * poly_tan.c
5024 *
5025 * Compute the tan of a FPU_REG, using a polynomial approximation.
5026 *
5027 *
5028 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
5029 * Vic 3163, Australia.
5030 * E-mail apm233m@vaxc.cc.monash.edu.au
5031 * All rights reserved.
5032 *
5033 * This copyright notice covers the redistribution and use of the
5034 * FPU emulator developed by W. Metzenthen. It covers only its use
5035 * in the 386BSD operating system. Any other use is not permitted
5036 * under this copyright.
5037 *
5038 * Redistribution and use in source and binary forms, with or without
5039 * modification, are permitted provided that the following conditions
5040 * are met:
5041 * 1. Redistributions of source code must retain the above copyright
5042 * notice, this list of conditions and the following disclaimer.
5043 * 2. Redistributions in binary form must include information specifying
5044 * that source code for the emulator is freely available and include
5045 * either:
5046 * a) an offer to provide the source code for a nominal distribution
5047 * fee, or
5048 * b) list at least two alternative methods whereby the source
5049 * can be obtained, e.g. a publically accessible bulletin board
5050 * and an anonymous ftp site from which the software can be
5051 * downloaded.
5052 * 3. All advertising materials specifically mentioning features or use of
5053 * this emulator must acknowledge that it was developed by W. Metzenthen.
5054 * 4. The name of W. Metzenthen may not be used to endorse or promote
5055 * products derived from this software without specific prior written
5056 * permission.
5057 *
5058 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5059 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
5060 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
5061 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
5062 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
5063 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
5064 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
5065 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
5066 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
5067 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5068 *
5069 */
5070
5071#include "exception.h"
5072#include "reg_constant.h"
5073#include "fpu_emu.h"
5074#include "control_w.h"
5075
5076
5077#define HIPOWERop 3 /* odd poly, positive terms */
5078static unsigned short oddplterms[HIPOWERop][4] =
5079{
5080 {0x846a, 0x42d1, 0xb544, 0x921f},
5081 {0x6fb2, 0x0215, 0x95c0, 0x099c},
5082 {0xfce6, 0x0cc8, 0x1c9a, 0x0000}
5083};
5084#define HIPOWERon 2 /* odd poly, negative terms */
5085static unsigned short oddnegterms[HIPOWERon][4] =
5086{
5087 {0x6906, 0xe205, 0x25c8, 0x8838},
5088 {0x1dd7, 0x3fe3, 0x944e, 0x002c}
5089};
5090#define HIPOWERep 2 /* even poly, positive terms */
5091static unsigned short evenplterms[HIPOWERep][4] =
5092{
5093 {0xdb8f, 0x3761, 0x1432, 0x2acf},
5094 {0x16eb, 0x13c1, 0x3099, 0x0003}
5095};
5096#define HIPOWERen 2 /* even poly, negative terms */
5097static unsigned short evennegterms[HIPOWERen][4] =
5098{
5099 {0x3a7c, 0xe4c5, 0x7f87, 0x2945},
5100 {0x572b, 0x664c, 0xc543, 0x018c}
5101};
5102
5103
5104/*--- poly_tan() ------------------------------------------------------------+
5105 | |
5106 +---------------------------------------------------------------------------*/
5107void
5108poly_tan(FPU_REG * arg, FPU_REG * y_reg)
5109{
5110 char invert = 0;
5111 short exponent;
5112 FPU_REG odd_poly, even_poly, pos_poly, neg_poly;
5113 FPU_REG argSq;
5114 long long arg_signif, argSqSq;
5115
5116
5117 exponent = arg->exp - EXP_BIAS;
5118
5119 if (arg->tag == TW_Zero) {
5120 /* Return 0.0 */
5121 reg_move(&CONST_Z, y_reg);
5122 return;
5123 }
5124 if (exponent >= -1) {
5125 /* argument is in the range [0.5 .. 1.0] */
5126 if (exponent >= 0) {
5127#ifdef PARANOID
5128 if ((exponent == 0) &&
5129 (arg->sigl == 0) && (arg->sigh == 0x80000000))
5130#endif /* PARANOID */
5131 {
5132 arith_overflow(y_reg);
5133 return;
5134 }
5135#ifdef PARANOID
5136 EXCEPTION(EX_INTERNAL | 0x104); /* There must be a logic
5137 * error */
5138 return;
5139#endif /* PARANOID */
5140 }
5141 /* The argument is in the range [0.5 .. 1.0) */
5142 /* Convert the argument to a number in the range (0.0 .. 0.5] */
5143 *((long long *) (&arg->sigl)) = -*((long long *) (&arg->sigl));
5144 normalize(arg); /* Needed later */
5145 exponent = arg->exp - EXP_BIAS;
5146 invert = 1;
5147 }
5148#ifdef PARANOID
5149 if (arg->sign != 0) { /* Can't hack a number < 0.0 */
5150 arith_invalid(y_reg);
5151 return;
5152 } /* Need a positive number */
5153#endif /* PARANOID */
5154
5155 *(long long *) &arg_signif = *(long long *) &(arg->sigl);
5156 if (exponent < -1) {
5157 /* shift the argument right by the required places */
5158 if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000)
5159 arg_signif++; /* round up */
5160 }
5161 mul64(&arg_signif, &arg_signif, (long long *) (&argSq.sigl));
5162 mul64((long long *) (&argSq.sigl), (long long *) (&argSq.sigl), &argSqSq);
5163
5164 /* will be a valid positive nr with expon = 0 */
5165 *(short *) &(pos_poly.sign) = 0;
5166 pos_poly.exp = EXP_BIAS;
5167
5168 /* Do the basic fixed point polynomial evaluation */
5169 polynomial(&pos_poly.sigl, (unsigned *) &argSqSq, oddplterms, HIPOWERop - 1);
5170
5171 /* will be a valid positive nr with expon = 0 */
5172 *(short *) &(neg_poly.sign) = 0;
5173 neg_poly.exp = EXP_BIAS;
5174
5175 /* Do the basic fixed point polynomial evaluation */
5176 polynomial(&neg_poly.sigl, (unsigned *) &argSqSq, oddnegterms, HIPOWERon - 1);
5177 mul64((long long *) (&argSq.sigl), (long long *) (&neg_poly.sigl),
5178 (long long *) (&neg_poly.sigl));
5179
5180 /* Subtract the mantissas */
5181 *((long long *) (&pos_poly.sigl)) -= *((long long *) (&neg_poly.sigl));
5182
5183 /* Convert to 64 bit signed-compatible */
5184 pos_poly.exp -= 1;
5185
5186 reg_move(&pos_poly, &odd_poly);
5187 normalize(&odd_poly);
5188
5189 reg_mul(&odd_poly, arg, &odd_poly, FULL_PRECISION);
5190 reg_u_add(&odd_poly, arg, &odd_poly, FULL_PRECISION); /* This is just the odd
5191 * polynomial */
5192
5193
5194 /* will be a valid positive nr with expon = 0 */
5195 *(short *) &(pos_poly.sign) = 0;
5196 pos_poly.exp = EXP_BIAS;
5197
5198 /* Do the basic fixed point polynomial evaluation */
5199 polynomial(&pos_poly.sigl, (unsigned *) &argSqSq, evenplterms, HIPOWERep - 1);
5200 mul64((long long *) (&argSq.sigl),
5201 (long long *) (&pos_poly.sigl), (long long *) (&pos_poly.sigl));
5202
5203 /* will be a valid positive nr with expon = 0 */
5204 *(short *) &(neg_poly.sign) = 0;
5205 neg_poly.exp = EXP_BIAS;
5206
5207 /* Do the basic fixed point polynomial evaluation */
5208 polynomial(&neg_poly.sigl, (unsigned *) &argSqSq, evennegterms, HIPOWERen - 1);
5209
5210 /* Subtract the mantissas */
5211 *((long long *) (&neg_poly.sigl)) -= *((long long *) (&pos_poly.sigl));
5212 /* and multiply by argSq */
5213
5214 /* Convert argSq to a valid reg number */
5215 *(short *) &(argSq.sign) = 0;
5216 argSq.exp = EXP_BIAS - 1;
5217 normalize(&argSq);
5218
5219 /* Convert to 64 bit signed-compatible */
5220 neg_poly.exp -= 1;
5221
5222 reg_move(&neg_poly, &even_poly);
5223 normalize(&even_poly);
5224
5225 reg_mul(&even_poly, &argSq, &even_poly, FULL_PRECISION);
5226 reg_add(&even_poly, &argSq, &even_poly, FULL_PRECISION);
5227 reg_sub(&CONST_1, &even_poly, &even_poly, FULL_PRECISION); /* This is just the even
5228 * polynomial */
5229
5230 /* Now ready to copy the results */
5231 if (invert) {
5232 reg_div(&even_poly, &odd_poly, y_reg, FULL_PRECISION);
5233 } else {
5234 reg_div(&odd_poly, &even_poly, y_reg, FULL_PRECISION);
5235 }
5236
5237}
5238\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/fpu_emu.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 13703 5462320156 12406\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
5239 * fpu_emu.h
5240 *
5241 *
5242 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
5243 * Vic 3163, Australia.
5244 * E-mail apm233m@vaxc.cc.monash.edu.au
5245 * All rights reserved.
5246 *
5247 * This copyright notice covers the redistribution and use of the
5248 * FPU emulator developed by W. Metzenthen. It covers only its use
5249 * in the 386BSD operating system. Any other use is not permitted
5250 * under this copyright.
5251 *
5252 * Redistribution and use in source and binary forms, with or without
5253 * modification, are permitted provided that the following conditions
5254 * are met:
5255 * 1. Redistributions of source code must retain the above copyright
5256 * notice, this list of conditions and the following disclaimer.
5257 * 2. Redistributions in binary form must include information specifying
5258 * that source code for the emulator is freely available and include
5259 * either:
5260 * a) an offer to provide the source code for a nominal distribution
5261 * fee, or
5262 * b) list at least two alternative methods whereby the source
5263 * can be obtained, e.g. a publically accessible bulletin board
5264 * and an anonymous ftp site from which the software can be
5265 * downloaded.
5266 * 3. All advertising materials specifically mentioning features or use of
5267 * this emulator must acknowledge that it was developed by W. Metzenthen.
5268 * 4. The name of W. Metzenthen may not be used to endorse or promote
5269 * products derived from this software without specific prior written
5270 * permission.
5271 *
5272 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5273 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
5274 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
5275 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
5276 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
5277 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
5278 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
5279 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
5280 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
5281 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5282 *
5283 */
5284
5285
5286#ifndef _FPU_EMU_H_
5287#define _FPU_EMU_H_
5288
5289/*
5290 * Define DENORM_OPERAND to make the emulator detect denormals
5291 * and use the denormal flag of the status word. Note: this only
5292 * affects the flag and corresponding interrupt, the emulator
5293 * will always generate denormals and operate upon them as required.
5294 */
5295#define DENORM_OPERAND
5296
5297/*
5298 * Define PECULIAR_486 to get a closer approximation to 80486 behaviour,
5299 * rather than behaviour which appears to be cleaner.
5300 * This is a matter of opinion: for all I know, the 80486 may simply
5301 * be complying with the IEEE spec. Maybe one day I'll get to see the
5302 * spec...
5303 */
5304#define PECULIAR_486
5305
5306#ifdef LOCORE
5307#include "fpu_asm.h"
5308#define Const(x) $/**/x
5309#else
5310#define Const(x) x
5311#endif
5312
5313#define EXP_BIAS Const(0)
5314#define EXP_OVER Const(0x4000) /* smallest invalid large exponent */
5315#define EXP_UNDER Const(-0x3fff) /* largest invalid small exponent */
5316
5317#define SIGN_POS Const(0)
5318#define SIGN_NEG Const(1)
5319
5320/* Keep the order TW_Valid, TW_Zero, TW_Denormal */
5321#define TW_Valid Const(0)/* valid */
5322#define TW_Zero Const(1)/* zero */
5323/* The following fold to 2 (Special) in the Tag Word */
5324#define TW_Denormal Const(4)/* De-normal */
5325#define TW_Infinity Const(5)/* + or - infinity */
5326#define TW_NaN Const(6)/* Not a Number */
5327
5328#define TW_Empty Const(7)/* empty */
5329
5330 /* #define TW_FPU_Interrupt Const(0x80) *//* Signals an interrupt */
5331
5332
5333#ifndef LOCORE
5334
5335#include "types.h"
5336#include "math_emu.h"
5337
5338#ifdef PARANOID
5339extern char emulating;
5340#define REENTRANT_CHECK(state) emulating = (state)
5341#define ON 1
5342#define OFF 0
5343#else
5344#define REENTRANT_CHECK(state)
5345#endif /* PARANOID */
5346
5347typedef void (*FUNC) (void);
5348typedef struct fpu_reg FPU_REG;
5349
5350#define st(x) ( regs[((top+x) &7 )] )
5351
5352#define STACK_OVERFLOW (st_new_ptr = &st(-1), st_new_ptr->tag != TW_Empty)
5353#define NOT_EMPTY(i) (st(i).tag != TW_Empty)
5354#define NOT_EMPTY_0 (FPU_st0_tag ^ TW_Empty)
5355
5356extern unsigned char FPU_rm;
5357
5358extern char FPU_st0_tag;
5359extern FPU_REG *FPU_st0_ptr;
5360
5361extern void *FPU_data_address;
5362
5363extern FPU_REG FPU_loaded_data;
5364
5365#define pop() { FPU_st0_ptr->tag = TW_Empty; top++; }
5366
5367/* push() does not affect the tags */
5368#define push() { top--; FPU_st0_ptr = st_new_ptr; }
5369
5370
5371#define reg_move(x, y) { \
5372 *(short *)&((y)->sign) = *(short *)&((x)->sign); \
5373 *(long *)&((y)->exp) = *(long *)&((x)->exp); \
5374 *(long long *)&((y)->sigl) = *(long long *)&((x)->sigl); }
5375
5376
5377/*----- Prototypes for functions written in assembler -----*/
5378/* extern void reg_move(FPU_REG *a, FPU_REG *b); */
5379
5380extern void mul64(long long *a, long long *b, long long *result);
5381extern void poly_div2(long long *x);
5382extern void poly_div4(long long *x);
5383extern void poly_div16(long long *x);
5384extern void
5385polynomial(unsigned accum[], unsigned x[],
5386 unsigned short terms[][4], int n);
5387 extern void normalize(FPU_REG * x);
5388 extern void normalize_nuo(FPU_REG * x);
5389 extern void reg_div(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ,
5390 unsigned int control_w);
5391 extern void reg_u_sub(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ,
5392 unsigned int control_w);
5393 extern void reg_u_mul(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ,
5394 unsigned int control_w);
5395 extern void reg_u_div(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ,
5396 unsigned int control_w);
5397 extern void reg_u_add(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ,
5398 unsigned int control_w);
5399 extern void wm_sqrt(FPU_REG * n, unsigned int control_w);
5400 extern unsigned shrx(void *l, unsigned x);
5401 extern unsigned shrxs(void *v, unsigned x);
5402 extern unsigned long div_small(unsigned long long *x, unsigned long y);
5403 extern void round_reg(FPU_REG * arg, unsigned int extent,
5404 unsigned int control_w);
5405
5406#ifndef MAKING_PROTO
5407#include "fpu_proto.h"
5408#endif
5409
5410#endif /* LOCORE */
5411
5412#endif /* _FPU_EMU_H_ */
5413\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/reg_compare.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 21642 5462320164 13224\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
5414 * reg_compare.c
5415 *
5416 * Compare two floating point registers
5417 *
5418 *
5419 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
5420 * Vic 3163, Australia.
5421 * E-mail apm233m@vaxc.cc.monash.edu.au
5422 * All rights reserved.
5423 *
5424 * This copyright notice covers the redistribution and use of the
5425 * FPU emulator developed by W. Metzenthen. It covers only its use
5426 * in the 386BSD operating system. Any other use is not permitted
5427 * under this copyright.
5428 *
5429 * Redistribution and use in source and binary forms, with or without
5430 * modification, are permitted provided that the following conditions
5431 * are met:
5432 * 1. Redistributions of source code must retain the above copyright
5433 * notice, this list of conditions and the following disclaimer.
5434 * 2. Redistributions in binary form must include information specifying
5435 * that source code for the emulator is freely available and include
5436 * either:
5437 * a) an offer to provide the source code for a nominal distribution
5438 * fee, or
5439 * b) list at least two alternative methods whereby the source
5440 * can be obtained, e.g. a publically accessible bulletin board
5441 * and an anonymous ftp site from which the software can be
5442 * downloaded.
5443 * 3. All advertising materials specifically mentioning features or use of
5444 * this emulator must acknowledge that it was developed by W. Metzenthen.
5445 * 4. The name of W. Metzenthen may not be used to endorse or promote
5446 * products derived from this software without specific prior written
5447 * permission.
5448 *
5449 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5450 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
5451 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
5452 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
5453 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
5454 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
5455 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
5456 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
5457 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
5458 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5459 *
5460 */
5461
5462/*---------------------------------------------------------------------------+
5463 | compare() is the core FPU_REG comparison function |
5464 +---------------------------------------------------------------------------*/
5465#include "param.h"
5466#include "proc.h"
5467#include "systm.h"
5468#include "machine/cpu.h"
5469#include "machine/pcb.h"
5470
5471#include "fpu_emu.h"
5472#include "fpu_system.h"
5473#include "exception.h"
5474#include "control_w.h"
5475#include "status_w.h"
5476
5477
5478int
5479compare(FPU_REG * b)
5480{
5481 int diff;
5482
5483 if (FPU_st0_ptr->tag | b->tag) {
5484 if (FPU_st0_ptr->tag == TW_Zero) {
5485 if (b->tag == TW_Zero)
5486 return COMP_A_eq_B;
5487 if (b->tag == TW_Valid) {
5488#ifdef DENORM_OPERAND
5489 if ((b->exp <= EXP_UNDER) && (denormal_operand()))
5490 return COMP_Denormal;
5491#endif /* DENORM_OPERAND */
5492 return (b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B;
5493 }
5494 } else
5495 if (b->tag == TW_Zero) {
5496 if (FPU_st0_ptr->tag == TW_Valid) {
5497#ifdef DENORM_OPERAND
5498 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
5499 return COMP_Denormal;
5500#endif /* DENORM_OPERAND */
5501 return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B;
5502 }
5503 }
5504 if (FPU_st0_ptr->tag == TW_Infinity) {
5505 if ((b->tag == TW_Valid) || (b->tag == TW_Zero)) {
5506#ifdef DENORM_OPERAND
5507 if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER)
5508 && (denormal_operand()))
5509 return COMP_Denormal;
5510#endif /* DENORM_OPERAND */
5511 return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B;
5512 } else
5513 if (b->tag == TW_Infinity) {
5514 /* The 80486 book says that infinities
5515 * can be equal! */
5516 return (FPU_st0_ptr->sign == b->sign) ? COMP_A_eq_B :
5517 ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
5518 }
5519 /* Fall through to the NaN code */
5520 } else
5521 if (b->tag == TW_Infinity) {
5522 if ((FPU_st0_ptr->tag == TW_Valid) || (FPU_st0_ptr->tag == TW_Zero)) {
5523#ifdef DENORM_OPERAND
5524 if ((FPU_st0_ptr->tag == TW_Valid)
5525 && (FPU_st0_ptr->exp <= EXP_UNDER)
5526 && (denormal_operand()))
5527 return COMP_Denormal;
5528#endif /* DENORM_OPERAND */
5529 return (b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B;
5530 }
5531 /* Fall through to the NaN code */
5532 }
5533 /* The only possibility now should be that one of the
5534 * arguments is a NaN */
5535 if ((FPU_st0_ptr->tag == TW_NaN) || (b->tag == TW_NaN)) {
5536 if (((FPU_st0_ptr->tag == TW_NaN) && !(FPU_st0_ptr->sigh & 0x40000000))
5537 || ((b->tag == TW_NaN) && !(b->sigh & 0x40000000)))
5538 /* At least one arg is a signaling NaN */
5539 return COMP_No_Comp | COMP_SNaN | COMP_NaN;
5540 else
5541 /* Neither is a signaling NaN */
5542 return COMP_No_Comp | COMP_NaN;
5543 }
5544 EXCEPTION(EX_Invalid);
5545 }
5546#ifdef PARANOID
5547 if (!(FPU_st0_ptr->sigh & 0x80000000))
5548 EXCEPTION(EX_Invalid);
5549 if (!(b->sigh & 0x80000000))
5550 EXCEPTION(EX_Invalid);
5551#endif /* PARANOID */
5552
5553#ifdef DENORM_OPERAND
5554 if (((FPU_st0_ptr->exp <= EXP_UNDER) ||
5555 (b->exp <= EXP_UNDER)) && (denormal_operand()))
5556 return COMP_Denormal;
5557#endif /* DENORM_OPERAND */
5558
5559 if (FPU_st0_ptr->sign != b->sign)
5560 return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B;
5561
5562 diff = FPU_st0_ptr->exp - b->exp;
5563 if (diff == 0) {
5564 diff = FPU_st0_ptr->sigh - b->sigh; /* Works only if ms bits
5565 * are identical */
5566 if (diff == 0) {
5567 diff = FPU_st0_ptr->sigl > b->sigl;
5568 if (diff == 0)
5569 diff = -(FPU_st0_ptr->sigl < b->sigl);
5570 }
5571 }
5572 if (diff > 0)
5573 return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B;
5574 if (diff < 0)
5575 return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B;
5576 return COMP_A_eq_B;
5577
5578}
5579
5580
5581/* This function requires that st(0) is not empty */
5582int
5583compare_st_data(void)
5584{
5585 int f, c;
5586
5587 c = compare(&FPU_loaded_data);
5588
5589 if (c & (COMP_NaN | COMP_Denormal)) {
5590 if (c & COMP_NaN) {
5591 EXCEPTION(EX_Invalid);
5592 f = SW_C3 | SW_C2 | SW_C0;
5593 } else {
5594 /* One of the operands is a de-normal */
5595 return 0;
5596 }
5597 } else
5598 switch (c) {
5599 case COMP_A_lt_B:
5600 f = SW_C0;
5601 break;
5602 case COMP_A_eq_B:
5603 f = SW_C3;
5604 break;
5605 case COMP_A_gt_B:
5606 f = 0;
5607 break;
5608 case COMP_No_Comp:
5609 f = SW_C3 | SW_C2 | SW_C0;
5610 break;
5611#ifdef PARANOID
5612 default:
5613 EXCEPTION(EX_INTERNAL | 0x121);
5614 f = SW_C3 | SW_C2 | SW_C0;
5615 break;
5616#endif /* PARANOID */
5617 }
5618 setcc(f);
5619 return 1;
5620}
5621
5622
5623static int
5624compare_st_st(int nr)
5625{
5626 int f, c;
5627
5628 if (!NOT_EMPTY_0 || !NOT_EMPTY(nr)) {
5629 setcc(SW_C3 | SW_C2 | SW_C0);
5630 /* Stack fault */
5631 EXCEPTION(EX_StackUnder);
5632 return control_word & CW_Invalid;
5633 }
5634 c = compare(&st(nr));
5635 if (c & (COMP_NaN | COMP_Denormal)) {
5636 if (c & COMP_NaN) {
5637 setcc(SW_C3 | SW_C2 | SW_C0);
5638 EXCEPTION(EX_Invalid);
5639 return control_word & CW_Invalid;
5640 } else {
5641 /* One of the operands is a de-normal */
5642 return control_word & CW_Denormal;
5643 }
5644 } else
5645 switch (c) {
5646 case COMP_A_lt_B:
5647 f = SW_C0;
5648 break;
5649 case COMP_A_eq_B:
5650 f = SW_C3;
5651 break;
5652 case COMP_A_gt_B:
5653 f = 0;
5654 break;
5655 case COMP_No_Comp:
5656 f = SW_C3 | SW_C2 | SW_C0;
5657 break;
5658#ifdef PARANOID
5659 default:
5660 EXCEPTION(EX_INTERNAL | 0x122);
5661 f = SW_C3 | SW_C2 | SW_C0;
5662 break;
5663#endif /* PARANOID */
5664 }
5665 setcc(f);
5666 return 1;
5667}
5668
5669
5670static int
5671compare_u_st_st(int nr)
5672{
5673 int f, c;
5674
5675 if (!NOT_EMPTY_0 || !NOT_EMPTY(nr)) {
5676 setcc(SW_C3 | SW_C2 | SW_C0);
5677 /* Stack fault */
5678 EXCEPTION(EX_StackUnder);
5679 return control_word & CW_Invalid;
5680 }
5681 c = compare(&st(nr));
5682 if (c & (COMP_NaN | COMP_Denormal)) {
5683 if (c & COMP_NaN) {
5684 setcc(SW_C3 | SW_C2 | SW_C0);
5685 if (c & COMP_SNaN) { /* This is the only difference
5686 * between un-ordered and
5687 * ordinary comparisons */
5688 EXCEPTION(EX_Invalid);
5689 return control_word & CW_Invalid;
5690 }
5691 return 1;
5692 } else {
5693 /* One of the operands is a de-normal */
5694 return control_word & CW_Denormal;
5695 }
5696 } else
5697 switch (c) {
5698 case COMP_A_lt_B:
5699 f = SW_C0;
5700 break;
5701 case COMP_A_eq_B:
5702 f = SW_C3;
5703 break;
5704 case COMP_A_gt_B:
5705 f = 0;
5706 break;
5707 case COMP_No_Comp:
5708 f = SW_C3 | SW_C2 | SW_C0;
5709 break;
5710#ifdef PARANOID
5711 default:
5712 EXCEPTION(EX_INTERNAL | 0x123);
5713 f = SW_C3 | SW_C2 | SW_C0;
5714 break;
5715#endif /* PARANOID */
5716 }
5717 setcc(f);
5718 return 1;
5719}
5720/*---------------------------------------------------------------------------*/
5721
5722void
5723fcom_st()
5724{
5725 /* fcom st(i) */
5726 compare_st_st(FPU_rm);
5727}
5728
5729
5730void
5731fcompst()
5732{
5733 /* fcomp st(i) */
5734 if (compare_st_st(FPU_rm))
5735 pop();
5736}
5737
5738
5739void
5740fcompp()
5741{
5742 /* fcompp */
5743 if (FPU_rm != 1)
5744 return Un_impl();
5745 if (compare_st_st(1)) {
5746 pop();
5747 FPU_st0_ptr = &st(0);
5748 pop();
5749 }
5750}
5751
5752
5753void
5754fucom_()
5755{
5756 /* fucom st(i) */
5757 compare_u_st_st(FPU_rm);
5758
5759}
5760
5761
5762void
5763fucomp()
5764{
5765 /* fucomp st(i) */
5766 if (compare_u_st_st(FPU_rm))
5767 pop();
5768}
5769
5770
5771void
5772fucompp()
5773{
5774 /* fucompp */
5775 if (FPU_rm == 1) {
5776 if (compare_u_st_st(1)) {
5777 pop();
5778 FPU_st0_ptr = &st(0);
5779 pop();
5780 }
5781 } else
5782 Un_impl();
5783}
5784\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/reg_constant.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 10724 5462320165 13427\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
5785 * reg_constant.c
5786 *
5787 * All of the constant FPU_REGs
5788 *
5789 *
5790 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
5791 * Vic 3163, Australia.
5792 * E-mail apm233m@vaxc.cc.monash.edu.au
5793 * All rights reserved.
5794 *
5795 * This copyright notice covers the redistribution and use of the
5796 * FPU emulator developed by W. Metzenthen. It covers only its use
5797 * in the 386BSD operating system. Any other use is not permitted
5798 * under this copyright.
5799 *
5800 * Redistribution and use in source and binary forms, with or without
5801 * modification, are permitted provided that the following conditions
5802 * are met:
5803 * 1. Redistributions of source code must retain the above copyright
5804 * notice, this list of conditions and the following disclaimer.
5805 * 2. Redistributions in binary form must include information specifying
5806 * that source code for the emulator is freely available and include
5807 * either:
5808 * a) an offer to provide the source code for a nominal distribution
5809 * fee, or
5810 * b) list at least two alternative methods whereby the source
5811 * can be obtained, e.g. a publically accessible bulletin board
5812 * and an anonymous ftp site from which the software can be
5813 * downloaded.
5814 * 3. All advertising materials specifically mentioning features or use of
5815 * this emulator must acknowledge that it was developed by W. Metzenthen.
5816 * 4. The name of W. Metzenthen may not be used to endorse or promote
5817 * products derived from this software without specific prior written
5818 * permission.
5819 *
5820 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5821 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
5822 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
5823 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
5824 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
5825 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
5826 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
5827 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
5828 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
5829 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5830 *
5831 */
5832#include "param.h"
5833#include "proc.h"
5834#include "systm.h"
5835#include "machine/cpu.h"
5836#include "machine/pcb.h"
5837
5838#include "fpu_emu.h"
5839#include "fpu_system.h"
5840#include "status_w.h"
5841#include "reg_constant.h"
5842
5843
5844FPU_REG CONST_1 = {SIGN_POS, TW_Valid, EXP_BIAS,
58450x00000000, 0x80000000};
5846FPU_REG CONST_2 = {SIGN_POS, TW_Valid, EXP_BIAS + 1,
58470x00000000, 0x80000000};
5848FPU_REG CONST_HALF = {SIGN_POS, TW_Valid, EXP_BIAS - 1,
58490x00000000, 0x80000000};
5850FPU_REG CONST_L2T = {SIGN_POS, TW_Valid, EXP_BIAS + 1,
58510xcd1b8afe, 0xd49a784b};
5852FPU_REG CONST_L2E = {SIGN_POS, TW_Valid, EXP_BIAS,
58530x5c17f0bc, 0xb8aa3b29};
5854FPU_REG CONST_PI = {SIGN_POS, TW_Valid, EXP_BIAS + 1,
58550x2168c235, 0xc90fdaa2};
5856FPU_REG CONST_PI2 = {SIGN_POS, TW_Valid, EXP_BIAS,
58570x2168c235, 0xc90fdaa2};
5858FPU_REG CONST_PI4 = {SIGN_POS, TW_Valid, EXP_BIAS - 1,
58590x2168c235, 0xc90fdaa2};
5860FPU_REG CONST_LG2 = {SIGN_POS, TW_Valid, EXP_BIAS - 2,
58610xfbcff799, 0x9a209a84};
5862FPU_REG CONST_LN2 = {SIGN_POS, TW_Valid, EXP_BIAS - 1,
58630xd1cf79ac, 0xb17217f7};
5864/* Only the sign (and tag) is used in internal zeroes */
5865FPU_REG CONST_Z = {SIGN_POS, TW_Zero, 0, 0x0, 0x0};
5866/* Only the sign and significand (and tag) are used in internal NaNs */
5867/* The 80486 never generates one of these
5868FPU_REG CONST_SNAN = { SIGN_POS, TW_NaN, EXP_OVER, 0x00000001, 0x80000000 };
5869 */
5870/* This is the real indefinite QNaN */
5871FPU_REG CONST_QNaN = {SIGN_NEG, TW_NaN, EXP_OVER, 0x00000000, 0xC0000000};
5872/* Only the sign (and tag) is used in internal infinities */
5873FPU_REG CONST_INF = {SIGN_POS, TW_Infinity, EXP_OVER, 0x00000000, 0x80000000};
5874
5875
5876
5877static void
5878fld_const(FPU_REG * c)
5879{
5880 FPU_REG *st_new_ptr;
5881
5882 if (STACK_OVERFLOW) {
5883 stack_overflow();
5884 return;
5885 }
5886 push();
5887 reg_move(c, FPU_st0_ptr);
5888 status_word &= ~SW_C1;
5889}
5890
5891
5892static void
5893fld1(void)
5894{
5895 fld_const(&CONST_1);
5896}
5897
5898static void
5899fldl2t(void)
5900{
5901 fld_const(&CONST_L2T);
5902}
5903
5904static void
5905fldl2e(void)
5906{
5907 fld_const(&CONST_L2E);
5908}
5909
5910static void
5911fldpi(void)
5912{
5913 fld_const(&CONST_PI);
5914}
5915
5916static void
5917fldlg2(void)
5918{
5919 fld_const(&CONST_LG2);
5920}
5921
5922static void
5923fldln2(void)
5924{
5925 fld_const(&CONST_LN2);
5926}
5927
5928static void
5929fldz(void)
5930{
5931 fld_const(&CONST_Z);
5932}
5933
5934static FUNC constants_table[] = {
5935 fld1, fldl2t, fldl2e, fldpi, fldlg2, fldln2, fldz, Un_impl
5936};
5937
5938void
5939fconst(void)
5940{
5941 (constants_table[FPU_rm]) ();
5942}
5943\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/reg_constant.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 24 \0 5332 5462320165 13440\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0staff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
5944 * reg_constant.h
5945 *
5946 *
5947 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
5948 * Vic 3163, Australia.
5949 * E-mail apm233m@vaxc.cc.monash.edu.au
5950 * All rights reserved.
5951 *
5952 * This copyright notice covers the redistribution and use of the
5953 * FPU emulator developed by W. Metzenthen. It covers only its use
5954 * in the 386BSD operating system. Any other use is not permitted
5955 * under this copyright.
5956 *
5957 * Redistribution and use in source and binary forms, with or without
5958 * modification, are permitted provided that the following conditions
5959 * are met:
5960 * 1. Redistributions of source code must retain the above copyright
5961 * notice, this list of conditions and the following disclaimer.
5962 * 2. Redistributions in binary form must include information specifying
5963 * that source code for the emulator is freely available and include
5964 * either:
5965 * a) an offer to provide the source code for a nominal distribution
5966 * fee, or
5967 * b) list at least two alternative methods whereby the source
5968 * can be obtained, e.g. a publically accessible bulletin board
5969 * and an anonymous ftp site from which the software can be
5970 * downloaded.
5971 * 3. All advertising materials specifically mentioning features or use of
5972 * this emulator must acknowledge that it was developed by W. Metzenthen.
5973 * 4. The name of W. Metzenthen may not be used to endorse or promote
5974 * products derived from this software without specific prior written
5975 * permission.
5976 *
5977 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5978 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
5979 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
5980 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
5981 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
5982 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
5983 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
5984 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
5985 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
5986 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5987 *
5988 */
5989
5990#ifndef _REG_CONSTANT_H_
5991#define _REG_CONSTANT_H_
5992
5993#include "fpu_emu.h"
5994
5995extern FPU_REG CONST_1;
5996extern FPU_REG CONST_2;
5997extern FPU_REG CONST_HALF;
5998extern FPU_REG CONST_L2T;
5999extern FPU_REG CONST_L2E;
6000extern FPU_REG CONST_PI;
6001extern FPU_REG CONST_PI2;
6002extern FPU_REG CONST_PI4;
6003extern FPU_REG CONST_LG2;
6004extern FPU_REG CONST_LN2;
6005extern FPU_REG CONST_Z;
6006extern FPU_REG CONST_PINF;
6007extern FPU_REG CONST_INF;
6008extern FPU_REG CONST_MINF;
6009extern FPU_REG CONST_QNaN;
6010
6011#endif /* _REG_CONSTANT_H_ */
6012\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/reg_ld_str.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 104454 5462474522 13120\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
6013 * reg_ld_str.c
6014 *
6015 * All of the functions which transfer data between user memory and FPU_REGs.
6016 *
6017 *
6018 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
6019 * Vic 3163, Australia.
6020 * E-mail apm233m@vaxc.cc.monash.edu.au
6021 * All rights reserved.
6022 *
6023 * This copyright notice covers the redistribution and use of the
6024 * FPU emulator developed by W. Metzenthen. It covers only its use
6025 * in the 386BSD operating system. Any other use is not permitted
6026 * under this copyright.
6027 *
6028 * Redistribution and use in source and binary forms, with or without
6029 * modification, are permitted provided that the following conditions
6030 * are met:
6031 * 1. Redistributions of source code must retain the above copyright
6032 * notice, this list of conditions and the following disclaimer.
6033 * 2. Redistributions in binary form must include information specifying
6034 * that source code for the emulator is freely available and include
6035 * either:
6036 * a) an offer to provide the source code for a nominal distribution
6037 * fee, or
6038 * b) list at least two alternative methods whereby the source
6039 * can be obtained, e.g. a publically accessible bulletin board
6040 * and an anonymous ftp site from which the software can be
6041 * downloaded.
6042 * 3. All advertising materials specifically mentioning features or use of
6043 * this emulator must acknowledge that it was developed by W. Metzenthen.
6044 * 4. The name of W. Metzenthen may not be used to endorse or promote
6045 * products derived from this software without specific prior written
6046 * permission.
6047 *
6048 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
6049 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
6050 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
6051 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
6052 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
6053 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
6054 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
6055 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
6056 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
6057 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6058 *
6059 */
6060
6061
6062/*---------------------------------------------------------------------------+
6063 | Note: |
6064 | The file contains code which accesses user memory. |
6065 | Emulator static data may change when user memory is accessed, due to |
6066 | other processes using the emulator while swapping is in progress. |
6067 +---------------------------------------------------------------------------*/
6068#include "param.h"
6069#include "proc.h"
6070#include "systm.h"
6071#include "machine/cpu.h"
6072#include "machine/pcb.h"
6073
6074#include "fpu_emu.h"
6075#include "fpu_system.h"
6076#include "exception.h"
6077#include "reg_constant.h"
6078#include "control_w.h"
6079#include "status_w.h"
6080
6081
6082#define EXTENDED_Emax 0x3fff /* largest valid exponent */
6083#define EXTENDED_Ebias 0x3fff
6084#define EXTENDED_Emin (-0x3ffe) /* smallest valid exponent */
6085
6086#define DOUBLE_Emax 1023 /* largest valid exponent */
6087#define DOUBLE_Ebias 1023
6088#define DOUBLE_Emin (-1022) /* smallest valid exponent */
6089
6090#define SINGLE_Emax 127 /* largest valid exponent */
6091#define SINGLE_Ebias 127
6092#define SINGLE_Emin (-126) /* smallest valid exponent */
6093
6094#define LOST_UP (EX_Precision | SW_C1)
6095#define LOST_DOWN EX_Precision
6096
6097FPU_REG FPU_loaded_data;
6098
6099
6100/* Get a long double from user memory */
6101void
6102reg_load_extended(void)
6103{
6104 long double *s = (long double *) FPU_data_address;
6105 unsigned long sigl, sigh, exp;
6106
6107 REENTRANT_CHECK(OFF);
6108 /* Use temporary variables here because FPU_loaded data is static and
6109 * hence re-entrancy problems can arise */
6110 sigl = fuword((unsigned long *) s);
6111 sigh = fuword(1 + (unsigned long *) s);
6112 exp = fuword(4 + (unsigned short *) s);
6113 REENTRANT_CHECK(ON);
6114
6115 FPU_loaded_data.sigl = sigl;
6116 FPU_loaded_data.sigh = sigh;
6117 FPU_loaded_data.exp = exp;
6118
6119 if (FPU_loaded_data.exp & 0x8000)
6120 FPU_loaded_data.sign = SIGN_NEG;
6121 else
6122 FPU_loaded_data.sign = SIGN_POS;
6123 if ((FPU_loaded_data.exp &= 0x7fff) == 0) {
6124 if (!(FPU_loaded_data.sigl | FPU_loaded_data.sigh)) {
6125 FPU_loaded_data.tag = TW_Zero;
6126 return;
6127 }
6128 /* The number is a de-normal or pseudodenormal. */
6129 /* The 80486 doesn't regard pseudodenormals as denormals here. */
6130 if (!(FPU_loaded_data.sigh & 0x80000000))
6131 EXCEPTION(EX_Denormal);
6132 FPU_loaded_data.exp++;
6133
6134 /* The default behaviour will now take care of it. */
6135 } else
6136 if (FPU_loaded_data.exp == 0x7fff) {
6137 FPU_loaded_data.exp = EXTENDED_Emax;
6138 if ((FPU_loaded_data.sigh == 0x80000000)
6139 && (FPU_loaded_data.sigl == 0)) {
6140 FPU_loaded_data.tag = TW_Infinity;
6141 return;
6142 } else
6143 if (!(FPU_loaded_data.sigh & 0x80000000)) {
6144 /* Unsupported NaN data type */
6145 EXCEPTION(EX_Invalid);
6146 FPU_loaded_data.tag = TW_NaN;
6147 return;
6148 }
6149 FPU_loaded_data.tag = TW_NaN;
6150 return;
6151 }
6152 FPU_loaded_data.exp = (FPU_loaded_data.exp & 0x7fff) - EXTENDED_Ebias
6153 + EXP_BIAS;
6154 FPU_loaded_data.tag = TW_Valid;
6155
6156 if (!(sigh & 0x80000000)) {
6157 /* Unsupported data type */
6158 EXCEPTION(EX_Invalid);
6159 normalize_nuo(&FPU_loaded_data);
6160 }
6161}
6162
6163
6164/* Get a double from user memory */
6165void
6166reg_load_double(void)
6167{
6168 double *dfloat = (double *) FPU_data_address;
6169 int exp;
6170 unsigned m64, l64;
6171
6172 REENTRANT_CHECK(OFF);
6173 m64 = fuword(1 + (unsigned long *) dfloat);
6174 l64 = fuword((unsigned long *) dfloat);
6175 REENTRANT_CHECK(ON);
6176
6177 if (m64 & 0x80000000)
6178 FPU_loaded_data.sign = SIGN_NEG;
6179 else
6180 FPU_loaded_data.sign = SIGN_POS;
6181 exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias;
6182 m64 &= 0xfffff;
6183 if (exp > DOUBLE_Emax) {
6184 /* Infinity or NaN */
6185 if ((m64 == 0) && (l64 == 0)) {
6186 /* +- infinity */
6187 FPU_loaded_data.exp = EXTENDED_Emax;
6188 FPU_loaded_data.tag = TW_Infinity;
6189 return;
6190 } else {
6191 /* Must be a signaling or quiet NaN */
6192 FPU_loaded_data.exp = EXTENDED_Emax;
6193 FPU_loaded_data.tag = TW_NaN;
6194 FPU_loaded_data.sigh = (m64 << 11) | 0x80000000;
6195 FPU_loaded_data.sigh |= l64 >> 21;
6196 FPU_loaded_data.sigl = l64 << 11;
6197 return;
6198 }
6199 } else
6200 if (exp < DOUBLE_Emin) {
6201 /* Zero or de-normal */
6202 if ((m64 == 0) && (l64 == 0)) {
6203 /* Zero */
6204 int c = FPU_loaded_data.sign;
6205 reg_move(&CONST_Z, &FPU_loaded_data);
6206 FPU_loaded_data.sign = c;
6207 return;
6208 } else {
6209 /* De-normal */
6210 EXCEPTION(EX_Denormal);
6211 FPU_loaded_data.exp = DOUBLE_Emin + EXP_BIAS;
6212 FPU_loaded_data.tag = TW_Valid;
6213 FPU_loaded_data.sigh = m64 << 11;
6214 FPU_loaded_data.sigh |= l64 >> 21;
6215 FPU_loaded_data.sigl = l64 << 11;
6216 normalize_nuo(&FPU_loaded_data);
6217 return;
6218 }
6219 } else {
6220 FPU_loaded_data.exp = exp + EXP_BIAS;
6221 FPU_loaded_data.tag = TW_Valid;
6222 FPU_loaded_data.sigh = (m64 << 11) | 0x80000000;
6223 FPU_loaded_data.sigh |= l64 >> 21;
6224 FPU_loaded_data.sigl = l64 << 11;
6225
6226 return;
6227 }
6228}
6229
6230
6231/* Get a float from user memory */
6232void
6233reg_load_single(void)
6234{
6235 float *single = (float *) FPU_data_address;
6236 unsigned m32;
6237 int exp;
6238
6239 REENTRANT_CHECK(OFF);
6240 m32 = fuword((unsigned long *) single);
6241 REENTRANT_CHECK(ON);
6242
6243 if (m32 & 0x80000000)
6244 FPU_loaded_data.sign = SIGN_NEG;
6245 else
6246 FPU_loaded_data.sign = SIGN_POS;
6247 if (!(m32 & 0x7fffffff)) {
6248 /* Zero */
6249 int c = FPU_loaded_data.sign;
6250 reg_move(&CONST_Z, &FPU_loaded_data);
6251 FPU_loaded_data.sign = c;
6252 return;
6253 }
6254 exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias;
6255 m32 = (m32 & 0x7fffff) << 8;
6256 if (exp < SINGLE_Emin) {
6257 /* De-normals */
6258 EXCEPTION(EX_Denormal);
6259 FPU_loaded_data.exp = SINGLE_Emin + EXP_BIAS;
6260 FPU_loaded_data.tag = TW_Valid;
6261 FPU_loaded_data.sigh = m32;
6262 FPU_loaded_data.sigl = 0;
6263 normalize_nuo(&FPU_loaded_data);
6264 return;
6265 } else
6266 if (exp > SINGLE_Emax) {
6267 /* Infinity or NaN */
6268 if (m32 == 0) {
6269 /* +- infinity */
6270 FPU_loaded_data.exp = EXTENDED_Emax;
6271 FPU_loaded_data.tag = TW_Infinity;
6272 return;
6273 } else {
6274 /* Must be a signaling or quiet NaN */
6275 FPU_loaded_data.exp = EXTENDED_Emax;
6276 FPU_loaded_data.tag = TW_NaN;
6277 FPU_loaded_data.sigh = m32 | 0x80000000;
6278 FPU_loaded_data.sigl = 0;
6279 return;
6280 }
6281 } else {
6282 FPU_loaded_data.exp = exp + EXP_BIAS;
6283 FPU_loaded_data.sigh = m32 | 0x80000000;
6284 FPU_loaded_data.sigl = 0;
6285 FPU_loaded_data.tag = TW_Valid;
6286 }
6287}
6288
6289
6290/* Get a long long from user memory */
6291void
6292reg_load_int64(void)
6293{
6294 long long *_s = (long long *) FPU_data_address;
6295 int e;
6296 long long s;
6297
6298 REENTRANT_CHECK(OFF);
6299 ((unsigned long *) &s)[0] = fuword((unsigned long *) _s);
6300 ((unsigned long *) &s)[1] = fuword(1 + (unsigned long *) _s);
6301 REENTRANT_CHECK(ON);
6302
6303 if (s == 0) {
6304 reg_move(&CONST_Z, &FPU_loaded_data);
6305 return;
6306 }
6307 if (s > 0)
6308 FPU_loaded_data.sign = SIGN_POS;
6309 else {
6310 s = -s;
6311 FPU_loaded_data.sign = SIGN_NEG;
6312 }
6313
6314 e = EXP_BIAS + 63;
6315 *((long long *) &FPU_loaded_data.sigl) = s;
6316 FPU_loaded_data.exp = e;
6317 FPU_loaded_data.tag = TW_Valid;
6318 normalize_nuo(&FPU_loaded_data);
6319}
6320
6321
6322/* Get a long from user memory */
6323void
6324reg_load_int32(void)
6325{
6326 long *_s = (long *) FPU_data_address;
6327 long s;
6328 int e;
6329
6330 REENTRANT_CHECK(OFF);
6331 s = (long) fuword((unsigned long *) _s);
6332 REENTRANT_CHECK(ON);
6333
6334 if (s == 0) {
6335 reg_move(&CONST_Z, &FPU_loaded_data);
6336 return;
6337 }
6338 if (s > 0)
6339 FPU_loaded_data.sign = SIGN_POS;
6340 else {
6341 s = -s;
6342 FPU_loaded_data.sign = SIGN_NEG;
6343 }
6344
6345 e = EXP_BIAS + 31;
6346 FPU_loaded_data.sigh = s;
6347 FPU_loaded_data.sigl = 0;
6348 FPU_loaded_data.exp = e;
6349 FPU_loaded_data.tag = TW_Valid;
6350 normalize_nuo(&FPU_loaded_data);
6351}
6352
6353
6354/* Get a short from user memory */
6355void
6356reg_load_int16(void)
6357{
6358 short *_s = (short *) FPU_data_address;
6359 int s, e;
6360
6361 REENTRANT_CHECK(OFF);
6362 /* Cast as short to get the sign extended. */
6363 s = (short) fuword((unsigned short *) _s);
6364 REENTRANT_CHECK(ON);
6365
6366 if (s == 0) {
6367 reg_move(&CONST_Z, &FPU_loaded_data);
6368 return;
6369 }
6370 if (s > 0)
6371 FPU_loaded_data.sign = SIGN_POS;
6372 else {
6373 s = -s;
6374 FPU_loaded_data.sign = SIGN_NEG;
6375 }
6376
6377 e = EXP_BIAS + 15;
6378 FPU_loaded_data.sigh = s << 16;
6379
6380 FPU_loaded_data.sigl = 0;
6381 FPU_loaded_data.exp = e;
6382 FPU_loaded_data.tag = TW_Valid;
6383 normalize_nuo(&FPU_loaded_data);
6384}
6385
6386
6387/* Get a packed bcd array from user memory */
6388void
6389reg_load_bcd(void)
6390{
6391 char *s = (char *) FPU_data_address;
6392 int pos;
6393 unsigned char bcd;
6394 long long l = 0;
6395
6396 for (pos = 8; pos >= 0; pos--) {
6397 l *= 10;
6398 REENTRANT_CHECK(OFF);
6399 bcd = (unsigned char) fubyte((unsigned char *) s + pos);
6400 REENTRANT_CHECK(ON);
6401 l += bcd >> 4;
6402 l *= 10;
6403 l += bcd & 0x0f;
6404 }
6405
6406 /* Finish all access to user memory before putting stuff into the
6407 * static FPU_loaded_data */
6408 REENTRANT_CHECK(OFF);
6409 FPU_loaded_data.sign =
6410 ((unsigned char) fubyte((unsigned char *) s + 9)) & 0x80 ?
6411 SIGN_NEG : SIGN_POS;
6412 REENTRANT_CHECK(ON);
6413
6414 if (l == 0) {
6415 char sign = FPU_loaded_data.sign;
6416 reg_move(&CONST_Z, &FPU_loaded_data);
6417 FPU_loaded_data.sign = sign;
6418 } else {
6419 *((long long *) &FPU_loaded_data.sigl) = l;
6420 FPU_loaded_data.exp = EXP_BIAS + 63;
6421 FPU_loaded_data.tag = TW_Valid;
6422 normalize_nuo(&FPU_loaded_data);
6423 }
6424}
6425/*===========================================================================*/
6426
6427/* Put a long double into user memory */
6428int
6429reg_store_extended(void)
6430{
6431 long double *d = (long double *) FPU_data_address;
6432 long e = FPU_st0_ptr->exp - EXP_BIAS + EXTENDED_Ebias;
6433 unsigned short sign = FPU_st0_ptr->sign * 0x8000;
6434 unsigned long ls, ms;
6435
6436
6437 if (FPU_st0_tag == TW_Valid) {
6438 if (e >= 0x7fff) {
6439 EXCEPTION(EX_Overflow); /* Overflow */
6440 /* This is a special case: see sec 16.2.5.1 of the
6441 * 80486 book */
6442 if (control_word & EX_Overflow) {
6443 /* Overflow to infinity */
6444 ls = 0;
6445 ms = 0x80000000;
6446 e = 0x7fff;
6447 } else
6448 return 0;
6449 } else
6450 if (e <= 0) {
6451 if (e > -63) {
6452 /* Correctly format the de-normal */
6453 int precision_loss;
6454 FPU_REG tmp;
6455
6456 EXCEPTION(EX_Denormal);
6457 reg_move(FPU_st0_ptr, &tmp);
6458 tmp.exp += -EXTENDED_Emin + 63; /* largest exp to be 62 */
6459 if ((precision_loss = round_to_int(&tmp))) {
6460 EXCEPTION(EX_Underflow | precision_loss);
6461 /* This is a special case: see
6462 * sec 16.2.5.1 of the 80486
6463 * book */
6464 if (!(control_word & EX_Underflow))
6465 return 0;
6466 }
6467 e = 0;
6468 ls = tmp.sigl;
6469 ms = tmp.sigh;
6470 } else {
6471 /* ****** ??? This should not be
6472 * possible */
6473 EXCEPTION(EX_Underflow); /* Underflow */
6474 /* This is a special case: see sec
6475 * 16.2.5.1 of the 80486 book */
6476 if (control_word & EX_Underflow) {
6477 /* Underflow to zero */
6478 ls = 0;
6479 ms = 0;
6480 e = FPU_st0_ptr->sign == SIGN_POS ? 0x7fff : 0xffff;
6481 } else
6482 return 0;
6483 }
6484 } else {
6485 ls = FPU_st0_ptr->sigl;
6486 ms = FPU_st0_ptr->sigh;
6487 }
6488 } else
6489 if (FPU_st0_tag == TW_Zero) {
6490 ls = ms = 0;
6491 e = 0;
6492 } else
6493 if (FPU_st0_tag == TW_Infinity) {
6494 ls = 0;
6495 ms = 0x80000000;
6496 e = 0x7fff;
6497 } else
6498 if (FPU_st0_tag == TW_NaN) {
6499 ls = FPU_st0_ptr->sigl;
6500 ms = FPU_st0_ptr->sigh;
6501 e = 0x7fff;
6502 } else
6503 if (FPU_st0_tag == TW_Empty) {
6504 /* Empty register (stack
6505 * underflow) */
6506 EXCEPTION(EX_StackUnder);
6507 if (control_word & EX_Invalid) {
6508 /* The masked response */
6509 /* Put out the QNaN
6510 * indefinite */
6511 ls = 0;
6512 ms = 0xc0000000;
6513 e = 0xffff;
6514 } else
6515 return 0;
6516 } else {
6517 /* We don't use TW_Denormal
6518 * yet ... perhaps never! */
6519 EXCEPTION(EX_Invalid);
6520 /* Store a NaN */
6521 e = 0x7fff;
6522 ls = 1;
6523 ms = 0x80000000;
6524 }
6525 REENTRANT_CHECK(OFF);
6526/* verify_area(VERIFY_WRITE, d, 10); */
6527 suword((unsigned long *) d, ls);
6528 suword(1 + (unsigned long *) d, ms);
6529 suword(4 + (short *) d, (unsigned short) e | sign);
6530 REENTRANT_CHECK(ON);
6531
6532 return 1;
6533
6534}
6535
6536
6537/* Put a double into user memory */
6538int
6539reg_store_double(void)
6540{
6541 double *dfloat = (double *) FPU_data_address;
6542 unsigned long l[2];
6543 if (FPU_st0_tag == TW_Valid) {
6544 int exp;
6545 FPU_REG tmp;
6546
6547 reg_move(FPU_st0_ptr, &tmp);
6548 exp = tmp.exp - EXP_BIAS;
6549
6550 if (exp < DOUBLE_Emin) { /* It may be a denormal */
6551 /* Make a de-normal */
6552 int precision_loss;
6553
6554 if (exp <= -EXTENDED_Ebias)
6555 EXCEPTION(EX_Denormal);
6556
6557 tmp.exp += -DOUBLE_Emin + 52; /* largest exp to be 51 */
6558
6559 if ((precision_loss = round_to_int(&tmp))) {
6560#ifdef PECULIAR_486
6561 /* Did it round to a non-denormal ? */
6562 /* This behaviour might be regarded as
6563 * peculiar, it appears that the 80486 rounds
6564 * to the dest precision, then converts to
6565 * decide underflow. */
6566 if ((tmp.sigh == 0x00100000) && (tmp.sigl == 0) &&
6567 (FPU_st0_ptr->sigl & 0x000007ff))
6568 EXCEPTION(precision_loss);
6569 else
6570#endif /* PECULIAR_486 */
6571 {
6572 EXCEPTION(EX_Underflow | precision_loss);
6573 /* This is a special case: see sec
6574 * 16.2.5.1 of the 80486 book */
6575 if (!(control_word & EX_Underflow))
6576 return 0;
6577 }
6578 }
6579 l[0] = tmp.sigl;
6580 l[1] = tmp.sigh;
6581 } else {
6582 if (tmp.sigl & 0x000007ff) {
6583 unsigned long increment = 0; /* avoid gcc warnings */
6584
6585 switch (control_word & CW_RC) {
6586 case RC_RND:
6587 /* Rounding can get a little messy.. */
6588 increment = ((tmp.sigl & 0x7ff) > 0x400) | /* nearest */
6589 ((tmp.sigl & 0xc00) == 0xc00); /* odd -> even */
6590 break;
6591 case RC_DOWN: /* towards -infinity */
6592 increment = (tmp.sign == SIGN_POS) ? 0 : tmp.sigl & 0x7ff;
6593 break;
6594 case RC_UP: /* towards +infinity */
6595 increment = (tmp.sign == SIGN_POS) ? tmp.sigl & 0x7ff : 0;
6596 break;
6597 case RC_CHOP:
6598 increment = 0;
6599 break;
6600 }
6601
6602 /* Truncate the mantissa */
6603 tmp.sigl &= 0xfffff800;
6604
6605 if (increment) {
6606 set_precision_flag_up();
6607
6608 if (tmp.sigl >= 0xfffff800) {
6609 /* the sigl part overflows */
6610 if (tmp.sigh == 0xffffffff) {
6611 /* The sigh part
6612 * overflows */
6613 tmp.sigh = 0x80000000;
6614 exp++;
6615 if (exp >= EXP_OVER)
6616 goto overflow;
6617 } else {
6618 tmp.sigh++;
6619 }
6620 tmp.sigl = 0x00000000;
6621 } else {
6622 /* We only need to increment
6623 * sigl */
6624 tmp.sigl += 0x00000800;
6625 }
6626 } else
6627 set_precision_flag_down();
6628 }
6629 l[0] = (tmp.sigl >> 11) | (tmp.sigh << 21);
6630 l[1] = ((tmp.sigh >> 11) & 0xfffff);
6631
6632 if (exp > DOUBLE_Emax) {
6633 overflow:
6634 EXCEPTION(EX_Overflow);
6635 /* This is a special case: see sec 16.2.5.1 of
6636 * the 80486 book */
6637 if (control_word & EX_Overflow) {
6638 /* Overflow to infinity */
6639 l[0] = 0x00000000; /* Set to */
6640 l[1] = 0x7ff00000; /* + INF */
6641 } else
6642 return 0;
6643 } else {
6644 /* Add the exponent */
6645 l[1] |= (((exp + DOUBLE_Ebias) & 0x7ff) << 20);
6646 }
6647 }
6648 } else
6649 if (FPU_st0_tag == TW_Zero) {
6650 /* Number is zero */
6651 l[0] = 0;
6652 l[1] = 0;
6653 } else
6654 if (FPU_st0_tag == TW_Infinity) {
6655 l[0] = 0;
6656 l[1] = 0x7ff00000;
6657 } else
6658 if (FPU_st0_tag == TW_NaN) {
6659 /* See if we can get a valid NaN from
6660 * the FPU_REG */
6661 l[0] = (FPU_st0_ptr->sigl >> 11) | (FPU_st0_ptr->sigh << 21);
6662 l[1] = ((FPU_st0_ptr->sigh >> 11) & 0xfffff);
6663 if (!(l[0] | l[1])) {
6664 /* This case does not seem to
6665 * be handled by the 80486
6666 * specs */
6667 EXCEPTION(EX_Invalid);
6668 /* Make the quiet NaN "real
6669 * indefinite" */
6670 goto put_indefinite;
6671 }
6672 l[1] |= 0x7ff00000;
6673 } else
6674 if (FPU_st0_tag == TW_Empty) {
6675 /* Empty register (stack
6676 * underflow) */
6677 EXCEPTION(EX_StackUnder);
6678 if (control_word & EX_Invalid) {
6679 /* The masked response */
6680 /* Put out the QNaN
6681 * indefinite */
6682 put_indefinite:
6683 REENTRANT_CHECK(OFF);
6684 /* verify_area(VERIFY_W
6685 * RITE, (void *)
6686 * dfloat, 8); */
6687 suword((unsigned long *) dfloat, 0);
6688 suword(1 + (unsigned long *) dfloat, 0xfff80000);
6689 REENTRANT_CHECK(ON);
6690 return 1;
6691 } else
6692 return 0;
6693 }
6694#if 0 /* TW_Denormal is not used yet, and probably
6695 * won't be */
6696 else
6697 if (FPU_st0_tag == TW_Denormal) {
6698 /* Extended real ->
6699 * double real will
6700 * always underflow */
6701 l[0] = l[1] = 0;
6702 EXCEPTION(EX_Underflow);
6703 }
6704#endif
6705 if (FPU_st0_ptr->sign)
6706 l[1] |= 0x80000000;
6707
6708 REENTRANT_CHECK(OFF);
6709/* verify_area(VERIFY_WRITE, (void *) dfloat, 8);*/
6710 suword((u_long *) dfloat, l[0]);
6711 suword((u_long *) dfloat + 1, l[1]);
6712/*
6713 suword(l[0], (unsigned long *) dfloat);
6714 suword(l[1], 1 + (unsigned long *) dfloat);*/
6715 REENTRANT_CHECK(ON);
6716
6717 return 1;
6718}
6719
6720
6721/* Put a float into user memory */
6722int
6723reg_store_single(void)
6724{
6725 float *single = (float *) FPU_data_address;
6726 long templ;
6727
6728 if (FPU_st0_tag == TW_Valid) {
6729 int exp;
6730 FPU_REG tmp;
6731
6732 reg_move(FPU_st0_ptr, &tmp);
6733 exp = tmp.exp - EXP_BIAS;
6734
6735 if (exp < SINGLE_Emin) {
6736 /* Make a de-normal */
6737 int precision_loss;
6738
6739 if (exp <= -EXTENDED_Ebias)
6740 EXCEPTION(EX_Denormal);
6741
6742 tmp.exp += -SINGLE_Emin + 23; /* largest exp to be 22 */
6743
6744 if ((precision_loss = round_to_int(&tmp))) {
6745#ifdef PECULIAR_486
6746 /* Did it round to a non-denormal ? */
6747 /* This behaviour might be regarded as
6748 * peculiar, it appears that the 80486 rounds
6749 * to the dest precision, then converts to
6750 * decide underflow. */
6751 if ((tmp.sigl == 0x00800000) &&
6752 ((FPU_st0_ptr->sigh & 0x000000ff) || FPU_st0_ptr->sigl))
6753 EXCEPTION(precision_loss);
6754 else
6755#endif /* PECULIAR_486 */
6756 {
6757 EXCEPTION(EX_Underflow | precision_loss);
6758 /* This is a special case: see sec
6759 * 16.2.5.1 of the 80486 book */
6760 if (!(control_word & EX_Underflow))
6761 return 0;
6762 }
6763 }
6764 templ = tmp.sigl;
6765 } else {
6766 if (tmp.sigl | (tmp.sigh & 0x000000ff)) {
6767 unsigned long increment = 0; /* avoid gcc warnings */
6768 unsigned long sigh = tmp.sigh;
6769 unsigned long sigl = tmp.sigl;
6770
6771 switch (control_word & CW_RC) {
6772 case RC_RND:
6773 increment = ((sigh & 0xff) > 0x80) /* more than half */
6774 ||(((sigh & 0xff) == 0x80) && sigl) /* more than half */
6775 ||((sigh & 0x180) == 0x180); /* round to even */
6776 break;
6777 case RC_DOWN: /* towards -infinity */
6778 increment = (tmp.sign == SIGN_POS)
6779 ? 0 : (sigl | (sigh & 0xff));
6780 break;
6781 case RC_UP: /* towards +infinity */
6782 increment = (tmp.sign == SIGN_POS)
6783 ? (sigl | (sigh & 0xff)) : 0;
6784 break;
6785 case RC_CHOP:
6786 increment = 0;
6787 break;
6788 }
6789
6790 /* Truncate part of the mantissa */
6791 tmp.sigl = 0;
6792
6793 if (increment) {
6794 set_precision_flag_up();
6795
6796 if (sigh >= 0xffffff00) {
6797 /* The sigh part overflows */
6798 tmp.sigh = 0x80000000;
6799 exp++;
6800 if (exp >= EXP_OVER)
6801 goto overflow;
6802 } else {
6803 tmp.sigh &= 0xffffff00;
6804 tmp.sigh += 0x100;
6805 }
6806 } else {
6807 set_precision_flag_down();
6808 tmp.sigh &= 0xffffff00; /* Finish the truncation */
6809 }
6810 }
6811 templ = (tmp.sigh >> 8) & 0x007fffff;
6812
6813 if (exp > SINGLE_Emax) {
6814 overflow:
6815 EXCEPTION(EX_Overflow);
6816 /* This is a special case: see sec 16.2.5.1 of
6817 * the 80486 book */
6818 if (control_word & EX_Overflow) {
6819 /* Overflow to infinity */
6820 templ = 0x7f800000;
6821 } else
6822 return 0;
6823 } else
6824 templ |= ((exp + SINGLE_Ebias) & 0xff) << 23;
6825 }
6826 } else
6827 if (FPU_st0_tag == TW_Zero) {
6828 templ = 0;
6829 } else
6830 if (FPU_st0_tag == TW_Infinity) {
6831 templ = 0x7f800000;
6832 } else
6833 if (FPU_st0_tag == TW_NaN) {
6834 /* See if we can get a valid NaN from
6835 * the FPU_REG */
6836 templ = FPU_st0_ptr->sigh >> 8;
6837 if (!(templ & 0x3fffff)) {
6838 /* This case does not seem to
6839 * be handled by the 80486
6840 * specs */
6841 EXCEPTION(EX_Invalid);
6842 /* Make the quiet NaN "real
6843 * indefinite" */
6844 goto put_indefinite;
6845 }
6846 templ |= 0x7f800000;
6847 } else
6848 if (FPU_st0_tag == TW_Empty) {
6849 /* Empty register (stack
6850 * underflow) */
6851 EXCEPTION(EX_StackUnder);
6852 if (control_word & EX_Invalid) {
6853 /* The masked response */
6854 /* Put out the QNaN
6855 * indefinite */
6856 put_indefinite:
6857 REENTRANT_CHECK(OFF);
6858/* verify_area(VERIFY_WRITE, (void *) single, 4); */
6859 suword((unsigned long *) single, 0xffc00000);
6860 REENTRANT_CHECK(ON);
6861 return 1;
6862 } else
6863 return 0;
6864 }
6865#if 0 /* TW_Denormal is not used yet, and probably
6866 * won't be */
6867 else
6868 if (FPU_st0_tag == TW_Denormal) {
6869 /* Extended real ->
6870 * real will always
6871 * underflow */
6872 templ = 0;
6873 EXCEPTION(EX_Underflow);
6874 }
6875#endif
6876#ifdef PARANOID
6877 else {
6878 EXCEPTION(EX_INTERNAL | 0x106);
6879 return 0;
6880 }
6881#endif
6882 if (FPU_st0_ptr->sign)
6883 templ |= 0x80000000;
6884
6885 REENTRANT_CHECK(OFF);
6886/* verify_area(VERIFY_WRITE, (void *) single, 4); */
6887 suword((unsigned long *) single, templ);
6888 REENTRANT_CHECK(ON);
6889
6890 return 1;
6891}
6892
6893
6894/* Put a long long into user memory */
6895int
6896reg_store_int64(void)
6897{
6898 long long *d = (long long *) FPU_data_address;
6899 FPU_REG t;
6900 long long tll;
6901
6902 if (FPU_st0_tag == TW_Empty) {
6903 /* Empty register (stack underflow) */
6904 EXCEPTION(EX_StackUnder);
6905 if (control_word & EX_Invalid) {
6906 /* The masked response */
6907 /* Put out the QNaN indefinite */
6908 goto put_indefinite;
6909 } else
6910 return 0;
6911 }
6912 reg_move(FPU_st0_ptr, &t);
6913 round_to_int(&t);
6914 ((long *) &tll)[0] = t.sigl;
6915 ((long *) &tll)[1] = t.sigh;
6916 if ((t.sigh & 0x80000000) &&
6917 !((t.sigh == 0x80000000) && (t.sigl == 0) && (t.sign == SIGN_NEG))) {
6918 EXCEPTION(EX_Invalid);
6919 /* This is a special case: see sec 16.2.5.1 of the 80486 book */
6920 if (control_word & EX_Invalid) {
6921 /* Produce "indefinite" */
6922 put_indefinite:
6923 ((long *) &tll)[1] = 0x80000000;
6924 ((long *) &tll)[0] = 0;
6925 } else
6926 return 0;
6927 } else
6928 if (t.sign)
6929 tll = -tll;
6930
6931 REENTRANT_CHECK(OFF);
6932/* verify_area(VERIFY_WRITE, (void *) d, 8); */
6933 suword((unsigned long *) d, ((long *) &tll)[0]);
6934 suword(1 + (unsigned long *) d, ((long *) &tll)[1]);
6935 REENTRANT_CHECK(ON);
6936
6937 return 1;
6938}
6939
6940
6941/* Put a long into user memory */
6942int
6943reg_store_int32(void)
6944{
6945 long *d = (long *) FPU_data_address;
6946 FPU_REG t;
6947
6948 if (FPU_st0_tag == TW_Empty) {
6949 /* Empty register (stack underflow) */
6950 EXCEPTION(EX_StackUnder);
6951 if (control_word & EX_Invalid) {
6952 /* The masked response */
6953 /* Put out the QNaN indefinite */
6954 REENTRANT_CHECK(OFF);
6955/* verify_area(VERIFY_WRITE, d, 4);*/
6956 suword((unsigned long *) d, 0x80000000);
6957 REENTRANT_CHECK(ON);
6958 return 1;
6959 } else
6960 return 0;
6961 }
6962 reg_move(FPU_st0_ptr, &t);
6963 round_to_int(&t);
6964 if (t.sigh ||
6965 ((t.sigl & 0x80000000) &&
6966 !((t.sigl == 0x80000000) && (t.sign == SIGN_NEG)))) {
6967 EXCEPTION(EX_Invalid);
6968 /* This is a special case: see sec 16.2.5.1 of the 80486 book */
6969 if (control_word & EX_Invalid) {
6970 /* Produce "indefinite" */
6971 t.sigl = 0x80000000;
6972 } else
6973 return 0;
6974 } else
6975 if (t.sign)
6976 t.sigl = -(long) t.sigl;
6977
6978 REENTRANT_CHECK(OFF);
6979/* verify_area(VERIFY_WRITE, d, 4); */
6980 suword((unsigned long *) d, t.sigl);
6981 REENTRANT_CHECK(ON);
6982
6983 return 1;
6984}
6985
6986
6987/* Put a short into user memory */
6988int
6989reg_store_int16(void)
6990{
6991 short *d = (short *) FPU_data_address;
6992 FPU_REG t;
6993 short ts;
6994
6995 if (FPU_st0_tag == TW_Empty) {
6996 /* Empty register (stack underflow) */
6997 EXCEPTION(EX_StackUnder);
6998 if (control_word & EX_Invalid) {
6999 /* The masked response */
7000 /* Put out the QNaN indefinite */
7001 REENTRANT_CHECK(OFF);
7002/* verify_area(VERIFY_WRITE, d, 2);*/
7003 suword((unsigned short *) d, 0x8000);
7004 REENTRANT_CHECK(ON);
7005 return 1;
7006 } else
7007 return 0;
7008 }
7009 reg_move(FPU_st0_ptr, &t);
7010 round_to_int(&t);
7011 if (t.sigh ||
7012 ((t.sigl & 0xffff8000) &&
7013 !((t.sigl == 0x8000) && (t.sign == SIGN_NEG)))) {
7014 EXCEPTION(EX_Invalid);
7015 /* This is a special case: see sec 16.2.5.1 of the 80486 book */
7016 if (control_word & EX_Invalid) {
7017 /* Produce "indefinite" */
7018 ts = 0x8000;
7019 } else
7020 return 0;
7021 } else
7022 if (t.sign)
7023 t.sigl = -t.sigl;
7024
7025 REENTRANT_CHECK(OFF);
7026/* verify_area(VERIFY_WRITE, d, 2); */
7027 suword((short *) d, (short) t.sigl);
7028 REENTRANT_CHECK(ON);
7029
7030 return 1;
7031}
7032
7033
7034/* Put a packed bcd array into user memory */
7035int
7036reg_store_bcd(void)
7037{
7038 char *d = (char *) FPU_data_address;
7039 FPU_REG t;
7040 long long ll;
7041 unsigned char b;
7042 int i;
7043 unsigned char sign = (FPU_st0_ptr->sign == SIGN_NEG) ? 0x80 : 0;
7044
7045 if (FPU_st0_tag == TW_Empty) {
7046 /* Empty register (stack underflow) */
7047 EXCEPTION(EX_StackUnder);
7048 if (control_word & EX_Invalid) {
7049 /* The masked response */
7050 /* Put out the QNaN indefinite */
7051 goto put_indefinite;
7052 } else
7053 return 0;
7054 }
7055 reg_move(FPU_st0_ptr, &t);
7056 round_to_int(&t);
7057 ll = *(long long *) (&t.sigl);
7058
7059 /* Check for overflow, by comparing with 999999999999999999 decimal. */
7060 if ((t.sigh > 0x0de0b6b3) ||
7061 ((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff))) {
7062 EXCEPTION(EX_Invalid);
7063 /* This is a special case: see sec 16.2.5.1 of the 80486 book */
7064 if (control_word & EX_Invalid) {
7065 put_indefinite:
7066 /* Produce "indefinite" */
7067 REENTRANT_CHECK(OFF);
7068/* verify_area(VERIFY_WRITE, d, 10);*/
7069 subyte((unsigned char *) d + 7, 0xff);
7070 subyte((unsigned char *) d + 8, 0xff);
7071 subyte((unsigned char *) d + 9, 0xff);
7072 REENTRANT_CHECK(ON);
7073 return 1;
7074 } else
7075 return 0;
7076 }
7077/* verify_area(VERIFY_WRITE, d, 10);*/
7078 for (i = 0; i < 9; i++) {
7079 b = div_small(&ll, 10);
7080 b |= (div_small(&ll, 10)) << 4;
7081 REENTRANT_CHECK(OFF);
7082 subyte((unsigned char *) d + i, b);
7083 REENTRANT_CHECK(ON);
7084 }
7085 REENTRANT_CHECK(OFF);
7086 subyte((unsigned char *) d + 9, sign);
7087 REENTRANT_CHECK(ON);
7088
7089 return 1;
7090}
7091/*===========================================================================*/
7092
7093/* r gets mangled such that sig is int, sign:
7094 it is NOT normalized */
7095/* The return value (in eax) is zero if the result is exact,
7096 if bits are changed due to rounding, truncation, etc, then
7097 a non-zero value is returned */
7098/* Overflow is signalled by a non-zero return value (in eax).
7099 In the case of overflow, the returned significand always has the
7100 the largest possible value */
7101/* The value returned in eax is never actually needed :-) */
7102int
7103round_to_int(FPU_REG * r)
7104{
7105 char very_big;
7106 unsigned eax;
7107
7108 if (r->tag == TW_Zero) {
7109 /* Make sure that zero is returned */
7110 *(long long *) &r->sigl = 0;
7111 return 0; /* o.k. */
7112 }
7113 if (r->exp > EXP_BIAS + 63) {
7114 r->sigl = r->sigh = ~0; /* The largest representable number */
7115 return 1; /* overflow */
7116 }
7117 eax = shrxs(&r->sigl, EXP_BIAS + 63 - r->exp);
7118 very_big = !(~(r->sigh) | ~(r->sigl)); /* test for 0xfff...fff */
7119#define half_or_more (eax & 0x80000000)
7120#define frac_part (eax)
7121#define more_than_half ((eax & 0x80000001) == 0x80000001)
7122 switch (control_word & CW_RC) {
7123 case RC_RND:
7124 if (more_than_half /* nearest */
7125 || (half_or_more && (r->sigl & 1))) { /* odd -> even */
7126 if (very_big)
7127 return 1; /* overflow */
7128 (*(long long *) (&r->sigl))++;
7129 return LOST_UP;
7130 }
7131 break;
7132 case RC_DOWN:
7133 if (frac_part && r->sign) {
7134 if (very_big)
7135 return 1; /* overflow */
7136 (*(long long *) (&r->sigl))++;
7137 return LOST_UP;
7138 }
7139 break;
7140 case RC_UP:
7141 if (frac_part && !r->sign) {
7142 if (very_big)
7143 return 1; /* overflow */
7144 (*(long long *) (&r->sigl))++;
7145 return LOST_UP;
7146 }
7147 break;
7148 case RC_CHOP:
7149 break;
7150 }
7151
7152 return eax ? LOST_DOWN : 0;
7153
7154}
7155/*===========================================================================*/
7156
7157char *
7158fldenv(void)
7159{
7160 char *s = (char *) FPU_data_address;
7161 unsigned short tag_word = 0;
7162 unsigned char tag;
7163 int i;
7164
7165 REENTRANT_CHECK(OFF);
7166 control_word = fuword((unsigned short *) s);
7167 status_word = fuword((unsigned short *) (s + 4));
7168 tag_word = fuword((unsigned short *) (s + 8));
7169 ip_offset = fuword((unsigned long *) (s + 0x0c));
7170 cs_selector = fuword((unsigned long *) (s + 0x10));
7171 data_operand_offset = fuword((unsigned long *) (s + 0x14));
7172 operand_selector = fuword((unsigned long *) (s + 0x18));
7173 REENTRANT_CHECK(ON);
7174
7175 top = (status_word >> SW_Top_Shift) & 7;
7176
7177 for (i = 0; i < 8; i++) {
7178 tag = tag_word & 3;
7179 tag_word >>= 2;
7180
7181 switch (tag) {
7182 case 0:
7183 regs[i].tag = TW_Valid;
7184 break;
7185 case 1:
7186 regs[i].tag = TW_Zero;
7187 break;
7188 case 2:
7189 regs[i].tag = TW_NaN;
7190 break;
7191 case 3:
7192 regs[i].tag = TW_Empty;
7193 break;
7194 }
7195 }
7196
7197 FPU_data_address = (void *) data_operand_offset; /* We want no net effect */
7198 FPU_entry_eip = ip_offset; /* We want no net effect */
7199
7200 return s + 0x1c;
7201}
7202
7203
7204void
7205frstor(void)
7206{
7207 int i, stnr;
7208 unsigned char tag;
7209 unsigned short saved_status, saved_control;
7210 char *s = (char *) fldenv();
7211
7212 saved_status = status_word;
7213 saved_control = control_word;
7214 control_word = 0x037f; /* Mask all interrupts while we load. */
7215 for (i = 0; i < 8; i++) {
7216 /* load each register */
7217 FPU_data_address = (void *) (s + i * 10);
7218 reg_load_extended();
7219 stnr = (i + top) & 7;
7220 tag = regs[stnr].tag; /* derived from the loaded tag word */
7221 reg_move(&FPU_loaded_data, &regs[stnr]);
7222 if (tag == TW_NaN) {
7223 /* The current data is a special, i.e. NaN,
7224 * unsupported, infinity, or denormal */
7225 unsigned char t = regs[stnr].tag; /* derived from the new
7226 * data */
7227 if ( /* (t == TW_Valid) || *** */ (t == TW_Zero))
7228 regs[stnr].tag = TW_NaN;
7229 } else
7230 regs[stnr].tag = tag;
7231 }
7232 control_word = saved_control;
7233 status_word = saved_status;
7234
7235 FPU_data_address = (void *) data_operand_offset; /* We want no net effect */
7236}
7237
7238
7239unsigned short
7240tag_word(void)
7241{
7242 unsigned short word = 0;
7243 unsigned char tag;
7244 int i;
7245
7246 for (i = 7; i >= 0; i--) {
7247 switch (tag = regs[i].tag) {
7248#if 0 /* TW_Denormal is not used yet, and probably
7249 * won't be */
7250 case TW_Denormal:
7251#endif
7252 case TW_Valid:
7253 if (regs[i].exp <= (EXP_BIAS - EXTENDED_Ebias))
7254 tag = 2;
7255 break;
7256 case TW_Infinity:
7257 case TW_NaN:
7258 tag = 2;
7259 break;
7260 case TW_Empty:
7261 tag = 3;
7262 break;
7263 /* TW_Valid and TW_Zero already have the correct value */
7264 }
7265 word <<= 2;
7266 word |= tag;
7267 }
7268 return word;
7269}
7270
7271
7272char *
7273fstenv(void)
7274{
7275 char *d = (char *) FPU_data_address;
7276
7277/* verify_area(VERIFY_WRITE, d, 28);*/
7278
7279#if 0 /****/
7280 *(unsigned short *) &cs_selector = fpu_cs;
7281 *(unsigned short *) &operand_selector = fpu_os;
7282#endif /****/
7283
7284 REENTRANT_CHECK(OFF);
7285 suword((unsigned short *) d, control_word);
7286 suword((unsigned short *) (d + 4), (status_word & ~SW_Top) | ((top & 7) << SW_Top_Shift));
7287 suword((unsigned short *) (d + 8), tag_word());
7288 suword((unsigned long *) (d + 0x0c), ip_offset);
7289 suword((unsigned long *) (d + 0x10), cs_selector);
7290 suword((unsigned long *) (d + 0x14), data_operand_offset);
7291 suword((unsigned long *) (d + 0x18), operand_selector);
7292 REENTRANT_CHECK(ON);
7293
7294 return d + 0x1c;
7295}
7296
7297
7298void
7299fsave(void)
7300{
7301 char *d;
7302 FPU_REG tmp, *rp;
7303 int i;
7304 short e;
7305
7306 d = fstenv();
7307/* verify_area(VERIFY_WRITE, d, 80);*/
7308 for (i = 0; i < 8; i++) {
7309 /* Store each register in the order: st(0), st(1), ... */
7310 rp = &regs[(top + i) & 7];
7311
7312 e = rp->exp - EXP_BIAS + EXTENDED_Ebias;
7313
7314 if (rp->tag == TW_Valid) {
7315 if (e >= 0x7fff) {
7316 /* Overflow to infinity */
7317 REENTRANT_CHECK(OFF);
7318 suword((unsigned long *) (d + i * 10), 0);
7319 suword((unsigned long *) (d + i * 10 + 4), 0);
7320 REENTRANT_CHECK(ON);
7321 e = 0x7fff;
7322 } else
7323 if (e <= 0) {
7324 if (e > -63) {
7325 /* Make a de-normal */
7326 reg_move(rp, &tmp);
7327 tmp.exp += -EXTENDED_Emin + 63; /* largest exp to be 62 */
7328 round_to_int(&tmp);
7329 REENTRANT_CHECK(OFF);
7330 suword((unsigned long *) (d + i * 10), tmp.sigl);
7331 suword((unsigned long *) (d + i * 10 + 4), tmp.sigh);
7332 REENTRANT_CHECK(ON);
7333 } else {
7334 /* Underflow to zero */
7335 REENTRANT_CHECK(OFF);
7336 suword((unsigned long *) (d + i * 10), 0);
7337 suword((unsigned long *) (d + i * 10 + 4), 0);
7338 REENTRANT_CHECK(ON);
7339 }
7340 e = 0;
7341 } else {
7342 REENTRANT_CHECK(OFF);
7343 suword((unsigned long *) (d + i * 10), rp->sigl);
7344 suword((unsigned long *) (d + i * 10 + 4), rp->sigh);
7345 REENTRANT_CHECK(ON);
7346 }
7347 } else
7348 if (rp->tag == TW_Zero) {
7349 REENTRANT_CHECK(OFF);
7350 suword((unsigned long *) (d + i * 10), 0);
7351 suword((unsigned long *) (d + i * 10 + 4), 0);
7352 REENTRANT_CHECK(ON);
7353 e = 0;
7354 } else
7355 if (rp->tag == TW_Infinity) {
7356 REENTRANT_CHECK(OFF);
7357 suword((unsigned long *) (d + i * 10), 0);
7358 suword((unsigned long *) (d + i * 10 + 4), 0x80000000);
7359 REENTRANT_CHECK(ON);
7360 e = 0x7fff;
7361 } else
7362 if (rp->tag == TW_NaN) {
7363 REENTRANT_CHECK(OFF);
7364 suword((unsigned long *) (d + i * 10), rp->sigl);
7365 suword((unsigned long *) (d + i * 10 + 4), rp->sigh);
7366 REENTRANT_CHECK(ON);
7367 e = 0x7fff;
7368 } else
7369 if (rp->tag == TW_Empty) {
7370 /* just copy the reg */
7371 REENTRANT_CHECK(OFF);
7372 suword((unsigned long *) (d + i * 10), rp->sigl);
7373 suword((unsigned long *) (d + i * 10 + 4), rp->sigh);
7374 REENTRANT_CHECK(ON);
7375 }
7376 e |= rp->sign == SIGN_POS ? 0 : 0x8000;
7377 REENTRANT_CHECK(OFF);
7378 suword((unsigned short *) (d + i * 10 + 8), e);
7379 REENTRANT_CHECK(ON);
7380 }
7381
7382 finit();
7383
7384}
7385/*===========================================================================*/
7386\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/reg_div.s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 14734 5462505570 12412\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 .file "reg_div.S"
7387/*
7388 * reg_div.S
7389 *
7390 * Divide one FPU_REG by another and put the result in a destination FPU_REG.
7391 *
7392 * Call from C as:
7393 * void reg_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest,
7394 *
7395 *
7396 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
7397 * Vic 3163, Australia.
7398 * E-mail apm233m@vaxc.cc.monash.edu.au
7399 * All rights reserved.
7400 *
7401 * This copyright notice covers the redistribution and use of the
7402 * FPU emulator developed by W. Metzenthen. It covers only its use
7403 * in the 386BSD operating system. Any other use is not permitted
7404 * under this copyright.
7405 *
7406 * Redistribution and use in source and binary forms, with or without
7407 * modification, are permitted provided that the following conditions
7408 * are met:
7409 * 1. Redistributions of source code must retain the above copyright
7410 * notice, this list of conditions and the following disclaimer.
7411 * 2. Redistributions in binary form must include information specifying
7412 * that source code for the emulator is freely available and include
7413 * either:
7414 * a) an offer to provide the source code for a nominal distribution
7415 * fee, or
7416 * b) list at least two alternative methods whereby the source
7417 * can be obtained, e.g. a publically accessible bulletin board
7418 * and an anonymous ftp site from which the software can be
7419 * downloaded.
7420 * 3. All advertising materials specifically mentioning features or use of
7421 * this emulator must acknowledge that it was developed by W. Metzenthen.
7422 * 4. The name of W. Metzenthen may not be used to endorse or promote
7423 * products derived from this software without specific prior written
7424 * permission.
7425 *
7426 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
7427 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
7428 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
7429 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
7430 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
7431 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
7432 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
7433 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
7434 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
7435 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7436 * unsigned int control_word)
7437 */
7438
7439#include "exception.h"
7440#include "fpu_asm.h"
7441#include "control_w.h"
7442
7443.text
7444 .align 2
7445
7446.globl _reg_div
7447_reg_div:
7448 pushl %ebp
7449 movl %esp,%ebp
7450
7451 pushl %esi
7452 pushl %edi
7453 pushl %ebx
7454
7455 movl PARAM1,%esi
7456 movl PARAM2,%ebx
7457 movl PARAM3,%edi
7458
7459 movb TAG(%esi),%al
7460 orb TAG(%ebx),%al
7461
7462 jne L_div_special /* Not (both numbers TW_Valid) */
7463
7464#ifdef DENORM_OPERAND
7465/* Check for denormals */
7466 cmpl EXP_UNDER,EXP(%esi)
7467 jg xL_arg1_not_denormal
7468
7469 call _denormal_operand
7470 orl %eax,%eax
7471 jnz FPU_Arith_exit
7472
7473xL_arg1_not_denormal:
7474 cmpl EXP_UNDER,EXP(%ebx)
7475 jg xL_arg2_not_denormal
7476
7477 call _denormal_operand
7478 orl %eax,%eax
7479 jnz FPU_Arith_exit
7480
7481xL_arg2_not_denormal:
7482#endif DENORM_OPERAND
7483
7484/* Both arguments are TW_Valid */
7485 movb TW_Valid,TAG(%edi)
7486
7487 movb SIGN(%esi),%cl
7488 cmpb %cl,SIGN(%ebx)
7489 setne (%edi) /* Set the sign, requires SIGN_NEG=1, SIGN_POS=0 */
7490
7491 movl EXP(%esi),%edx
7492 movl EXP(%ebx),%eax
7493 subl %eax,%edx
7494 addl EXP_BIAS,%edx
7495 movl %edx,EXP(%edi)
7496
7497 jmp _divide_kernel
7498
7499
7500/*-----------------------------------------------------------------------*/
7501L_div_special:
7502 cmpb TW_NaN,TAG(%esi) /* A NaN with anything to give NaN */
7503 je L_arg1_NaN
7504
7505 cmpb TW_NaN,TAG(%ebx) /* A NaN with anything to give NaN */
7506 jne L_no_NaN_arg
7507
7508/* Operations on NaNs */
7509L_arg1_NaN:
7510L_arg2_NaN:
7511 pushl %edi /* Destination */
7512 pushl %ebx
7513 pushl %esi
7514 call _real_2op_NaN
7515 jmp LDiv_exit
7516
7517/* Invalid operations */
7518L_zero_zero:
7519L_inf_inf:
7520 pushl %edi /* Destination */
7521 call _arith_invalid /* 0/0 or Infinity/Infinity */
7522 jmp LDiv_exit
7523
7524L_no_NaN_arg:
7525 cmpb TW_Infinity,TAG(%esi)
7526 jne L_arg1_not_inf
7527
7528 cmpb TW_Infinity,TAG(%ebx)
7529 je L_inf_inf /* invalid operation */
7530
7531 cmpb TW_Valid,TAG(%ebx)
7532 je L_inf_valid
7533
7534#ifdef PARANOID
7535 /* arg2 must be zero or valid */
7536 cmpb TW_Zero,TAG(%ebx)
7537 ja L_unknown_tags
7538#endif PARANOID
7539
7540 /* Note that p16-9 says that infinity/0 returns infinity */
7541 jmp L_copy_arg1 /* Answer is Inf */
7542
7543L_inf_valid:
7544#ifdef DENORM_OPERAND
7545 cmpl EXP_UNDER,EXP(%ebx)
7546 jg L_copy_arg1 /* Answer is Inf */
7547
7548 call _denormal_operand
7549 orl %eax,%eax
7550 jnz FPU_Arith_exit
7551#endif DENORM_OPERAND
7552
7553 jmp L_copy_arg1 /* Answer is Inf */
7554
7555L_arg1_not_inf:
7556 cmpb TW_Zero,TAG(%ebx) /* Priority to div-by-zero error */
7557 jne L_arg2_not_zero
7558
7559 cmpb TW_Zero,TAG(%esi)
7560 je L_zero_zero /* invalid operation */
7561
7562#ifdef PARANOID
7563 /* arg1 must be valid */
7564 cmpb TW_Valid,TAG(%esi)
7565 ja L_unknown_tags
7566#endif PARANOID
7567
7568/* Division by zero error */
7569 pushl %edi /* destination */
7570 movb SIGN(%esi),%al
7571 xorb SIGN(%ebx),%al
7572 pushl %eax /* lower 8 bits have the sign */
7573 call _divide_by_zero
7574 jmp LDiv_exit
7575
7576L_arg2_not_zero:
7577 cmpb TW_Infinity,TAG(%ebx)
7578 jne L_arg2_not_inf
7579
7580#ifdef DENORM_OPERAND
7581 cmpb TW_Valid,TAG(%esi)
7582 jne L_return_zero
7583
7584 cmpl EXP_UNDER,EXP(%esi)
7585 jg L_return_zero /* Answer is zero */
7586
7587 call _denormal_operand
7588 orl %eax,%eax
7589 jnz FPU_Arith_exit
7590#endif DENORM_OPERAND
7591
7592 jmp L_return_zero /* Answer is zero */
7593
7594L_arg2_not_inf:
7595
7596#ifdef PARANOID
7597 cmpb TW_Zero,TAG(%esi)
7598 jne L_unknown_tags
7599#endif PARANOID
7600
7601 /* arg1 is zero, arg2 is not Infinity or a NaN */
7602
7603#ifdef DENORM_OPERAND
7604 cmpl EXP_UNDER,EXP(%ebx)
7605 jg L_copy_arg1 /* Answer is zero */
7606
7607 call _denormal_operand
7608 orl %eax,%eax
7609 jnz FPU_Arith_exit
7610#endif DENORM_OPERAND
7611
7612L_copy_arg1:
7613 movb TAG(%esi),%ax
7614 movb %ax,TAG(%edi)
7615 movl EXP(%esi),%eax
7616 movl %eax,EXP(%edi)
7617 movl SIGL(%esi),%eax
7618 movl %eax,SIGL(%edi)
7619 movl SIGH(%esi),%eax
7620 movl %eax,SIGH(%edi)
7621
7622 movb SIGN(%esi),%cl
7623 cmpb %cl,SIGN(%ebx)
7624 jne LDiv_negative_result
7625
7626 movb SIGN_POS,SIGN(%edi)
7627 jmp LDiv_exit
7628
7629LDiv_set_result_sign:
7630 movb SIGN(%esi),%cl
7631 cmpb %cl,SIGN(%edi)
7632 jne LDiv_negative_result
7633
7634 movb SIGN_POS,SIGN(%ebx)
7635 jmp LDiv_exit
7636
7637LDiv_negative_result:
7638 movb SIGN_NEG,SIGN(%edi)
7639
7640LDiv_exit:
7641 leal -12(%ebp),%esp
7642
7643 popl %ebx
7644 popl %edi
7645 popl %esi
7646 leave
7647 ret
7648
7649
7650L_return_zero:
7651 movb TW_Zero,TAG(%edi)
7652 jmp LDiv_set_result_sign
7653
7654#ifdef PARANOID
7655L_unknown_tags:
7656 push EX_INTERNAL | 0x208
7657 call EXCEPTION
7658
7659 /* Generate a NaN for unknown tags */
7660 movl _CONST_QNaN,%eax
7661 movl %eax,(%edi)
7662 movl _CONST_QNaN+4,%eax
7663 movl %eax,SIGL(%edi)
7664 movl _CONST_QNaN+8,%eax
7665 movl %eax,SIGH(%edi)
7666 jmp LDiv_exit
7667#endif PARANOID
7668\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/reg_mul.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 24 \0 11742 5462320166 12422\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0staff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
7669 * reg_mul.c
7670 *
7671 * Multiply one FPU_REG by another, put the result in a destination FPU_REG.
7672 *
7673 *
7674 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
7675 * Vic 3163, Australia.
7676 * E-mail apm233m@vaxc.cc.monash.edu.au
7677 * All rights reserved.
7678 *
7679 * This copyright notice covers the redistribution and use of the
7680 * FPU emulator developed by W. Metzenthen. It covers only its use
7681 * in the 386BSD operating system. Any other use is not permitted
7682 * under this copyright.
7683 *
7684 * Redistribution and use in source and binary forms, with or without
7685 * modification, are permitted provided that the following conditions
7686 * are met:
7687 * 1. Redistributions of source code must retain the above copyright
7688 * notice, this list of conditions and the following disclaimer.
7689 * 2. Redistributions in binary form must include information specifying
7690 * that source code for the emulator is freely available and include
7691 * either:
7692 * a) an offer to provide the source code for a nominal distribution
7693 * fee, or
7694 * b) list at least two alternative methods whereby the source
7695 * can be obtained, e.g. a publically accessible bulletin board
7696 * and an anonymous ftp site from which the software can be
7697 * downloaded.
7698 * 3. All advertising materials specifically mentioning features or use of
7699 * this emulator must acknowledge that it was developed by W. Metzenthen.
7700 * 4. The name of W. Metzenthen may not be used to endorse or promote
7701 * products derived from this software without specific prior written
7702 * permission.
7703 *
7704 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
7705 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
7706 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
7707 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
7708 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
7709 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
7710 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
7711 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
7712 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
7713 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7714 *
7715 */
7716
7717/*---------------------------------------------------------------------------+
7718 | The destination may be any FPU_REG, including one of the source FPU_REGs. |
7719 +---------------------------------------------------------------------------*/
7720
7721#include "exception.h"
7722#include "reg_constant.h"
7723#include "fpu_emu.h"
7724#include "fpu_system.h"
7725
7726
7727/* This routine must be called with non-empty source registers */
7728void
7729reg_mul(FPU_REG * a, FPU_REG * b, FPU_REG * dest, unsigned int control_w)
7730{
7731 char sign = (a->sign ^ b->sign);
7732
7733 if (!(a->tag | b->tag)) {
7734 /* This should be the most common case */
7735 reg_u_mul(a, b, dest, control_w);
7736 dest->sign = sign;
7737 return;
7738 } else
7739 if ((a->tag <= TW_Zero) && (b->tag <= TW_Zero)) {
7740#ifdef DENORM_OPERAND
7741 if (((b->tag == TW_Valid) && (b->exp <= EXP_UNDER)) ||
7742 ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER))) {
7743 if (denormal_operand())
7744 return;
7745 }
7746#endif /* DENORM_OPERAND */
7747 /* Must have either both arguments == zero, or one
7748 * valid and the other zero. The result is therefore
7749 * zero. */
7750 reg_move(&CONST_Z, dest);
7751#ifdef PECULIAR_486
7752 /* The 80486 book says that the answer is +0, but a
7753 * real 80486 appears to behave this way... */
7754 dest->sign = sign;
7755#endif /* PECULIAR_486 */
7756 return;
7757 }
7758#if 0 /* TW_Denormal is not used yet... perhaps
7759 * never will be. */
7760 else
7761 if ((a->tag <= TW_Denormal) && (b->tag <= TW_Denormal)) {
7762 /* One or both arguments are de-normalized */
7763 /* Internal de-normalized numbers are not
7764 * supported yet */
7765 EXCEPTION(EX_INTERNAL | 0x105);
7766 reg_move(&CONST_Z, dest);
7767 }
7768#endif
7769 else {
7770 /* Must have infinities, NaNs, etc */
7771 if ((a->tag == TW_NaN) || (b->tag == TW_NaN)) {
7772 real_2op_NaN(a, b, dest);
7773 return;
7774 } else
7775 if (a->tag == TW_Infinity) {
7776 if (b->tag == TW_Zero) {
7777 arith_invalid(dest);
7778 return;
7779 }
7780 /* Zero*Infinity is invalid */
7781 else {
7782#ifdef DENORM_OPERAND
7783 if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) &&
7784 denormal_operand())
7785 return;
7786#endif /* DENORM_OPERAND */
7787 reg_move(a, dest);
7788 dest->sign = sign;
7789 }
7790 return;
7791 } else
7792 if (b->tag == TW_Infinity) {
7793 if (a->tag == TW_Zero) {
7794 arith_invalid(dest);
7795 return;
7796 }
7797 /* Zero*Infinity is
7798 * invalid */
7799 else {
7800#ifdef DENORM_OPERAND
7801 if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) &&
7802 denormal_operand())
7803 return;
7804#endif /* DENORM_OPERAND */
7805 reg_move(b, dest);
7806 dest->sign = sign;
7807 }
7808 return;
7809 }
7810#ifdef PARANOID
7811 else {
7812 EXCEPTION(EX_INTERNAL | 0x102);
7813 }
7814#endif /* PARANOID */
7815 }
7816}
7817\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/reg_norm.s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 10233 5462505570 12571\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
7818 * reg_norm.s
7819 *
7820 * Normalize the value in a FPU_REG.
7821 *
7822 * Call from C as:
7823 * void normalize(FPU_REG *n)
7824 *
7825 * void normalize_nuo(FPU_REG *n)
7826 *
7827 *
7828 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
7829 * Vic 3163, Australia.
7830 * E-mail apm233m@vaxc.cc.monash.edu.au
7831 * All rights reserved.
7832 *
7833 * This copyright notice covers the redistribution and use of the
7834 * FPU emulator developed by W. Metzenthen. It covers only its use
7835 * in the 386BSD operating system. Any other use is not permitted
7836 * under this copyright.
7837 *
7838 * Redistribution and use in source and binary forms, with or without
7839 * modification, are permitted provided that the following conditions
7840 * are met:
7841 * 1. Redistributions of source code must retain the above copyright
7842 * notice, this list of conditions and the following disclaimer.
7843 * 2. Redistributions in binary form must include information specifying
7844 * that source code for the emulator is freely available and include
7845 * either:
7846 * a) an offer to provide the source code for a nominal distribution
7847 * fee, or
7848 * b) list at least two alternative methods whereby the source
7849 * can be obtained, e.g. a publically accessible bulletin board
7850 * and an anonymous ftp site from which the software can be
7851 * downloaded.
7852 * 3. All advertising materials specifically mentioning features or use of
7853 * this emulator must acknowledge that it was developed by W. Metzenthen.
7854 * 4. The name of W. Metzenthen may not be used to endorse or promote
7855 * products derived from this software without specific prior written
7856 * permission.
7857 *
7858 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
7859 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
7860 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
7861 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
7862 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
7863 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
7864 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
7865 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
7866 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
7867 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7868 *
7869 */
7870
7871
7872#include "fpu_asm.h"
7873
7874
7875.text
7876
7877 .align 2,144
7878.globl _normalize
7879
7880_normalize:
7881 pushl %ebp
7882 movl %esp,%ebp
7883 pushl %ebx
7884
7885 movl PARAM1,%ebx
7886
7887 movl SIGH(%ebx),%edx
7888 movl SIGL(%ebx),%eax
7889
7890 orl %edx,%edx /* ms bits */
7891 js L_done /* Already normalized */
7892 jnz L_shift_1 /* Shift left 1 - 31 bits */
7893
7894 orl %eax,%eax
7895 jz L_zero /* The contents are zero */
7896
7897/* L_shift_32: */
7898 movl %eax,%edx
7899 xorl %eax,%eax
7900 subl $32,EXP(%ebx) /* This can cause an underflow */
7901
7902/* We need to shift left by 1 - 31 bits */
7903L_shift_1:
7904 bsrl %edx,%ecx /* get the required shift in %ecx */
7905 subl $31,%ecx
7906 negl %ecx
7907 shld %cl,%eax,%edx
7908 shl %cl,%eax
7909 subl %ecx,EXP(%ebx) /* This can cause an underflow */
7910
7911 movl %edx,SIGH(%ebx)
7912 movl %eax,SIGL(%ebx)
7913
7914L_done:
7915 cmpl EXP_OVER,EXP(%ebx)
7916 jge L_overflow
7917
7918 cmpl EXP_UNDER,EXP(%ebx)
7919 jle L_underflow
7920
7921L_exit:
7922 popl %ebx
7923 leave
7924 ret
7925
7926
7927L_zero:
7928 movl EXP_UNDER,EXP(%ebx)
7929 movb TW_Zero,TAG(%ebx)
7930 jmp L_exit
7931
7932L_underflow:
7933 push %ebx
7934 call _arith_underflow
7935 pop %ebx
7936 jmp L_exit
7937
7938L_overflow:
7939 push %ebx
7940 call _arith_overflow
7941 pop %ebx
7942 jmp L_exit
7943
7944
7945
7946/* Normalise without reporting underflow or overflow */
7947 .align 2,144
7948.globl _normalize_nuo
7949
7950_normalize_nuo:
7951 pushl %ebp
7952 movl %esp,%ebp
7953 pushl %ebx
7954
7955 movl PARAM1,%ebx
7956
7957 movl SIGH(%ebx),%edx
7958 movl SIGL(%ebx),%eax
7959
7960 orl %edx,%edx /* ms bits */
7961 js L_exit /* Already normalized */
7962 jnz L_nuo_shift_1 /* Shift left 1 - 31 bits */
7963
7964 orl %eax,%eax
7965 jz L_zero /* The contents are zero */
7966
7967/* L_nuo_shift_32: */
7968 movl %eax,%edx
7969 xorl %eax,%eax
7970 subl $32,EXP(%ebx) /* This can cause an underflow */
7971
7972/* We need to shift left by 1 - 31 bits */
7973L_nuo_shift_1:
7974 bsrl %edx,%ecx /* get the required shift in %ecx */
7975 subl $31,%ecx
7976 negl %ecx
7977 shld %cl,%eax,%edx
7978 shl %cl,%eax
7979 subl %ecx,EXP(%ebx) /* This can cause an underflow */
7980
7981 movl %edx,SIGH(%ebx)
7982 movl %eax,SIGL(%ebx)
7983 jmp L_exit
7984
7985
7986\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/bde_trapinfo.mail\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100600 \0 0 \0 24 \0 2454 5462277677 14116\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0staff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0From bde@kralizec.zeta.org.au Sun Jun 27 01:18:32 1993
7987Received: from ultima.socs.uts.EDU.AU by bsd.coe.montana.edu (5.67/KAOS-1)
7988 id AA11952; Sun, 27 Jun 93 01:18:32 -0600
7989Received: by ultima.socs.uts.EDU.AU (5.65+/SMI-3.3)
7990 id AA03033; Sun, 27 Jun 93 17:10:22 +1000
7991Received: by kralizec.zeta.org.au (4.0/SMI-4.0)
7992 id AA15074; Sat, 26 Jun 93 02:32:58 EST
7993Date: Sat, 26 Jun 93 02:32:58 EST
7994From: bde@kralizec.zeta.org.au (Bruce Evans)
7995Message-Id: <9306251632.AA15074@kralizec.zeta.org.au>
7996To: nate@bsd.coe.montana.edu
7997Subject: Re: Trapframe information
7998Status: OR
7999
8000tf_isp original esp (probably spare - popal ignores it)
8001tf_trapno s/w trap no (may be spare - trap.c has already looked at it)
8002tf_err h/w error code (probably spare - gets discarded before iret)
8003
8004___fs not stored in 386BSD pcb. Constant anyway unless user has
8005 screwed with it (?).
8006___gs ditto
8007___orig_eip in linux, this is on the stack just before the call to the
8008 emulator. The reason that it's not a local variable is to
8009 avoid passing around pointers to it - current->frame (or
8010 whatever) points to everything in the stack frame. The
8011 macros hide a lot of slow memory references
8012 current->frame->var.
8013
8014>(And I need to see if I can map orig_eip to one of the three that I'm unsure of
8015>in the BSD sources)
8016
8017tf_isp is the least evil.
8018
8019Bruce
8020
8021\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/fpu_proto.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 24 \0 6610 5462320157 12770\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0staff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/* errors.c */
8022extern void Un_impl(void);
8023extern void emu_printall(void);
8024extern void exception(int n);
8025extern void real_2op_NaN(FPU_REG * a, FPU_REG * b, FPU_REG * dest);
8026extern void arith_invalid(FPU_REG * dest);
8027extern void divide_by_zero(int sign, FPU_REG * dest);
8028extern void set_precision_flag_up(void);
8029extern void set_precision_flag_down(void);
8030extern int denormal_operand(void);
8031extern void arith_overflow(FPU_REG * dest);
8032extern void arith_underflow(FPU_REG * dest);
8033extern void stack_overflow(void);
8034extern void stack_underflow(void);
8035extern void stack_underflow_i(int i);
8036extern void stack_underflow_pop(int i);
8037/* fpu_arith.c */
8038extern void fadd__(void);
8039extern void fmul__(void);
8040extern void fsub__(void);
8041extern void fsubr_(void);
8042extern void fdiv__(void);
8043extern void fdivr_(void);
8044extern void fadd_i(void);
8045extern void fmul_i(void);
8046extern void fsubri(void);
8047extern void fsub_i(void);
8048extern void fdivri(void);
8049extern void fdiv_i(void);
8050extern void faddp_(void);
8051extern void fmulp_(void);
8052extern void fsubrp(void);
8053extern void fsubp_(void);
8054extern void fdivrp(void);
8055extern void fdivp_(void);
8056/* fpu_aux.c */
8057extern void fclex(void);
8058extern void finit(void);
8059extern void finit_(void);
8060extern void fstsw_(void);
8061extern void fp_nop(void);
8062extern void fld_i_(void);
8063extern void fxch_i(void);
8064extern void ffree_(void);
8065extern void ffreep(void);
8066extern void fst_i_(void);
8067extern void fstp_i(void);
8068/* fpu_entry.c */
8069extern int math_emulate(struct trapframe * info);
8070/* fpu_etc.c */
8071extern void fp_etc(void);
8072/* fpu_trig.c */
8073extern void convert_l2reg(long *arg, FPU_REG * dest);
8074extern void trig_a(void);
8075extern void trig_b(void);
8076/* get_address.c */
8077extern void get_address(unsigned char FPU_modrm);
8078/* load_store.c */
8079extern void load_store_instr(char type);
8080/* poly_2xm1.c */
8081extern int poly_2xm1(FPU_REG * arg, FPU_REG * result);
8082/* poly_atan.c */
8083extern void poly_atan(FPU_REG * arg);
8084extern void poly_add_1(FPU_REG * src);
8085/* poly_l2.c */
8086extern void poly_l2(FPU_REG * arg, FPU_REG * result);
8087extern int poly_l2p1(FPU_REG * arg, FPU_REG * result);
8088/* poly_sin.c */
8089extern void poly_sine(FPU_REG * arg, FPU_REG * result);
8090/* poly_tan.c */
8091extern void poly_tan(FPU_REG * arg, FPU_REG * y_reg);
8092/* reg_add_sub.c */
8093extern void reg_add(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w);
8094extern void reg_sub(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w);
8095/* reg_compare.c */
8096extern int compare(FPU_REG * b);
8097extern int compare_st_data(void);
8098extern void fcom_st(void);
8099extern void fcompst(void);
8100extern void fcompp(void);
8101extern void fucom_(void);
8102extern void fucomp(void);
8103extern void fucompp(void);
8104/* reg_constant.c */
8105extern void fconst(void);
8106/* reg_ld_str.c */
8107extern void reg_load_extended(void);
8108extern void reg_load_double(void);
8109extern void reg_load_single(void);
8110extern void reg_load_int64(void);
8111extern void reg_load_int32(void);
8112extern void reg_load_int16(void);
8113extern void reg_load_bcd(void);
8114extern int reg_store_extended(void);
8115extern int reg_store_double(void);
8116extern int reg_store_single(void);
8117extern int reg_store_int64(void);
8118extern int reg_store_int32(void);
8119extern int reg_store_int16(void);
8120extern int reg_store_bcd(void);
8121extern int round_to_int(FPU_REG * r);
8122extern char *fldenv(void);
8123extern void frstor(void);
8124extern unsigned short tag_word(void);
8125extern char *fstenv(void);
8126extern void fsave(void);
8127/* reg_mul.c */
8128extern void reg_mul(FPU_REG * a, FPU_REG * b, FPU_REG * dest, unsigned int control_w);
8129\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/poly_mul64.s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 6170 5462505570 12760\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
8130 * poly_mul64.S
8131 *
8132 * Multiply two 64 bit integers.
8133 *
8134 * Call from C as:
8135 * void mul64(long long *a, long long *b, long long *result)
8136 *
8137 *
8138 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
8139 * Vic 3163, Australia.
8140 * E-mail apm233m@vaxc.cc.monash.edu.au
8141 * All rights reserved.
8142 *
8143 * This copyright notice covers the redistribution and use of the
8144 * FPU emulator developed by W. Metzenthen. It covers only its use
8145 * in the 386BSD operating system. Any other use is not permitted
8146 * under this copyright.
8147 *
8148 * Redistribution and use in source and binary forms, with or without
8149 * modification, are permitted provided that the following conditions
8150 * are met:
8151 * 1. Redistributions of source code must retain the above copyright
8152 * notice, this list of conditions and the following disclaimer.
8153 * 2. Redistributions in binary form must include information specifying
8154 * that source code for the emulator is freely available and include
8155 * either:
8156 * a) an offer to provide the source code for a nominal distribution
8157 * fee, or
8158 * b) list at least two alternative methods whereby the source
8159 * can be obtained, e.g. a publically accessible bulletin board
8160 * and an anonymous ftp site from which the software can be
8161 * downloaded.
8162 * 3. All advertising materials specifically mentioning features or use of
8163 * this emulator must acknowledge that it was developed by W. Metzenthen.
8164 * 4. The name of W. Metzenthen may not be used to endorse or promote
8165 * products derived from this software without specific prior written
8166 * permission.
8167 *
8168 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
8169 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
8170 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
8171 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
8172 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
8173 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
8174 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
8175 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
8176 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
8177 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8178 *
8179 */
8180
8181
8182#include "fpu_asm.h"
8183
8184.text
8185 .align 2,144
8186.globl _mul64
8187_mul64:
8188 pushl %ebp
8189 movl %esp,%ebp
8190 subl $16,%esp
8191 pushl %esi
8192 pushl %ebx
8193
8194 movl PARAM1,%esi
8195 movl PARAM2,%ecx
8196 movl PARAM3,%ebx
8197
8198 xor %eax,%eax
8199 movl %eax,-4(%ebp)
8200 movl %eax,-8(%ebp)
8201
8202 movl (%esi),%eax
8203 mull (%ecx)
8204 movl %eax,-16(%ebp) /* Not used */
8205 movl %edx,-12(%ebp)
8206
8207 movl (%esi),%eax
8208 mull 4(%ecx)
8209 addl %eax,-12(%ebp)
8210 adcl %edx,-8(%ebp)
8211 adcl $0,-4(%ebp)
8212
8213 movl 4(%esi),%eax
8214 mull (%ecx)
8215 addl %eax,-12(%ebp)
8216 adcl %edx,-8(%ebp)
8217 adcl $0,-4(%ebp)
8218
8219 movl 4(%esi),%eax
8220 mull 4(%ecx)
8221 addl %eax,-8(%ebp)
8222 adcl %edx,-4(%ebp)
8223
8224 testb $128,-9(%ebp)
8225 je L_no_round
8226
8227 addl $1,-8(%ebp)
8228 adcl $0,-4(%ebp)
8229
8230L_no_round:
8231 movl -8(%ebp),%esi
8232 movl %esi,(%ebx)
8233 movl -4(%ebp),%esi
8234 movl %esi,4(%ebx)
8235
8236 popl %ebx
8237 popl %esi
8238 leave
8239 ret
8240\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/status_w.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 7206 5462320166 12601\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
8241 * status_w.h
8242 *
8243 *
8244 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
8245 * Vic 3163, Australia.
8246 * E-mail apm233m@vaxc.cc.monash.edu.au
8247 * All rights reserved.
8248 *
8249 * This copyright notice covers the redistribution and use of the
8250 * FPU emulator developed by W. Metzenthen. It covers only its use
8251 * in the 386BSD operating system. Any other use is not permitted
8252 * under this copyright.
8253 *
8254 * Redistribution and use in source and binary forms, with or without
8255 * modification, are permitted provided that the following conditions
8256 * are met:
8257 * 1. Redistributions of source code must retain the above copyright
8258 * notice, this list of conditions and the following disclaimer.
8259 * 2. Redistributions in binary form must include information specifying
8260 * that source code for the emulator is freely available and include
8261 * either:
8262 * a) an offer to provide the source code for a nominal distribution
8263 * fee, or
8264 * b) list at least two alternative methods whereby the source
8265 * can be obtained, e.g. a publically accessible bulletin board
8266 * and an anonymous ftp site from which the software can be
8267 * downloaded.
8268 * 3. All advertising materials specifically mentioning features or use of
8269 * this emulator must acknowledge that it was developed by W. Metzenthen.
8270 * 4. The name of W. Metzenthen may not be used to endorse or promote
8271 * products derived from this software without specific prior written
8272 * permission.
8273 *
8274 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
8275 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
8276 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
8277 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
8278 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
8279 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
8280 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
8281 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
8282 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
8283 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8284 *
8285 */
8286
8287
8288#ifndef _STATUS_H_
8289#define _STATUS_H_
8290
8291
8292#ifdef LOCORE
8293#define Const__(x) $/**/x
8294#else
8295#define Const__(x) x
8296#endif
8297
8298#define SW_Backward Const__(0x8000) /* backward compatibility */
8299#define SW_C3 Const__(0x4000) /* condition bit 3 */
8300#define SW_Top Const__(0x3800) /* top of stack */
8301#define SW_Top_Shift Const__(11) /* shift for top of stack bits */
8302#define SW_C2 Const__(0x0400) /* condition bit 2 */
8303#define SW_C1 Const__(0x0200) /* condition bit 1 */
8304#define SW_C0 Const__(0x0100) /* condition bit 0 */
8305#define SW_Summary Const__(0x0080) /* exception summary */
8306#define SW_Stack_Fault Const__(0x0040) /* stack fault */
8307#define SW_Precision Const__(0x0020) /* loss of precision */
8308#define SW_Underflow Const__(0x0010) /* underflow */
8309#define SW_Overflow Const__(0x0008) /* overflow */
8310#define SW_Zero_Div Const__(0x0004) /* divide by zero */
8311#define SW_Denorm_Op Const__(0x0002) /* denormalized operand */
8312#define SW_Invalid Const__(0x0001) /* invalid operation */
8313
8314#define SW_Exc_Mask Const__(0x27f) /* Status word exception bit mask */
8315
8316#ifndef LOCORE
8317
8318#define COMP_A_gt_B 1
8319#define COMP_A_eq_B 2
8320#define COMP_A_lt_B 3
8321#define COMP_No_Comp 4
8322#define COMP_Denormal 0x20
8323#define COMP_NaN 0x40
8324#define COMP_SNaN 0x80
8325
8326#define setcc(cc) ({ \
8327 status_word &= ~(SW_C0|SW_C1|SW_C2|SW_C3); \
8328 status_word |= (cc) & (SW_C0|SW_C1|SW_C2|SW_C3); })
8329
8330#endif /* LOCORE */
8331
8332#endif /* _STATUS_H_ */
8333\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/version.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 24 \0 4431 5462320167 12440\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0staff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
8334 * version.h
8335 *
8336 *
8337 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
8338 * Vic 3163, Australia.
8339 * E-mail apm233m@vaxc.cc.monash.edu.au
8340 * All rights reserved.
8341 *
8342 * This copyright notice covers the redistribution and use of the
8343 * FPU emulator developed by W. Metzenthen. It covers only its use
8344 * in the 386BSD operating system. Any other use is not permitted
8345 * under this copyright.
8346 *
8347 * Redistribution and use in source and binary forms, with or without
8348 * modification, are permitted provided that the following conditions
8349 * are met:
8350 * 1. Redistributions of source code must retain the above copyright
8351 * notice, this list of conditions and the following disclaimer.
8352 * 2. Redistributions in binary form must include information specifying
8353 * that source code for the emulator is freely available and include
8354 * either:
8355 * a) an offer to provide the source code for a nominal distribution
8356 * fee, or
8357 * b) list at least two alternative methods whereby the source
8358 * can be obtained, e.g. a publically accessible bulletin board
8359 * and an anonymous ftp site from which the software can be
8360 * downloaded.
8361 * 3. All advertising materials specifically mentioning features or use of
8362 * this emulator must acknowledge that it was developed by W. Metzenthen.
8363 * 4. The name of W. Metzenthen may not be used to endorse or promote
8364 * products derived from this software without specific prior written
8365 * permission.
8366 *
8367 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
8368 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
8369 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
8370 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
8371 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
8372 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
8373 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
8374 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
8375 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
8376 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8377 *
8378 */
8379
8380#define FPU_VERSION "wm-FPU-emu version BETA 1.4"
8381\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/reg_round.s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 40214 5462505570 12747\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 .file "reg_round.S"
8382/*
8383 * reg_round.S
8384 *
8385 * Rounding/truncation/etc for FPU basic arithmetic functions.
8386 *
8387 * This code has four possible entry points.
8388 * The following must be entered by a jmp intruction:
8389 * FPU_round, FPU_round_sqrt, and FPU_Arith_exit.
8390 *
8391 * The _round_reg entry point is intended to be used by C code.
8392 * From C, call as:
8393 * void round_reg(FPU_REG *arg, unsigned int extent, unsigned int control_w)
8394 *
8395 *
8396 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
8397 * Vic 3163, Australia.
8398 * E-mail apm233m@vaxc.cc.monash.edu.au
8399 * All rights reserved.
8400 *
8401 * This copyright notice covers the redistribution and use of the
8402 * FPU emulator developed by W. Metzenthen. It covers only its use
8403 * in the 386BSD operating system. Any other use is not permitted
8404 * under this copyright.
8405 *
8406 * Redistribution and use in source and binary forms, with or without
8407 * modification, are permitted provided that the following conditions
8408 * are met:
8409 * 1. Redistributions of source code must retain the above copyright
8410 * notice, this list of conditions and the following disclaimer.
8411 * 2. Redistributions in binary form must include information specifying
8412 * that source code for the emulator is freely available and include
8413 * either:
8414 * a) an offer to provide the source code for a nominal distribution
8415 * fee, or
8416 * b) list at least two alternative methods whereby the source
8417 * can be obtained, e.g. a publically accessible bulletin board
8418 * and an anonymous ftp site from which the software can be
8419 * downloaded.
8420 * 3. All advertising materials specifically mentioning features or use of
8421 * this emulator must acknowledge that it was developed by W. Metzenthen.
8422 * 4. The name of W. Metzenthen may not be used to endorse or promote
8423 * products derived from this software without specific prior written
8424 * permission.
8425 *
8426 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
8427 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
8428 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
8429 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
8430 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
8431 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
8432 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
8433 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
8434 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
8435 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8436 *
8437 */
8438
8439
8440/*---------------------------------------------------------------------------+
8441 | Four entry points. |
8442 | |
8443 | Needed by both the FPU_round and FPU_round_sqrt entry points: |
8444 | %eax:%ebx 64 bit significand |
8445 | %edx 32 bit extension of the significand |
8446 | %edi pointer to an FPU_REG for the result to be stored |
8447 | stack calling function must have set up a C stack frame and |
8448 | pushed %esi, %edi, and %ebx |
8449 | |
8450 | Needed just for the FPU_round_sqrt entry point: |
8451 | %cx A control word in the same format as the FPU control word. |
8452 | Otherwise, PARAM4 must give such a value. |
8453 | |
8454 | |
8455 | The significand and its extension are assumed to be exact in the |
8456 | following sense: |
8457 | If the significand by itself is the exact result then the significand |
8458 | extension (%edx) must contain 0, otherwise the significand extension |
8459 | must be non-zero. |
8460 | If the significand extension is non-zero then the significand is |
8461 | smaller than the magnitude of the correct exact result by an amount |
8462 | greater than zero and less than one ls bit of the significand. |
8463 | The significand extension is only required to have three possible |
8464 | non-zero values: |
8465 | less than 0x80000000 <=> the significand is less than 1/2 an ls |
8466 | bit smaller than the magnitude of the |
8467 | true exact result. |
8468 | exactly 0x80000000 <=> the significand is exactly 1/2 an ls bit |
8469 | smaller than the magnitude of the true |
8470 | exact result. |
8471 | greater than 0x80000000 <=> the significand is more than 1/2 an ls |
8472 | bit smaller than the magnitude of the |
8473 | true exact result. |
8474 | |
8475 +---------------------------------------------------------------------------*/
8476
8477/*---------------------------------------------------------------------------+
8478 | The code in this module has become quite complex, but it should handle |
8479 | all of the FPU flags which are set at this stage of the basic arithmetic |
8480 | computations. |
8481 | There are a few rare cases where the results are not set identically to |
8482 | a real FPU. These require a bit more thought because at this stage the |
8483 | results of the code here appear to be more consistent... |
8484 | This may be changed in a future version. |
8485 +---------------------------------------------------------------------------*/
8486
8487
8488#include "fpu_asm.h"
8489#include "exception.h"
8490#include "control_w.h"
8491
8492#define LOST_DOWN $1
8493#define LOST_UP $2
8494#define DENORMAL $1
8495#define UNMASKED_UNDERFLOW $2
8496
8497.data
8498 .align 2,0
8499FPU_bits_lost:
8500 .byte 0
8501FPU_denormal:
8502 .byte 0
8503
8504.text
8505 .align 2,144
8506.globl FPU_round
8507.globl FPU_round_sqrt
8508.globl FPU_Arith_exit
8509.globl _round_reg
8510
8511/* Entry point when called from C */
8512_round_reg:
8513 pushl %ebp
8514 movl %esp,%ebp
8515 pushl %esi
8516 pushl %edi
8517 pushl %ebx
8518
8519 movl PARAM1,%edi
8520 movl SIGH(%edi),%eax
8521 movl SIGL(%edi),%ebx
8522 movl PARAM2,%edx
8523 movl PARAM3,%ecx
8524 jmp FPU_round_sqrt
8525
8526FPU_round: /* Normal entry point */
8527 movl PARAM4,%ecx
8528
8529FPU_round_sqrt: /* Entry point from wm_sqrt.S */
8530
8531#ifdef PARANOID
8532/* Cannot use this here yet */
8533/* orl %eax,%eax */
8534/* jns L_entry_bugged */
8535#endif PARANOID
8536
8537 cmpl EXP_UNDER,EXP(%edi)
8538 jle xMake_denorm /* The number is a de-normal*/
8539
8540 movb $0,FPU_denormal /* 0 -> not a de-normal*/
8541
8542xDenorm_done:
8543 movb $0,FPU_bits_lost /*No bits yet lost in rounding*/
8544
8545 movl %ecx,%esi
8546 andl CW_PC,%ecx
8547 cmpl PR_64_BITS,%ecx
8548 je LRound_To_64
8549
8550 cmpl PR_53_BITS,%ecx
8551 je LRound_To_53
8552
8553 cmpl PR_24_BITS,%ecx
8554 je LRound_To_24
8555
8556#ifdef PARANOID
8557 jmp L_bugged /* There is no bug, just a bad control word */
8558#endif PARANOID
8559
8560
8561/* Round etc to 24 bit precision */
8562LRound_To_24:
8563 movl %esi,%ecx
8564 andl CW_RC,%ecx
8565 cmpl RC_RND,%ecx
8566 je LRound_nearest_24
8567
8568 cmpl RC_CHOP,%ecx
8569 je LCheck_truncate_24
8570
8571 cmpl RC_UP,%ecx /* Towards +infinity */
8572 je LUp_24
8573
8574 cmpl RC_DOWN,%ecx /* Towards -infinity */
8575 je LDown_24
8576
8577#ifdef PARANOID
8578 jmp L_bugged
8579#endif PARANOID
8580
8581LUp_24:
8582 cmpb SIGN_POS,SIGN(%edi)
8583 jne LCheck_truncate_24 /* If negative then up==truncate */
8584
8585 jmp LCheck_24_round_up
8586
8587LDown_24:
8588 cmpb SIGN_POS,SIGN(%edi)
8589 je LCheck_truncate_24 /* If positive then down==truncate */
8590
8591LCheck_24_round_up:
8592 movl %eax,%ecx
8593 andl $0x000000ff,%ecx
8594 orl %ebx,%ecx
8595 orl %edx,%ecx
8596 jnz LDo_24_round_up
8597 jmp LRe_normalise
8598
8599LRound_nearest_24:
8600 /* Do rounding of the 24th bit if needed (nearest or even) */
8601 movl %eax,%ecx
8602 andl $0x000000ff,%ecx
8603 cmpl $0x00000080,%ecx
8604 jc LCheck_truncate_24 /*less than half, no increment needed*/
8605
8606 jne LGreater_Half_24 /* greater than half, increment needed*/
8607
8608 /* Possibly half, we need to check the ls bits */
8609 orl %ebx,%ebx
8610 jnz LGreater_Half_24 /* greater than half, increment needed*/
8611
8612 orl %edx,%edx
8613 jnz LGreater_Half_24 /* greater than half, increment needed*/
8614
8615 /* Exactly half, increment only if 24th bit is 1 (round to even)*/
8616 testl $0x00000100,%eax
8617 jz LDo_truncate_24
8618
8619LGreater_Half_24: /*Rounding: increment at the 24th bit*/
8620LDo_24_round_up:
8621 andl $0xffffff00,%eax /*Truncate to 24 bits*/
8622 xorl %ebx,%ebx
8623 movb LOST_UP,FPU_bits_lost
8624 addl $0x00000100,%eax
8625 jmp LCheck_Round_Overflow
8626
8627LCheck_truncate_24:
8628 movl %eax,%ecx
8629 andl $0x000000ff,%ecx
8630 orl %ebx,%ecx
8631 orl %edx,%ecx
8632 jz LRe_normalise /* No truncation needed*/
8633
8634LDo_truncate_24:
8635 andl $0xffffff00,%eax /* Truncate to 24 bits*/
8636 xorl %ebx,%ebx
8637 movb LOST_DOWN,FPU_bits_lost
8638 jmp LRe_normalise
8639
8640
8641/* Round etc to 53 bit precision */
8642LRound_To_53:
8643 movl %esi,%ecx
8644 andl CW_RC,%ecx
8645 cmpl RC_RND,%ecx
8646 je LRound_nearest_53
8647
8648 cmpl RC_CHOP,%ecx
8649 je LCheck_truncate_53
8650
8651 cmpl RC_UP,%ecx /* Towards +infinity*/
8652 je LUp_53
8653
8654 cmpl RC_DOWN,%ecx /* Towards -infinity*/
8655 je LDown_53
8656
8657#ifdef PARANOID
8658 jmp L_bugged
8659#endif PARANOID
8660
8661LUp_53:
8662 cmpb SIGN_POS,SIGN(%edi)
8663 jne LCheck_truncate_53 /* If negative then up==truncate*/
8664
8665 jmp LCheck_53_round_up
8666
8667LDown_53:
8668 cmpb SIGN_POS,SIGN(%edi)
8669 je LCheck_truncate_53 /* If positive then down==truncate*/
8670
8671LCheck_53_round_up:
8672 movl %ebx,%ecx
8673 andl $0x000007ff,%ecx
8674 orl %edx,%ecx
8675 jnz LDo_53_round_up
8676 jmp LRe_normalise
8677
8678LRound_nearest_53:
8679 /*Do rounding of the 53rd bit if needed (nearest or even)*/
8680 movl %ebx,%ecx
8681 andl $0x000007ff,%ecx
8682 cmpl $0x00000400,%ecx
8683 jc LCheck_truncate_53 /* less than half, no increment needed*/
8684
8685 jnz LGreater_Half_53 /* greater than half, increment needed*/
8686
8687 /*Possibly half, we need to check the ls bits*/
8688 orl %edx,%edx
8689 jnz LGreater_Half_53 /* greater than half, increment needed*/
8690
8691 /* Exactly half, increment only if 53rd bit is 1 (round to even)*/
8692 testl $0x00000800,%ebx
8693 jz LTruncate_53
8694
8695LGreater_Half_53: /*Rounding: increment at the 53rd bit*/
8696LDo_53_round_up:
8697 movb LOST_UP,FPU_bits_lost
8698 andl $0xfffff800,%ebx /* Truncate to 53 bits*/
8699 addl $0x00000800,%ebx
8700 adcl $0,%eax
8701 jmp LCheck_Round_Overflow
8702
8703LCheck_truncate_53:
8704 movl %ebx,%ecx
8705 andl $0x000007ff,%ecx
8706 orl %edx,%ecx
8707 jz LRe_normalise
8708
8709LTruncate_53:
8710 movb LOST_DOWN,FPU_bits_lost
8711 andl $0xfffff800,%ebx /* Truncate to 53 bits*/
8712 jmp LRe_normalise
8713
8714
8715/* Round etc to 64 bit precision*/
8716LRound_To_64:
8717 movl %esi,%ecx
8718 andl CW_RC,%ecx
8719 cmpl RC_RND,%ecx
8720 je LRound_nearest_64
8721
8722 cmpl RC_CHOP,%ecx
8723 je LCheck_truncate_64
8724
8725 cmpl RC_UP,%ecx /* Towards +infinity*/
8726 je LUp_64
8727
8728 cmpl RC_DOWN,%ecx /* Towards -infinity*/
8729 je LDown_64
8730
8731#ifdef PARANOID
8732 jmp L_bugged
8733#endif PARANOID
8734
8735LUp_64:
8736 cmpb SIGN_POS,SIGN(%edi)
8737 jne LCheck_truncate_64 /* If negative then up==truncate*/
8738
8739 orl %edx,%edx
8740 jnz LDo_64_round_up
8741 jmp LRe_normalise
8742
8743LDown_64:
8744 cmpb SIGN_POS,SIGN(%edi)
8745 je LCheck_truncate_64 /*If positive then down==truncate*/
8746
8747 orl %edx,%edx
8748 jnz LDo_64_round_up
8749 jmp LRe_normalise
8750
8751LRound_nearest_64:
8752 cmpl $0x80000000,%edx
8753 jc LCheck_truncate_64
8754
8755 jne LDo_64_round_up
8756
8757 /* Now test for round-to-even */
8758 testb $1,%ebx
8759 jz LCheck_truncate_64
8760
8761LDo_64_round_up:
8762 movb LOST_UP,FPU_bits_lost
8763 addl $1,%ebx
8764 adcl $0,%eax
8765
8766LCheck_Round_Overflow:
8767 jnc LRe_normalise /* Rounding done, no overflow */
8768
8769 /* Overflow, adjust the result (to 1.0) */
8770 rcrl $1,%eax
8771 rcrl $1,%ebx
8772 incl EXP(%edi)
8773 jmp LRe_normalise
8774
8775LCheck_truncate_64:
8776 orl %edx,%edx
8777 jz LRe_normalise
8778
8779LTruncate_64:
8780 movb LOST_DOWN,FPU_bits_lost
8781
8782LRe_normalise:
8783 testb $0xff,FPU_denormal
8784 jnz xNormalise_result
8785
8786xL_Normalised:
8787 cmpb LOST_UP,FPU_bits_lost
8788 je xL_precision_lost_up
8789
8790 cmpb LOST_DOWN,FPU_bits_lost
8791 je xL_precision_lost_down
8792
8793xL_no_precision_loss:
8794 cmpl EXP_OVER,EXP(%edi)
8795 jge L_overflow
8796
8797 /* store the result */
8798 movb TW_Valid,TAG(%edi)
8799
8800xL_Store_significand:
8801 movl %eax,SIGH(%edi)
8802 movl %ebx,SIGL(%edi)
8803
8804FPU_Arith_exit:
8805 popl %ebx
8806 popl %edi
8807 popl %esi
8808 leave
8809 ret
8810
8811
8812/* Set the FPU status flags to represent precision loss due to*/
8813/* round-up.*/
8814xL_precision_lost_up:
8815 push %eax
8816 call _set_precision_flag_up
8817 popl %eax
8818 jmp xL_no_precision_loss
8819
8820/* Set the FPU status flags to represent precision loss due to*/
8821/* truncation.*/
8822xL_precision_lost_down:
8823 push %eax
8824 call _set_precision_flag_down
8825 popl %eax
8826 jmp xL_no_precision_loss
8827
8828
8829/* The number is a denormal (which might get rounded up to a normal)
8830// Shift the number right the required number of bits, which will
8831// have to be undone later...*/
8832xMake_denorm:
8833 /* The action to be taken depends upon whether the underflow
8834 // exception is masked*/
8835 testb CW_Underflow,%cl /* Underflow mask.*/
8836 jz xUnmasked_underflow /* Do not make a denormal.*/
8837
8838 movb DENORMAL,FPU_denormal
8839
8840 pushl %ecx /* Save*/
8841 movl EXP(%edi),%ecx
8842 subl EXP_UNDER+1,%ecx
8843 negl %ecx
8844
8845 cmpl $64,%ecx /* shrd only works for 0..31 bits */
8846 jnc xDenorm_shift_more_than_63
8847
8848 cmpl $32,%ecx /* shrd only works for 0..31 bits */
8849 jnc xDenorm_shift_more_than_32
8850
8851/* We got here without jumps by assuming that the most common requirement
8852// is for a small de-normalising shift.
8853// Shift by [1..31] bits */
8854 addl %ecx,EXP(%edi)
8855 orl %edx,%edx /* extension*/
8856 setne %ch
8857 xorl %edx,%edx
8858 shrd %cl,%ebx,%edx
8859 shrd %cl,%eax,%ebx
8860 shr %cl,%eax
8861 orb %ch,%dl
8862 popl %ecx
8863 jmp xDenorm_done
8864
8865/* Shift by [32..63] bits*/
8866xDenorm_shift_more_than_32:
8867 addl %ecx,EXP(%edi)
8868 subb $32,%cl
8869 orl %edx,%edx
8870 setne %ch
8871 orb %ch,%bl
8872 xorl %edx,%edx
8873 shrd %cl,%ebx,%edx
8874 shrd %cl,%eax,%ebx
8875 shr %cl,%eax
8876 orl %edx,%edx /*test these 32 bits*/
8877 setne %cl
8878 orb %ch,%bl
8879 orb %cl,%bl
8880 movl %ebx,%edx
8881 movl %eax,%ebx
8882 xorl %eax,%eax
8883 popl %ecx
8884 jmp xDenorm_done
8885
8886/* Shift by [64..) bits*/
8887xDenorm_shift_more_than_63:
8888 cmpl $64,%ecx
8889 jne xDenorm_shift_more_than_64
8890
8891/* Exactly 64 bit shift*/
8892 addl %ecx,EXP(%edi)
8893 xorl %ecx,%ecx
8894 orl %edx,%edx
8895 setne %cl
8896 orl %ebx,%ebx
8897 setne %ch
8898 orb %ch,%cl
8899 orb %cl,%al
8900 movl %eax,%edx
8901 xorl %eax,%eax
8902 xorl %ebx,%ebx
8903 popl %ecx
8904 jmp xDenorm_done
8905
8906xDenorm_shift_more_than_64:
8907 movl EXP_UNDER+1,EXP(%edi)
8908/* This is easy, %eax must be non-zero, so..*/
8909 movl $1,%edx
8910 xorl %eax,%eax
8911 xorl %ebx,%ebx
8912 popl %ecx
8913 jmp xDenorm_done
8914
8915
8916xUnmasked_underflow:
8917 /* Increase the exponent by the magic number*/
8918 addl $(3*(1<<13)),EXP(%edi)
8919 movb UNMASKED_UNDERFLOW,FPU_denormal
8920 jmp xDenorm_done
8921
8922
8923/* Undo the de-normalisation.*/
8924xNormalise_result:
8925 cmpb UNMASKED_UNDERFLOW,FPU_denormal
8926 je xSignal_underflow
8927
8928/* The number must be a denormal if we got here.*/
8929#ifdef PARANOID
8930 /* But check it... just in case.*/
8931 cmpl EXP_UNDER+1,EXP(%edi)
8932 jne L_norm_bugged
8933#endif PARANOID
8934
8935 orl %eax,%eax /* ms bits*/
8936 jnz LNormalise_shift_up_to_31 /* Shift left 0 - 31 bits*/
8937
8938 orl %ebx,%ebx
8939 jz L_underflow_to_zero /* The contents are zero*/
8940
8941/* Shift left 32 - 63 bits*/
8942 movl %ebx,%eax
8943 xorl %ebx,%ebx
8944 subl $32,EXP(%edi)
8945
8946LNormalise_shift_up_to_31:
8947 bsrl %eax,%ecx /* get the required shift in %ecx */
8948 subl $31,%ecx
8949 negl %ecx
8950 shld %cl,%ebx,%eax
8951 shl %cl,%ebx
8952 subl %ecx,EXP(%edi)
8953
8954LNormalise_shift_done:
8955 testb $0xff,FPU_bits_lost /* bits lost == underflow*/
8956 jz xL_Normalised
8957
8958 /* There must be a masked underflow*/
8959 push %eax
8960 pushl EX_Underflow
8961 call _exception
8962 popl %eax
8963 popl %eax
8964 jmp xL_Normalised
8965
8966
8967/* The operations resulted in a number too small to represent.
8968// Masked response.*/
8969L_underflow_to_zero:
8970 push %eax
8971 call _set_precision_flag_down
8972 popl %eax
8973
8974 push %eax
8975 pushl EX_Underflow
8976 call _exception
8977 popl %eax
8978 popl %eax
8979
8980 movb TW_Zero,TAG(%edi)
8981 jmp xL_Store_significand
8982
8983
8984/* The operations resulted in a number too large to represent.*/
8985L_overflow:
8986 push %edi
8987 call _arith_overflow
8988 pop %edi
8989 jmp FPU_Arith_exit
8990
8991
8992xSignal_underflow:
8993 push %eax
8994 pushl EX_Underflow
8995 call EXCEPTION
8996 popl %eax
8997 popl %eax
8998 jmp xL_Normalised
8999
9000
9001#ifdef PARANOID
9002/* If we ever get here then we have problems! */
9003L_bugged:
9004 pushl EX_INTERNAL|0x201
9005 call EXCEPTION
9006 popl %ebx
9007 jmp FPU_Arith_exit
9008
9009L_norm_bugged:
9010 pushl EX_INTERNAL|0x216
9011 call EXCEPTION
9012 popl %ebx
9013 jmp FPU_Arith_exit
9014
9015L_entry_bugged:
9016 pushl EX_INTERNAL|0x217
9017 call EXCEPTION
9018 popl %ebx
9019 jmp FPU_Arith_exit
9020#endif PARANOID
9021\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/reg_u_add.s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 12727 5462505570 12704\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 .file "reg_u_add.S"
9022/*
9023 * reg_u_add.S
9024 *
9025 * Add two valid (TW_Valid) FPU_REG numbers, of the same sign, and put the
9026 * result in a destination FPU_REG.
9027 *
9028 * Call from C as:
9029 * void reg_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
9030 * int control_w)
9031 *
9032 *
9033 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
9034 * Vic 3163, Australia.
9035 * E-mail apm233m@vaxc.cc.monash.edu.au
9036 * All rights reserved.
9037 *
9038 * This copyright notice covers the redistribution and use of the
9039 * FPU emulator developed by W. Metzenthen. It covers only its use
9040 * in the 386BSD operating system. Any other use is not permitted
9041 * under this copyright.
9042 *
9043 * Redistribution and use in source and binary forms, with or without
9044 * modification, are permitted provided that the following conditions
9045 * are met:
9046 * 1. Redistributions of source code must retain the above copyright
9047 * notice, this list of conditions and the following disclaimer.
9048 * 2. Redistributions in binary form must include information specifying
9049 * that source code for the emulator is freely available and include
9050 * either:
9051 * a) an offer to provide the source code for a nominal distribution
9052 * fee, or
9053 * b) list at least two alternative methods whereby the source
9054 * can be obtained, e.g. a publically accessible bulletin board
9055 * and an anonymous ftp site from which the software can be
9056 * downloaded.
9057 * 3. All advertising materials specifically mentioning features or use of
9058 * this emulator must acknowledge that it was developed by W. Metzenthen.
9059 * 4. The name of W. Metzenthen may not be used to endorse or promote
9060 * products derived from this software without specific prior written
9061 * permission.
9062 *
9063 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
9064 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
9065 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
9066 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9067 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9068 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9069 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
9070 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
9071 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
9072 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9073 *
9074 */
9075
9076
9077/*
9078 | Kernel addition routine reg_u_add(reg *arg1, reg *arg2, reg *answ).
9079 | Takes two valid reg f.p. numbers (TW_Valid), which are
9080 | treated as unsigned numbers,
9081 | and returns their sum as a TW_Valid or TW_S f.p. number.
9082 | The returned number is normalized.
9083 | Basic checks are performed if PARANOID is defined.
9084 */
9085
9086#include "exception.h"
9087#include "fpu_asm.h"
9088#include "control_w.h"
9089
9090.text
9091 .align 2,144
9092.globl _reg_u_add
9093_reg_u_add:
9094 pushl %ebp
9095 movl %esp,%ebp
9096/* subl $16,%esp*/
9097 pushl %esi
9098 pushl %edi
9099 pushl %ebx
9100
9101 movl PARAM1,%esi /* source 1 */
9102 movl PARAM2,%edi /* source 2 */
9103
9104#ifdef DENORM_OPERAND
9105 cmpl EXP_UNDER,EXP(%esi)
9106 jg xOp1_not_denorm
9107
9108 call _denormal_operand
9109 orl %eax,%eax
9110 jnz FPU_Arith_exit
9111
9112xOp1_not_denorm:
9113 cmpl EXP_UNDER,EXP(%edi)
9114 jg xOp2_not_denorm
9115
9116 call _denormal_operand
9117 orl %eax,%eax
9118 jnz FPU_Arith_exit
9119
9120xOp2_not_denorm:
9121#endif DENORM_OPERAND
9122
9123/* xorl %ecx,%ecx*/
9124 movl EXP(%esi),%ecx
9125 subl EXP(%edi),%ecx /* exp1 - exp2 */
9126/* jnc L_arg1_larger*/
9127 jge L_arg1_larger
9128
9129 /* num1 is smaller */
9130 movl SIGL(%esi),%ebx
9131 movl SIGH(%esi),%eax
9132
9133 movl %edi,%esi
9134 negw %cx
9135 jmp L_accum_loaded
9136
9137L_arg1_larger:
9138 /* num1 has larger or equal exponent */
9139 movl SIGL(%edi),%ebx
9140 movl SIGH(%edi),%eax
9141
9142L_accum_loaded:
9143 movl PARAM3,%edi /* destination */
9144 movb SIGN(%esi),%dl
9145 movb %dl,SIGN(%edi) /* Copy the sign from the first arg */
9146
9147
9148 movl EXP(%esi),%edx
9149 movl %edx,EXP(%edi) /* Copy exponent to destination */
9150
9151 xorl %edx,%edx /* clear the extension */
9152
9153#ifdef PARANOID
9154 testl $0x80000000,%eax
9155 je L_bugged
9156
9157 testl $0x80000000,SIGH(%esi)
9158 je L_bugged
9159#endif PARANOID
9160
9161/* The number to be shifted is in %eax:%ebx:%edx*/
9162 cmpw $32,%cx /* shrd only works for 0..31 bits */
9163 jnc L_more_than_31
9164
9165/* less than 32 bits */
9166 shrd %cl,%ebx,%edx
9167 shrd %cl,%eax,%ebx
9168 shr %cl,%eax
9169 jmp L_shift_done
9170
9171L_more_than_31:
9172 cmpw $64,%cx
9173 jnc L_more_than_63
9174
9175 subb $32,%cl
9176 jz L_exactly_32
9177
9178 shrd %cl,%eax,%edx
9179 shr %cl,%eax
9180 orl %ebx,%ebx
9181 jz L_more_31_no_low /* none of the lowest bits is set*/
9182
9183 orl $1,%edx /* record the fact in the extension*/
9184
9185L_more_31_no_low:
9186 movl %eax,%ebx
9187 xorl %eax,%eax
9188 jmp L_shift_done
9189
9190L_exactly_32:
9191 movl %ebx,%edx
9192 movl %eax,%ebx
9193 xorl %eax,%eax
9194 jmp L_shift_done
9195
9196L_more_than_63:
9197 cmpw $65,%cx
9198 jnc L_more_than_64
9199
9200 movl %eax,%edx
9201 orl %ebx,%ebx
9202 jz L_more_63_no_low
9203
9204 orl $1,%edx
9205 jmp L_more_63_no_low
9206
9207L_more_than_64:
9208 movl $1,%edx /* The shifted nr always at least one '1'*/
9209
9210L_more_63_no_low:
9211 xorl %ebx,%ebx
9212 xorl %eax,%eax
9213
9214L_shift_done:
9215 /* Now do the addition */
9216 addl SIGL(%esi),%ebx
9217 adcl SIGH(%esi),%eax
9218 jnc L_round_the_result
9219
9220 /* Overflow, adjust the result */
9221 rcrl $1,%eax
9222 rcrl $1,%ebx
9223 rcrl $1,%edx
9224 jnc L_no_bit_lost
9225
9226 orl $1,%edx
9227
9228L_no_bit_lost:
9229 incl EXP(%edi)
9230
9231L_round_the_result:
9232 jmp FPU_round /* Round the result*/
9233
9234
9235
9236#ifdef PARANOID
9237/* If we ever get here then we have problems! */
9238L_bugged:
9239 pushl EX_INTERNAL|0x201
9240 call EXCEPTION
9241 pop %ebx
9242 jmp L_exit
9243#endif PARANOID
9244
9245
9246L_exit:
9247 popl %ebx
9248 popl %edi
9249 popl %esi
9250 leave
9251 ret
9252\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/reg_u_div.s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 31130 5462505570 12723\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 .file "reg_u_div.S"
9253/*
9254 * reg_u_div.S
9255 *
9256 * Core division routines
9257 *
9258 *
9259 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
9260 * Vic 3163, Australia.
9261 * E-mail apm233m@vaxc.cc.monash.edu.au
9262 * All rights reserved.
9263 *
9264 * This copyright notice covers the redistribution and use of the
9265 * FPU emulator developed by W. Metzenthen. It covers only its use
9266 * in the 386BSD operating system. Any other use is not permitted
9267 * under this copyright.
9268 *
9269 * Redistribution and use in source and binary forms, with or without
9270 * modification, are permitted provided that the following conditions
9271 * are met:
9272 * 1. Redistributions of source code must retain the above copyright
9273 * notice, this list of conditions and the following disclaimer.
9274 * 2. Redistributions in binary form must include information specifying
9275 * that source code for the emulator is freely available and include
9276 * either:
9277 * a) an offer to provide the source code for a nominal distribution
9278 * fee, or
9279 * b) list at least two alternative methods whereby the source
9280 * can be obtained, e.g. a publically accessible bulletin board
9281 * and an anonymous ftp site from which the software can be
9282 * downloaded.
9283 * 3. All advertising materials specifically mentioning features or use of
9284 * this emulator must acknowledge that it was developed by W. Metzenthen.
9285 * 4. The name of W. Metzenthen may not be used to endorse or promote
9286 * products derived from this software without specific prior written
9287 * permission.
9288 *
9289 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
9290 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
9291 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
9292 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9293 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9294 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9295 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
9296 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
9297 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
9298 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9299 *
9300 */
9301
9302/*---------------------------------------------------------------------------+
9303 | Kernel for the division routines. |
9304 | |
9305 | void reg_u_div(FPU_REG *a, FPU_REG *a, |
9306 | FPU_REG *dest, unsigned int control_word) |
9307 | |
9308 | Does not compute the destination exponent, but does adjust it. |
9309 +---------------------------------------------------------------------------*/
9310
9311#include "exception.h"
9312#include "fpu_asm.h"
9313#include "control_w.h"
9314
9315
9316/* #define dSIGL(x) (x) */
9317/* #define dSIGH(x) 4(x) */
9318
9319
9320.data
9321/*
9322 Local storage:
9323 Result: accum_3:accum_2:accum_1:accum_0
9324 Overflow flag: ovfl_flag
9325 */
9326 .align 2,0
9327accum_3:
9328 .long 0
9329accum_2:
9330 .long 0
9331accum_1:
9332 .long 0
9333accum_0:
9334 .long 0
9335result_1:
9336 .long 0
9337result_2:
9338 .long 0
9339ovfl_flag:
9340 .byte 0
9341
9342
9343.text
9344 .align 2,144
9345
9346.globl _reg_u_div
9347
9348.globl _divide_kernel
9349
9350_reg_u_div:
9351 pushl %ebp
9352 movl %esp,%ebp
9353
9354 pushl %esi
9355 pushl %edi
9356 pushl %ebx
9357
9358 movl PARAM1,%esi /* pointer to num */
9359 movl PARAM2,%ebx /* pointer to denom */
9360 movl PARAM3,%edi /* pointer to answer */
9361
9362#ifdef DENORM_OPERAND
9363 movl EXP(%esi),%eax
9364 cmpl EXP_UNDER,%eax
9365 jg xOp1_not_denorm
9366
9367 call _denormal_operand
9368 orl %eax,%eax
9369 jnz FPU_Arith_exit
9370
9371xOp1_not_denorm:
9372 movl EXP(%ebx),%eax
9373 cmpl EXP_UNDER,%eax
9374 jg xOp2_not_denorm
9375
9376 call _denormal_operand
9377 orl %eax,%eax
9378 jnz FPU_Arith_exit
9379
9380xOp2_not_denorm:
9381#endif DENORM_OPERAND
9382
9383_divide_kernel:
9384#ifdef PARANOID
9385/* testl $0x80000000, SIGH(%esi) *//* Dividend */
9386/* je L_bugged */
9387 testl $0x80000000, SIGH(%ebx) /* Divisor*/
9388 je L_bugged
9389#endif PARANOID
9390
9391/* Check if the divisor can be treated as having just 32 bits */
9392 cmpl $0,SIGL(%ebx)
9393 jnz L_Full_Division /* Can't do a quick divide */
9394
9395/* We should be able to zip through the division here */
9396 movl SIGH(%ebx),%ecx /* The divisor */
9397 movl SIGH(%esi),%edx /* Dividend */
9398 movl SIGL(%esi),%eax /* Dividend */
9399
9400 cmpl %ecx,%edx
9401 setaeb ovfl_flag /* Keep a record */
9402 jb L_no_adjust
9403
9404 subl %ecx,%edx /* Prevent the overflow */
9405
9406L_no_adjust:
9407 /* Divide the 64 bit number by the 32 bit denominator */
9408 divl %ecx
9409 movl %eax,result_2
9410
9411 /* Work on the remainder of the first division */
9412 xorl %eax,%eax
9413 divl %ecx
9414 movl %eax,result_1
9415
9416 /* Work on the remainder of the 64 bit division */
9417 xorl %eax,%eax
9418 divl %ecx
9419
9420 testb $255,ovfl_flag /* was the num > denom ? */
9421 je L_no_overflow
9422
9423 /* Do the shifting here */
9424 /* increase the exponent */
9425 incl EXP(%edi)
9426
9427 /* shift the mantissa right one bit */
9428 stc /* To set the ms bit */
9429 rcrl result_2
9430 rcrl result_1
9431 rcrl %eax
9432
9433L_no_overflow:
9434 jmp LRound_precision /* Do the rounding as required*/
9435
9436
9437/*---------------------------------------------------------------------------+
9438 | Divide: Return arg1/arg2 to arg3. |
9439 | |
9440 | This routine does not use the exponents of arg1 and arg2, but does |
9441 | adjust the exponent of arg3. |
9442 | |
9443 | The maximum returned value is (ignoring exponents) |
9444 | .ffffffff ffffffff |
9445 | ------------------ = 1.ffffffff fffffffe |
9446 | .80000000 00000000 |
9447 | and the minimum is |
9448 | .80000000 00000000 |
9449 | ------------------ = .80000000 00000001 (rounded) |
9450 | .ffffffff ffffffff |
9451 | |
9452 +---------------------------------------------------------------------------*/
9453
9454
9455L_Full_Division:
9456 /* Save extended dividend in local register*/
9457 movl SIGL(%esi),%eax
9458 movl %eax,accum_2
9459 movl SIGH(%esi),%eax
9460 movl %eax,accum_3
9461 xorl %eax,%eax
9462 movl %eax,accum_1 /* zero the extension */
9463 movl %eax,accum_0 /* zero the extension */
9464
9465 movl SIGL(%esi),%eax /* Get the current num */
9466 movl SIGH(%esi),%edx
9467
9468/*----------------------------------------------------------------------*/
9469/* Initialization done */
9470/* Do the first 32 bits */
9471
9472 movb $0,ovfl_flag
9473 cmpl SIGH(%ebx),%edx /* Test for imminent overflow */
9474 jb LLess_than_1
9475 ja LGreater_than_1
9476
9477 cmpl SIGL(%ebx),%eax
9478 jb LLess_than_1
9479
9480LGreater_than_1:
9481/* The dividend is greater or equal, would cause overflow */
9482 setaeb ovfl_flag /* Keep a record */
9483
9484 subl SIGL(%ebx),%eax
9485 sbbl SIGH(%ebx),%edx /* Prevent the overflow */
9486 movl %eax,accum_2
9487 movl %edx,accum_3
9488
9489LLess_than_1:
9490/* At this point, we have a dividend < divisor, with a record of
9491 adjustment in ovfl_flag */
9492
9493 /* We will divide by a number which is too large */
9494 movl SIGH(%ebx),%ecx
9495 addl $1,%ecx
9496 jnc LFirst_div_not_1
9497
9498 /* here we need to divide by 100000000h,
9499 i.e., no division at all.. */
9500 mov %edx,%eax
9501 jmp LFirst_div_done
9502
9503LFirst_div_not_1:
9504 divl %ecx /* Divide the numerator by the augmented
9505 denom ms dw */
9506
9507LFirst_div_done:
9508 movl %eax,result_2 /* Put the result in the answer */
9509
9510 mull SIGH(%ebx) /* mul by the ms dw of the denom */
9511
9512 subl %eax,accum_2 /* Subtract from the num local reg */
9513 sbbl %edx,accum_3
9514
9515 movl result_2,%eax /* Get the result back */
9516 mull SIGL(%ebx) /* now mul the ls dw of the denom */
9517
9518 subl %eax,accum_1 /* Subtract from the num local reg */
9519 sbbl %edx,accum_2
9520 sbbl $0,accum_3
9521 je LDo_2nd_32_bits /* Must check for non-zero result here */
9522
9523#ifdef PARANOID
9524 jb L_bugged_1
9525#endif PARANOID
9526
9527 /* need to subtract another once of the denom */
9528 incl result_2 /* Correct the answer */
9529
9530 movl SIGL(%ebx),%eax
9531 movl SIGH(%ebx),%edx
9532 subl %eax,accum_1 /* Subtract from the num local reg */
9533 sbbl %edx,accum_2
9534
9535#ifdef PARANOID
9536 sbbl $0,accum_3
9537 jne L_bugged_1 /* Must check for non-zero result here */
9538#endif PARANOID
9539
9540/*----------------------------------------------------------------------*/
9541/* Half of the main problem is done, there is just a reduced numerator
9542 to handle now */
9543/* Work with the second 32 bits, accum_0 not used from now on */
9544LDo_2nd_32_bits:
9545 movl accum_2,%edx /* get the reduced num */
9546 movl accum_1,%eax
9547
9548 /* need to check for possible subsequent overflow */
9549 cmpl SIGH(%ebx),%edx
9550 jb LDo_2nd_div
9551 ja LPrevent_2nd_overflow
9552
9553 cmpl SIGL(%ebx),%eax
9554 jb LDo_2nd_div
9555
9556LPrevent_2nd_overflow:
9557/* The numerator is greater or equal, would cause overflow */
9558 /* prevent overflow */
9559 subl SIGL(%ebx),%eax
9560 sbbl SIGH(%ebx),%edx
9561 movl %edx,accum_2
9562 movl %eax,accum_1
9563
9564 incl result_2 /* Reflect the subtraction in the answer */
9565
9566#ifdef PARANOID
9567 je L_bugged_2 /* Can't bump the result to 1.0 */
9568#endif PARANOID
9569
9570LDo_2nd_div:
9571 cmpl $0,%ecx /* augmented denom msw*/
9572 jnz LSecond_div_not_1
9573
9574 /* %ecx == 0, we are dividing by 1.0 */
9575 mov %edx,%eax
9576 jmp LSecond_div_done
9577
9578LSecond_div_not_1:
9579 divl %ecx /* Divide the numerator by the denom ms dw */
9580
9581LSecond_div_done:
9582 movl %eax,result_1 /* Put the result in the answer */
9583
9584 mull SIGH(%ebx) /* mul by the ms dw of the denom */
9585
9586 subl %eax,accum_1 /* Subtract from the num local reg */
9587 sbbl %edx,accum_2
9588
9589#ifdef PARANOID
9590 jc L_bugged_2
9591#endif PARANOID
9592
9593 movl result_1,%eax /* Get the result back */
9594 mull SIGL(%ebx) /* now mul the ls dw of the denom */
9595
9596 subl %eax,accum_0 /* Subtract from the num local reg */
9597 sbbl %edx,accum_1 /* Subtract from the num local reg */
9598 sbbl $0,accum_2
9599
9600#ifdef PARANOID
9601 jc L_bugged_2
9602#endif PARANOID
9603
9604 jz LDo_3rd_32_bits
9605
9606#ifdef PARANOID
9607 cmpl $1,accum_2
9608 jne L_bugged_2
9609#endif PARANOID
9610
9611 /* need to subtract another once of the denom */
9612 movl SIGL(%ebx),%eax
9613 movl SIGH(%ebx),%edx
9614 subl %eax,accum_0 /* Subtract from the num local reg */
9615 sbbl %edx,accum_1
9616 sbbl $0,accum_2
9617
9618#ifdef PARANOID
9619 jc L_bugged_2
9620 jne L_bugged_2
9621#endif PARANOID
9622
9623 addl $1,result_1 /* Correct the answer */
9624 adcl $0,result_2
9625
9626#ifdef PARANOID
9627 jc L_bugged_2 /* Must check for non-zero result here */
9628#endif PARANOID
9629
9630/*----------------------------------------------------------------------*/
9631/* The division is essentially finished here, we just need to perform
9632 tidying operations. */
9633/* deal with the 3rd 32 bits */
9634LDo_3rd_32_bits:
9635 movl accum_1,%edx /* get the reduced num */
9636 movl accum_0,%eax
9637
9638 /* need to check for possible subsequent overflow */
9639 cmpl SIGH(%ebx),%edx /* denom*/
9640 jb LRound_prep
9641 ja LPrevent_3rd_overflow
9642
9643 cmpl SIGL(%ebx),%eax /* denom */
9644 jb LRound_prep
9645
9646LPrevent_3rd_overflow:
9647 /* prevent overflow */
9648 subl SIGL(%ebx),%eax
9649 sbbl SIGH(%ebx),%edx
9650 movl %edx,accum_1
9651 movl %eax,accum_0
9652
9653 addl $1,result_1 /* Reflect the subtraction in the answer */
9654 adcl $0,result_2
9655 jne LRound_prep
9656 jnc LRound_prep
9657
9658 /* This is a tricky spot, there is an overflow of the answer */
9659 movb $255,ovfl_flag /* Overflow -> 1.000 */
9660
9661LRound_prep:
9662/* Prepare for rounding.
9663// To test for rounding, we just need to compare 2*accum with the
9664// denom. */
9665 movl accum_0,%ecx
9666 movl accum_1,%edx
9667 movl %ecx,%eax
9668 orl %edx,%eax
9669 jz LRound_ovfl /* The accumulator contains zero.*/
9670
9671 /* Multiply by 2 */
9672 clc
9673 rcll $1,%ecx
9674 rcll $1,%edx
9675 jc LRound_large /* No need to compare, denom smaller */
9676
9677 subl SIGL(%ebx),%ecx
9678 sbbl SIGH(%ebx),%edx
9679 jnc LRound_not_small
9680
9681 movl $0x70000000,%eax /* Denom was larger */
9682 jmp LRound_ovfl
9683
9684LRound_not_small:
9685 jnz LRound_large
9686
9687 movl $0x80000000,%eax /* Remainder was exactly 1/2 denom */
9688 jmp LRound_ovfl
9689
9690LRound_large:
9691 movl $0xff000000,%eax /* Denom was smaller */
9692
9693LRound_ovfl:
9694/* We are now ready to deal with rounding, but first we must get
9695 the bits properly aligned */
9696 testb $255,ovfl_flag /* was the num > denom ? */
9697 je LRound_precision
9698
9699 incl EXP(%edi)
9700
9701 /* shift the mantissa right one bit */
9702 stc /* Will set the ms bit */
9703 rcrl result_2
9704 rcrl result_1
9705 rcrl %eax
9706
9707/* Round the result as required */
9708LRound_precision:
9709 decl EXP(%edi) /* binary point between 1st & 2nd bits */
9710
9711 movl %eax,%edx
9712 movl result_1,%ebx
9713 movl result_2,%eax
9714 jmp FPU_round
9715
9716
9717#ifdef PARANOID
9718/* The logic is wrong if we got here */
9719L_bugged:
9720 pushl EX_INTERNAL|0x202
9721 call EXCEPTION
9722 pop %ebx
9723 jmp L_exit
9724
9725L_bugged_1:
9726 pushl EX_INTERNAL|0x203
9727 call EXCEPTION
9728 pop %ebx
9729 jmp L_exit
9730
9731L_bugged_2:
9732 pushl EX_INTERNAL|0x204
9733 call EXCEPTION
9734 pop %ebx
9735 jmp L_exit
9736
9737L_exit:
9738 popl %ebx
9739 popl %edi
9740 popl %esi
9741
9742 leave
9743 ret
9744#endif PARANOID
9745\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/div_small.s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 5753 5462505570 12726\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 .file "div_small.S"
9746/*
9747 * div_small.S
9748 *
9749 * Divide a 64 bit integer by a 32 bit integer & return remainder.
9750 *
9751 *
9752 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
9753 * Vic 3163, Australia.
9754 * E-mail apm233m@vaxc.cc.monash.edu.au
9755 * All rights reserved.
9756 *
9757 * This copyright notice covers the redistribution and use of the
9758 * FPU emulator developed by W. Metzenthen. It covers only its use
9759 * in the 386BSD operating system. Any other use is not permitted
9760 * under this copyright.
9761 *
9762 * Redistribution and use in source and binary forms, with or without
9763 * modification, are permitted provided that the following conditions
9764 * are met:
9765 * 1. Redistributions of source code must retain the above copyright
9766 * notice, this list of conditions and the following disclaimer.
9767 * 2. Redistributions in binary form must include information specifying
9768 * that source code for the emulator is freely available and include
9769 * either:
9770 * a) an offer to provide the source code for a nominal distribution
9771 * fee, or
9772 * b) list at least two alternative methods whereby the source
9773 * can be obtained, e.g. a publically accessible bulletin board
9774 * and an anonymous ftp site from which the software can be
9775 * downloaded.
9776 * 3. All advertising materials specifically mentioning features or use of
9777 * this emulator must acknowledge that it was developed by W. Metzenthen.
9778 * 4. The name of W. Metzenthen may not be used to endorse or promote
9779 * products derived from this software without specific prior written
9780 * permission.
9781 *
9782 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
9783 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
9784 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
9785 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9786 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9787 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9788 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
9789 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
9790 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
9791 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9792 *
9793 */
9794
9795/*---------------------------------------------------------------------------+
9796 | unsigned long div_small(unsigned long long *x, unsigned long y) |
9797 +---------------------------------------------------------------------------*/
9798
9799#include "fpu_asm.h"
9800
9801.text
9802 .align 2,144
9803
9804.globl _div_small
9805
9806_div_small:
9807 pushl %ebp
9808 movl %esp,%ebp
9809
9810 pushl %esi
9811
9812 movl PARAM1,%esi /* pointer to num */
9813 movl PARAM2,%ecx /* The denominator */
9814
9815 movl 4(%esi),%eax /* Get the current num msw */
9816 xorl %edx,%edx
9817 divl %ecx
9818
9819 movl %eax,4(%esi)
9820
9821 movl (%esi),%eax /* Get the num lsw */
9822 divl %ecx
9823
9824 movl %eax,(%esi)
9825
9826 movl %edx,%eax /* Return the remainder in eax */
9827
9828 popl %esi
9829
9830 leave
9831 ret
9832
9833\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/poly_div.s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 6731 5462505570 12576\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 .file "poly_div.S"
9834/*
9835 * poly_div.S
9836 *
9837 * A set of functions to divide 64 bit integers by fixed numbers.
9838 *
9839 *
9840 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
9841 * Vic 3163, Australia.
9842 * E-mail apm233m@vaxc.cc.monash.edu.au
9843 * All rights reserved.
9844 *
9845 * This copyright notice covers the redistribution and use of the
9846 * FPU emulator developed by W. Metzenthen. It covers only its use
9847 * in the 386BSD operating system. Any other use is not permitted
9848 * under this copyright.
9849 *
9850 * Redistribution and use in source and binary forms, with or without
9851 * modification, are permitted provided that the following conditions
9852 * are met:
9853 * 1. Redistributions of source code must retain the above copyright
9854 * notice, this list of conditions and the following disclaimer.
9855 * 2. Redistributions in binary form must include information specifying
9856 * that source code for the emulator is freely available and include
9857 * either:
9858 * a) an offer to provide the source code for a nominal distribution
9859 * fee, or
9860 * b) list at least two alternative methods whereby the source
9861 * can be obtained, e.g. a publically accessible bulletin board
9862 * and an anonymous ftp site from which the software can be
9863 * downloaded.
9864 * 3. All advertising materials specifically mentioning features or use of
9865 * this emulator must acknowledge that it was developed by W. Metzenthen.
9866 * 4. The name of W. Metzenthen may not be used to endorse or promote
9867 * products derived from this software without specific prior written
9868 * permission.
9869 *
9870 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
9871 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
9872 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
9873 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9874 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9875 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9876 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
9877 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
9878 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
9879 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9880 *
9881 */
9882
9883#include "fpu_asm.h"
9884
9885.text
9886
9887/*---------------------------------------------------------------------------*/
9888 .align 2,144
9889.globl _poly_div2
9890_poly_div2:
9891 pushl %ebp
9892 movl %esp,%ebp
9893
9894 movl PARAM1,%ecx
9895 movw (%ecx),%ax
9896
9897 shrl $1,4(%ecx)
9898 rcrl $1,(%ecx)
9899
9900 testw $1,%ax
9901 je poly_div2_exit
9902
9903 addl $1,(%ecx)
9904 adcl $0,4(%ecx)
9905poly_div2_exit:
9906
9907 leave
9908 ret
9909/*---------------------------------------------------------------------------*/
9910 .align 2,144
9911.globl _poly_div4
9912_poly_div4:
9913 pushl %ebp
9914 movl %esp,%ebp
9915
9916 movl PARAM1,%ecx
9917 movw (%ecx),%ax
9918
9919 movl 4(%ecx),%edx
9920 shll $30,%edx
9921
9922 shrl $2,4(%ecx)
9923 shrl $2,(%ecx)
9924
9925 orl %edx,(%ecx)
9926
9927 testw $2,%ax
9928 je poly_div4_exit
9929
9930 addl $1,(%ecx)
9931 adcl $0,4(%ecx)
9932poly_div4_exit:
9933
9934 leave
9935 ret
9936/*---------------------------------------------------------------------------*/
9937 .align 2,144
9938.globl _poly_div16
9939_poly_div16:
9940 pushl %ebp
9941 movl %esp,%ebp
9942
9943 movl PARAM1,%ecx
9944 movw (%ecx),%ax
9945
9946 movl 4(%ecx),%edx
9947 shll $28,%edx
9948
9949 shrl $4,4(%ecx)
9950 shrl $4,(%ecx)
9951
9952 orl %edx,(%ecx)
9953
9954 testw $8,%ax
9955 je poly_div16_exit
9956
9957 addl $1,(%ecx)
9958 adcl $0,4(%ecx)
9959poly_div16_exit:
9960
9961 leave
9962 ret
9963/*---------------------------------------------------------------------------*/
9964\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/polynomial.s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 10713 5462505570 13147\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
9965 * polynomial.S
9966 *
9967 * Fixed point arithmetic polynomial evaluation.
9968 *
9969 * Call from C as:
9970 * void polynomial(unsigned accum[], unsigned x[], unsigned terms[][2],
9971 * int n)
9972 *
9973 * Computes:
9974 * terms[0] + (terms[1] + (terms[2] + ... + (terms[n-1]*x)*x)*x)*x) ... )*x
9975 * The result is returned in accum.
9976 *
9977 *
9978 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
9979 * Vic 3163, Australia.
9980 * E-mail apm233m@vaxc.cc.monash.edu.au
9981 * All rights reserved.
9982 *
9983 * This copyright notice covers the redistribution and use of the
9984 * FPU emulator developed by W. Metzenthen. It covers only its use
9985 * in the 386BSD operating system. Any other use is not permitted
9986 * under this copyright.
9987 *
9988 * Redistribution and use in source and binary forms, with or without
9989 * modification, are permitted provided that the following conditions
9990 * are met:
9991 * 1. Redistributions of source code must retain the above copyright
9992 * notice, this list of conditions and the following disclaimer.
9993 * 2. Redistributions in binary form must include information specifying
9994 * that source code for the emulator is freely available and include
9995 * either:
9996 * a) an offer to provide the source code for a nominal distribution
9997 * fee, or
9998 * b) list at least two alternative methods whereby the source
9999 * can be obtained, e.g. a publically accessible bulletin board
10000 * and an anonymous ftp site from which the software can be
10001 * downloaded.
10002 * 3. All advertising materials specifically mentioning features or use of
10003 * this emulator must acknowledge that it was developed by W. Metzenthen.
10004 * 4. The name of W. Metzenthen may not be used to endorse or promote
10005 * products derived from this software without specific prior written
10006 * permission.
10007 *
10008 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
10009 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
10010 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
10011 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10012 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
10013 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
10014 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
10015 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10016 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
10017 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10018 *
10019 */
10020
10021 .file "fpolynom.s"
10022
10023#include "fpu_asm.h"
10024
10025
10026/* #define EXTRA_PRECISE*/
10027
10028#define TERM_SIZE $8
10029
10030
10031.text
10032 .align 2,144
10033.globl _polynomial
10034_polynomial:
10035 pushl %ebp
10036 movl %esp,%ebp
10037 subl $32,%esp
10038 pushl %esi
10039 pushl %edi
10040 pushl %ebx
10041
10042 movl PARAM1,%esi /* accum */
10043 movl PARAM2,%edi /* x */
10044 movl PARAM3,%ebx /* terms */
10045 movl PARAM4,%ecx /* n */
10046
10047 movl TERM_SIZE,%eax
10048 mull %ecx
10049 movl %eax,%ecx
10050
10051 movl 4(%ebx,%ecx,1),%edx /* terms[n] */
10052 movl %edx,-20(%ebp)
10053 movl (%ebx,%ecx,1),%edx /* terms[n] */
10054 movl %edx,-24(%ebp)
10055 xor %eax,%eax
10056 movl %eax,-28(%ebp)
10057
10058 subl TERM_SIZE,%ecx
10059 js L_accum_done
10060
10061L_accum_loop:
10062 xor %eax,%eax
10063 movl %eax,-4(%ebp)
10064 movl %eax,-8(%ebp)
10065
10066#ifdef EXTRA_PRECISE
10067 movl -28(%ebp),%eax
10068 mull 4(%edi) /* x ms long */
10069 movl %edx,-12(%ebp)
10070#endif EXTRA_PRECISE
10071
10072 movl -24(%ebp),%eax
10073 mull (%edi) /* x ls long */
10074/* movl %eax,-16(%ebp) */ /* Not needed */
10075 addl %edx,-12(%ebp)
10076 adcl $0,-8(%ebp)
10077
10078 movl -24(%ebp),%eax
10079 mull 4(%edi) /* x ms long */
10080 addl %eax,-12(%ebp)
10081 adcl %edx,-8(%ebp)
10082 adcl $0,-4(%ebp)
10083
10084 movl -20(%ebp),%eax
10085 mull (%edi)
10086 addl %eax,-12(%ebp)
10087 adcl %edx,-8(%ebp)
10088 adcl $0,-4(%ebp)
10089
10090 movl -20(%ebp),%eax
10091 mull 4(%edi)
10092 addl %eax,-8(%ebp)
10093 adcl %edx,-4(%ebp)
10094
10095/* Now add the next term */
10096 movl (%ebx,%ecx,1),%eax
10097 addl %eax,-8(%ebp)
10098 movl 4(%ebx,%ecx,1),%eax
10099 adcl %eax,-4(%ebp)
10100
10101/* And put into the second register */
10102 movl -4(%ebp),%eax
10103 movl %eax,-20(%ebp)
10104 movl -8(%ebp),%eax
10105 movl %eax,-24(%ebp)
10106
10107#ifdef EXTRA_PRECISE
10108 movl -12(%ebp),%eax
10109 movl %eax,-28(%ebp)
10110#else
10111 testb $128,-25(%ebp)
10112 je L_no_poly_round
10113
10114 addl $1,-24(%ebp)
10115 adcl $0,-20(%ebp)
10116L_no_poly_round:
10117#endif EXTRA_PRECISE
10118
10119 subl TERM_SIZE,%ecx
10120 jns L_accum_loop
10121
10122L_accum_done:
10123#ifdef EXTRA_PRECISE
10124/* And round the result */
10125 testb $128,-25(%ebp)
10126 je L_poly_done
10127
10128 addl $1,-24(%ebp)
10129 adcl $0,-20(%ebp)
10130#endif EXTRA_PRECISE
10131
10132L_poly_done:
10133 movl -24(%ebp),%eax
10134 movl %eax,(%esi)
10135 movl -20(%ebp),%eax
10136 movl %eax,4(%esi)
10137
10138 popl %ebx
10139 popl %edi
10140 popl %esi
10141 leave
10142 ret
10143\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/reg_u_mul.s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 11460 5462505570 12742\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 .file "reg_u_mul.S"
10144/*
10145 * reg_u_mul.S
10146 *
10147 * Core multiplication routine
10148 *
10149 *
10150 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
10151 * Vic 3163, Australia.
10152 * E-mail apm233m@vaxc.cc.monash.edu.au
10153 * All rights reserved.
10154 *
10155 * This copyright notice covers the redistribution and use of the
10156 * FPU emulator developed by W. Metzenthen. It covers only its use
10157 * in the 386BSD operating system. Any other use is not permitted
10158 * under this copyright.
10159 *
10160 * Redistribution and use in source and binary forms, with or without
10161 * modification, are permitted provided that the following conditions
10162 * are met:
10163 * 1. Redistributions of source code must retain the above copyright
10164 * notice, this list of conditions and the following disclaimer.
10165 * 2. Redistributions in binary form must include information specifying
10166 * that source code for the emulator is freely available and include
10167 * either:
10168 * a) an offer to provide the source code for a nominal distribution
10169 * fee, or
10170 * b) list at least two alternative methods whereby the source
10171 * can be obtained, e.g. a publically accessible bulletin board
10172 * and an anonymous ftp site from which the software can be
10173 * downloaded.
10174 * 3. All advertising materials specifically mentioning features or use of
10175 * this emulator must acknowledge that it was developed by W. Metzenthen.
10176 * 4. The name of W. Metzenthen may not be used to endorse or promote
10177 * products derived from this software without specific prior written
10178 * permission.
10179 *
10180 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
10181 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
10182 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
10183 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10184 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
10185 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
10186 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
10187 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10188 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
10189 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10190 *
10191 */
10192
10193/*---------------------------------------------------------------------------+
10194 | Basic multiplication routine. |
10195 | Does not check the resulting exponent for overflow/underflow |
10196 | |
10197 | reg_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw); |
10198 | |
10199 | Internal working is at approx 128 bits. |
10200 | Result is rounded to nearest 53 or 64 bits, using "nearest or even". |
10201 +---------------------------------------------------------------------------*/
10202
10203#include "exception.h"
10204#include "fpu_asm.h"
10205#include "control_w.h"
10206
10207
10208.data
10209 .align 2,0
10210accum_0:
10211 .long 0
10212accum_1:
10213 .long 0
10214
10215
10216.text
10217 .align 2,144
10218
10219.globl _reg_u_mul
10220_reg_u_mul:
10221 pushl %ebp
10222 movl %esp,%ebp
10223 pushl %esi
10224 pushl %edi
10225 pushl %ebx
10226
10227 movl PARAM1,%esi
10228 movl PARAM2,%edi
10229
10230#ifdef PARANOID
10231 testl $0x80000000,SIGH(%esi)
10232 jz L_bugged
10233 testl $0x80000000,SIGH(%edi)
10234 jz L_bugged
10235#endif PARANOID
10236
10237#ifdef DENORM_OPERAND
10238 movl EXP(%esi),%eax
10239 cmpl EXP_UNDER,%eax
10240 jg xOp1_not_denorm
10241
10242 call _denormal_operand
10243 orl %eax,%eax
10244 jnz FPU_Arith_exit
10245
10246xOp1_not_denorm:
10247 movl EXP(%edi),%eax
10248 cmpl EXP_UNDER,%eax
10249 jg xOp2_not_denorm
10250
10251 call _denormal_operand
10252 orl %eax,%eax
10253 jnz FPU_Arith_exit
10254
10255xOp2_not_denorm:
10256#endif DENORM_OPERAND
10257
10258 xorl %ecx,%ecx
10259 xorl %ebx,%ebx
10260
10261 movl SIGL(%esi),%eax
10262 mull SIGL(%edi)
10263 movl %eax,accum_0
10264 movl %edx,accum_1
10265
10266 movl SIGL(%esi),%eax
10267 mull SIGH(%edi)
10268 addl %eax,accum_1
10269 adcl %edx,%ebx
10270/* adcl $0,%ecx *//* overflow here is not possible */
10271
10272 movl SIGH(%esi),%eax
10273 mull SIGL(%edi)
10274 addl %eax,accum_1
10275 adcl %edx,%ebx
10276 adcl $0,%ecx
10277
10278 movl SIGH(%esi),%eax
10279 mull SIGH(%edi)
10280 addl %eax,%ebx
10281 adcl %edx,%ecx
10282
10283 movl EXP(%esi),%eax /* Compute the exponent */
10284 addl EXP(%edi),%eax
10285 subl EXP_BIAS-1,%eax
10286/* Have now finished with the sources */
10287 movl PARAM3,%edi /* Point to the destination */
10288 movl %eax,EXP(%edi)
10289
10290/* Now make sure that the result is normalized */
10291 testl $0x80000000,%ecx
10292 jnz LResult_Normalised
10293
10294 /* Normalize by shifting left one bit */
10295 shll $1,accum_0
10296 rcll $1,accum_1
10297 rcll $1,%ebx
10298 rcll $1,%ecx
10299 decl EXP(%edi)
10300
10301LResult_Normalised:
10302 movl accum_0,%eax
10303 movl accum_1,%edx
10304 orl %eax,%eax
10305 jz L_extent_zero
10306
10307 orl $1,%edx
10308
10309L_extent_zero:
10310 movl %ecx,%eax
10311 jmp FPU_round
10312
10313
10314#ifdef PARANOID
10315L_bugged:
10316 pushl EX_INTERNAL|0x205
10317 call EXCEPTION
10318 pop %ebx
10319 jmp L_exit
10320
10321L_exit:
10322 popl %ebx
10323 popl %edi
10324 popl %esi
10325 leave
10326 ret
10327#endif PARANOID
10328
10329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/reg_u_sub.s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 17550 5462505570 12744\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 .file "reg_u_sub.S"
10330/*
10331 * reg_u_sub.S
10332 *
10333 * Core floating point subtraction routine.
10334 *
10335 * Call from C as:
10336 * void reg_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
10337 * int control_w)
10338 *
10339 *
10340 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
10341 * Vic 3163, Australia.
10342 * E-mail apm233m@vaxc.cc.monash.edu.au
10343 * All rights reserved.
10344 *
10345 * This copyright notice covers the redistribution and use of the
10346 * FPU emulator developed by W. Metzenthen. It covers only its use
10347 * in the 386BSD operating system. Any other use is not permitted
10348 * under this copyright.
10349 *
10350 * Redistribution and use in source and binary forms, with or without
10351 * modification, are permitted provided that the following conditions
10352 * are met:
10353 * 1. Redistributions of source code must retain the above copyright
10354 * notice, this list of conditions and the following disclaimer.
10355 * 2. Redistributions in binary form must include information specifying
10356 * that source code for the emulator is freely available and include
10357 * either:
10358 * a) an offer to provide the source code for a nominal distribution
10359 * fee, or
10360 * b) list at least two alternative methods whereby the source
10361 * can be obtained, e.g. a publically accessible bulletin board
10362 * and an anonymous ftp site from which the software can be
10363 * downloaded.
10364 * 3. All advertising materials specifically mentioning features or use of
10365 * this emulator must acknowledge that it was developed by W. Metzenthen.
10366 * 4. The name of W. Metzenthen may not be used to endorse or promote
10367 * products derived from this software without specific prior written
10368 * permission.
10369 *
10370 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
10371 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
10372 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
10373 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10374 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
10375 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
10376 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
10377 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10378 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
10379 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10380 *
10381 */
10382
10383/*
10384 | Kernel subtraction routine reg_u_sub(reg *arg1, reg *arg2, reg *answ).
10385 | Takes two valid reg f.p. numbers (TW_Valid), which are
10386 | treated as unsigned numbers,
10387 | and returns their difference as a TW_Valid or TW_Zero f.p.
10388 | number.
10389 | The first number (arg1) must be the larger.
10390 | The returned number is normalized.
10391 | Basic checks are performed if PARANOID is defined.
10392 */
10393
10394#include "exception.h"
10395#include "fpu_asm.h"
10396#include "control_w.h"
10397
10398.text
10399 .align 2,144
10400.globl _reg_u_sub
10401_reg_u_sub:
10402 pushl %ebp
10403 movl %esp,%ebp
10404 pushl %esi
10405 pushl %edi
10406 pushl %ebx
10407
10408 movl PARAM1,%esi /* source 1 */
10409 movl PARAM2,%edi /* source 2 */
10410
10411#ifdef DENORM_OPERAND
10412 cmpl EXP_UNDER,EXP(%esi)
10413 jg xOp1_not_denorm
10414
10415 call _denormal_operand
10416 orl %eax,%eax
10417 jnz FPU_Arith_exit
10418
10419xOp1_not_denorm:
10420 cmpl EXP_UNDER,EXP(%edi)
10421 jg xOp2_not_denorm
10422
10423 call _denormal_operand
10424 orl %eax,%eax
10425 jnz FPU_Arith_exit
10426
10427xOp2_not_denorm:
10428#endif DENORM_OPERAND
10429
10430/* xorl %ecx,%ecx */
10431 movl EXP(%esi),%ecx
10432 subl EXP(%edi),%ecx /* exp1 - exp2 */
10433
10434#ifdef PARANOID
10435 /* source 2 is always smaller than source 1 */
10436/* jc L_bugged */
10437 js L_bugged_1
10438
10439 testl $0x80000000,SIGH(%edi) /* The args are assumed to be be normalized */
10440 je L_bugged_2
10441
10442 testl $0x80000000,SIGH(%esi)
10443 je L_bugged_2
10444#endif PARANOID
10445
10446/*--------------------------------------+
10447 | Form a register holding the |
10448 | smaller number |
10449 +--------------------------------------*/
10450 movl SIGH(%edi),%eax /* register ms word */
10451 movl SIGL(%edi),%ebx /* register ls word */
10452
10453 movl PARAM3,%edi /* destination */
10454 movl EXP(%esi),%edx
10455 movl %edx,EXP(%edi) /* Copy exponent to destination */
10456 movb SIGN(%esi),%dl
10457 movb %dl,SIGN(%edi) /* Copy the sign from the first arg */
10458
10459 xorl %edx,%edx /* register extension */
10460
10461/*--------------------------------------+
10462 | Shift the temporary register |
10463 | right the required number of |
10464 | places. |
10465 +--------------------------------------*/
10466L_shift_r:
10467 cmpl $32,%ecx /* shrd only works for 0..31 bits */
10468 jnc L_more_than_31
10469
10470/* less than 32 bits */
10471 shrd %cl,%ebx,%edx
10472 shrd %cl,%eax,%ebx
10473 shr %cl,%eax
10474 jmp L_shift_done
10475
10476L_more_than_31:
10477 cmpl $64,%ecx
10478 jnc L_more_than_63
10479
10480 subb $32,%cl
10481 jz L_exactly_32
10482
10483 shrd %cl,%eax,%edx
10484 shr %cl,%eax
10485 orl %ebx,%ebx
10486 jz L_more_31_no_low /* none of the lowest bits is set */
10487
10488 orl $1,%edx /* record the fact in the extension */
10489
10490L_more_31_no_low:
10491 movl %eax,%ebx
10492 xorl %eax,%eax
10493 jmp L_shift_done
10494
10495L_exactly_32:
10496 movl %ebx,%edx
10497 movl %eax,%ebx
10498 xorl %eax,%eax
10499 jmp L_shift_done
10500
10501L_more_than_63:
10502 cmpw $65,%cx
10503 jnc L_more_than_64
10504
10505 /* Shift right by 64 bits */
10506 movl %eax,%edx
10507 orl %ebx,%ebx
10508 jz L_more_63_no_low
10509
10510 orl $1,%edx
10511 jmp L_more_63_no_low
10512
10513L_more_than_64:
10514 jne L_more_than_65
10515
10516 /* Shift right by 65 bits */
10517 /* Carry is clear if we get here */
10518 movl %eax,%edx
10519 rcrl %edx
10520 jnc L_shift_65_nc
10521
10522 orl $1,%edx
10523 jmp L_more_63_no_low
10524
10525L_shift_65_nc:
10526 orl %ebx,%ebx
10527 jz L_more_63_no_low
10528
10529 orl $1,%edx
10530 jmp L_more_63_no_low
10531
10532L_more_than_65:
10533 movl $1,%edx /* The shifted nr always at least one '1' */
10534
10535L_more_63_no_low:
10536 xorl %ebx,%ebx
10537 xorl %eax,%eax
10538
10539L_shift_done:
10540L_subtr:
10541/*------------------------------+
10542 | Do the subtraction |
10543 +------------------------------*/
10544 xorl %ecx,%ecx
10545 subl %edx,%ecx
10546 movl %ecx,%edx
10547 movl SIGL(%esi),%ecx
10548 sbbl %ebx,%ecx
10549 movl %ecx,%ebx
10550 movl SIGH(%esi),%ecx
10551 sbbl %eax,%ecx
10552 movl %ecx,%eax
10553
10554#ifdef PARANOID
10555 /* We can never get a borrow */
10556 jc L_bugged
10557#endif PARANOID
10558
10559/*--------------------------------------+
10560 | Normalize the result |
10561 +--------------------------------------*/
10562 testl $0x80000000,%eax
10563 jnz L_round /* no shifting needed */
10564
10565 orl %eax,%eax
10566 jnz L_shift_1 /* shift left 1 - 31 bits */
10567
10568 orl %ebx,%ebx
10569 jnz L_shift_32 /* shift left 32 - 63 bits */
10570
10571/* A rare case, the only one which is non-zero if we got here
10572// is: 1000000 .... 0000
10573// -0111111 .... 1111 1
10574// --------------------
10575// 0000000 .... 0000 1 */
10576
10577 cmpl $0x80000000,%edx
10578 jnz L_must_be_zero
10579
10580 /* Shift left 64 bits */
10581 subl $64,EXP(%edi)
10582 movl %edx,%eax
10583 jmp L_store
10584
10585L_must_be_zero:
10586#ifdef PARANOID
10587 orl %edx,%edx
10588 jnz L_bugged_3
10589#endif PARANOID
10590
10591 /* The result is zero */
10592 movb TW_Zero,TAG(%edi)
10593 movl $0,EXP(%edi) /* exponent */
10594 movl $0,SIGL(%edi)
10595 movl $0,SIGH(%edi)
10596 jmp L_exit /* Does not underflow */
10597
10598L_shift_32:
10599 movl %ebx,%eax
10600 movl %edx,%ebx
10601 movl $0,%edx
10602 subl $32,EXP(%edi) /* Can get underflow here */
10603
10604/* We need to shift left by 1 - 31 bits */
10605L_shift_1:
10606 bsrl %eax,%ecx /* get the required shift in %ecx */
10607 subl $31,%ecx
10608 negl %ecx
10609 shld %cl,%ebx,%eax
10610 shld %cl,%edx,%ebx
10611 shl %cl,%edx
10612 subl %ecx,EXP(%edi) /* Can get underflow here */
10613
10614L_round:
10615 jmp FPU_round /* Round the result */
10616
10617
10618#ifdef PARANOID
10619L_bugged_1:
10620 pushl EX_INTERNAL|0x206
10621 call EXCEPTION
10622 pop %ebx
10623 jmp L_exit
10624
10625L_bugged_2:
10626 pushl EX_INTERNAL|0x209
10627 call EXCEPTION
10628 pop %ebx
10629 jmp L_exit
10630
10631L_bugged_3:
10632 pushl EX_INTERNAL|0x210
10633 call EXCEPTION
10634 pop %ebx
10635 jmp L_exit
10636
10637L_bugged_4:
10638 pushl EX_INTERNAL|0x211
10639 call EXCEPTION
10640 pop %ebx
10641 jmp L_exit
10642
10643L_bugged:
10644 pushl EX_INTERNAL|0x212
10645 call EXCEPTION
10646 pop %ebx
10647 jmp L_exit
10648#endif PARANOID
10649
10650
10651L_store:
10652/*------------------------------+
10653 | Store the result |
10654 +------------------------------*/
10655 movl %eax,SIGH(%edi)
10656 movl %ebx,SIGL(%edi)
10657
10658 movb TW_Valid,TAG(%edi) /* Set the tags to TW_Valid */
10659
10660 cmpl EXP_UNDER,EXP(%edi)
10661 jle L_underflow
10662
10663L_exit:
10664 popl %ebx
10665 popl %edi
10666 popl %esi
10667 leave
10668 ret
10669
10670
10671L_underflow:
10672 push %edi
10673 call _arith_underflow
10674 pop %ebx
10675 jmp L_exit
10676
10677\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/wm_shrx.s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 16475 5462505570 12466\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 .file "wm_shrx.S"
10678/*
10679 * wm_shrx.S
10680 *
10681 * 64 bit right shift functions
10682 *
10683 * Call from C as:
10684 * unsigned shrx(void *arg1, unsigned arg2)
10685 * and
10686 * unsigned shrxs(void *arg1, unsigned arg2)
10687 *
10688 *
10689 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
10690 * Vic 3163, Australia.
10691 * E-mail apm233m@vaxc.cc.monash.edu.au
10692 * All rights reserved.
10693 *
10694 * This copyright notice covers the redistribution and use of the
10695 * FPU emulator developed by W. Metzenthen. It covers only its use
10696 * in the 386BSD operating system. Any other use is not permitted
10697 * under this copyright.
10698 *
10699 * Redistribution and use in source and binary forms, with or without
10700 * modification, are permitted provided that the following conditions
10701 * are met:
10702 * 1. Redistributions of source code must retain the above copyright
10703 * notice, this list of conditions and the following disclaimer.
10704 * 2. Redistributions in binary form must include information specifying
10705 * that source code for the emulator is freely available and include
10706 * either:
10707 * a) an offer to provide the source code for a nominal distribution
10708 * fee, or
10709 * b) list at least two alternative methods whereby the source
10710 * can be obtained, e.g. a publically accessible bulletin board
10711 * and an anonymous ftp site from which the software can be
10712 * downloaded.
10713 * 3. All advertising materials specifically mentioning features or use of
10714 * this emulator must acknowledge that it was developed by W. Metzenthen.
10715 * 4. The name of W. Metzenthen may not be used to endorse or promote
10716 * products derived from this software without specific prior written
10717 * permission.
10718 *
10719 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
10720 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
10721 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
10722 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10723 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
10724 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
10725 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
10726 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10727 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
10728 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10729 *
10730 */
10731
10732
10733#include "fpu_asm.h"
10734
10735.text
10736 .align 2,144
10737
10738/*---------------------------------------------------------------------------+
10739 | unsigned shrx(void *arg1, unsigned arg2) |
10740 | |
10741 | Extended shift right function. |
10742 | Fastest for small shifts. |
10743 | Shifts the 64 bit quantity pointed to by the first arg (arg1) |
10744 | right by the number of bits specified by the second arg (arg2). |
10745 | Forms a 96 bit quantity from the 64 bit arg and eax: |
10746 | [ 64 bit arg ][ eax ] |
10747 | shift right ---------> |
10748 | The eax register is initialized to 0 before the shifting. |
10749 | Results returned in the 64 bit arg and eax. |
10750 +---------------------------------------------------------------------------*/
10751
10752 .globl _shrx
10753
10754_shrx:
10755 push %ebp
10756 movl %esp,%ebp
10757 pushl %esi
10758 movl PARAM2,%ecx
10759 movl PARAM1,%esi
10760 cmpl $32,%ecx /* shrd only works for 0..31 bits */
10761 jnc L_more_than_31
10762
10763/* less than 32 bits */
10764 pushl %ebx
10765 movl (%esi),%ebx /* lsl */
10766 movl 4(%esi),%edx /* msl */
10767 xorl %eax,%eax /* extension */
10768 shrd %cl,%ebx,%eax
10769 shrd %cl,%edx,%ebx
10770 shr %cl,%edx
10771 movl %ebx,(%esi)
10772 movl %edx,4(%esi)
10773 popl %ebx
10774 popl %esi
10775 leave
10776 ret
10777
10778L_more_than_31:
10779 cmpl $64,%ecx
10780 jnc L_more_than_63
10781
10782 subb $32,%cl
10783 movl (%esi),%eax /* lsl */
10784 movl 4(%esi),%edx /* msl */
10785 shrd %cl,%edx,%eax
10786 shr %cl,%edx
10787 movl %edx,(%esi)
10788 movl $0,4(%esi)
10789 popl %esi
10790 leave
10791 ret
10792
10793L_more_than_63:
10794 cmpl $96,%ecx
10795 jnc L_more_than_95
10796
10797 subb $64,%cl
10798 movl 4(%esi),%eax /* msl */
10799 shr %cl,%eax
10800 xorl %edx,%edx
10801 movl %edx,(%esi)
10802 movl %edx,4(%esi)
10803 popl %esi
10804 leave
10805 ret
10806
10807L_more_than_95:
10808 xorl %eax,%eax
10809 movl %eax,(%esi)
10810 movl %eax,4(%esi)
10811 popl %esi
10812 leave
10813 ret
10814
10815
10816/*---------------------------------------------------------------------------+
10817 | unsigned shrxs(void *arg1, unsigned arg2) |
10818 | |
10819 | Extended shift right function (optimized for small floating point |
10820 | integers). |
10821 | Shifts the 64 bit quantity pointed to by the first arg (arg1) |
10822 | right by the number of bits specified by the second arg (arg2). |
10823 | Forms a 96 bit quantity from the 64 bit arg and eax: |
10824 | [ 64 bit arg ][ eax ] |
10825 | shift right ---------> |
10826 | The eax register is initialized to 0 before the shifting. |
10827 | The lower 8 bits of eax are lost and replaced by a flag which is |
10828 | set (to 0x01) if any bit, apart from the first one, is set in the |
10829 | part which has been shifted out of the arg. |
10830 | Results returned in the 64 bit arg and eax. |
10831 +---------------------------------------------------------------------------*/
10832 .globl _shrxs
10833_shrxs:
10834 push %ebp
10835 movl %esp,%ebp
10836 pushl %esi
10837 pushl %ebx
10838 movl PARAM2,%ecx
10839 movl PARAM1,%esi
10840 cmpl $64,%ecx /* shrd only works for 0..31 bits */
10841 jnc Ls_more_than_63
10842
10843 cmpl $32,%ecx /* shrd only works for 0..31 bits */
10844 jc Ls_less_than_32
10845
10846/* We got here without jumps by assuming that the most common requirement
10847 is for small integers */
10848/* Shift by [32..63] bits */
10849 subb $32,%cl
10850 movl (%esi),%eax /* lsl */
10851 movl 4(%esi),%edx /* msl */
10852 xorl %ebx,%ebx
10853 shrd %cl,%eax,%ebx
10854 shrd %cl,%edx,%eax
10855 shr %cl,%edx
10856 orl %ebx,%ebx /* test these 32 bits */
10857 setne %bl
10858 test $0x7fffffff,%eax /* and 31 bits here */
10859 setne %bh
10860 orw %bx,%bx /* Any of the 63 bit set ? */
10861 setne %al
10862 movl %edx,(%esi)
10863 movl $0,4(%esi)
10864 popl %ebx
10865 popl %esi
10866 leave
10867 ret
10868
10869/* Shift by [0..31] bits */
10870Ls_less_than_32:
10871 movl (%esi),%ebx /* lsl */
10872 movl 4(%esi),%edx /* msl */
10873 xorl %eax,%eax /* extension */
10874 shrd %cl,%ebx,%eax
10875 shrd %cl,%edx,%ebx
10876 shr %cl,%edx
10877 test $0x7fffffff,%eax /* only need to look at eax here */
10878 setne %al
10879 movl %ebx,(%esi)
10880 movl %edx,4(%esi)
10881 popl %ebx
10882 popl %esi
10883 leave
10884 ret
10885
10886/* Shift by [64..95] bits */
10887Ls_more_than_63:
10888 cmpl $96,%ecx
10889 jnc Ls_more_than_95
10890
10891 subb $64,%cl
10892 movl (%esi),%ebx /* lsl */
10893 movl 4(%esi),%eax /* msl */
10894 xorl %edx,%edx /* extension */
10895 shrd %cl,%ebx,%edx
10896 shrd %cl,%eax,%ebx
10897 shr %cl,%eax
10898 orl %ebx,%edx
10899 setne %bl
10900 test $0x7fffffff,%eax /* only need to look at eax here */
10901 setne %bh
10902 orw %bx,%bx
10903 setne %al
10904 xorl %edx,%edx
10905 movl %edx,(%esi) /* set to zero */
10906 movl %edx,4(%esi) /* set to zero */
10907 popl %ebx
10908 popl %esi
10909 leave
10910 ret
10911
10912Ls_more_than_95:
10913/* Shift by [96..inf) bits */
10914 xorl %eax,%eax
10915 movl (%esi),%ebx
10916 orl 4(%esi),%ebx
10917 setne %al
10918 xorl %ebx,%ebx
10919 movl %ebx,(%esi)
10920 movl %ebx,4(%esi)
10921 popl %ebx
10922 popl %esi
10923 leave
10924 ret
10925\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/wm_sqrt.s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 0 \0 26276 5462505570 12473\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0wheel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 .file "wm_sqrt.S"
10926/*
10927 * wm_sqrt.S
10928 *
10929 * Fixed point arithmetic square root evaluation.
10930 *
10931 * Call from C as:
10932 * void wm_sqrt(FPU_REG *n, unsigned int control_word)
10933 *
10934 *
10935 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
10936 * Vic 3163, Australia.
10937 * E-mail apm233m@vaxc.cc.monash.edu.au
10938 * All rights reserved.
10939 *
10940 * This copyright notice covers the redistribution and use of the
10941 * FPU emulator developed by W. Metzenthen. It covers only its use
10942 * in the 386BSD operating system. Any other use is not permitted
10943 * under this copyright.
10944 *
10945 * Redistribution and use in source and binary forms, with or without
10946 * modification, are permitted provided that the following conditions
10947 * are met:
10948 * 1. Redistributions of source code must retain the above copyright
10949 * notice, this list of conditions and the following disclaimer.
10950 * 2. Redistributions in binary form must include information specifying
10951 * that source code for the emulator is freely available and include
10952 * either:
10953 * a) an offer to provide the source code for a nominal distribution
10954 * fee, or
10955 * b) list at least two alternative methods whereby the source
10956 * can be obtained, e.g. a publically accessible bulletin board
10957 * and an anonymous ftp site from which the software can be
10958 * downloaded.
10959 * 3. All advertising materials specifically mentioning features or use of
10960 * this emulator must acknowledge that it was developed by W. Metzenthen.
10961 * 4. The name of W. Metzenthen may not be used to endorse or promote
10962 * products derived from this software without specific prior written
10963 * permission.
10964 *
10965 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
10966 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
10967 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
10968 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10969 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
10970 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
10971 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
10972 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10973 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
10974 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10975 *
10976 */
10977
10978
10979/*---------------------------------------------------------------------------+
10980 | wm_sqrt(FPU_REG *n, unsigned int control_word) |
10981 | returns the square root of n in n. |
10982 | |
10983 | Use Newton's method to compute the square root of a number, which must |
10984 | be in the range [1.0 .. 4.0), to 64 bits accuracy. |
10985 | Does not check the sign or tag of the argument. |
10986 | Sets the exponent, but not the sign or tag of the result. |
10987 | |
10988 | The guess is kept in %esi:%edi |
10989 +---------------------------------------------------------------------------*/
10990
10991#include "exception.h"
10992#include "fpu_asm.h"
10993
10994
10995.data
10996/*
10997 Local storage:
10998 */
10999 .align 4,0
11000accum_3:
11001 .long 0 /* ms word */
11002accum_2:
11003 .long 0
11004accum_1:
11005 .long 0
11006accum_0:
11007 .long 0
11008
11009/* The de-normalised argument:
11010// sq_2 sq_1 sq_0
11011// b b b b b b b ... b b b b b b .... b b b b 0 0 0 ... 0
11012// ^ binary point here */
11013fsqrt_arg_2:
11014 .long 0 /* ms word */
11015fsqrt_arg_1:
11016 .long 0
11017fsqrt_arg_0:
11018 .long 0 /* ls word, at most the ms bit is set */
11019
11020.text
11021 .align 2,144
11022
11023.globl _wm_sqrt
11024
11025_wm_sqrt:
11026 pushl %ebp
11027 movl %esp,%ebp
11028 pushl %esi
11029 pushl %edi
11030 pushl %ebx
11031
11032 movl PARAM1,%esi
11033
11034 movl SIGH(%esi),%eax
11035 movl SIGL(%esi),%ecx
11036 xorl %edx,%edx
11037
11038/* We use a rough linear estimate for the first guess.. */
11039
11040 cmpl EXP_BIAS,EXP(%esi)
11041 jnz sqrt_arg_ge_2
11042
11043 shrl $1,%eax /* arg is in the range [1.0 .. 2.0) */
11044 rcrl $1,%ecx
11045 rcrl $1,%edx
11046
11047sqrt_arg_ge_2:
11048/* From here on, n is never accessed directly again until it is
11049// replaced by the answer. */
11050
11051 movl %eax,fsqrt_arg_2 /* ms word of n */
11052 movl %ecx,fsqrt_arg_1
11053 movl %edx,fsqrt_arg_0
11054
11055/* Make a linear first estimate */
11056 shrl $1,%eax
11057 addl $0x40000000,%eax
11058 movl $0xaaaaaaaa,%ecx
11059 mull %ecx
11060 shll %edx /* max result was 7fff... */
11061 testl $0x80000000,%edx /* but min was 3fff... */
11062 jnz sqrt_prelim_no_adjust
11063
11064 movl $0x80000000,%edx /* round up */
11065
11066sqrt_prelim_no_adjust:
11067 movl %edx,%esi /* Our first guess */
11068
11069/* We have now computed (approx) (2 + x) / 3, which forms the basis
11070 for a few iterations of Newton's method */
11071
11072 movl fsqrt_arg_2,%ecx /* ms word */
11073
11074/* From our initial estimate, three iterations are enough to get us
11075// to 30 bits or so. This will then allow two iterations at better
11076// precision to complete the process.
11077
11078// Compute (g + n/g)/2 at each iteration (g is the guess). */
11079 shrl %ecx /* Doing this first will prevent a divide */
11080 /* overflow later. */
11081
11082 movl %ecx,%edx /* msw of the arg / 2 */
11083 divl %esi /* current estimate */
11084 shrl %esi /* divide by 2 */
11085 addl %eax,%esi /* the new estimate */
11086
11087 movl %ecx,%edx
11088 divl %esi
11089 shrl %esi
11090 addl %eax,%esi
11091
11092 movl %ecx,%edx
11093 divl %esi
11094 shrl %esi
11095 addl %eax,%esi
11096
11097/* Now that an estimate accurate to about 30 bits has been obtained (in %esi),
11098// we improve it to 60 bits or so.
11099
11100// The strategy from now on is to compute new estimates from
11101// guess := guess + (n - guess^2) / (2 * guess) */
11102
11103/* First, find the square of the guess */
11104 movl %esi,%eax
11105 mull %esi
11106/* guess^2 now in %edx:%eax */
11107
11108 movl fsqrt_arg_1,%ecx
11109 subl %ecx,%eax
11110 movl fsqrt_arg_2,%ecx /* ms word of normalized n */
11111 sbbl %ecx,%edx
11112 jnc sqrt_stage_2_positive
11113/* subtraction gives a negative result
11114// negate the result before division */
11115 notl %edx
11116 notl %eax
11117 addl $1,%eax
11118 adcl $0,%edx
11119
11120 divl %esi
11121 movl %eax,%ecx
11122
11123 movl %edx,%eax
11124 divl %esi
11125 jmp sqrt_stage_2_finish
11126
11127sqrt_stage_2_positive:
11128 divl %esi
11129 movl %eax,%ecx
11130
11131 movl %edx,%eax
11132 divl %esi
11133
11134 notl %ecx
11135 notl %eax
11136 addl $1,%eax
11137 adcl $0,%ecx
11138
11139sqrt_stage_2_finish:
11140 sarl $1,%ecx /* divide by 2 */
11141 rcrl $1,%eax
11142
11143 /* Form the new estimate in %esi:%edi */
11144 movl %eax,%edi
11145 addl %ecx,%esi
11146
11147 jnz sqrt_stage_2_done /* result should be [1..2) */
11148
11149#ifdef PARANOID
11150/* It should be possible to get here only if the arg is ffff....ffff*/
11151 cmp $0xffffffff,fsqrt_arg_1
11152 jnz sqrt_stage_2_error
11153#endif PARANOID
11154
11155/* The best rounded result.*/
11156 xorl %eax,%eax
11157 decl %eax
11158 movl %eax,%edi
11159 movl %eax,%esi
11160 movl $0x7fffffff,%eax
11161 jmp sqrt_round_result
11162
11163#ifdef PARANOID
11164sqrt_stage_2_error:
11165 pushl EX_INTERNAL|0x213
11166 call EXCEPTION
11167#endif PARANOID
11168
11169sqrt_stage_2_done:
11170
11171/* Now the square root has been computed to better than 60 bits */
11172
11173/* Find the square of the guess*/
11174 movl %edi,%eax /* ls word of guess*/
11175 mull %edi
11176 movl %edx,accum_1
11177
11178 movl %esi,%eax
11179 mull %esi
11180 movl %edx,accum_3
11181 movl %eax,accum_2
11182
11183 movl %edi,%eax
11184 mull %esi
11185 addl %eax,accum_1
11186 adcl %edx,accum_2
11187 adcl $0,accum_3
11188
11189/* movl %esi,%eax*/
11190/* mull %edi*/
11191 addl %eax,accum_1
11192 adcl %edx,accum_2
11193 adcl $0,accum_3
11194
11195/* guess^2 now in accum_3:accum_2:accum_1*/
11196
11197 movl fsqrt_arg_0,%eax /* get normalized n*/
11198 subl %eax,accum_1
11199 movl fsqrt_arg_1,%eax
11200 sbbl %eax,accum_2
11201 movl fsqrt_arg_2,%eax /* ms word of normalized n*/
11202 sbbl %eax,accum_3
11203 jnc sqrt_stage_3_positive
11204
11205/* subtraction gives a negative result*/
11206/* negate the result before division */
11207 notl accum_1
11208 notl accum_2
11209 notl accum_3
11210 addl $1,accum_1
11211 adcl $0,accum_2
11212
11213#ifdef PARANOID
11214 adcl $0,accum_3 /* This must be zero */
11215 jz sqrt_stage_3_no_error
11216
11217sqrt_stage_3_error:
11218 pushl EX_INTERNAL|0x207
11219 call EXCEPTION
11220
11221sqrt_stage_3_no_error:
11222#endif PARANOID
11223
11224 movl accum_2,%edx
11225 movl accum_1,%eax
11226 divl %esi
11227 movl %eax,%ecx
11228
11229 movl %edx,%eax
11230 divl %esi
11231
11232 sarl $1,%ecx / divide by 2*/
11233 rcrl $1,%eax
11234
11235 /* prepare to round the result*/
11236
11237 addl %ecx,%edi
11238 adcl $0,%esi
11239
11240 jmp sqrt_stage_3_finished
11241
11242sqrt_stage_3_positive:
11243 movl accum_2,%edx
11244 movl accum_1,%eax
11245 divl %esi
11246 movl %eax,%ecx
11247
11248 movl %edx,%eax
11249 divl %esi
11250
11251 sarl $1,%ecx /* divide by 2*/
11252 rcrl $1,%eax
11253
11254 /* prepare to round the result*/
11255
11256 notl %eax /* Negate the correction term*/
11257 notl %ecx
11258 addl $1,%eax
11259 adcl $0,%ecx /* carry here ==> correction == 0*/
11260 adcl $0xffffffff,%esi
11261
11262 addl %ecx,%edi
11263 adcl $0,%esi
11264
11265sqrt_stage_3_finished:
11266
11267/* The result in %esi:%edi:%esi should be good to about 90 bits here,
11268// and the rounding information here does not have sufficient accuracy
11269// in a few rare cases. */
11270 cmpl $0xffffffe0,%eax
11271 ja sqrt_near_exact_x
11272
11273 cmpl $0x00000020,%eax
11274 jb sqrt_near_exact
11275
11276 cmpl $0x7fffffe0,%eax
11277 jb sqrt_round_result
11278
11279 cmpl $0x80000020,%eax
11280 jb sqrt_get_more_precision
11281
11282sqrt_round_result:
11283/* Set up for rounding operations*/
11284 movl %eax,%edx
11285 movl %esi,%eax
11286 movl %edi,%ebx
11287 movl PARAM1,%edi
11288 movl EXP_BIAS,EXP(%edi) /* Result is in [1.0 .. 2.0)*/
11289 movl PARAM2,%ecx
11290 jmp FPU_round_sqrt
11291
11292
11293sqrt_near_exact_x:
11294/* First, the estimate must be rounded up.*/
11295 addl $1,%edi
11296 adcl $0,%esi
11297
11298sqrt_near_exact:
11299/* This is an easy case because x^1/2 is monotonic.
11300// We need just find the square of our estimate, compare it
11301// with the argument, and deduce whether our estimate is
11302// above, below, or exact. We use the fact that the estimate
11303// is known to be accurate to about 90 bits. */
11304 movl %edi,%eax /* ls word of guess*/
11305 mull %edi
11306 movl %edx,%ebx /* 2nd ls word of square*/
11307 movl %eax,%ecx /* ls word of square*/
11308
11309 movl %edi,%eax
11310 mull %esi
11311 addl %eax,%ebx
11312 addl %eax,%ebx
11313
11314#ifdef PARANOID
11315 cmp $0xffffffb0,%ebx
11316 jb sqrt_near_exact_ok
11317
11318 cmp $0x00000050,%ebx
11319 ja sqrt_near_exact_ok
11320
11321 pushl EX_INTERNAL|0x214
11322 call EXCEPTION
11323
11324sqrt_near_exact_ok:
11325#endif PARANOID
11326
11327 or %ebx,%ebx
11328 js sqrt_near_exact_small
11329
11330 jnz sqrt_near_exact_large
11331
11332 or %ebx,%edx
11333 jnz sqrt_near_exact_large
11334
11335/* Our estimate is exactly the right answer*/
11336 xorl %eax,%eax
11337 jmp sqrt_round_result
11338
11339sqrt_near_exact_small:
11340/* Our estimate is too small*/
11341 movl $0x000000ff,%eax
11342 jmp sqrt_round_result
11343
11344sqrt_near_exact_large:
11345/* Our estimate is too large, we need to decrement it*/
11346 subl $1,%edi
11347 sbbl $0,%esi
11348 movl $0xffffff00,%eax
11349 jmp sqrt_round_result
11350
11351
11352sqrt_get_more_precision:
11353/* This case is almost the same as the above, except we start*/
11354/* with an extra bit of precision in the estimate.*/
11355 stc /* The extra bit.*/
11356 rcll $1,%edi /* Shift the estimate left one bit*/
11357 rcll $1,%esi
11358
11359 movl %edi,%eax /* ls word of guess*/
11360 mull %edi
11361 movl %edx,%ebx /* 2nd ls word of square*/
11362 movl %eax,%ecx /* ls word of square*/
11363
11364 movl %edi,%eax
11365 mull %esi
11366 addl %eax,%ebx
11367 addl %eax,%ebx
11368
11369/* Put our estimate back to its original value*/
11370 stc /* The ms bit.*/
11371 rcrl $1,%esi /* Shift the estimate left one bit*/
11372 rcrl $1,%edi
11373
11374#ifdef PARANOID
11375 cmp $0xffffff60,%ebx
11376 jb sqrt_more_prec_ok
11377
11378 cmp $0x000000a0,%ebx
11379 ja sqrt_more_prec_ok
11380
11381 pushl EX_INTERNAL|0x215
11382 call EXCEPTION
11383
11384sqrt_more_prec_ok:
11385#endif PARANOID
11386
11387 or %ebx,%ebx
11388 js sqrt_more_prec_small
11389
11390 jnz sqrt_more_prec_large
11391
11392 or %ebx,%ecx
11393 jnz sqrt_more_prec_large
11394
11395/* Our estimate is exactly the right answer*/
11396 movl $0x80000000,%eax
11397 jmp sqrt_round_result
11398
11399sqrt_more_prec_small:
11400/* Our estimate is too small*/
11401 movl $0x800000ff,%eax
11402 jmp sqrt_round_result
11403
11404sqrt_more_prec_large:
11405/* Our estimate is too large*/
11406 movl $0x7fffff00,%eax
11407 jmp sqrt_round_result
11408\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0fpemul/reg_add_sub.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0100644 \0 0 \0 24 \0 20551 5462320164 13222\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0staff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
11409 * reg_add_sub.c
11410 *
11411 * Functions to add or subtract two registers and put the result in a third.
11412 *
11413 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
11414 * Vic 3163, Australia.
11415 * E-mail apm233m@vaxc.cc.monash.edu.au
11416 * All rights reserved.
11417 *
11418 * This copyright notice covers the redistribution and use of the
11419 * FPU emulator developed by W. Metzenthen. It covers only its use
11420 * in the 386BSD operating system. Any other use is not permitted
11421 * under this copyright.
11422 *
11423 * Redistribution and use in source and binary forms, with or without
11424 * modification, are permitted provided that the following conditions
11425 * are met:
11426 * 1. Redistributions of source code must retain the above copyright
11427 * notice, this list of conditions and the following disclaimer.
11428 * 2. Redistributions in binary form must include information specifying
11429 * that source code for the emulator is freely available and include
11430 * either:
11431 * a) an offer to provide the source code for a nominal distribution
11432 * fee, or
11433 * b) list at least two alternative methods whereby the source
11434 * can be obtained, e.g. a publically accessible bulletin board
11435 * and an anonymous ftp site from which the software can be
11436 * downloaded.
11437 * 3. All advertising materials specifically mentioning features or use of
11438 * this emulator must acknowledge that it was developed by W. Metzenthen.
11439 * 4. The name of W. Metzenthen may not be used to endorse or promote
11440 * products derived from this software without specific prior written
11441 * permission.
11442 *
11443 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
11444 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
11445 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
11446 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
11447 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
11448 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
11449 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
11450 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
11451 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
11452 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11453 *
11454 */
11455
11456/*---------------------------------------------------------------------------+
11457 | For each function, the destination may be any FPU_REG, including one of |
11458 | the source FPU_REGs. |
11459 +---------------------------------------------------------------------------*/
11460
11461#include "exception.h"
11462#include "reg_constant.h"
11463#include "fpu_emu.h"
11464#include "control_w.h"
11465#include "fpu_system.h"
11466
11467
11468void
11469reg_add(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w)
11470{
11471 int diff;
11472
11473 if (!(a->tag | b->tag)) {
11474 /* Both registers are valid */
11475 if (!(a->sign ^ b->sign)) {
11476 /* signs are the same */
11477 reg_u_add(a, b, dest, control_w);
11478 dest->sign = a->sign;
11479 return;
11480 }
11481 /* The signs are different, so do a subtraction */
11482 diff = a->exp - b->exp;
11483 if (!diff) {
11484 diff = a->sigh - b->sigh; /* Works only if ms bits
11485 * are identical */
11486 if (!diff) {
11487 diff = a->sigl > b->sigl;
11488 if (!diff)
11489 diff = -(a->sigl < b->sigl);
11490 }
11491 }
11492 if (diff > 0) {
11493 reg_u_sub(a, b, dest, control_w);
11494 dest->sign = a->sign;
11495 } else
11496 if (diff == 0) {
11497 reg_move(&CONST_Z, dest);
11498 /* sign depends upon rounding mode */
11499 dest->sign = ((control_w & CW_RC) != RC_DOWN)
11500 ? SIGN_POS : SIGN_NEG;
11501 } else {
11502 reg_u_sub(b, a, dest, control_w);
11503 dest->sign = b->sign;
11504 }
11505 return;
11506 } else {
11507 if ((a->tag == TW_NaN) || (b->tag == TW_NaN)) {
11508 real_2op_NaN(a, b, dest);
11509 return;
11510 } else
11511 if (a->tag == TW_Zero) {
11512 if (b->tag == TW_Zero) {
11513 char different_signs = a->sign ^ b->sign;
11514 /* Both are zero, result will be zero. */
11515 reg_move(a, dest);
11516 if (different_signs) {
11517 /* Signs are different. */
11518 /* Sign of answer depends upon
11519 * rounding mode. */
11520 dest->sign = ((control_w & CW_RC) != RC_DOWN)
11521 ? SIGN_POS : SIGN_NEG;
11522 }
11523 } else {
11524#ifdef DENORM_OPERAND
11525 if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) &&
11526 denormal_operand())
11527 return;
11528#endif /* DENORM_OPERAND */
11529 reg_move(b, dest);
11530 }
11531 return;
11532 } else
11533 if (b->tag == TW_Zero) {
11534#ifdef DENORM_OPERAND
11535 if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) &&
11536 denormal_operand())
11537 return;
11538#endif /* DENORM_OPERAND */
11539 reg_move(a, dest);
11540 return;
11541 } else
11542 if (a->tag == TW_Infinity) {
11543 if (b->tag != TW_Infinity) {
11544#ifdef DENORM_OPERAND
11545 if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) &&
11546 denormal_operand())
11547 return;
11548#endif /* DENORM_OPERAND */
11549 reg_move(a, dest);
11550 return;
11551 }
11552 if (a->sign == b->sign) {
11553 /* They are both + or
11554 * - infinity */
11555 reg_move(a, dest);
11556 return;
11557 }
11558 arith_invalid(dest); /* Infinity-Infinity is
11559 * undefined. */
11560 return;
11561 } else
11562 if (b->tag == TW_Infinity) {
11563#ifdef DENORM_OPERAND
11564 if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) &&
11565 denormal_operand())
11566 return;
11567#endif /* DENORM_OPERAND */
11568 reg_move(b, dest);
11569 return;
11570 }
11571 }
11572#ifdef PARANOID
11573 EXCEPTION(EX_INTERNAL | 0x101);
11574#endif
11575}
11576
11577
11578/* Subtract b from a. (a-b) -> dest */
11579void
11580reg_sub(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w)
11581{
11582 int diff;
11583
11584 if (!(a->tag | b->tag)) {
11585 /* Both registers are valid */
11586 diff = a->exp - b->exp;
11587 if (!diff) {
11588 diff = a->sigh - b->sigh; /* Works only if ms bits
11589 * are identical */
11590 if (!diff) {
11591 diff = a->sigl > b->sigl;
11592 if (!diff)
11593 diff = -(a->sigl < b->sigl);
11594 }
11595 }
11596 switch (a->sign * 2 + b->sign) {
11597 case 0: /* P - P */
11598 case 3: /* N - N */
11599 if (diff > 0) {
11600 reg_u_sub(a, b, dest, control_w);
11601 dest->sign = a->sign;
11602 } else
11603 if (diff == 0) {
11604#ifdef DENORM_OPERAND
11605 if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) &&
11606 denormal_operand())
11607 return;
11608#endif /* DENORM_OPERAND */
11609 reg_move(&CONST_Z, dest);
11610 /* sign depends upon rounding mode */
11611 dest->sign = ((control_w & CW_RC) != RC_DOWN)
11612 ? SIGN_POS : SIGN_NEG;
11613 } else {
11614 reg_u_sub(b, a, dest, control_w);
11615 dest->sign = a->sign ^ SIGN_POS ^ SIGN_NEG;
11616 }
11617 return;
11618 case 1: /* P - N */
11619 reg_u_add(a, b, dest, control_w);
11620 dest->sign = SIGN_POS;
11621 return;
11622 case 2: /* N - P */
11623 reg_u_add(a, b, dest, control_w);
11624 dest->sign = SIGN_NEG;
11625 return;
11626 }
11627 } else {
11628 if ((a->tag == TW_NaN) || (b->tag == TW_NaN)) {
11629 real_2op_NaN(a, b, dest);
11630 return;
11631 } else
11632 if (b->tag == TW_Zero) {
11633 if (a->tag == TW_Zero) {
11634 char same_signs = !(a->sign ^ b->sign);
11635 /* Both are zero, result will be zero. */
11636 reg_move(a, dest); /* Answer for different
11637 * signs. */
11638 if (same_signs) {
11639 /* Sign depends upon rounding
11640 * mode */
11641 dest->sign = ((control_w & CW_RC) != RC_DOWN)
11642 ? SIGN_POS : SIGN_NEG;
11643 }
11644 } else {
11645#ifdef DENORM_OPERAND
11646 if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) &&
11647 denormal_operand())
11648 return;
11649#endif /* DENORM_OPERAND */
11650 reg_move(a, dest);
11651 }
11652 return;
11653 } else
11654 if (a->tag == TW_Zero) {
11655#ifdef DENORM_OPERAND
11656 if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) &&
11657 denormal_operand())
11658 return;
11659#endif /* DENORM_OPERAND */
11660 reg_move(b, dest);
11661 dest->sign ^= SIGN_POS ^ SIGN_NEG;
11662 return;
11663 } else
11664 if (a->tag == TW_Infinity) {
11665 if (b->tag != TW_Infinity) {
11666#ifdef DENORM_OPERAND
11667 if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) &&
11668 denormal_operand())
11669 return;
11670#endif /* DENORM_OPERAND */
11671 reg_move(a, dest);
11672 return;
11673 }
11674 /* Both args are Infinity */
11675 if (a->sign == b->sign) {
11676 arith_invalid(dest); /* Infinity-Infinity is
11677 * undefined. */
11678 return;
11679 }
11680 reg_move(a, dest);
11681 return;
11682 } else
11683 if (b->tag == TW_Infinity) {
11684#ifdef DENORM_OPERAND
11685 if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) &&
11686 denormal_operand())
11687 return;
11688#endif /* DENORM_OPERAND */
11689 reg_move(b, dest);
11690 dest->sign ^= SIGN_POS ^ SIGN_NEG;
11691 return;
11692 }
11693 }
11694#ifdef PARANOID
11695 EXCEPTION(EX_INTERNAL | 0x110);
11696#endif
11697}
11698\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0