diff options
author | peter <peter@FreeBSD.org> | 2003-07-22 08:11:17 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2003-07-22 08:11:17 +0000 |
commit | 7c1e58684a0e6e588206d5592175b02c0211418b (patch) | |
tree | 2c9dbc0404e063bb1ce254beaf778c7ce4e8e0bf /sys | |
parent | 6e0440c7df7efab49749a25ee9be7d78b8780c15 (diff) | |
download | FreeBSD-src-7c1e58684a0e6e588206d5592175b02c0211418b.zip FreeBSD-src-7c1e58684a0e6e588206d5592175b02c0211418b.tar.gz |
Initiate de-orbit burn for fpu-less operation. 386+387 is still
theoretically supportable, but you'd really be happier with FreeBSD 2.1.8
on it.
Diffstat (limited to 'sys')
58 files changed, 6 insertions, 14046 deletions
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index ca1ca7d..66e03ba 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -156,38 +156,6 @@ geom/geom_bsd.c standard geom/geom_bsd_enc.c standard geom/geom_mbr.c standard geom/geom_mbr_enc.c standard -gnu/i386/fpemul/div_small.s optional gpl_math_emulate \ - warning "kernel contains GPL contaminated math emulator" -gnu/i386/fpemul/errors.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_arith.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_aux.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_entry.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_etc.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_trig.c optional gpl_math_emulate -gnu/i386/fpemul/get_address.c optional gpl_math_emulate -gnu/i386/fpemul/load_store.c optional gpl_math_emulate -gnu/i386/fpemul/poly_2xm1.c optional gpl_math_emulate -gnu/i386/fpemul/poly_atan.c optional gpl_math_emulate -gnu/i386/fpemul/poly_div.s optional gpl_math_emulate -gnu/i386/fpemul/poly_l2.c optional gpl_math_emulate -gnu/i386/fpemul/poly_mul64.s optional gpl_math_emulate -gnu/i386/fpemul/poly_sin.c optional gpl_math_emulate -gnu/i386/fpemul/poly_tan.c optional gpl_math_emulate -gnu/i386/fpemul/polynomial.s optional gpl_math_emulate -gnu/i386/fpemul/reg_add_sub.c optional gpl_math_emulate -gnu/i386/fpemul/reg_compare.c optional gpl_math_emulate -gnu/i386/fpemul/reg_constant.c optional gpl_math_emulate -gnu/i386/fpemul/reg_div.s optional gpl_math_emulate -gnu/i386/fpemul/reg_ld_str.c optional gpl_math_emulate -gnu/i386/fpemul/reg_mul.c optional gpl_math_emulate -gnu/i386/fpemul/reg_norm.s optional gpl_math_emulate -gnu/i386/fpemul/reg_round.s optional gpl_math_emulate -gnu/i386/fpemul/reg_u_add.s optional gpl_math_emulate -gnu/i386/fpemul/reg_u_div.s optional gpl_math_emulate -gnu/i386/fpemul/reg_u_mul.s optional gpl_math_emulate -gnu/i386/fpemul/reg_u_sub.s optional gpl_math_emulate -gnu/i386/fpemul/wm_shrx.s optional gpl_math_emulate -gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate i386/acpica/OsdEnvironment.c optional acpi i386/acpica/acpi_machdep.c optional acpi i386/acpica/acpi_wakeup.c optional acpi @@ -226,7 +194,6 @@ i386/i386/k6_mem.c standard i386/i386/legacy.c standard i386/i386/locore.s standard no-obj i386/i386/machdep.c standard -i386/i386/math_emulate.c optional math_emulate i386/i386/mem.c standard i386/i386/mp_clock.c optional smp i386/i386/mp_machdep.c optional smp diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98 index b305f19..aad6029 100644 --- a/sys/conf/files.pc98 +++ b/sys/conf/files.pc98 @@ -133,38 +133,6 @@ geom/geom_bsd.c standard geom/geom_bsd_enc.c standard geom/geom_pc98.c standard geom/geom_pc98_enc.c standard -gnu/i386/fpemul/div_small.s optional gpl_math_emulate \ - warning "kernel contains GPL contaminated math emulator" -gnu/i386/fpemul/errors.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_arith.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_aux.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_entry.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_etc.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_trig.c optional gpl_math_emulate -gnu/i386/fpemul/get_address.c optional gpl_math_emulate -gnu/i386/fpemul/load_store.c optional gpl_math_emulate -gnu/i386/fpemul/poly_2xm1.c optional gpl_math_emulate -gnu/i386/fpemul/poly_atan.c optional gpl_math_emulate -gnu/i386/fpemul/poly_div.s optional gpl_math_emulate -gnu/i386/fpemul/poly_l2.c optional gpl_math_emulate -gnu/i386/fpemul/poly_mul64.s optional gpl_math_emulate -gnu/i386/fpemul/poly_sin.c optional gpl_math_emulate -gnu/i386/fpemul/poly_tan.c optional gpl_math_emulate -gnu/i386/fpemul/polynomial.s optional gpl_math_emulate -gnu/i386/fpemul/reg_add_sub.c optional gpl_math_emulate -gnu/i386/fpemul/reg_compare.c optional gpl_math_emulate -gnu/i386/fpemul/reg_constant.c optional gpl_math_emulate -gnu/i386/fpemul/reg_div.s optional gpl_math_emulate -gnu/i386/fpemul/reg_ld_str.c optional gpl_math_emulate -gnu/i386/fpemul/reg_mul.c optional gpl_math_emulate -gnu/i386/fpemul/reg_norm.s optional gpl_math_emulate -gnu/i386/fpemul/reg_round.s optional gpl_math_emulate -gnu/i386/fpemul/reg_u_add.s optional gpl_math_emulate -gnu/i386/fpemul/reg_u_div.s optional gpl_math_emulate -gnu/i386/fpemul/reg_u_mul.s optional gpl_math_emulate -gnu/i386/fpemul/reg_u_sub.s optional gpl_math_emulate -gnu/i386/fpemul/wm_shrx.s optional gpl_math_emulate -gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate i386/bios/apm.c optional apm i386/i386/atomic.c standard \ compile-with "${CC} -c ${CFLAGS} ${DEFINED_PROF:S/^$/-fomit-frame-pointer/} ${.IMPSRC}" @@ -187,7 +155,6 @@ i386/i386/initcpu.c standard i386/i386/k6_mem.c standard i386/i386/legacy.c standard i386/i386/locore.s standard no-obj -i386/i386/math_emulate.c optional math_emulate i386/i386/mem.c standard i386/i386/mp_clock.c optional smp i386/i386/mp_machdep.c optional smp diff --git a/sys/conf/options.i386 b/sys/conf/options.i386 index e5e8cd5..96fad27 100644 --- a/sys/conf/options.i386 +++ b/sys/conf/options.i386 @@ -1,8 +1,6 @@ # $FreeBSD$ # Options specific to the i386 platform kernels -MATH_EMULATE opt_math_emulate.h -GPL_MATH_EMULATE opt_math_emulate.h DISABLE_PSE opt_pmap.h PMAP_SHPGPERPROC opt_pmap.h DISABLE_PG_G opt_pmap.h diff --git a/sys/conf/options.pc98 b/sys/conf/options.pc98 index 2a55086..ac48c87 100644 --- a/sys/conf/options.pc98 +++ b/sys/conf/options.pc98 @@ -1,8 +1,6 @@ # $FreeBSD$ # Options specific to the pc98 platform kernels -MATH_EMULATE opt_math_emulate.h -GPL_MATH_EMULATE opt_math_emulate.h DISABLE_PSE opt_pmap.h PMAP_SHPGPERPROC opt_pmap.h DISABLE_PG_G opt_pmap.h diff --git a/sys/gnu/i386/fpemul/Changelog b/sys/gnu/i386/fpemul/Changelog deleted file mode 100644 index 80d3885..0000000 --- a/sys/gnu/i386/fpemul/Changelog +++ /dev/null @@ -1,38 +0,0 @@ -$FreeBSD$ - -This file contains the changes made to W. Metzenthem's 387 FPU -emulator to make it work under NetBSD. - -a, Changes to make it compile: - - 1 - Changed the #include's to get the appropriate .h files. - 2 - Renamed .S to .s, to satisfy the kernel Makefile. - 3 - Changed the C++ style // comments to /* */ - 4 - Changed the FPU_ORIG_EIP macro. A letter from bde included - in the package suggested using tf_isp for using instead - of the linux __orig_eip. This later turned out to interfere - with the user stack, so i created a separate variable, stored - in the i387_union. - 5 - Changed the get_fs_.. put_fs_.. fns to fubyte,fuword,subyte, - suword. - 6 - Removed the verify_area fns. I don't really know what they do, - i suppose they verify access to memory. The sufu routines - should do this. - -b, Changes to make it work: - - 1 - Made math_emulate() to return 0 when successful, so trap() won't - try to generate a signal. - 2 - Changed the size of the save87 struct in /sys/arch/i387/include/ - npx.h to accomodate the i387_union. - -d, Other changes: - - 1 - Removed obsolate and/or linux specific stuff. - 2 - Changed the RE_ENTRANT_CHECK_[ON|OFF] macro to - REENTRANT_CHECK([ON|OFF]) so indent can grok it. - 3 - Re-indented to Berkeley style. - 4 - Limited max no of lookaheads. LOOKAHEAD_LIMIT in fpu_entry.c - - - Szabolcs Szigeti (pink@fsz.bme.hu) diff --git a/sys/gnu/i386/fpemul/README b/sys/gnu/i386/fpemul/README deleted file mode 100644 index d677145..0000000 --- a/sys/gnu/i386/fpemul/README +++ /dev/null @@ -1,278 +0,0 @@ -/* - * wm-FPU-emu an FPU emulator for 80386 and 80486SX microprocessors. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * $FreeBSD$ - */ - -wm-FPU-emu is an FPU emulator for Linux. It is derived from wm-emu387 -which is my 80387 emulator for djgpp (gcc under msdos); wm-emu387 was -in turn based upon emu387 which was written by DJ Delorie for djgpp. -The interface to the Linux kernel is based upon the original Linux -math emulator by Linus Torvalds. - -My target FPU for wm-FPU-emu is that described in the Intel486 -Programmer's Reference Manual (1992 edition). Numerous facets of the -functioning of the FPU are not well covered in the Reference Manual; -in the absence of clear details I have made guesses about the most -reasonable behaviour. Recently, this situation has improved because -I now have some access to the results produced by a real 80486 FPU. - -wm-FPU-emu does not implement all of the behaviour of the 80486 FPU. -See "Limitations" later in this file for a partial list of some -differences. I believe that the missing features are never used by -normal C or FORTRAN programs. - - -Please report bugs, etc to me at: - apm233m@vaxc.cc.monash.edu.au - - ---Bill Metzenthen - May 1993 - - ------------------------ Internals of wm-FPU-emu ----------------------- - -Numeric algorithms: -(1) Add, subtract, and multiply. Nothing remarkable in these. -(2) Divide has been tuned to get reasonable performance. The algorithm - is not the obvious one which most people seem to use, but is designed - to take advantage of the characteristics of the 80386. I expect that - it has been invented many times before I discovered it, but I have not - seen it. It is based upon one of those ideas which one carries around - for years without ever bothering to check it out. -(3) The sqrt function has been tuned to get good performance. It is based - upon Newton's classic method. Performance was improved by capitalizing - upon the properties of Newton's method, and the code is once again - structured taking account of the 80386 characteristics. -(4) The trig, log, and exp functions are based in each case upon quasi- - "optimal" polynomial approximations. My definition of "optimal" was - based upon getting good accuracy with reasonable speed. - -The code of the emulator is complicated slightly by the need to -account for a limited form of re-entrancy. Normally, the emulator will -emulate each FPU instruction to completion without interruption. -However, it may happen that when the emulator is accessing the user -memory space, swapping may be needed. In this case the emulator may be -temporarily suspended while disk i/o takes place. During this time -another process may use the emulator, thereby changing some static -variables (eg FPU_st0_ptr, etc). The code which accesses user memory -is confined to five files: - fpu_entry.c - reg_ld_str.c - load_store.c - get_address.c - errors.c - ------------------------ Limitations of wm-FPU-emu ----------------------- - -There are a number of differences between the current wm-FPU-emu -(version beta 1.4) and the 80486 FPU (apart from bugs). Some of the -more important differences are listed below: - -All internal computations are performed at 64 bit or higher precision -and rounded etc as required by the PC bits of the FPU control word. -Under the crt0 version for Linux current at March 1993, the FPU PC -bits specify 53 bits precision. - -The precision flag (PE of the FPU status word) and the Roundup flag -(C1 of the status word) are now partially implemented. Does anyone -write code which uses these features? - -The functions which load/store the FPU state are partially implemented, -but the implementation should be sufficient for handling FPU errors etc -in 32 bit protected mode. - -The implementation of the exception mechanism is flawed for unmasked -interrupts. - -Detection of certain conditions, such as denormal operands, is not yet -complete. - ------------------------ Performance of wm-FPU-emu ----------------------- - -Speed. ------ - -The speed of floating point computation with the emulator will depend -upon instruction mix. Relative performance is best for the instructions -which require most computation. The simple instructions are adversely -affected by the fpu instruction trap overhead. - - -Timing: Some simple timing tests have been made on the emulator functions. -The times include load/store instructions. All times are in microseconds -measured on a 33MHz 386 with 64k cache. The Turbo C tests were under -ms-dos, the next two columns are for emulators running with the djgpp -ms-dos extender. The final column is for wm-FPU-emu in Linux 0.97, -using libm4.0 (hard). - -function Turbo C djgpp 1.06 WM-emu387 wm-FPU-emu - - + 60.5 154.8 76.5 139.4 - - 61.1-65.5 157.3-160.8 76.2-79.5 142.9-144.7 - * 71.0 190.8 79.6 146.6 - / 61.2-75.0 261.4-266.9 75.3-91.6 142.2-158.1 - - sin() 310.8 4692.0 319.0 398.5 - cos() 284.4 4855.2 308.0 388.7 - tan() 495.0 8807.1 394.9 504.7 - atan() 328.9 4866.4 601.1 419.5-491.9 - - sqrt() 128.7 crashed 145.2 227.0 - log() 413.1-419.1 5103.4-5354.21 254.7-282.2 409.4-437.1 - exp() 479.1 6619.2 469.1 850.8 - - -The performance under Linux is improved by the use of look-ahead code. -The following results show the improvement which is obtained under -Linux due to the look-ahead code. Also given are the times for the -original Linux emulator with the 4.1 'soft' lib. - - [ Linus' note: I changed look-ahead to be the default under linux, as - there was no reason not to use it after I had edited it to be - disabled during tracing ] - - wm-FPU-emu w original w - look-ahead 'soft' lib - + 106.4 190.2 - - 108.6-111.6 192.4-216.2 - * 113.4 193.1 - / 108.8-124.4 700.1-706.2 - - sin() 390.5 2642.0 - cos() 381.5 2767.4 - tan() 496.5 3153.3 - atan() 367.2-435.5 2439.4-3396.8 - - sqrt() 195.1 4732.5 - log() 358.0-387.5 3359.2-3390.3 - exp() 619.3 4046.4 - - -These figures are now somewhat out-of-date. The emulator has become -progressively slower for most functions as more of the 80486 features -have been implemented. - - ------------------------ Accuracy of wm-FPU-emu ----------------------- - - -Accuracy: The following table gives the accuracy of the sqrt(), trig -and log functions. Each function was tested at about 400 points. Ideal -results would be 64 bits. The reduced accuracy of cos() and tan() for -arguments greater than pi/4 can be thought of as being due to the -precision of the argument x; e.g. an argument of pi/2-(1e-10) which is -accurate to 64 bits can result in a relative accuracy in cos() of about -64 + log2(cos(x)) = 31 bits. Results for the Turbo C emulator are given -in the last column. - - -Function Tested x range Worst result (bits) Turbo C - -sqrt(x) 1 .. 2 64.1 63.2 -atan(x) 1e-10 .. 200 62.6 62.8 -cos(x) 0 .. pi/2-(1e-10) 63.2 (x <= pi/4) 62.4 - 35.2 (x = pi/2-(1e-10)) 31.9 -sin(x) 1e-10 .. pi/2 63.0 62.8 -tan(x) 1e-10 .. pi/2-(1e-10) 62.4 (x <= pi/4) 62.1 - 35.2 (x = pi/2-(1e-10)) 31.9 -exp(x) 0 .. 1 63.1 62.9 -log(x) 1+1e-6 .. 2 62.4 62.1 - - -As of version 1.3 of the emulator, the accuracy of the basic -arithmetic has been improved (by a small fraction of a bit). Care has -been taken to ensure full accuracy of the rounding of the basic -arithmetic functions (+,-,*,/,and fsqrt), and they all now produce -results which are exact to the 64th bit (unless there are any bugs -left). To ensure this, it was necessary to effectively get information -of up to about 128 bits precision. The emulator now passes the -"paranoia" tests (compiled with gcc 2.3.3) for 'float' variables (24 -bit precision numbers) when precision control is set to 24, 53 or 64 -bits, and for 'double' variables (53 bit precision numbers) when -precision control is set to 53 bits (a properly performing FPU cannot -pass the 'paranoia' tests for 'double' variables when precision -control is set to 64 bits). - -------------------------- Contributors ------------------------------- - -A number of people have contributed to the development of the -emulator, often by just reporting bugs, sometimes with a suggested -fix, and a few kind people have provided me with access in one way or -another to an 80486 machine. Contributors include (to those people who -I have forgotten, please excuse me): - -Linus Torvalds -Tommy.Thorn@daimi.aau.dk -Andrew.Tridgell@anu.edu.au -Nick Holloway alfie@dcs.warwick.ac.uk -Hermano Moura moura@dcs.gla.ac.uk -Jon Jagger J.Jagger@scp.ac.uk -Lennart Benschop -Brian Gallew geek+@CMU.EDU -Thomas Staniszewski ts3v+@andrew.cmu.edu -Martin Howell mph@plasma.apana.org.au -M Saggaf alsaggaf@athena.mit.edu -Peter Barker PETER@socpsy.sci.fau.edu -tom@vlsivie.tuwien.ac.at -Dan Russel russed@rpi.edu -Daniel Carosone danielce@ee.mu.oz.au -cae@jpmorgan.com -Hamish Coleman t933093@minyos.xx.rmit.oz.au - -...and numerous others who responded to my request for help with -a real 80486. - diff --git a/sys/gnu/i386/fpemul/control_w.h b/sys/gnu/i386/fpemul/control_w.h deleted file mode 100644 index 5c7aca4..0000000 --- a/sys/gnu/i386/fpemul/control_w.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * control_w.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -#ifndef _CONTROLW_H_ -#define _CONTROLW_H_ - -#ifdef LOCORE -#define _Const_(x) $/**/x -#else -#define _Const_(x) x -#endif - -#define CW_RC _Const_(0x0C00) /* rounding control */ -#define CW_PC _Const_(0x0300) /* precision control */ - -#define CW_Precision Const_(0x0020) /* loss of precision mask */ -#define CW_Underflow Const_(0x0010) /* underflow mask */ -#define CW_Overflow Const_(0x0008) /* overflow mask */ -#define CW_ZeroDiv Const_(0x0004) /* divide by zero mask */ -#define CW_Denormal Const_(0x0002) /* denormalized operand mask */ -#define CW_Invalid Const_(0x0001) /* invalid operation mask */ - -#define CW_Exceptions _Const_(0x003f) /* all masks */ - -#define RC_RND _Const_(0x0000) -#define RC_DOWN _Const_(0x0400) -#define RC_UP _Const_(0x0800) -#define RC_CHOP _Const_(0x0C00) - -/* p 15-5: Precision control bits affect only the following: - ADD, SUB(R), MUL, DIV(R), and SQRT */ -#define PR_24_BITS _Const_(0x000) -#define PR_53_BITS _Const_(0x200) -#define PR_64_BITS _Const_(0x300) -/* FULL_PRECISION simulates all exceptions masked */ -#define FULL_PRECISION (PR_64_BITS | RC_RND | 0x3f) - -#endif /* _CONTROLW_H_ */ diff --git a/sys/gnu/i386/fpemul/div_small.s b/sys/gnu/i386/fpemul/div_small.s deleted file mode 100644 index 944a93f..0000000 --- a/sys/gnu/i386/fpemul/div_small.s +++ /dev/null @@ -1,97 +0,0 @@ - .file "div_small.S" -/* - * div_small.S - * - * Divide a 64 bit integer by a 32 bit integer & return remainder. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -/*---------------------------------------------------------------------------+ - | unsigned long div_small(unsigned long long *x, unsigned long y) | - +---------------------------------------------------------------------------*/ - -#include <gnu/i386/fpemul/fpu_asm.h> - -.text -ENTRY(div_small) - pushl %ebp - movl %esp,%ebp - - pushl %esi - - movl PARAM1,%esi /* pointer to num */ - movl PARAM2,%ecx /* The denominator */ - - movl 4(%esi),%eax /* Get the current num msw */ - xorl %edx,%edx - divl %ecx - - movl %eax,4(%esi) - - movl (%esi),%eax /* Get the num lsw */ - divl %ecx - - movl %eax,(%esi) - - movl %edx,%eax /* Return the remainder in eax */ - - popl %esi - - leave - ret - diff --git a/sys/gnu/i386/fpemul/errors.c b/sys/gnu/i386/fpemul/errors.c deleted file mode 100644 index 7ee9136..0000000 --- a/sys/gnu/i386/fpemul/errors.c +++ /dev/null @@ -1,608 +0,0 @@ -/* - * errors.c - * - * The error handling functions for wm-FPU-emu - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ - - - - - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <machine/pcb.h> - -#include <gnu/i386/fpemul/fpu_emu.h> -#include <gnu/i386/fpemul/fpu_system.h> -#include <gnu/i386/fpemul/exception.h> -#include <gnu/i386/fpemul/status_w.h> -#include <gnu/i386/fpemul/control_w.h> -#include <gnu/i386/fpemul/reg_constant.h> -#include <gnu/i386/fpemul/version.h> - -/* */ -#undef PRINT_MESSAGES -/* */ - - -void -Un_impl(void) -{ - unsigned char byte1, FPU_modrm; - - REENTRANT_CHECK(OFF); - byte1 = fubyte((unsigned char *) FPU_ORIG_EIP); - FPU_modrm = fubyte(1 + (unsigned char *) FPU_ORIG_EIP); - - printf("Unimplemented FPU Opcode at eip=%#08x : %02x ", - FPU_ORIG_EIP, byte1); - - if (FPU_modrm >= 0300) - printf("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7); - else - printf("/%d\n", (FPU_modrm >> 3) & 7); - REENTRANT_CHECK(ON); - - EXCEPTION(EX_Invalid); - -} - - - - -void -emu_printall() -{ - int i; - static char *tag_desc[] = {"Valid", "Zero", "ERROR", "ERROR", - "DeNorm", "Inf", "NaN", "Empty"}; - unsigned char byte1, FPU_modrm; - - REENTRANT_CHECK(OFF); - byte1 = fubyte((unsigned char *) FPU_ORIG_EIP); - FPU_modrm = fubyte(1 + (unsigned char *) FPU_ORIG_EIP); - -#ifdef DEBUGGING - if (status_word & SW_Backward) - printf("SW: backward compatibility\n"); - if (status_word & SW_C3) - printf("SW: condition bit 3\n"); - if (status_word & SW_C2) - printf("SW: condition bit 2\n"); - if (status_word & SW_C1) - printf("SW: condition bit 1\n"); - if (status_word & SW_C0) - printf("SW: condition bit 0\n"); - if (status_word & SW_Summary) - printf("SW: exception summary\n"); - if (status_word & SW_Stack_Fault) - printf("SW: stack fault\n"); - if (status_word & SW_Precision) - printf("SW: loss of precision\n"); - if (status_word & SW_Underflow) - printf("SW: underflow\n"); - if (status_word & SW_Overflow) - printf("SW: overflow\n"); - if (status_word & SW_Zero_Div) - printf("SW: divide by zero\n"); - if (status_word & SW_Denorm_Op) - printf("SW: denormalized operand\n"); - if (status_word & SW_Invalid) - printf("SW: invalid operation\n"); -#endif /* DEBUGGING */ - - status_word = status_word & ~SW_Top; - status_word |= (top & 7) << SW_Top_Shift; - - printf("At %#08x: %02x ", FPU_ORIG_EIP, byte1); - if (FPU_modrm >= 0300) - printf("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7); - else - printf("/%d, mod=%d rm=%d\n", - (FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7); - - printf(" SW: b=%d st=%d es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n", - status_word & 0x8000 ? 1 : 0, /* busy */ - (int)((status_word & 0x3800) >> 11), /* stack top pointer */ - status_word & 0x80 ? 1 : 0, /* Error summary status */ - status_word & 0x40 ? 1 : 0, /* Stack flag */ - status_word & SW_C3 ? 1 : 0, status_word & SW_C2 ? 1 : 0, /* cc */ - status_word & SW_C1 ? 1 : 0, status_word & SW_C0 ? 1 : 0, /* cc */ - status_word & SW_Precision ? 1 : 0, status_word & SW_Underflow ? 1 : 0, - status_word & SW_Overflow ? 1 : 0, status_word & SW_Zero_Div ? 1 : 0, - status_word & SW_Denorm_Op ? 1 : 0, status_word & SW_Invalid ? 1 : 0); - - printf(" CW: ic=%d rc=%d%d pc=%d%d iem=%d ef=%d%d%d%d%d%d\n", - control_word & 0x1000 ? 1 : 0, - (int)((control_word & 0x800) >> 11), - (int)((control_word & 0x400) >> 10), - (int)((control_word & 0x200) >> 9), - (int)((control_word & 0x100) >> 8), - control_word & 0x80 ? 1 : 0, - control_word & SW_Precision ? 1 : 0, control_word & SW_Underflow ? 1 : 0, - control_word & SW_Overflow ? 1 : 0, control_word & SW_Zero_Div ? 1 : 0, - control_word & SW_Denorm_Op ? 1 : 0, control_word & SW_Invalid ? 1 : 0); - - for (i = 0; i < 8; i++) { - FPU_REG *r = &st(i); - switch (r->tag) { - case TW_Empty: - continue; - break; - case TW_Zero: - printf("st(%d) %c .0000 0000 0000 0000 ", - i, r->sign ? '-' : '+'); - break; - case TW_Valid: - case TW_NaN: - case TW_Denormal: - case TW_Infinity: - printf("st(%d) %c .%04lx %04lx %04lx %04lx e%+-6ld ", - i, r->sign ? '-' : '+', r->sigh >> 16, - r->sigh & 0xFFFF, r->sigl >> 16, r->sigl & 0xFFFF, - r->exp - EXP_BIAS + 1); - break; - default: - printf("Whoops! Error in errors.c "); - break; - } - printf("%s\n", tag_desc[(int) (unsigned) r->tag]); - } - - printf("[data] %c .%04lx %04lx %04lx %04lx e%+-6ld ", - FPU_loaded_data.sign ? '-' : '+', FPU_loaded_data.sigh >> 16, - FPU_loaded_data.sigh & 0xFFFF, FPU_loaded_data.sigl >> 16, - FPU_loaded_data.sigl & 0xFFFF, FPU_loaded_data.exp - EXP_BIAS + 1); - printf("%s\n", tag_desc[(int) (unsigned) FPU_loaded_data.tag]); - REENTRANT_CHECK(ON); - -} - -static struct { - int type; - char *name; -} exception_names[] = { - { - EX_StackOver, "stack overflow" - }, - { - EX_StackUnder, "stack underflow" - }, - { - EX_Precision, "loss of precision" - }, - { - EX_Underflow, "underflow" - }, - { - EX_Overflow, "overflow" - }, - { - EX_ZeroDiv, "divide by zero" - }, - { - EX_Denormal, "denormalized operand" - }, - { - EX_Invalid, "invalid operation" - }, - { - EX_INTERNAL, "INTERNAL BUG in " FPU_VERSION - }, - { - 0, NULL - } -}; -/* - EX_INTERNAL is always given with a code which indicates where the - error was detected. - - Internal error types: - 0x14 in e14.c - 0x1nn in a *.c file: - 0x101 in reg_add_sub.c - 0x102 in reg_mul.c - 0x103 in poly_sin.c - 0x104 in poly_tan.c - 0x105 in reg_mul.c - 0x106 in reg_mov.c - 0x107 in fpu_trig.c - 0x108 in reg_compare.c - 0x109 in reg_compare.c - 0x110 in reg_add_sub.c - 0x111 in interface.c - 0x112 in fpu_trig.c - 0x113 in reg_add_sub.c - 0x114 in reg_ld_str.c - 0x115 in fpu_trig.c - 0x116 in fpu_trig.c - 0x117 in fpu_trig.c - 0x118 in fpu_trig.c - 0x119 in fpu_trig.c - 0x120 in poly_atan.c - 0x121 in reg_compare.c - 0x122 in reg_compare.c - 0x123 in reg_compare.c - 0x2nn in an *.s file: - 0x201 in reg_u_add.S - 0x202 in reg_u_div.S - 0x203 in reg_u_div.S - 0x204 in reg_u_div.S - 0x205 in reg_u_mul.S - 0x206 in reg_u_sub.S - 0x207 in wm_sqrt.S - 0x208 in reg_div.S - 0x209 in reg_u_sub.S - 0x210 in reg_u_sub.S - 0x211 in reg_u_sub.S - 0x212 in reg_u_sub.S - 0x213 in wm_sqrt.S - 0x214 in wm_sqrt.S - 0x215 in wm_sqrt.S - 0x216 in reg_round.S - 0x217 in reg_round.S - 0x218 in reg_round.S - */ - -void -exception(int n) -{ - int i, int_type; - - int_type = 0; /* Needed only to stop compiler warnings */ - if (n & EX_INTERNAL) { - int_type = n - EX_INTERNAL; - n = EX_INTERNAL; - /* Set lots of exception bits! */ - status_word |= (SW_Exc_Mask | SW_Summary | FPU_BUSY); - } else { - /* Extract only the bits which we use to set the status word */ - n &= (SW_Exc_Mask); - /* Set the corresponding exception bit */ - status_word |= n; - if (status_word & ~control_word & CW_Exceptions) - status_word |= SW_Summary; - if (n & (SW_Stack_Fault | EX_Precision)) { - if (!(n & SW_C1)) - /* This bit distinguishes over- from underflow - * for a stack fault, and roundup from - * round-down for precision loss. */ - status_word &= ~SW_C1; - } - } - - REENTRANT_CHECK(OFF); - if ((~control_word & n & CW_Exceptions) || (n == EX_INTERNAL)) { -#ifdef PRINT_MESSAGES - /* My message from the sponsor */ - printf(FPU_VERSION " " __DATE__ " (C) W. Metzenthen.\n"); -#endif /* PRINT_MESSAGES */ - - /* Get a name string for error reporting */ - for (i = 0; exception_names[i].type; i++) - if ((exception_names[i].type & n) == exception_names[i].type) - break; - - if (exception_names[i].type) { -#ifdef PRINT_MESSAGES - printf("FP Exception: %s!\n", exception_names[i].name); -#endif /* PRINT_MESSAGES */ - } else - printf("FP emulator: Unknown Exception: 0x%04x!\n", n); - - if (n == EX_INTERNAL) { - printf("FP emulator: Internal error type 0x%04x\n", int_type); - emu_printall(); - } -#ifdef PRINT_MESSAGES - else - emu_printall(); -#endif /* PRINT_MESSAGES */ - - /* The 80486 generates an interrupt on the next non-control - * FPU instruction. So we need some means of flagging it. We - * use the ES (Error Summary) bit for this, assuming that this - * is the way a real FPU does it (until I can check it out), - * if not, then some method such as the following kludge might - * be needed. */ -/* regs[0].tag |= TW_FPU_Interrupt; */ - } - REENTRANT_CHECK(ON); - -#ifdef __DEBUG__ - math_abort(SIGFPE); -#endif /* __DEBUG__ */ - -} - - -/* Real operation attempted on two operands, one a NaN */ -void -real_2op_NaN(FPU_REG * a, FPU_REG * b, FPU_REG * dest) -{ - FPU_REG *x; - int signalling; - - x = a; - if (a->tag == TW_NaN) { - if (b->tag == TW_NaN) { - signalling = !(a->sigh & b->sigh & 0x40000000); - /* find the "larger" */ - if (*(long long *) &(a->sigl) < *(long long *) &(b->sigl)) - x = b; - } else { - /* return the quiet version of the NaN in a */ - signalling = !(a->sigh & 0x40000000); - } - } else -#ifdef PARANOID - if (b->tag == TW_NaN) -#endif /* PARANOID */ - { - signalling = !(b->sigh & 0x40000000); - x = b; - } -#ifdef PARANOID - else { - signalling = 0; - EXCEPTION(EX_INTERNAL | 0x113); - x = &CONST_QNaN; - } -#endif /* PARANOID */ - - if (!signalling) { - if (!(x->sigh & 0x80000000)) /* pseudo-NaN ? */ - x = &CONST_QNaN; - reg_move(x, dest); - return; - } - if (control_word & CW_Invalid) { - /* The masked response */ - if (!(x->sigh & 0x80000000)) /* pseudo-NaN ? */ - x = &CONST_QNaN; - reg_move(x, dest); - /* ensure a Quiet NaN */ - dest->sigh |= 0x40000000; - } - EXCEPTION(EX_Invalid); - - return; -} -/* Invalid arith operation on Valid registers */ -void -arith_invalid(FPU_REG * dest) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - reg_move(&CONST_QNaN, dest); - } - EXCEPTION(EX_Invalid); - - return; - -} - - -/* Divide a finite number by zero */ -void -divide_by_zero(int sign, FPU_REG * dest) -{ - - if (control_word & CW_ZeroDiv) { - /* The masked response */ - reg_move(&CONST_INF, dest); - dest->sign = (unsigned char) sign; - } - EXCEPTION(EX_ZeroDiv); - - return; - -} - - -/* This may be called often, so keep it lean */ -void -set_precision_flag_up(void) -{ - if (control_word & CW_Precision) - status_word |= (SW_Precision | SW_C1); /* The masked response */ - else - exception(EX_Precision | SW_C1); - -} - - -/* This may be called often, so keep it lean */ -void -set_precision_flag_down(void) -{ - if (control_word & CW_Precision) { /* The masked response */ - status_word &= ~SW_C1; - status_word |= SW_Precision; - } else - exception(EX_Precision); -} - - -int -denormal_operand(void) -{ - if (control_word & CW_Denormal) { /* The masked response */ - status_word |= SW_Denorm_Op; - return 0; - } else { - exception(EX_Denormal); - return 1; - } -} - - -void -arith_overflow(FPU_REG * dest) -{ - - if (control_word & CW_Overflow) { - char sign; - /* The masked response */ -/* **** The response here depends upon the rounding mode */ - sign = dest->sign; - reg_move(&CONST_INF, dest); - dest->sign = sign; - } else { - /* Subtract the magic number from the exponent */ - dest->exp -= (3 * (1 << 13)); - } - - /* By definition, precision is lost. It appears that the roundup bit - * (C1) is also set by convention. */ - EXCEPTION(EX_Overflow | EX_Precision | SW_C1); - - return; - -} - - -void -arith_underflow(FPU_REG * dest) -{ - - if (control_word & CW_Underflow) { - /* The masked response */ - if (dest->exp <= EXP_UNDER - 63) - reg_move(&CONST_Z, dest); - } else { - /* Add the magic number to the exponent */ - dest->exp += (3 * (1 << 13)); - } - - EXCEPTION(EX_Underflow); - - return; -} - - -void -stack_overflow(void) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - top--; - reg_move(&CONST_QNaN, FPU_st0_ptr = &st(0)); - } - EXCEPTION(EX_StackOver); - - return; - -} - - -void -stack_underflow(void) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - reg_move(&CONST_QNaN, FPU_st0_ptr); - } - EXCEPTION(EX_StackUnder); - - return; - -} - - -void -stack_underflow_i(int i) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - reg_move(&CONST_QNaN, &(st(i))); - } - EXCEPTION(EX_StackUnder); - - return; - -} - - -void -stack_underflow_pop(int i) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - reg_move(&CONST_QNaN, &(st(i))); - pop(); - } - EXCEPTION(EX_StackUnder); - - return; - -} diff --git a/sys/gnu/i386/fpemul/exception.h b/sys/gnu/i386/fpemul/exception.h deleted file mode 100644 index 50e7d60..0000000 --- a/sys/gnu/i386/fpemul/exception.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * exception.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - * - */ - -#ifndef _EXCEPTION_H_ -#define _EXCEPTION_H_ - - -#ifdef LOCORE -#define Const_(x) $/**/x -#else -#define Const_(x) x -#endif - -#ifndef SW_C1 -#include <gnu/i386/fpemul/fpu_emu.h> -#endif /* SW_C1 */ - -#define FPU_BUSY Const_(0x8000) /* FPU busy bit (8087 compatibility) */ -#define EX_ErrorSummary Const_(0x0080) /* Error summary status */ -/* Special exceptions: */ -#define EX_INTERNAL Const_(0x8000) /* Internal error in wm-FPU-emu */ -#define EX_StackOver Const_(0x0041|SW_C1) /* stack overflow */ -#define EX_StackUnder Const_(0x0041) /* stack underflow */ -/* Exception flags: */ -#define EX_Precision Const_(0x0020) /* loss of precision */ -#define EX_Underflow Const_(0x0010) /* underflow */ -#define EX_Overflow Const_(0x0008) /* overflow */ -#define EX_ZeroDiv Const_(0x0004) /* divide by zero */ -#define EX_Denormal Const_(0x0002) /* denormalized operand */ -#define EX_Invalid Const_(0x0001) /* invalid operation */ - - -#ifndef LOCORE - -#ifdef DEBUG -#define EXCEPTION(x) \ - do { \ - printf("exception in %s at line %d\n", __FILE__, __LINE__); \ - exception(x); \ - } while (0) -#else -#define EXCEPTION(x) exception(x) -#endif - -#endif /* LOCORE */ - -#endif /* _EXCEPTION_H_ */ diff --git a/sys/gnu/i386/fpemul/fpu_arith.c b/sys/gnu/i386/fpemul/fpu_arith.c deleted file mode 100644 index e8fa93f..0000000 --- a/sys/gnu/i386/fpemul/fpu_arith.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * fpu_arith.c - * - * Code to implement the FPU register/register arithmetic instructions - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - - - -#include <sys/param.h> -#include <sys/proc.h> -#include <machine/pcb.h> - -#include <gnu/i386/fpemul/fpu_emu.h> -#include <gnu/i386/fpemul/fpu_system.h> - - -void -fadd__() -{ - /* fadd st,st(i) */ - reg_add(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); -} - - -void -fmul__() -{ - /* fmul st,st(i) */ - reg_mul(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); -} - - - -void -fsub__() -{ - /* fsub st,st(i) */ - reg_sub(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); -} - - -void -fsubr_() -{ - /* fsubr st,st(i) */ - reg_sub(&st(FPU_rm), FPU_st0_ptr, FPU_st0_ptr, control_word); -} - - -void -fdiv__() -{ - /* fdiv st,st(i) */ - reg_div(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); -} - - -void -fdivr_() -{ - /* fdivr st,st(i) */ - reg_div(&st(FPU_rm), FPU_st0_ptr, FPU_st0_ptr, control_word); -} - - - -void -fadd_i() -{ - /* fadd st(i),st */ - reg_add(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); -} - - -void -fmul_i() -{ - /* fmul st(i),st */ - reg_mul(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); -} - - -void -fsubri() -{ - /* fsubr st(i),st */ - /* This is the sense of the 80486 manual reg_sub(&st(FPU_rm), - * FPU_st0_ptr, &st(FPU_rm), control_word); */ - reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); -} - - -void -fsub_i() -{ - /* fsub st(i),st */ - /* This is the sense of the 80486 manual reg_sub(FPU_st0_ptr, - * &st(FPU_rm), &st(FPU_rm), control_word); */ - reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); -} - - -void -fdivri() -{ - /* fdivr st(i),st */ - reg_div(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); -} - - -void -fdiv_i() -{ - /* fdiv st(i),st */ - reg_div(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); -} - - - -void -faddp_() -{ - /* faddp st(i),st */ - reg_add(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); - pop(); -} - - -void -fmulp_() -{ - /* fmulp st(i),st */ - reg_mul(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); - pop(); -} - - - -void -fsubrp() -{ - /* fsubrp st(i),st */ - /* This is the sense of the 80486 manual reg_sub(&st(FPU_rm), - * FPU_st0_ptr, &st(FPU_rm), control_word); */ - reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); - pop(); -} - - -void -fsubp_() -{ - /* fsubp st(i),st */ - /* This is the sense of the 80486 manual reg_sub(FPU_st0_ptr, - * &st(FPU_rm), &st(FPU_rm), control_word); */ - reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); - pop(); -} - - -void -fdivrp() -{ - /* fdivrp st(i),st */ - reg_div(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); - pop(); -} - - -void -fdivp_() -{ - /* fdivp st(i),st */ - reg_div(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); - pop(); -} diff --git a/sys/gnu/i386/fpemul/fpu_asm.h b/sys/gnu/i386/fpemul/fpu_asm.h deleted file mode 100644 index 44a3278..0000000 --- a/sys/gnu/i386/fpemul/fpu_asm.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * fpu_asm.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -#ifndef _FPU_ASM_H_ -#define _FPU_ASM_H_ - -#include <machine/asmacros.h> -#include <gnu/i386/fpemul/fpu_emu.h> - -#define EXCEPTION exception - - -#define PARAM1 8(%ebp) -#define PARAM2 12(%ebp) -#define PARAM3 16(%ebp) -#define PARAM4 20(%ebp) - -#define SIGL_OFFSET 8 -#define SIGN(x) (x) -#define TAG(x) 1(x) -#define EXP(x) 4(x) -#define SIG(x) SIGL_OFFSET/**/(x) -#define SIGL(x) SIGL_OFFSET/**/(x) -#define SIGH(x) 12(x) - -#endif /* _FPU_ASM_H_ */ diff --git a/sys/gnu/i386/fpemul/fpu_aux.c b/sys/gnu/i386/fpemul/fpu_aux.c deleted file mode 100644 index b7b901f..0000000 --- a/sys/gnu/i386/fpemul/fpu_aux.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * fpu_aux.c - * - * Code to implement some of the FPU auxiliary instructions. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <machine/cpu.h> -#include <machine/pcb.h> - -#include <gnu/i386/fpemul/fpu_emu.h> -#include <gnu/i386/fpemul/fpu_system.h> -#include <gnu/i386/fpemul/exception.h> -#include <gnu/i386/fpemul/status_w.h> - - -static void -fclex(void) -{ - status_word &= ~(SW_Backward | SW_Summary | SW_Stack_Fault | SW_Precision | - SW_Underflow | SW_Overflow | SW_Zero_Div | SW_Denorm_Op | - SW_Invalid); - FPU_entry_eip = ip_offset; /* We want no net effect */ -} -/* Needs to be externally visible */ -void -finit() -{ - int r; - control_word = 0x037f; - status_word = 0; - top = 0; /* We don't keep top in the status word - * internally. */ - for (r = 0; r < 8; r++) { - regs[r].tag = TW_Empty; - } - FPU_entry_eip = ip_offset = 0; -} - -static FUNC finit_table[] = { - Un_impl, Un_impl, fclex, finit, Un_impl, Un_impl, Un_impl, Un_impl -}; - -void -finit_() -{ - (finit_table[FPU_rm]) (); -} - - -static void -fstsw_ax(void) -{ - - status_word &= ~SW_Top; - status_word |= (top & 7) << SW_Top_Shift; - - *(short *) &FPU_EAX = status_word; - -} - -static FUNC fstsw_table[] = { - fstsw_ax, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl -}; - -void -fstsw_() -{ - (fstsw_table[FPU_rm]) (); -} - - - -static void -fnop(void) -{ -} - -static FUNC fp_nop_table[] = { - fnop, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl -}; - -void -fp_nop() -{ - (fp_nop_table[FPU_rm]) (); -} - - -void -fld_i_() -{ - FPU_REG *st_new_ptr; - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - /* fld st(i) */ - if (NOT_EMPTY(FPU_rm)) { - reg_move(&st(FPU_rm), st_new_ptr); - push(); - } else { - if (control_word & EX_Invalid) { - /* The masked response */ - push(); - stack_underflow(); - } else - EXCEPTION(EX_StackUnder); - } - -} - - -void -fxch_i() -{ - /* fxch st(i) */ - FPU_REG t; - register FPU_REG *sti_ptr = &st(FPU_rm); - - if (FPU_st0_tag == TW_Empty) { - if (sti_ptr->tag == TW_Empty) { - stack_underflow(); - stack_underflow_i(FPU_rm); - return; - } - reg_move(sti_ptr, FPU_st0_ptr); - stack_underflow_i(FPU_rm); - return; - } - if (sti_ptr->tag == TW_Empty) { - reg_move(FPU_st0_ptr, sti_ptr); - stack_underflow(); - return; - } - reg_move(FPU_st0_ptr, &t); - reg_move(sti_ptr, FPU_st0_ptr); - reg_move(&t, sti_ptr); -} - - -void -ffree_() -{ - /* ffree st(i) */ - st(FPU_rm).tag = TW_Empty; -} - - -void -ffreep() -{ - /* ffree st(i) + pop - unofficial code */ - st(FPU_rm).tag = TW_Empty; - pop(); -} - - -void -fst_i_() -{ - /* fst st(i) */ - reg_move(FPU_st0_ptr, &st(FPU_rm)); -} - - -void -fstp_i() -{ - /* fstp st(i) */ - reg_move(FPU_st0_ptr, &st(FPU_rm)); - pop(); -} diff --git a/sys/gnu/i386/fpemul/fpu_emu.h b/sys/gnu/i386/fpemul/fpu_emu.h deleted file mode 100644 index 0dd2f7e..0000000 --- a/sys/gnu/i386/fpemul/fpu_emu.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * fpu_emu.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - -#ifndef _FPU_EMU_H_ -#define _FPU_EMU_H_ - -/* - * Define DENORM_OPERAND to make the emulator detect denormals - * and use the denormal flag of the status word. Note: this only - * affects the flag and corresponding interrupt, the emulator - * will always generate denormals and operate upon them as required. - */ -#define DENORM_OPERAND - -/* - * Define PECULIAR_486 to get a closer approximation to 80486 behaviour, - * rather than behaviour which appears to be cleaner. - * This is a matter of opinion: for all I know, the 80486 may simply - * be complying with the IEEE spec. Maybe one day I'll get to see the - * spec... - */ -#define PECULIAR_486 - -#ifdef LOCORE -#include <gnu/i386/fpemul/fpu_asm.h> -#define Const(x) $/**/x -#else -#define Const(x) x -#endif - -#define EXP_BIAS Const(0) -#define EXP_OVER Const(0x4000) /* smallest invalid large exponent */ -#define EXP_UNDER Const(-0x3fff) /* largest invalid small exponent */ - -#define SIGN_POS Const(0) -#define SIGN_NEG Const(1) - -/* Keep the order TW_Valid, TW_Zero, TW_Denormal */ -#define TW_Valid Const(0)/* valid */ -#define TW_Zero Const(1)/* zero */ -/* The following fold to 2 (Special) in the Tag Word */ -#define TW_Denormal Const(4)/* De-normal */ -#define TW_Infinity Const(5)/* + or - infinity */ -#define TW_NaN Const(6)/* Not a Number */ - -#define TW_Empty Const(7)/* empty */ - - /* #define TW_FPU_Interrupt Const(0x80) *//* Signals an interrupt */ - - -#ifndef LOCORE - -#include <sys/types.h> -#include <gnu/i386/fpemul/math_emu.h> - -#ifdef PARANOID -extern char emulating; -#define REENTRANT_CHECK(state) emulating = (state) -#define ON 1 -#define OFF 0 -#else -#define REENTRANT_CHECK(state) -#endif /* PARANOID */ - -typedef void (*FUNC) (void); -typedef struct fpu_reg FPU_REG; - -#define st(x) ( regs[((top+x) &7 )] ) - -#define STACK_OVERFLOW (st_new_ptr = &st(-1), st_new_ptr->tag != TW_Empty) -#define NOT_EMPTY(i) (st(i).tag != TW_Empty) -#define NOT_EMPTY_0 (FPU_st0_tag ^ TW_Empty) - -extern unsigned char FPU_rm; - -extern char FPU_st0_tag; -extern FPU_REG *FPU_st0_ptr; - -extern void *FPU_data_address; - -extern FPU_REG FPU_loaded_data; - -#define pop() { FPU_st0_ptr->tag = TW_Empty; top++; } - -/* push() does not affect the tags */ -#define push() { top--; FPU_st0_ptr = st_new_ptr; } - - -#define reg_move(x, y) { \ - *(short *)&((y)->sign) = *(short *)&((x)->sign); \ - *(long *)&((y)->exp) = *(long *)&((x)->exp); \ - *(long long *)&((y)->sigl) = *(long long *)&((x)->sigl); } - - -/*----- Prototypes for functions written in assembler -----*/ -/* extern void reg_move(FPU_REG *a, FPU_REG *b); */ - -extern void mul64(long long *a, long long *b, long long *result); -extern void poly_div2(long long *x); -extern void poly_div4(long long *x); -extern void poly_div16(long long *x); -extern void -polynomial(unsigned accum[], unsigned x[], - unsigned short terms[][4], int n); - extern void normalize(FPU_REG * x); - extern void normalize_nuo(FPU_REG * x); - extern void reg_div(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void reg_u_sub(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void reg_u_mul(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void reg_u_div(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void reg_u_add(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void wm_sqrt(FPU_REG * n, unsigned int control_w); - extern unsigned shrx(void *l, unsigned x); - extern unsigned shrxs(void *v, unsigned x); - extern unsigned long div_small(unsigned long long *x, unsigned long y); - extern void round_reg(FPU_REG * arg, unsigned int extent, - unsigned int control_w); - -#ifndef MAKING_PROTO -#include <gnu/i386/fpemul/fpu_proto.h> -#endif - -#endif /* LOCORE */ - -#endif /* _FPU_EMU_H_ */ diff --git a/sys/gnu/i386/fpemul/fpu_entry.c b/sys/gnu/i386/fpemul/fpu_entry.c deleted file mode 100644 index 589ac48..0000000 --- a/sys/gnu/i386/fpemul/fpu_entry.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - * fpu_entry.c - * - * The entry function for wm-FPU-emu - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * $FreeBSD$ - * - */ - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------+ - | math_emulate() is the sole entry point for wm-FPU-emu | - +---------------------------------------------------------------------------*/ - - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/proc.h> - -#include <machine/cpu.h> -#include <machine/pcb.h> - -#include <gnu/i386/fpemul/fpu_emu.h> -#include <gnu/i386/fpemul/fpu_system.h> -#include <gnu/i386/fpemul/exception.h> -#include <gnu/i386/fpemul/status_w.h> - - -#define __BAD__ Un_impl /* Not implemented */ - -#define FPU_LOOKAHEAD 1 /* For performance boost */ - -#if FPU_LOOKAHEAD != 0 /* I think thet we have to limit the */ -#define LOOKAHEAD_LIMIT 7 /* Max number of lookahead instructions*/ -#endif /* Or else a prog consisting of a million */ - /* fnops will spend all its time in kernel*/ - -#ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by - * default. */ - -/* WARNING: These codes are not documented by Intel in their 80486 manual - and may not work on FPU clones or later Intel FPUs. */ - -/* Changes to support the un-doc codes provided by Linus Torvalds. */ - -#define _d9_d8_ fstp_i /* unofficial code (19) */ -#define _dc_d0_ fcom_st /* unofficial code (14) */ -#define _dc_d8_ fcompst /* unofficial code (1c) */ -#define _dd_c8_ fxch_i /* unofficial code (0d) */ -#define _de_d0_ fcompst /* unofficial code (16) */ -#define _df_c0_ ffreep /* unofficial code (07) ffree + pop */ -#define _df_c8_ fxch_i /* unofficial code (0f) */ -#define _df_d0_ fstp_i /* unofficial code (17) */ -#define _df_d8_ fstp_i /* unofficial code (1f) */ - -static FUNC st_instr_table[64] = { - fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, _df_c0_, - fmul__, fxch_i, __BAD__, __BAD__, fmul_i, _dd_c8_, fmulp_, _df_c8_, - fcom_st, fp_nop, __BAD__, __BAD__, _dc_d0_, fst_i_, _de_d0_, _df_d0_, - fcompst, _d9_d8_, __BAD__, __BAD__, _dc_d8_, fstp_i, fcompp, _df_d8_, - fsub__, fp_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_, - fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__, - fdiv__, trig_a, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__, - fdivr_, trig_b, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__, -}; -#else /* Support only documented FPU op-codes */ - -static FUNC st_instr_table[64] = { - fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, __BAD__, - fmul__, fxch_i, __BAD__, __BAD__, fmul_i, __BAD__, fmulp_, __BAD__, - fcom_st, fp_nop, __BAD__, __BAD__, __BAD__, fst_i_, __BAD__, __BAD__, - fcompst, __BAD__, __BAD__, __BAD__, __BAD__, fstp_i, fcompp, __BAD__, - fsub__, fp_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_, - fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__, - fdiv__, trig_a, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__, - fdivr_, trig_b, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__, -}; -#endif /* NO_UNDOC_CODE */ - - -#define _NONE_ 0 /* Take no special action */ -#define _REG0_ 1 /* Need to check for not empty st(0) */ -#define _REGI_ 2 /* Need to check for not empty st(0) and - * st(rm) */ -#define _REGi_ 0 /* Uses st(rm) */ -#define _PUSH_ 3 /* Need to check for space to push onto stack */ -#define _null_ 4 /* Function illegal or not implemented */ -#define _REGIi 5 /* Uses st(0) and st(rm), result to st(rm) */ -#define _REGIp 6 /* Uses st(0) and st(rm), result to st(rm) - * then pop */ -#define _REGIc 0 /* Compare st(0) and st(rm) */ -#define _REGIn 0 /* Uses st(0) and st(rm), but handle checks - * later */ - -#ifndef NO_UNDOC_CODE - -/* Un-documented FPU op-codes supported by default. (see above) */ - -static unsigned char type_table[64] = { - _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _REGi_, - _REGI_, _REGIn, _null_, _null_, _REGIi, _REGI_, _REGIp, _REGI_, - _REGIc, _NONE_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_, - _REGIc, _REG0_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_, - _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_, - _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_ -}; -#else /* Support only documented FPU op-codes */ - -static unsigned char type_table[64] = { - _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _null_, - _REGI_, _REGIn, _null_, _null_, _REGIi, _null_, _REGIp, _null_, - _REGIc, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_, - _REGIc, _null_, _null_, _null_, _null_, _REG0_, _REGIc, _null_, - _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_, - _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_ -}; -#endif /* NO_UNDOC_CODE */ - -/* Be careful when using any of these global variables... - they might change if swapping is triggered */ -unsigned char FPU_rm; -char FPU_st0_tag; -FPU_REG *FPU_st0_ptr; - -#ifdef PARANOID -char emulating = 0; -#endif /* PARANOID */ - -#define bswapw(x) __asm__("xchgb %%al,%%ah":"+a" ((short)(x))) -#define math_abort(signo) \ - FPU_EIP = FPU_ORIG_EIP;REENTRANT_CHECK(OFF);return(signo); - -static int -math_emulate(struct trapframe * tframe) -{ - struct proc *p; - unsigned char FPU_modrm; - unsigned short code; -#ifdef LOOKAHEAD_LIMIT - int lookahead_limit = LOOKAHEAD_LIMIT; -#endif -#ifdef PARANOID - if (emulating) { - printf("ERROR: wm-FPU-emu is not RE-ENTRANT!\n"); - } - REENTRANT_CHECK(ON); -#endif /* PARANOID */ - - if ((curthread->td_pcb->pcb_flags & FP_SOFTFP) == 0) { - finit(); - control_word = __INITIAL_NPXCW__; - curthread->td_pcb->pcb_flags |= FP_SOFTFP; - } - FPU_info = tframe; - FPU_ORIG_EIP = FPU_EIP; /* --pink-- */ - - if (FPU_CS != 0x001f) { - printf("math_emulate: %x : %x\n", FPU_CS, FPU_EIP); - panic("FPU emulation in kernel"); - } -#ifdef notyet - /* We cannot handle emulation in v86-mode */ - if (FPU_EFLAGS & 0x00020000) { - FPU_ORIG_EIP = FPU_EIP; - math_abort(FPU_info, SIGILL); - } -#endif - - FPU_lookahead = FPU_LOOKAHEAD; - p = curthread->td_proc; - PROC_LOCK(p); - if (p->p_flag & P_TRACED) - FPU_lookahead = 0; - PROC_UNLOCK(p); - -do_another_FPU_instruction: - - REENTRANT_CHECK(OFF); - code = fuword((u_int *) FPU_EIP); - REENTRANT_CHECK(ON); - if ((code & 0xff) == 0x9b) { /* fwait */ - if (status_word & SW_Summary) - goto do_the_FPU_interrupt; - else { - FPU_EIP++; - goto FPU_instruction_done; - } - } - if (status_word & SW_Summary) { - /* Ignore the error for now if the current instruction is a - * no-wait control instruction */ - /* The 80486 manual contradicts itself on this topic, so I use - * the following list of such instructions until I can check - * on a real 80486: fninit, fnstenv, fnsave, fnstsw, fnstenv, - * fnclex. */ - if (!((((code & 0xf803) == 0xe003) || /* fnclex, fninit, - * fnstsw */ - (((code & 0x3003) == 0x3001) && /* fnsave, fnstcw, - * fnstenv, fnstsw */ - ((code & 0xc000) != 0xc000))))) { - /* This is a guess about what a real FPU might do to - * this bit: */ -/* status_word &= ~SW_Summary; ****/ - - /* We need to simulate the action of the kernel to FPU - * interrupts here. Currently, the "real FPU" part of - * the kernel (0.99.10) clears the exception flags, - * sets the registers to empty, and passes information - * back to the interrupted process via the cs selector - * and operand selector, so we do the same. */ - do_the_FPU_interrupt: - cs_selector &= 0xffff0000; - cs_selector |= (status_word & ~SW_Top) | ((top & 7) << SW_Top_Shift); - operand_selector = tag_word(); - status_word = 0; - top = 0; - { - int r; - for (r = 0; r < 8; r++) { - regs[r].tag = TW_Empty; - } - } - REENTRANT_CHECK(OFF); - math_abort(SIGFPE); - } - } - FPU_entry_eip = FPU_ORIG_EIP = FPU_EIP; - - if ((code & 0xff) == 0x66) { /* size prefix */ - FPU_EIP++; - REENTRANT_CHECK(OFF); - code = fuword((u_int *) FPU_EIP); - REENTRANT_CHECK(ON); - } - FPU_EIP += 2; - - FPU_modrm = code >> 8; - FPU_rm = FPU_modrm & 7; - - if (FPU_modrm < 0300) { - /* All of these instructions use the mod/rm byte to get a data - * address */ - get_address(FPU_modrm); - if (!(code & 1)) { - unsigned short status1 = status_word; - FPU_st0_ptr = &st(0); - FPU_st0_tag = FPU_st0_ptr->tag; - - /* Stack underflow has priority */ - if (NOT_EMPTY_0) { - switch ((code >> 1) & 3) { - case 0: - reg_load_single(); - break; - case 1: - reg_load_int32(); - break; - case 2: - reg_load_double(); - break; - case 3: - reg_load_int16(); - break; - } - - /* No more access to user memory, it is safe - * to use static data now */ - FPU_st0_ptr = &st(0); - FPU_st0_tag = FPU_st0_ptr->tag; - - /* NaN operands have the next priority. */ - /* We have to delay looking at st(0) until - * after loading the data, because that data - * might contain an SNaN */ - if ((FPU_st0_tag == TW_NaN) || - (FPU_loaded_data.tag == TW_NaN)) { - /* Restore the status word; we might - * have loaded a denormal. */ - status_word = status1; - if ((FPU_modrm & 0x30) == 0x10) { - /* fcom or fcomp */ - EXCEPTION(EX_Invalid); - setcc(SW_C3 | SW_C2 | SW_C0); - if (FPU_modrm & 0x08) - pop(); /* fcomp, so we pop. */ - } else - real_2op_NaN(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr); - goto reg_mem_instr_done; - } - switch ((FPU_modrm >> 3) & 7) { - case 0: /* fadd */ - reg_add(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word); - break; - case 1: /* fmul */ - reg_mul(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word); - break; - case 2: /* fcom */ - compare_st_data(); - break; - case 3: /* fcomp */ - compare_st_data(); - pop(); - break; - case 4: /* fsub */ - reg_sub(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word); - break; - case 5: /* fsubr */ - reg_sub(&FPU_loaded_data, FPU_st0_ptr, FPU_st0_ptr, control_word); - break; - case 6: /* fdiv */ - reg_div(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word); - break; - case 7: /* fdivr */ - if (FPU_st0_tag == TW_Zero) - status_word = status1; /* Undo any denorm tag, - * zero-divide has - * priority. */ - reg_div(&FPU_loaded_data, FPU_st0_ptr, FPU_st0_ptr, control_word); - break; - } - } else { - if ((FPU_modrm & 0x30) == 0x10) { - /* The instruction is fcom or fcomp */ - EXCEPTION(EX_StackUnder); - setcc(SW_C3 | SW_C2 | SW_C0); - if (FPU_modrm & 0x08) - pop(); /* fcomp, Empty or not, - * we pop. */ - } else - stack_underflow(); - } - } else { - load_store_instr(((FPU_modrm & 0x38) | (code & 6)) >> 1); - } - -reg_mem_instr_done: - - data_operand_offset = (intptr_t) (void *) FPU_data_address; - } else { - /* None of these instructions access user memory */ - unsigned char instr_index = (FPU_modrm & 0x38) | (code & 7); - - FPU_st0_ptr = &st(0); - FPU_st0_tag = FPU_st0_ptr->tag; - switch (type_table[(int) instr_index]) { - case _NONE_: /* also _REGIc: _REGIn */ - break; - case _REG0_: - if (!NOT_EMPTY_0) { - stack_underflow(); - goto FPU_instruction_done; - } - break; - case _REGIi: - if (!NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm)) { - stack_underflow_i(FPU_rm); - goto FPU_instruction_done; - } - break; - case _REGIp: - if (!NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm)) { - stack_underflow_i(FPU_rm); - pop(); - goto FPU_instruction_done; - } - break; - case _REGI_: - if (!NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm)) { - stack_underflow(); - goto FPU_instruction_done; - } - break; - case _PUSH_: /* Only used by the fld st(i) instruction */ - break; - case _null_: - Un_impl(); - goto FPU_instruction_done; - default: - EXCEPTION(EX_INTERNAL | 0x111); - goto FPU_instruction_done; - } - (*st_instr_table[(int) instr_index]) (); - } - -FPU_instruction_done: - - ip_offset = FPU_entry_eip; - bswapw(code); - *(1 + (unsigned short *) &cs_selector) = code & 0x7ff; - -#ifdef DEBUG - REENTRANT_CHECK(OFF); - emu_printall(); - REENTRANT_CHECK(ON); -#endif /* DEBUG */ -#ifdef LOOKAHEAD_LIMIT -if (--lookahead_limit) -#endif - if (FPU_lookahead) { - unsigned char next; - - /* (This test should generate no machine code) */ - while (1) { - REENTRANT_CHECK(OFF); - next = fubyte((u_char *) FPU_EIP); - REENTRANT_CHECK(ON); - if (((next & 0xf8) == 0xd8) || (next == 0x9b)) { /* fwait */ - goto do_another_FPU_instruction; - } else - if (next == 0x66) { /* size prefix */ - REENTRANT_CHECK(OFF); - next = fubyte((u_char *) (FPU_EIP + 1)); - REENTRANT_CHECK(ON); - if ((next & 0xf8) == 0xd8) { - FPU_EIP++; - goto do_another_FPU_instruction; - } - } - break; - } - } - REENTRANT_CHECK(OFF); - return (0); /* --pink-- */ -} - -static int -gnufpu_modevent(module_t mod, int type, void *unused) -{ - switch (type) { - case MOD_LOAD: - if (pmath_emulate) { - printf("Another Math emulator already present\n"); - return EACCES; - } - pmath_emulate = math_emulate; - if (bootverbose) - printf("GPL Math emulator present\n"); - break; - case MOD_UNLOAD: - if (pmath_emulate != math_emulate) { - printf("Cannot unload another math emulator\n"); - return EACCES; - } - pmath_emulate = 0; - if (bootverbose) - printf("GPL Math emulator unloaded\n"); - break; - default: - break; - } - return 0; - -} -static moduledata_t gnufpumod = { - "gnufpu", - gnufpu_modevent, - 0 -}; -DECLARE_MODULE(gnufpu, gnufpumod, SI_SUB_DRIVERS, SI_ORDER_ANY); diff --git a/sys/gnu/i386/fpemul/fpu_etc.c b/sys/gnu/i386/fpemul/fpu_etc.c deleted file mode 100644 index cd91e80..0000000 --- a/sys/gnu/i386/fpemul/fpu_etc.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * fpu_etc.c - * - * Implement a few FPU instructions. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -#include <sys/param.h> -#ifdef DEBUG -#include <sys/systm.h> /* for printf() in EXCEPTION() */ -#endif -#include <sys/proc.h> -#include <machine/pcb.h> - -#include <gnu/i386/fpemul/fpu_emu.h> -#include <gnu/i386/fpemul/fpu_system.h> -#include <gnu/i386/fpemul/exception.h> -#include <gnu/i386/fpemul/status_w.h> - - -static void -fchs(void) -{ - if (NOT_EMPTY_0) { - FPU_st0_ptr->sign ^= SIGN_POS ^ SIGN_NEG; - status_word &= ~SW_C1; - } else - stack_underflow(); -} - -static void -fabs(void) -{ - if (FPU_st0_tag ^ TW_Empty) { - FPU_st0_ptr->sign = SIGN_POS; - status_word &= ~SW_C1; - } else - stack_underflow(); -} - - -static void -ftst_(void) -{ - switch (FPU_st0_tag) { - case TW_Zero: - setcc(SW_C3); - break; - case TW_Valid: - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign == SIGN_POS) - setcc(0); - else - setcc(SW_C0); - break; - case TW_NaN: - setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */ - EXCEPTION(EX_Invalid); - break; - case TW_Infinity: - if (FPU_st0_ptr->sign == SIGN_POS) - setcc(0); - else - setcc(SW_C0); - EXCEPTION(EX_Invalid); - break; - case TW_Empty: - setcc(SW_C0 | SW_C2 | SW_C3); - EXCEPTION(EX_StackUnder); - break; - default: - setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */ - EXCEPTION(EX_INTERNAL | 0x14); - break; - } -} - -static void -fxam(void) -{ - int c = 0; - switch (FPU_st0_tag) { - case TW_Empty: - c = SW_C3 | SW_C0; - break; - case TW_Zero: - c = SW_C3; - break; - case TW_Valid: - /* This will need to be changed if TW_Denormal is ever used. */ - if (FPU_st0_ptr->exp <= EXP_UNDER) - c = SW_C2 | SW_C3; /* Denormal */ - else - c = SW_C3; - break; - case TW_NaN: - c = SW_C0; - break; - case TW_Infinity: - c = SW_C2 | SW_C0; - break; - } - if (FPU_st0_ptr->sign == SIGN_NEG) - c |= SW_C1; - setcc(c); -} - -static FUNC fp_etc_table[] = { - fchs, fabs, Un_impl, Un_impl, ftst_, fxam, Un_impl, Un_impl -}; - -void -fp_etc() -{ - (fp_etc_table[FPU_rm]) (); -} diff --git a/sys/gnu/i386/fpemul/fpu_proto.h b/sys/gnu/i386/fpemul/fpu_proto.h deleted file mode 100644 index fc36478..0000000 --- a/sys/gnu/i386/fpemul/fpu_proto.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * $FreeBSD$ - * - */ - - -/* errors.c */ -extern void Un_impl(void); -extern void emu_printall(void); -extern void exception(int n); -extern void real_2op_NaN(FPU_REG * a, FPU_REG * b, FPU_REG * dest); -extern void arith_invalid(FPU_REG * dest); -extern void divide_by_zero(int sign, FPU_REG * dest); -extern void set_precision_flag_up(void); -extern void set_precision_flag_down(void); -extern int denormal_operand(void); -extern void arith_overflow(FPU_REG * dest); -extern void arith_underflow(FPU_REG * dest); -extern void stack_overflow(void); -extern void stack_underflow(void); -extern void stack_underflow_i(int i); -extern void stack_underflow_pop(int i); -/* fpu_arith.c */ -extern void fadd__(void); -extern void fmul__(void); -extern void fsub__(void); -extern void fsubr_(void); -extern void fdiv__(void); -extern void fdivr_(void); -extern void fadd_i(void); -extern void fmul_i(void); -extern void fsubri(void); -extern void fsub_i(void); -extern void fdivri(void); -extern void fdiv_i(void); -extern void faddp_(void); -extern void fmulp_(void); -extern void fsubrp(void); -extern void fsubp_(void); -extern void fdivrp(void); -extern void fdivp_(void); -/* fpu_aux.c */ -extern void finit(void); -extern void finit_(void); -extern void fstsw_(void); -extern void fp_nop(void); -extern void fld_i_(void); -extern void fxch_i(void); -extern void ffree_(void); -extern void ffreep(void); -extern void fst_i_(void); -extern void fstp_i(void); -/* fpu_entry.c */ -#if 0 -extern int math_emulate(struct trapframe * info); -#endif -/* fpu_etc.c */ -extern void fp_etc(void); -/* fpu_trig.c */ -extern void trig_a(void); -extern void trig_b(void); -/* get_address.c */ -extern void get_address(unsigned char FPU_modrm); -/* load_store.c */ -extern void load_store_instr(char type); -/* poly_2xm1.c */ -extern int poly_2xm1(FPU_REG * arg, FPU_REG * result); -/* poly_atan.c */ -extern void poly_atan(FPU_REG * arg); -/* poly_l2.c */ -extern void poly_l2(FPU_REG * arg, FPU_REG * result); -extern int poly_l2p1(FPU_REG * arg, FPU_REG * result); -/* poly_sin.c */ -extern void poly_sine(FPU_REG * arg, FPU_REG * result); -/* poly_tan.c */ -extern void poly_tan(FPU_REG * arg, FPU_REG * y_reg); -/* reg_add_sub.c */ -extern void reg_add(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w); -extern void reg_sub(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w); -/* reg_compare.c */ -extern int compare(FPU_REG * b); -extern int compare_st_data(void); -extern void fcom_st(void); -extern void fcompst(void); -extern void fcompp(void); -extern void fucom_(void); -extern void fucomp(void); -extern void fucompp(void); -/* reg_constant.c */ -extern void fconst(void); -/* reg_ld_str.c */ -extern void reg_load_extended(void); -extern void reg_load_double(void); -extern void reg_load_single(void); -extern void reg_load_int64(void); -extern void reg_load_int32(void); -extern void reg_load_int16(void); -extern void reg_load_bcd(void); -extern int reg_store_extended(void); -extern int reg_store_double(void); -extern int reg_store_single(void); -extern int reg_store_int64(void); -extern int reg_store_int32(void); -extern int reg_store_int16(void); -extern int reg_store_bcd(void); -extern int round_to_int(FPU_REG * r); -extern char *fldenv(void); -extern void frstor(void); -extern unsigned short tag_word(void); -extern char *fstenv(void); -extern void fsave(void); -/* reg_mul.c */ -extern void reg_mul(FPU_REG * a, FPU_REG * b, FPU_REG * dest, unsigned int control_w); diff --git a/sys/gnu/i386/fpemul/fpu_system.h b/sys/gnu/i386/fpemul/fpu_system.h deleted file mode 100644 index f4927c8..0000000 --- a/sys/gnu/i386/fpemul/fpu_system.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * fpu_system.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - -#ifndef _FPU_SYSTEM_H -#define _FPU_SYSTEM_H - -/* system dependent definitions */ - -/* -#include <linux/sched.h> -#include <linux/kernel.h> -*/ - -#define I387 (*(union i387_union *)&(curthread->td_pcb->pcb_save.sv_87)) -#define FPU_info (I387.soft.frame) - -#define FPU_CS (*(unsigned short *) &(FPU_info->tf_cs)) -#define FPU_DS (*(unsigned short *) &(FPU_info->tf_ds)) -#define FPU_EAX (FPU_info->tf_eax) -#define FPU_EFLAGS (FPU_info->tf_eflags) -#define FPU_EIP (FPU_info->tf_eip) -/*#define FPU_ORIG_EIP (FPU_info->___orig_eip) */ -/*#define FPU_ORIG_EIP (FPU_info->tf_isp)*/ -#define FPU_ORIG_EIP (I387.soft.orig_eip) - -#define FPU_lookahead (I387.soft.lookahead) -#define FPU_entry_eip (I387.soft.entry_eip) - -#define status_word (I387.soft.swd) -#define control_word (I387.soft.cwd) -#define regs (I387.soft.regs) -#define top (I387.soft.top) - -#define ip_offset (I387.soft.fip) -#define cs_selector (I387.soft.fcs) -#define data_operand_offset (I387.soft.foo) -#define operand_selector (I387.soft.fos) - -#endif diff --git a/sys/gnu/i386/fpemul/fpu_trig.c b/sys/gnu/i386/fpemul/fpu_trig.c deleted file mode 100644 index 9eaab4f..0000000 --- a/sys/gnu/i386/fpemul/fpu_trig.c +++ /dev/null @@ -1,1371 +0,0 @@ -/* - * fpu_trig.c - * - * Implementation of the FPU "transcendental" functions. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - -#include <sys/param.h> -#ifdef DEBUG -#include <sys/systm.h> /* for printf() in EXCEPTION() */ -#endif -#include <sys/proc.h> -#include <machine/pcb.h> - -#include <gnu/i386/fpemul/fpu_emu.h> -#include <gnu/i386/fpemul/fpu_system.h> -#include <gnu/i386/fpemul/exception.h> -#include <gnu/i386/fpemul/status_w.h> -#include <gnu/i386/fpemul/reg_constant.h> -#include <gnu/i386/fpemul/control_w.h> - -static void convert_l2reg(long *arg, FPU_REG * dest); - -static int -trig_arg(FPU_REG * X) -{ - FPU_REG tmp, quot; - int rv; - long long q; - int old_cw = control_word; - - control_word &= ~CW_RC; - control_word |= RC_CHOP; - - reg_move(X, "); - reg_div(", &CONST_PI2, ", FULL_PRECISION); - - reg_move(", &tmp); - round_to_int(&tmp); - if (tmp.sigh & 0x80000000) - return -1; /* |Arg| is >= 2^63 */ - tmp.exp = EXP_BIAS + 63; - q = *(long long *) &(tmp.sigl); - normalize(&tmp); - - reg_sub(", &tmp, X, FULL_PRECISION); - rv = q & 7; - - control_word = old_cw; - return rv; -} - - -/* Convert a long to register */ -static void -convert_l2reg(long *arg, FPU_REG * dest) -{ - long num = *arg; - - if (num == 0) { - reg_move(&CONST_Z, dest); - return; - } - if (num > 0) - dest->sign = SIGN_POS; - else { - num = -num; - dest->sign = SIGN_NEG; - } - - dest->sigh = num; - dest->sigl = 0; - dest->exp = EXP_BIAS + 31; - dest->tag = TW_Valid; - normalize(dest); -} - - -static void -single_arg_error(void) -{ - switch (FPU_st0_tag) { - case TW_NaN: - if (!(FPU_st0_ptr->sigh & 0x40000000)) { /* Signaling ? */ - EXCEPTION(EX_Invalid); - /* Convert to a QNaN */ - FPU_st0_ptr->sigh |= 0x40000000; - } - break; /* return with a NaN in st(0) */ - case TW_Empty: - stack_underflow(); /* Puts a QNaN in st(0) */ - break; -#ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL | 0x0112); -#endif /* PARANOID */ - } -} - - -/*---------------------------------------------------------------------------*/ - -static void -f2xm1(void) -{ - switch (FPU_st0_tag) { - case TW_Valid: - { - FPU_REG rv, tmp; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign == SIGN_POS) { - /* poly_2xm1(x) requires 0 < x < 1. */ - if (poly_2xm1(FPU_st0_ptr, &rv)) - return; /* error */ - reg_mul(&rv, FPU_st0_ptr, FPU_st0_ptr, FULL_PRECISION); - } else { -/* **** Should change poly_2xm1() to at least handle numbers near 0 */ - /* poly_2xm1(x) doesn't handle negative - * numbers. */ - /* So we compute (poly_2xm1(x+1)-1)/2, for -1 - * < x < 0 */ - reg_add(FPU_st0_ptr, &CONST_1, &tmp, FULL_PRECISION); - poly_2xm1(&tmp, &rv); - reg_mul(&rv, &tmp, &tmp, FULL_PRECISION); - reg_sub(&tmp, &CONST_1, FPU_st0_ptr, FULL_PRECISION); - FPU_st0_ptr->exp--; - if (FPU_st0_ptr->exp <= EXP_UNDER) - arith_underflow(FPU_st0_ptr); - } - return; - } - case TW_Zero: - return; - case TW_Infinity: - if (FPU_st0_ptr->sign == SIGN_NEG) { - /* -infinity gives -1 (p16-10) */ - reg_move(&CONST_1, FPU_st0_ptr); - FPU_st0_ptr->sign = SIGN_NEG; - } - return; - default: - single_arg_error(); - } -} - -static void -fptan(void) -{ - FPU_REG *st_new_ptr; - int q; - char arg_sign = FPU_st0_ptr->sign; - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - switch (FPU_st0_tag) { - case TW_Valid: - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - FPU_st0_ptr->sign = SIGN_POS; - if ((q = trig_arg(FPU_st0_ptr)) != -1) { - if (q & 1) - reg_sub(&CONST_1, FPU_st0_ptr, FPU_st0_ptr, FULL_PRECISION); - - poly_tan(FPU_st0_ptr, FPU_st0_ptr); - - FPU_st0_ptr->sign = (q & 1) ^ arg_sign; - - if (FPU_st0_ptr->exp <= EXP_UNDER) - arith_underflow(FPU_st0_ptr); - - push(); - reg_move(&CONST_1, FPU_st0_ptr); - setcc(0); - } else { - /* Operand is out of range */ - setcc(SW_C2); - FPU_st0_ptr->sign = arg_sign; /* restore st(0) */ - return; - } - break; - case TW_Infinity: - /* Operand is out of range */ - setcc(SW_C2); - FPU_st0_ptr->sign = arg_sign; /* restore st(0) */ - return; - case TW_Zero: - push(); - reg_move(&CONST_1, FPU_st0_ptr); - setcc(0); - break; - default: - single_arg_error(); - break; - } -} - - -static void -fxtract(void) -{ - FPU_REG *st_new_ptr; - register FPU_REG *st1_ptr = FPU_st0_ptr; /* anticipate */ - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - if (!(FPU_st0_tag ^ TW_Valid)) { - long e; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - push(); - reg_move(st1_ptr, FPU_st0_ptr); - FPU_st0_ptr->exp = EXP_BIAS; - e = st1_ptr->exp - EXP_BIAS; - convert_l2reg(&e, st1_ptr); - return; - } else - if (FPU_st0_tag == TW_Zero) { - char sign = FPU_st0_ptr->sign; - divide_by_zero(SIGN_NEG, FPU_st0_ptr); - push(); - reg_move(&CONST_Z, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } else - if (FPU_st0_tag == TW_Infinity) { - char sign = FPU_st0_ptr->sign; - FPU_st0_ptr->sign = SIGN_POS; - push(); - reg_move(&CONST_INF, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } else - if (FPU_st0_tag == TW_NaN) { - if (!(FPU_st0_ptr->sigh & 0x40000000)) { /* Signaling ? */ - EXCEPTION(EX_Invalid); - /* Convert to a QNaN */ - FPU_st0_ptr->sigh |= 0x40000000; - } - push(); - reg_move(st1_ptr, FPU_st0_ptr); - return; - } else - if (FPU_st0_tag == TW_Empty) { - /* Is this the correct - * behaviour? */ - if (control_word & EX_Invalid) { - stack_underflow(); - push(); - stack_underflow(); - } else - EXCEPTION(EX_StackUnder); - } -#ifdef PARANOID - else - EXCEPTION(EX_INTERNAL | 0x119); -#endif /* PARANOID */ -} - - -static void -fdecstp(void) -{ - top--; /* FPU_st0_ptr will be fixed in math_emulate() - * before the next instr */ -} - -static void -fincstp(void) -{ - top++; /* FPU_st0_ptr will be fixed in math_emulate() - * before the next instr */ -} - - -static void -fsqrt_(void) -{ - if (!(FPU_st0_tag ^ TW_Valid)) { - int expon; - - if (FPU_st0_ptr->sign == SIGN_NEG) { - arith_invalid(FPU_st0_ptr); /* sqrt(negative) is - * invalid */ - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - expon = FPU_st0_ptr->exp - EXP_BIAS; - FPU_st0_ptr->exp = EXP_BIAS + (expon & 1); /* make st(0) in [1.0 - * .. 4.0) */ - - wm_sqrt(FPU_st0_ptr, control_word); /* Do the computation */ - - FPU_st0_ptr->exp += expon >> 1; - FPU_st0_ptr->sign = SIGN_POS; - } else - if (FPU_st0_tag == TW_Zero) - return; - else - if (FPU_st0_tag == TW_Infinity) { - if (FPU_st0_ptr->sign == SIGN_NEG) - arith_invalid(FPU_st0_ptr); /* sqrt(-Infinity) is - * invalid */ - return; - } else { - single_arg_error(); - return; - } - -} - - -static void -frndint_(void) -{ - if (!(FPU_st0_tag ^ TW_Valid)) { - if (FPU_st0_ptr->exp > EXP_BIAS + 63) - return; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - round_to_int(FPU_st0_ptr); /* Fortunately, this can't - * overflow to 2^64 */ - FPU_st0_ptr->exp = EXP_BIAS + 63; - normalize(FPU_st0_ptr); - return; - } else - if ((FPU_st0_tag == TW_Zero) || (FPU_st0_tag == TW_Infinity)) - return; - else - single_arg_error(); -} - - -static void -fsin(void) -{ - char arg_sign = FPU_st0_ptr->sign; - - if (FPU_st0_tag == TW_Valid) { - int q; - FPU_st0_ptr->sign = SIGN_POS; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if ((q = trig_arg(FPU_st0_ptr)) != -1) { - FPU_REG rv; - - if (q & 1) - reg_sub(&CONST_1, FPU_st0_ptr, FPU_st0_ptr, FULL_PRECISION); - - poly_sine(FPU_st0_ptr, &rv); - - setcc(0); - if (q & 2) - rv.sign ^= SIGN_POS ^ SIGN_NEG; - rv.sign ^= arg_sign; - reg_move(&rv, FPU_st0_ptr); - - if (FPU_st0_ptr->exp <= EXP_UNDER) - arith_underflow(FPU_st0_ptr); - - set_precision_flag_up(); /* We do not really know - * if up or down */ - - return; - } else { - /* Operand is out of range */ - setcc(SW_C2); - FPU_st0_ptr->sign = arg_sign; /* restore st(0) */ - return; - } - } else - if (FPU_st0_tag == TW_Zero) { - setcc(0); - return; - } else - if (FPU_st0_tag == TW_Infinity) { - /* Operand is out of range */ - setcc(SW_C2); - FPU_st0_ptr->sign = arg_sign; /* restore st(0) */ - return; - } else - single_arg_error(); -} - - -static int -f_cos(FPU_REG * arg) -{ - char arg_sign = arg->sign; - - if (arg->tag == TW_Valid) { - int q; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return 1; -#endif /* DENORM_OPERAND */ - - arg->sign = SIGN_POS; - if ((q = trig_arg(arg)) != -1) { - FPU_REG rv; - - if (!(q & 1)) - reg_sub(&CONST_1, arg, arg, FULL_PRECISION); - - poly_sine(arg, &rv); - - setcc(0); - if ((q + 1) & 2) - rv.sign ^= SIGN_POS ^ SIGN_NEG; - reg_move(&rv, arg); - - set_precision_flag_up(); /* We do not really know - * if up or down */ - - return 0; - } else { - /* Operand is out of range */ - setcc(SW_C2); - arg->sign = arg_sign; /* restore st(0) */ - return 1; - } - } else - if (arg->tag == TW_Zero) { - reg_move(&CONST_1, arg); - setcc(0); - return 0; - } else - if (FPU_st0_tag == TW_Infinity) { - /* Operand is out of range */ - setcc(SW_C2); - arg->sign = arg_sign; /* restore st(0) */ - return 1; - } else { - single_arg_error(); /* requires arg == - * &st(0) */ - return 1; - } -} - - -static void -fcos(void) -{ - f_cos(FPU_st0_ptr); -} - - -static void -fsincos(void) -{ - FPU_REG *st_new_ptr; - FPU_REG arg; - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - reg_move(FPU_st0_ptr, &arg); - if (!f_cos(&arg)) { - fsin(); - push(); - reg_move(&arg, FPU_st0_ptr); - } -} - - -/*---------------------------------------------------------------------------*/ -/* The following all require two arguments: st(0) and st(1) */ - -/* remainder of st(0) / st(1) */ -/* Assumes that st(0) and st(1) are both TW_Valid */ -static void -fprem_kernel(int round) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - FPU_REG tmp; - int old_cw = control_word; - int expdif = FPU_st0_ptr->exp - (st1_ptr)->exp; - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - control_word &= ~CW_RC; - control_word |= round; - - if (expdif < 64) { - /* This should be the most common case */ - long long q; - int c = 0; - - reg_div(FPU_st0_ptr, st1_ptr, &tmp, FULL_PRECISION); - - round_to_int(&tmp); /* Fortunately, this can't - * overflow to 2^64 */ - tmp.exp = EXP_BIAS + 63; - q = *(long long *) &(tmp.sigl); - normalize(&tmp); - - reg_mul(st1_ptr, &tmp, &tmp, FULL_PRECISION); - reg_sub(FPU_st0_ptr, &tmp, FPU_st0_ptr, FULL_PRECISION); - - if (q & 4) - c |= SW_C3; - if (q & 2) - c |= SW_C1; - if (q & 1) - c |= SW_C0; - - setcc(c); - } else { - /* There is a large exponent difference ( >= 64 ) */ - int N_exp; - - reg_div(FPU_st0_ptr, st1_ptr, &tmp, FULL_PRECISION); - /* N is 'a number between 32 and 63' (p26-113) */ - N_exp = (tmp.exp & 31) + 32; - tmp.exp = EXP_BIAS + N_exp; - - round_to_int(&tmp); /* Fortunately, this can't - * overflow to 2^64 */ - tmp.exp = EXP_BIAS + 63; - normalize(&tmp); - - tmp.exp = EXP_BIAS + expdif - N_exp; - - reg_mul(st1_ptr, &tmp, &tmp, FULL_PRECISION); - reg_sub(FPU_st0_ptr, &tmp, FPU_st0_ptr, FULL_PRECISION); - - setcc(SW_C2); - } - control_word = old_cw; - - if (FPU_st0_ptr->exp <= EXP_UNDER) - arith_underflow(FPU_st0_ptr); - return; - } else - if ((FPU_st0_tag == TW_Empty) | (st1_tag == TW_Empty)) { - stack_underflow(); - return; - } else - if (FPU_st0_tag == TW_Zero) { - if (st1_tag == TW_Valid) { - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - setcc(0); - return; - } else - if (st1_tag == TW_Zero) { - arith_invalid(FPU_st0_ptr); - return; - } - /* fprem(?,0) always invalid */ - else - if (st1_tag == TW_Infinity) { - setcc(0); - return; - } - } else - if (FPU_st0_tag == TW_Valid) { - if (st1_tag == TW_Zero) { - arith_invalid(FPU_st0_ptr); /* fprem(Valid,Zero) is - * invalid */ - return; - } else - if (st1_tag != TW_NaN) { -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (st1_tag == TW_Infinity) { - /* fprem(Valid, - * Infinity) - * is o.k. */ - setcc(0); - return; - } - } - } else - if (FPU_st0_tag == TW_Infinity) { - if (st1_tag != TW_NaN) { - arith_invalid(FPU_st0_ptr); /* fprem(Infinity,?) is - * invalid */ - return; - } - } - /* One of the registers must contain a NaN is we got here. */ - -#ifdef PARANOID - if ((FPU_st0_tag != TW_NaN) && (st1_tag != TW_NaN)) - EXCEPTION(EX_INTERNAL | 0x118); -#endif /* PARANOID */ - - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - -} - - -/* ST(1) <- ST(1) * log ST; pop ST */ -static void -fyl2x(void) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - if (FPU_st0_ptr->sign == SIGN_POS) { - int saved_control, saved_status; - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - /* We use the general purpose arithmetic, so we need - * to save these. */ - saved_status = status_word; - saved_control = control_word; - control_word = FULL_PRECISION; - - poly_l2(FPU_st0_ptr, FPU_st0_ptr); - - /* Enough of the basic arithmetic is done now */ - control_word = saved_control; - status_word = saved_status; - - /* Let the multiply set the flags */ - reg_mul(FPU_st0_ptr, st1_ptr, st1_ptr, FULL_PRECISION); - - pop(); - FPU_st0_ptr = &st(0); - } else { - /* negative */ - pop(); - FPU_st0_ptr = &st(0); - arith_invalid(FPU_st0_ptr); /* st(0) cannot be - * negative */ - return; - } - } else - if ((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty)) { - stack_underflow_pop(1); - return; - } else - if ((FPU_st0_tag == TW_NaN) || (st1_tag == TW_NaN)) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } else - if ((FPU_st0_tag <= TW_Zero) && (st1_tag <= TW_Zero)) { - /* one of the args is zero, the other - * valid, or both zero */ - if (FPU_st0_tag == TW_Zero) { - pop(); - FPU_st0_ptr = &st(0); - if (FPU_st0_ptr->tag == TW_Zero) - arith_invalid(FPU_st0_ptr); /* Both args zero is - * invalid */ -#ifdef PECULIAR_486 - /* This case is not - * specifically covered in the - * manual, but divide-by-zero - * would seem to be the best - * response. However, a real - * 80486 does it this way... */ - else - if (FPU_st0_ptr->tag == TW_Infinity) { - reg_move(&CONST_INF, FPU_st0_ptr); - return; - } -#endif /* PECULIAR_486 */ - else - divide_by_zero(st1_ptr->sign ^ SIGN_NEG ^ SIGN_POS, FPU_st0_ptr); - return; - } else { - /* st(1) contains zero, st(0) - * valid <> 0 */ - /* Zero is the valid answer */ - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - if (FPU_st0_ptr->sign == SIGN_NEG) { - pop(); - FPU_st0_ptr = &st(0); - arith_invalid(FPU_st0_ptr); /* log(negative) */ - return; - } - if (FPU_st0_ptr->exp < EXP_BIAS) - sign ^= SIGN_NEG ^ SIGN_POS; - pop(); - FPU_st0_ptr = &st(0); - reg_move(&CONST_Z, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } - } - /* One or both arg must be an infinity */ - else - if (FPU_st0_tag == TW_Infinity) { - if ((FPU_st0_ptr->sign == SIGN_NEG) || (st1_tag == TW_Zero)) { - pop(); - FPU_st0_ptr = &st(0); - arith_invalid(FPU_st0_ptr); /* log(-infinity) or - * 0*log(infinity) */ - return; - } else { - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - pop(); - FPU_st0_ptr = &st(0); - reg_move(&CONST_INF, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } - } - /* st(1) must be infinity here */ - else - if ((FPU_st0_tag == TW_Valid) && (FPU_st0_ptr->sign == SIGN_POS)) { - if (FPU_st0_ptr->exp >= EXP_BIAS) { - if ((FPU_st0_ptr->exp == EXP_BIAS) && - (FPU_st0_ptr->sigh == 0x80000000) && - (FPU_st0_ptr->sigl == 0)) { - /* st(0 - * ) - * hold - * s - * 1.0 */ - pop(); - FPU_st0_ptr = &st(0); - arith_invalid(FPU_st0_ptr); /* infinity*log(1) */ - return; - } - /* st(0) is - * positive - * and > 1.0 */ - pop(); - } else { - /* st(0) is - * positive - * and < 1.0 */ - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - st1_ptr->sign ^= SIGN_NEG; - pop(); - } - return; - } else { - /* st(0) must be zero - * or negative */ - if (FPU_st0_ptr->tag == TW_Zero) { - pop(); - FPU_st0_ptr = st1_ptr; - st1_ptr->sign ^= SIGN_NEG ^ SIGN_POS; - /* This should - * be invalid, - * but a real - * 80486 is - * happy with - * it. */ -#ifndef PECULIAR_486 - divide_by_zero(st1_ptr->sign, FPU_st0_ptr); -#endif /* PECULIAR_486 */ - } else { - pop(); - FPU_st0_ptr = st1_ptr; - arith_invalid(FPU_st0_ptr); /* log(negative) */ - } - return; - } -} - - -static void -fpatan(void) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - int saved_control, saved_status; - FPU_REG sum; - int quadrant = st1_ptr->sign | ((FPU_st0_ptr->sign) << 1); - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - /* We use the general purpose arithmetic so we need to save - * these. */ - saved_status = status_word; - saved_control = control_word; - control_word = FULL_PRECISION; - - st1_ptr->sign = FPU_st0_ptr->sign = SIGN_POS; - if (compare(st1_ptr) == COMP_A_lt_B) { - quadrant |= 4; - reg_div(FPU_st0_ptr, st1_ptr, &sum, FULL_PRECISION); - } else - reg_div(st1_ptr, FPU_st0_ptr, &sum, FULL_PRECISION); - - poly_atan(&sum); - - if (quadrant & 4) { - reg_sub(&CONST_PI2, &sum, &sum, FULL_PRECISION); - } - if (quadrant & 2) { - reg_sub(&CONST_PI, &sum, &sum, FULL_PRECISION); - } - if (quadrant & 1) - sum.sign ^= SIGN_POS ^ SIGN_NEG; - - /* All of the basic arithmetic is done now */ - control_word = saved_control; - status_word = saved_status; - - reg_move(&sum, st1_ptr); - } else - if ((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty)) { - stack_underflow_pop(1); - return; - } else - if ((FPU_st0_tag == TW_NaN) || (st1_tag == TW_NaN)) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } else - if ((FPU_st0_tag == TW_Infinity) || (st1_tag == TW_Infinity)) { - char sign = st1_ptr->sign; - if (FPU_st0_tag == TW_Infinity) { - if (st1_tag == TW_Infinity) { - if (FPU_st0_ptr->sign == SIGN_POS) { - reg_move(&CONST_PI4, st1_ptr); - } else - reg_add(&CONST_PI4, &CONST_PI2, st1_ptr, FULL_PRECISION); - } else { - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign == SIGN_POS) { - reg_move(&CONST_Z, st1_ptr); - pop(); - return; - } else - reg_move(&CONST_PI, st1_ptr); - } - } else { - /* st(1) is infinity, st(0) - * not infinity */ -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - reg_move(&CONST_PI2, st1_ptr); - } - st1_ptr->sign = sign; - } else - if (st1_tag == TW_Zero) { - /* st(0) must be valid or zero */ - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign == SIGN_POS) { - reg_move(&CONST_Z, st1_ptr); - pop(); - return; - } else - reg_move(&CONST_PI, st1_ptr); - st1_ptr->sign = sign; - } else - if (FPU_st0_tag == TW_Zero) { - /* st(1) must be - * TW_Valid here */ - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - reg_move(&CONST_PI2, st1_ptr); - st1_ptr->sign = sign; - } -#ifdef PARANOID - else - EXCEPTION(EX_INTERNAL | 0x220); -#endif /* PARANOID */ - - pop(); - set_precision_flag_up();/* We do not really know if up or down */ -} - - -static void -fprem(void) -{ - fprem_kernel(RC_CHOP); -} - - -static void -fprem1(void) -{ - fprem_kernel(RC_RND); -} - - -static void -fyl2xp1(void) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - int saved_control, saved_status; - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - /* We use the general purpose arithmetic so we need to save - * these. */ - saved_status = status_word; - saved_control = control_word; - control_word = FULL_PRECISION; - - if (poly_l2p1(FPU_st0_ptr, FPU_st0_ptr)) { - arith_invalid(st1_ptr); /* poly_l2p1() returned - * invalid */ - pop(); - return; - } - /* Enough of the basic arithmetic is done now */ - control_word = saved_control; - status_word = saved_status; - - /* Let the multiply set the flags */ - reg_mul(FPU_st0_ptr, st1_ptr, st1_ptr, FULL_PRECISION); - - pop(); - } else - if ((FPU_st0_tag == TW_Empty) | (st1_tag == TW_Empty)) { - stack_underflow_pop(1); - return; - } else - if (FPU_st0_tag == TW_Zero) { - if (st1_tag <= TW_Zero) { - -#ifdef DENORM_OPERAND - if ((st1_tag == TW_Valid) && (st1_ptr->exp <= EXP_UNDER) && - (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - st1_ptr->sign ^= FPU_st0_ptr->sign; - reg_move(FPU_st0_ptr, st1_ptr); - } else - if (st1_tag == TW_Infinity) { - arith_invalid(st1_ptr); /* Infinity*log(1) */ - pop(); - return; - } else - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } -#ifdef PARANOID - else { - EXCEPTION(EX_INTERNAL | 0x116); - return; - } -#endif /* PARANOID */ - pop(); - return; - } else - if (FPU_st0_tag == TW_Valid) { - if (st1_tag == TW_Zero) { - if (FPU_st0_ptr->sign == SIGN_NEG) { - if (FPU_st0_ptr->exp >= EXP_BIAS) { - /* st(0) holds - * <= -1.0 */ - arith_invalid(st1_ptr); /* infinity*log(1) */ - pop(); - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - st1_ptr->sign ^= SIGN_POS ^ SIGN_NEG; - pop(); - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - pop(); - return; - } - if (st1_tag == TW_Infinity) { - if (FPU_st0_ptr->sign == SIGN_NEG) { - if ((FPU_st0_ptr->exp >= EXP_BIAS) && - !((FPU_st0_ptr->sigh == 0x80000000) && - (FPU_st0_ptr->sigl == 0))) { - /* st(0) holds - * < -1.0 */ - arith_invalid(st1_ptr); - pop(); - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - st1_ptr->sign ^= SIGN_POS ^ SIGN_NEG; - pop(); - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - pop(); - return; - } - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } - } else - if (FPU_st0_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } else - if (FPU_st0_tag == TW_Infinity) { - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } else - if ((FPU_st0_ptr->sign == SIGN_NEG) || - (st1_tag == TW_Zero)) { - arith_invalid(st1_ptr); /* log(infinity) */ - pop(); - return; - } - /* st(1) must be valid - * here. */ - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - /* The Manual says - * that log(Infinity) - * is invalid, but a - * real 80486 sensibly - * says that it is - * o.k. */ - { - char sign = st1_ptr->sign; - reg_move(&CONST_INF, st1_ptr); - st1_ptr->sign = sign; - } - pop(); - return; - } -#ifdef PARANOID - else { - EXCEPTION(EX_INTERNAL | 0x117); - } -#endif /* PARANOID */ -} - - -static void -emu_fscale(void) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - int old_cw = control_word; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - long scale; - FPU_REG tmp; - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (st1_ptr->exp > EXP_BIAS + 30) { - /* 2^31 is far too large, would require 2^(2^30) or - * 2^(-2^30) */ - char sign; - - if (st1_ptr->sign == SIGN_POS) { - EXCEPTION(EX_Overflow); - sign = FPU_st0_ptr->sign; - reg_move(&CONST_INF, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - } else { - EXCEPTION(EX_Underflow); - sign = FPU_st0_ptr->sign; - reg_move(&CONST_Z, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - } - return; - } - control_word &= ~CW_RC; - control_word |= RC_CHOP; - reg_move(st1_ptr, &tmp); - round_to_int(&tmp); /* This can never overflow here */ - control_word = old_cw; - scale = st1_ptr->sign ? -tmp.sigl : tmp.sigl; - scale += FPU_st0_ptr->exp; - FPU_st0_ptr->exp = scale; - - /* Use round_reg() to properly detect under/overflow etc */ - round_reg(FPU_st0_ptr, 0, control_word); - - return; - } else - if (FPU_st0_tag == TW_Valid) { - if (st1_tag == TW_Zero) { - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - return; - } - if (st1_tag == TW_Infinity) { - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (sign == SIGN_POS) { - reg_move(&CONST_INF, FPU_st0_ptr); - } else - reg_move(&CONST_Z, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - return; - } - } else - if (FPU_st0_tag == TW_Zero) { - if (st1_tag == TW_Valid) { - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - return; - } else - if (st1_tag == TW_Zero) { - return; - } else - if (st1_tag == TW_Infinity) { - if (st1_ptr->sign == SIGN_NEG) - return; - else { - arith_invalid(FPU_st0_ptr); /* Zero scaled by - * +Infinity */ - return; - } - } else - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - return; - } - } else - if (FPU_st0_tag == TW_Infinity) { - if (st1_tag == TW_Valid) { - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - return; - } - if (((st1_tag == TW_Infinity) && (st1_ptr->sign == SIGN_POS)) - || (st1_tag == TW_Zero)) - return; - else - if (st1_tag == TW_Infinity) { - arith_invalid(FPU_st0_ptr); /* Infinity scaled by - * -Infinity */ - return; - } else - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - return; - } - } else - if (FPU_st0_tag == TW_NaN) { - if (st1_tag != TW_Empty) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - return; - } - } -#ifdef PARANOID - if (!((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty))) { - EXCEPTION(EX_INTERNAL | 0x115); - return; - } -#endif - - /* At least one of st(0), st(1) must be empty */ - stack_underflow(); - -} - - -/*---------------------------------------------------------------------------*/ - -static FUNC trig_table_a[] = { - f2xm1, fyl2x, fptan, fpatan, fxtract, fprem1, fdecstp, fincstp -}; - -void -trig_a(void) -{ - (trig_table_a[FPU_rm]) (); -} - - -static FUNC trig_table_b[] = -{ - fprem, fyl2xp1, fsqrt_, fsincos, frndint_, emu_fscale, fsin, fcos -}; - -void -trig_b(void) -{ - (trig_table_b[FPU_rm]) (); -} diff --git a/sys/gnu/i386/fpemul/get_address.c b/sys/gnu/i386/fpemul/get_address.c deleted file mode 100644 index 4ae998b..0000000 --- a/sys/gnu/i386/fpemul/get_address.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * get_address.c - * - * Get the effective address from an FPU instruction. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ - -#include <sys/param.h> -#include <sys/proc.h> -#include <sys/systm.h> -#include <machine/cpu.h> -#include <machine/pcb.h> -#include <machine/reg.h> - -#include <gnu/i386/fpemul/fpu_emu.h> -#include <gnu/i386/fpemul/fpu_system.h> -#include <gnu/i386/fpemul/exception.h> - -static int reg_offset[] = { -tEAX, tECX, tEDX, tEBX, tESP, tEBP, tESI, tEDI}; -#define REG_(x) (*(((int*)FPU_info) + reg_offset[(x)])) - -void *FPU_data_address; - - -/* Decode the SIB byte. This function assumes mod != 0 */ -static void * -sib(int mod) -{ - unsigned char ss, index, base; - long offset; - - REENTRANT_CHECK(OFF); - base = fubyte((char *) FPU_EIP); /* The SIB byte */ - REENTRANT_CHECK(ON); - FPU_EIP++; - ss = base >> 6; - index = (base >> 3) & 7; - base &= 7; - - if ((mod == 0) && (base == 5)) - offset = 0; /* No base register */ - else - offset = REG_(base); - - if (index == 4) { - /* No index register */ - /* A non-zero ss is illegal */ - if (ss) - EXCEPTION(EX_Invalid); - } else { - offset += (REG_(index)) << ss; - } - - if (mod == 1) { - /* 8 bit signed displacement */ - REENTRANT_CHECK(OFF); - offset += (signed char) fubyte((char *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP++; - } else - if (mod == 2 || base == 5) { /* The second condition also - * has mod==0 */ - /* 32 bit displacment */ - REENTRANT_CHECK(OFF); - offset += (signed) fuword((unsigned long *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP += 4; - } - return (void *) (intptr_t) offset; -} - - -/* - MOD R/M byte: MOD == 3 has a special use for the FPU - SIB byte used iff R/M = 100b - - 7 6 5 4 3 2 1 0 - ..... ......... ......... - MOD OPCODE(2) R/M - - - SIB byte - - 7 6 5 4 3 2 1 0 - ..... ......... ......... - SS INDEX BASE - -*/ - -void -get_address(unsigned char FPU_modrm) -{ - unsigned char mod; - long *cpu_reg_ptr; - int offset = 0; /* Initialized just to stop compiler warnings. */ - - mod = (FPU_modrm >> 6) & 3; - - if (FPU_rm == 4 && mod != 3) { - FPU_data_address = sib(mod); - return; - } - cpu_reg_ptr = (long *) ®_(FPU_rm); - switch (mod) { - case 0: - if (FPU_rm == 5) { - /* Special case: disp32 */ - REENTRANT_CHECK(OFF); - offset = fuword((unsigned long *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP += 4; - FPU_data_address = (void *) offset; - return; - } else { - /* Just return the contents of the cpu register */ - FPU_data_address = (void *) (intptr_t) *cpu_reg_ptr; - return; - } - case 1: - /* 8 bit signed displacement */ - REENTRANT_CHECK(OFF); - offset = (signed char) fubyte((char *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP++; - break; - case 2: - /* 32 bit displacement */ - REENTRANT_CHECK(OFF); - offset = (signed) fuword((unsigned long *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP += 4; - break; - case 3: - /* Not legal for the FPU */ - EXCEPTION(EX_Invalid); - } - - FPU_data_address = (void *) (intptr_t) (offset + *cpu_reg_ptr); -} diff --git a/sys/gnu/i386/fpemul/load_store.c b/sys/gnu/i386/fpemul/load_store.c deleted file mode 100644 index 28e35f4..0000000 --- a/sys/gnu/i386/fpemul/load_store.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * load_store.c - * - * This file contains most of the code to interpret the FPU instructions - * which load and store from user memory. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ - -#include <sys/param.h> -#include <sys/proc.h> -#include <sys/systm.h> -#include <machine/pcb.h> - -#include <gnu/i386/fpemul/fpu_emu.h> -#include <gnu/i386/fpemul/fpu_system.h> -#include <gnu/i386/fpemul/status_w.h> - - -#define _NONE_ 0 /* FPU_st0_ptr etc not needed */ -#define _REG0_ 1 /* Will be storing st(0) */ -#define _PUSH_ 3 /* Need to check for space to push onto stack */ -#define _null_ 4 /* Function illegal or not implemented */ - -#define pop_0() { pop_ptr->tag = TW_Empty; top++; } - - -static unsigned char type_table[32] = { - _PUSH_, _PUSH_, _PUSH_, _PUSH_, - _null_, _null_, _null_, _null_, - _REG0_, _REG0_, _REG0_, _REG0_, - _REG0_, _REG0_, _REG0_, _REG0_, - _NONE_, _null_, _NONE_, _PUSH_, - _NONE_, _PUSH_, _null_, _PUSH_, - _NONE_, _null_, _NONE_, _REG0_, - _NONE_, _REG0_, _NONE_, _REG0_ -}; - -void -load_store_instr(char type) -{ - FPU_REG *pop_ptr; /* We need a version of FPU_st0_ptr which - * won't change. */ - - pop_ptr = NULL; /* Initialized just to stop compiler warnings. */ - - - switch (type_table[(int) (unsigned) type]) { - case _NONE_: - break; - case _REG0_: - pop_ptr = &st(0); /* Some of these instructions pop - * after storing */ - - FPU_st0_ptr = pop_ptr; /* Set the global variables. */ - FPU_st0_tag = FPU_st0_ptr->tag; - break; - case _PUSH_: - { - pop_ptr = &st(-1); - if (pop_ptr->tag != TW_Empty) { - stack_overflow(); - return; - } - top--; - } - break; - case _null_: - Un_impl(); - return; -#ifdef PARANOID - default: - return EXCEPTION(EX_INTERNAL); -#endif /* PARANOID */ - } - - switch (type) { - case 000: /* fld m32real */ - reg_load_single(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 001: /* fild m32int */ - reg_load_int32(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 002: /* fld m64real */ - reg_load_double(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 003: /* fild m16int */ - reg_load_int16(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 010: /* fst m32real */ - reg_store_single(); - break; - case 011: /* fist m32int */ - reg_store_int32(); - break; - case 012: /* fst m64real */ - reg_store_double(); - break; - case 013: /* fist m16int */ - reg_store_int16(); - break; - case 014: /* fstp m32real */ - if (reg_store_single()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 015: /* fistp m32int */ - if (reg_store_int32()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 016: /* fstp m64real */ - if (reg_store_double()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 017: /* fistp m16int */ - if (reg_store_int16()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 020: /* fldenv m14/28byte */ - fldenv(); - break; - case 022: /* frstor m94/108byte */ - frstor(); - break; - case 023: /* fbld m80dec */ - reg_load_bcd(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 024: /* fldcw */ - REENTRANT_CHECK(OFF); - control_word = fuword16((unsigned short *) FPU_data_address); - REENTRANT_CHECK(ON); -#ifdef NO_UNDERFLOW_TRAP - if (!(control_word & EX_Underflow)) { - control_word |= EX_Underflow; - } -#endif - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 025: /* fld m80real */ - reg_load_extended(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 027: /* fild m64int */ - reg_load_int64(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 030: /* fstenv m14/28byte */ - fstenv(); - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 032: /* fsave */ - fsave(); - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 033: /* fbstp m80dec */ - if (reg_store_bcd()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 034: /* fstcw m16int */ - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, FPU_data_address, 2);*/ - suword16( (short *) FPU_data_address,control_word); - REENTRANT_CHECK(ON); - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t ) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 035: /* fstp m80real */ - if (reg_store_extended()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 036: /* fstsw m2byte */ - status_word &= ~SW_Top; - status_word |= (top & 7) << SW_Top_Shift; - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, FPU_data_address, 2);*/ - suword16( (short *) FPU_data_address,status_word); - REENTRANT_CHECK(ON); - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 037: /* fistp m64int */ - if (reg_store_int64()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - } -} diff --git a/sys/gnu/i386/fpemul/math_emu.h b/sys/gnu/i386/fpemul/math_emu.h deleted file mode 100644 index 302be7b..0000000 --- a/sys/gnu/i386/fpemul/math_emu.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * $FreeBSD$ - * - */ - -#ifndef _MATH_EMU_H -#define _MATH_EMU_H - -struct fpu_reg { - char sign; - char tag; - long exp; - u_long sigl; - u_long sigh; -}; - -union i387_union { - struct i387_hard_struct { - long cwd; - long swd; - long twd; - long fip; - long fcs; - long foo; - long fos; - long st_space[20]; /* 8*10 bytes for each FP-reg = 80 - * bytes */ - } hard; - struct i387_soft_struct { - long cwd; - long swd; - long twd; - long fip; - long fcs; - long foo; - long fos; - long top; - struct fpu_reg regs[8]; /* 8*16 bytes for each FP-reg = 128 - * bytes */ - unsigned char lookahead; - struct trapframe *frame; - unsigned long entry_eip; - int orig_eip; - } soft; -}; -#endif diff --git a/sys/gnu/i386/fpemul/poly_2xm1.c b/sys/gnu/i386/fpemul/poly_2xm1.c deleted file mode 100644 index e5a6515..0000000 --- a/sys/gnu/i386/fpemul/poly_2xm1.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * poly_2xm1.c - * - * Function to compute 2^x-1 by a polynomial approximation. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -#include <gnu/i386/fpemul/reg_constant.h> - - - -#define HIPOWER 13 -static unsigned short lterms[HIPOWER][4] = -{ - {0x79b5, 0xd1cf, 0x17f7, 0xb172}, - {0x1b56, 0x058b, 0x7bff, 0x3d7f}, - {0x8bb0, 0x8250, 0x846b, 0x0e35}, - {0xbc65, 0xf747, 0x556d, 0x0276}, - {0x17cb, 0x9e39, 0x61ff, 0x0057}, - {0xe018, 0x9776, 0x1848, 0x000a}, - {0x66f2, 0xff30, 0xffe5, 0x0000}, - {0x682f, 0xffb6, 0x162b, 0x0000}, - {0xb7ca, 0x2956, 0x01b5, 0x0000}, - {0xcd3e, 0x4817, 0x001e, 0x0000}, - {0xb7e2, 0xecbe, 0x0001, 0x0000}, - {0x0ed5, 0x1a27, 0x0000, 0x0000}, - {0x101d, 0x0222, 0x0000, 0x0000}, -}; - - -/*--- poly_2xm1() -----------------------------------------------------------+ - | | - +---------------------------------------------------------------------------*/ -int -poly_2xm1(FPU_REG * arg, FPU_REG * result) -{ - short exponent; - long long Xll; - FPU_REG accum; - - - exponent = arg->exp - EXP_BIAS; - - if (arg->tag == TW_Zero) { - /* Return 0.0 */ - reg_move(&CONST_Z, result); - return 0; - } - if (exponent >= 0) { /* Can't hack a number >= 1.0 */ - arith_invalid(result); /* Number too large */ - return 1; - } - if (arg->sign != SIGN_POS) { /* Can't hack a number < 0.0 */ - arith_invalid(result); /* Number negative */ - return 1; - } - if (exponent < -64) { - reg_move(&CONST_LN2, result); - return 0; - } - *(unsigned *) &Xll = arg->sigl; - *(((unsigned *) &Xll) + 1) = arg->sigh; - if (exponent < -1) { - /* shift the argument right by the required places */ - if (shrx(&Xll, -1 - exponent) >= (unsigned)0x80000000) - Xll++; /* round up */ - } - *(short *) &(accum.sign) = 0; /* will be a valid positive nr with - * expon = 0 */ - accum.exp = 0; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((unsigned *) &accum.sigl, (unsigned *) &Xll, lterms, HIPOWER - 1); - - /* Convert to 64 bit signed-compatible */ - accum.exp += EXP_BIAS - 1; - - reg_move(&accum, result); - - normalize(result); - - return 0; - -} diff --git a/sys/gnu/i386/fpemul/poly_atan.c b/sys/gnu/i386/fpemul/poly_atan.c deleted file mode 100644 index 4f937fb..0000000 --- a/sys/gnu/i386/fpemul/poly_atan.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * p_atan.c - * - * Compute the tan of a FPU_REG, using a polynomial approximation. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -#include <gnu/i386/fpemul/reg_constant.h> -#include <gnu/i386/fpemul/control_w.h> - - -#define HIPOWERon 6 /* odd poly, negative terms */ -static unsigned oddnegterms[HIPOWERon][2] = -{ - {0x00000000, 0x00000000}, /* for + 1.0 */ - {0x763b6f3d, 0x1adc4428}, - {0x20f0630b, 0x0502909d}, - {0x4e825578, 0x0198ce38}, - {0x22b7cb87, 0x008da6e3}, - {0x9b30ca03, 0x00239c79} -}; -#define HIPOWERop 6 /* odd poly, positive terms */ -static unsigned oddplterms[HIPOWERop][2] = -{ - {0xa6f67cb8, 0x94d910bd}, - {0xa02ffab4, 0x0a43cb45}, - {0x04265e6b, 0x02bf5655}, - {0x0a728914, 0x00f280f7}, - {0x6d640e01, 0x004d6556}, - {0xf1dd2dbf, 0x000a530a} -}; - - -static unsigned denomterm[2] = -{0xfc4bd208, 0xea2e6612}; - - -static void poly_add_1(FPU_REG * src); - -/*--- poly_atan() -----------------------------------------------------------+ - | | - +---------------------------------------------------------------------------*/ -void -poly_atan(FPU_REG * arg) -{ - char recursions = 0; - short exponent; - FPU_REG odd_poly, even_poly, pos_poly, neg_poly; - FPU_REG argSq; - long long arg_signif, argSqSq; - - -#ifdef PARANOID - if (arg->sign != 0) { /* Can't hack a number < 0.0 */ - arith_invalid(arg); - return; - } /* Need a positive number */ -#endif /* PARANOID */ - - exponent = arg->exp - EXP_BIAS; - - if (arg->tag == TW_Zero) { - /* Return 0.0 */ - reg_move(&CONST_Z, arg); - return; - } - if (exponent >= -2) { - /* argument is in the range [0.25 .. 1.0] */ - if (exponent >= 0) { -#ifdef PARANOID - if ((exponent == 0) && - (arg->sigl == 0) && (arg->sigh == 0x80000000)) -#endif /* PARANOID */ - { - reg_move(&CONST_PI4, arg); - return; - } -#ifdef PARANOID - EXCEPTION(EX_INTERNAL | 0x104); /* There must be a logic - * error */ -#endif /* PARANOID */ - } - /* If the argument is greater than sqrt(2)-1 (=0.414213562...) */ - /* convert the argument by an identity for atan */ - if ((exponent >= -1) || (arg->sigh > 0xd413ccd0)) { - FPU_REG numerator, denom; - - recursions++; - - arg_signif = *(long long *) &(arg->sigl); - if (exponent < -1) { - if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000) - arg_signif++; /* round up */ - } - *(long long *) &(numerator.sigl) = -arg_signif; - numerator.exp = EXP_BIAS - 1; - normalize(&numerator); /* 1 - arg */ - - arg_signif = *(long long *) &(arg->sigl); - if (shrx(&arg_signif, -exponent) >= (unsigned)0x80000000) - arg_signif++; /* round up */ - *(long long *) &(denom.sigl) = arg_signif; - denom.sigh |= 0x80000000; /* 1 + arg */ - - arg->exp = numerator.exp; - reg_u_div(&numerator, &denom, arg, FULL_PRECISION); - - exponent = arg->exp - EXP_BIAS; - } - } - *(long long *) &arg_signif = *(long long *) &(arg->sigl); - -#ifdef PARANOID - /* This must always be true */ - if (exponent >= -1) { - EXCEPTION(EX_INTERNAL | 0x120); /* There must be a logic error */ - } -#endif /* PARANOID */ - - /* shift the argument right by the required places */ - if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000) - arg_signif++; /* round up */ - - /* Now have arg_signif with binary point at the left .1xxxxxxxx */ - mul64(&arg_signif, &arg_signif, (long long *) (&argSq.sigl)); - mul64((long long *) (&argSq.sigl), (long long *) (&argSq.sigl), &argSqSq); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(pos_poly.sign) = 0; - pos_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &pos_poly.sigl, (unsigned *) &argSqSq, - (unsigned short (*)[4]) oddplterms, HIPOWERop - 1); - mul64((long long *) (&argSq.sigl), (long long *) (&pos_poly.sigl), - (long long *) (&pos_poly.sigl)); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(neg_poly.sign) = 0; - neg_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &neg_poly.sigl, (unsigned *) &argSqSq, - (unsigned short (*)[4]) oddnegterms, HIPOWERon - 1); - - /* Subtract the mantissas */ - *((long long *) (&pos_poly.sigl)) -= *((long long *) (&neg_poly.sigl)); - - reg_move(&pos_poly, &odd_poly); - poly_add_1(&odd_poly); - - /* The complete odd polynomial */ - reg_u_mul(&odd_poly, arg, &odd_poly, FULL_PRECISION); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(even_poly.sign) = 0; - - mul64((long long *) (&argSq.sigl), - (long long *) (&denomterm), (long long *) (&even_poly.sigl)); - - poly_add_1(&even_poly); - - reg_div(&odd_poly, &even_poly, arg, FULL_PRECISION); - - if (recursions) - reg_sub(&CONST_PI4, arg, arg, FULL_PRECISION); -} - - -/* The argument to this function must be polynomial() compatible, - i.e. have an exponent (not checked) of EXP_BIAS-1 but need not - be normalized. - This function adds 1.0 to the (assumed positive) argument. */ -static void -poly_add_1(FPU_REG * src) -{ -/* Rounding in a consistent direction produces better results - for the use of this function in poly_atan. Simple truncation - is used here instead of round-to-nearest. */ - -#ifdef OBSOLETE - char round = (src->sigl & 3) == 3; -#endif /* OBSOLETE */ - - shrx(&src->sigl, 1); - -#ifdef OBSOLETE - if (round) - (*(long long *) &src->sigl)++; /* Round to even */ -#endif /* OBSOLETE */ - - src->sigh |= 0x80000000; - - src->exp = EXP_BIAS; - -} diff --git a/sys/gnu/i386/fpemul/poly_div.s b/sys/gnu/i386/fpemul/poly_div.s deleted file mode 100644 index 505588d..0000000 --- a/sys/gnu/i386/fpemul/poly_div.s +++ /dev/null @@ -1,138 +0,0 @@ - .file "poly_div.S" -/* - * poly_div.S - * - * A set of functions to divide 64 bit integers by fixed numbers. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -#include <gnu/i386/fpemul/fpu_asm.h> - -.text - -/*---------------------------------------------------------------------------*/ -ENTRY(poly_div2) - pushl %ebp - movl %esp,%ebp - - movl PARAM1,%ecx - movw (%ecx),%ax - - shrl $1,4(%ecx) - rcrl $1,(%ecx) - - testw $1,%ax - je poly_div2_exit - - addl $1,(%ecx) - adcl $0,4(%ecx) -poly_div2_exit: - - leave - ret -/*---------------------------------------------------------------------------*/ -ENTRY(poly_div4) - pushl %ebp - movl %esp,%ebp - - movl PARAM1,%ecx - movw (%ecx),%ax - - movl 4(%ecx),%edx - shll $30,%edx - - shrl $2,4(%ecx) - shrl $2,(%ecx) - - orl %edx,(%ecx) - - testw $2,%ax - je poly_div4_exit - - addl $1,(%ecx) - adcl $0,4(%ecx) -poly_div4_exit: - - leave - ret -/*---------------------------------------------------------------------------*/ -ENTRY(poly_div16) - pushl %ebp - movl %esp,%ebp - - movl PARAM1,%ecx - movw (%ecx),%ax - - movl 4(%ecx),%edx - shll $28,%edx - - shrl $4,4(%ecx) - shrl $4,(%ecx) - - orl %edx,(%ecx) - - testw $8,%ax - je poly_div16_exit - - addl $1,(%ecx) - adcl $0,4(%ecx) -poly_div16_exit: - - leave - ret -/*---------------------------------------------------------------------------*/ diff --git a/sys/gnu/i386/fpemul/poly_l2.c b/sys/gnu/i386/fpemul/poly_l2.c deleted file mode 100644 index 19a5501..0000000 --- a/sys/gnu/i386/fpemul/poly_l2.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * poly_l2.c - * - * Compute the base 2 log of a FPU_REG, using a polynomial approximation. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - -#include <gnu/i386/fpemul/reg_constant.h> -#include <gnu/i386/fpemul/control_w.h> - - - -#define HIPOWER 9 -static unsigned short lterms[HIPOWER][4] = -{ - /* Ideal computation with these coeffs gives about 64.6 bit rel - * accuracy. */ - {0xe177, 0xb82f, 0x7652, 0x7154}, - {0xee0f, 0xe80f, 0x2770, 0x7b1c}, - {0x0fc0, 0xbe87, 0xb143, 0x49dd}, - {0x78b9, 0xdadd, 0xec54, 0x34c2}, - {0x003a, 0x5de9, 0x628b, 0x2909}, - {0x5588, 0xed16, 0x4abf, 0x2193}, - {0xb461, 0x85f7, 0x347a, 0x1c6a}, - {0x0975, 0x87b3, 0xd5bf, 0x1876}, - {0xe85c, 0xcec9, 0x84e7, 0x187d} -}; - - - - -/*--- poly_l2() -------------------------------------------------------------+ - | Base 2 logarithm by a polynomial approximation. | - +---------------------------------------------------------------------------*/ -void -poly_l2(FPU_REG * arg, FPU_REG * result) -{ - short exponent; - char zero; /* flag for an Xx == 0 */ - unsigned short bits, shift; - long long Xsq; - FPU_REG accum, denom, num, Xx; - - - exponent = arg->exp - EXP_BIAS; - - accum.tag = TW_Valid; /* set the tags to Valid */ - - if (arg->sigh > (unsigned) 0xb504f334) { - /* This is good enough for the computation of the polynomial - * sum, but actually results in a loss of precision for the - * computation of Xx. This will matter only if exponent - * becomes zero. */ - exponent++; - accum.sign = 1; /* sign to negative */ - num.exp = EXP_BIAS; /* needed to prevent errors in div - * routine */ - reg_u_div(&CONST_1, arg, &num, FULL_PRECISION); - } else { - accum.sign = 0; /* set the sign to positive */ - num.sigl = arg->sigl; /* copy the mantissa */ - num.sigh = arg->sigh; - } - - - /* shift num left, lose the ms bit */ - num.sigh <<= 1; - if (num.sigl & 0x80000000) - num.sigh |= 1; - num.sigl <<= 1; - - denom.sigl = num.sigl; - denom.sigh = num.sigh; - poly_div4((long long *) &(denom.sigl)); - denom.sigh += 0x80000000; /* set the msb */ - Xx.exp = EXP_BIAS; /* needed to prevent errors in div routine */ - reg_u_div(&num, &denom, &Xx, FULL_PRECISION); - - zero = !(Xx.sigh | Xx.sigl); - - mul64((long long *) &Xx.sigl, (long long *) &Xx.sigl, &Xsq); - poly_div16(&Xsq); - - accum.exp = -1; /* exponent of accum */ - - /* Do the basic fixed point polynomial evaluation */ - polynomial((unsigned *) &accum.sigl, (unsigned *) &Xsq, lterms, HIPOWER - 1); - - if (!exponent) { - /* If the exponent is zero, then we would lose precision by - * sticking to fixed point computation here */ - /* We need to re-compute Xx because of loss of precision. */ - FPU_REG lXx; - char sign; - - sign = accum.sign; - accum.sign = 0; - - /* make accum compatible and normalize */ - accum.exp = EXP_BIAS + accum.exp; - normalize(&accum); - - if (zero) { - reg_move(&CONST_Z, result); - } else { - /* we need to re-compute lXx to better accuracy */ - num.tag = TW_Valid; /* set the tags to Vaild */ - num.sign = 0; /* set the sign to positive */ - num.exp = EXP_BIAS - 1; - if (sign) { - /* The argument is of the form 1-x */ - /* Use 1-1/(1-x) = x/(1-x) */ - *((long long *) &num.sigl) = -*((long long *) &(arg->sigl)); - normalize(&num); - reg_div(&num, arg, &num, FULL_PRECISION); - } else { - normalize(&num); - } - - denom.tag = TW_Valid; /* set the tags to Valid */ - denom.sign = SIGN_POS; /* set the sign to positive */ - denom.exp = EXP_BIAS; - - reg_div(&num, &denom, &lXx, FULL_PRECISION); - - reg_u_mul(&lXx, &accum, &accum, FULL_PRECISION); - - reg_u_add(&lXx, &accum, result, FULL_PRECISION); - - normalize(result); - } - - result->sign = sign; - return; - } - mul64((long long *) &accum.sigl, - (long long *) &Xx.sigl, (long long *) &accum.sigl); - - *((long long *) (&accum.sigl)) += *((long long *) (&Xx.sigl)); - - if (Xx.sigh > accum.sigh) { - /* There was an overflow */ - - poly_div2((long long *) &accum.sigl); - accum.sigh |= 0x80000000; - accum.exp++; - } - /* When we add the exponent to the accum result later, we will require - * that their signs are the same. Here we ensure that this is so. */ - if (exponent && ((exponent < 0) ^ (accum.sign))) { - /* signs are different */ - - accum.sign = !accum.sign; - - /* An exceptional case is when accum is zero */ - if (accum.sigl | accum.sigh) { - /* find 1-accum */ - /* Shift to get exponent == 0 */ - if (accum.exp < 0) { - poly_div2((long long *) &accum.sigl); - accum.exp++; - } - /* Just negate, but throw away the sign */ - *((long long *) &(accum.sigl)) = -*((long long *) &(accum.sigl)); - if (exponent < 0) - exponent++; - else - exponent--; - } - } - shift = exponent >= 0 ? exponent : -exponent; - bits = 0; - if (shift) { - if (accum.exp) { - accum.exp++; - poly_div2((long long *) &accum.sigl); - } - while (shift) { - poly_div2((long long *) &accum.sigl); - if (shift & 1) - accum.sigh |= 0x80000000; - shift >>= 1; - bits++; - } - } - /* Convert to 64 bit signed-compatible */ - accum.exp += bits + EXP_BIAS - 1; - - reg_move(&accum, result); - normalize(result); - - return; -} - - -/*--- poly_l2p1() -----------------------------------------------------------+ - | Base 2 logarithm by a polynomial approximation. | - | log2(x+1) | - +---------------------------------------------------------------------------*/ -int -poly_l2p1(FPU_REG * arg, FPU_REG * result) -{ - char sign = 0; - long long Xsq; - FPU_REG arg_pl1, denom, accum, local_arg, poly_arg; - - - sign = arg->sign; - - reg_add(arg, &CONST_1, &arg_pl1, FULL_PRECISION); - - if ((arg_pl1.sign) | (arg_pl1.tag)) { /* We need a valid positive - * number! */ - return 1; - } - reg_add(&CONST_1, &arg_pl1, &denom, FULL_PRECISION); - reg_div(arg, &denom, &local_arg, FULL_PRECISION); - local_arg.sign = 0; /* Make the sign positive */ - - /* Now we need to check that |local_arg| is less than 3-2*sqrt(2) = - * 0.17157.. = .0xafb0ccc0 * 2^-2 */ - - if (local_arg.exp >= EXP_BIAS - 3) { - if ((local_arg.exp > EXP_BIAS - 3) || - (local_arg.sigh > (unsigned) 0xafb0ccc0)) { - /* The argument is large */ - poly_l2(&arg_pl1, result); - return 0; - } - } - /* Make a copy of local_arg */ - reg_move(&local_arg, &poly_arg); - - /* Get poly_arg bits aligned as required */ - shrx((unsigned *) &(poly_arg.sigl), -(poly_arg.exp - EXP_BIAS + 3)); - - mul64((long long *) &(poly_arg.sigl), (long long *) &(poly_arg.sigl), &Xsq); - poly_div16(&Xsq); - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &accum.sigl, (unsigned *) &Xsq, lterms, HIPOWER - 1); - - accum.tag = TW_Valid; /* set the tags to Valid */ - accum.sign = SIGN_POS; /* and make accum positive */ - - /* make accum compatible and normalize */ - accum.exp = EXP_BIAS - 1; - normalize(&accum); - - reg_u_mul(&local_arg, &accum, &accum, FULL_PRECISION); - - reg_u_add(&local_arg, &accum, result, FULL_PRECISION); - - /* Multiply the result by 2 */ - result->exp++; - - result->sign = sign; - - return 0; -} diff --git a/sys/gnu/i386/fpemul/poly_mul64.s b/sys/gnu/i386/fpemul/poly_mul64.s deleted file mode 100644 index 2c6f12e..0000000 --- a/sys/gnu/i386/fpemul/poly_mul64.s +++ /dev/null @@ -1,122 +0,0 @@ -/* - * poly_mul64.S - * - * Multiply two 64 bit integers. - * - * Call from C as: - * void mul64(long long *a, long long *b, long long *result) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - -#include <gnu/i386/fpemul/fpu_asm.h> - -.text -ENTRY(mul64) - pushl %ebp - movl %esp,%ebp - subl $16,%esp - pushl %esi - pushl %ebx - - movl PARAM1,%esi - movl PARAM2,%ecx - movl PARAM3,%ebx - - xor %eax,%eax - movl %eax,-4(%ebp) - movl %eax,-8(%ebp) - - movl (%esi),%eax - mull (%ecx) - movl %eax,-16(%ebp) /* Not used */ - movl %edx,-12(%ebp) - - movl (%esi),%eax - mull 4(%ecx) - addl %eax,-12(%ebp) - adcl %edx,-8(%ebp) - adcl $0,-4(%ebp) - - movl 4(%esi),%eax - mull (%ecx) - addl %eax,-12(%ebp) - adcl %edx,-8(%ebp) - adcl $0,-4(%ebp) - - movl 4(%esi),%eax - mull 4(%ecx) - addl %eax,-8(%ebp) - adcl %edx,-4(%ebp) - - testb $128,-9(%ebp) - je L_no_round - - addl $1,-8(%ebp) - adcl $0,-4(%ebp) - -L_no_round: - movl -8(%ebp),%esi - movl %esi,(%ebx) - movl -4(%ebp),%esi - movl %esi,4(%ebx) - - popl %ebx - popl %esi - leave - ret diff --git a/sys/gnu/i386/fpemul/poly_sin.c b/sys/gnu/i386/fpemul/poly_sin.c deleted file mode 100644 index efc478f..0000000 --- a/sys/gnu/i386/fpemul/poly_sin.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * poly_sin.c - * - * Computation of an approximation of the sin function by a polynomial - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -#ifdef DEBUG -#include <sys/types.h> -#include <sys/systm.h> /* for printf() in EXCEPTION() */ -#endif - -#include <gnu/i386/fpemul/exception.h> -#include <gnu/i386/fpemul/reg_constant.h> -#include <gnu/i386/fpemul/control_w.h> - - -#define HIPOWER 5 -static unsigned short lterms[HIPOWER][4] = -{ - {0x846a, 0x42d1, 0xb544, 0x921f}, - {0xe110, 0x75aa, 0xbc67, 0x1466}, - {0x503d, 0xa43f, 0x83c1, 0x000a}, - {0x8f9d, 0x7a19, 0x00f4, 0x0000}, - {0xda03, 0x06aa, 0x0000, 0x0000}, -}; - -static unsigned short negterms[HIPOWER][4] = -{ - {0x95ed, 0x2df2, 0xe731, 0xa55d}, - {0xd159, 0xe62b, 0xd2cc, 0x0132}, - {0x6342, 0xe9fb, 0x3c60, 0x0000}, - {0x6256, 0xdf5a, 0x0002, 0x0000}, - {0xf279, 0x000b, 0x0000, 0x0000}, -}; - - -/*--- poly_sine() -----------------------------------------------------------+ - | | - +---------------------------------------------------------------------------*/ -void -poly_sine(FPU_REG * arg, FPU_REG * result) -{ - short exponent; - FPU_REG Xx, Xx2, Xx4, accum, negaccum; - - - exponent = arg->exp - EXP_BIAS; - - if (arg->tag == TW_Zero) { - /* Return 0.0 */ - reg_move(&CONST_Z, result); - return; - } -#ifdef PARANOID - if (arg->sign != 0) { /* Can't hack a number < 0.0 */ - EXCEPTION(EX_Invalid); - reg_move(&CONST_QNaN, result); - return; - } - if (exponent >= 0) { /* Can't hack a number > 1.0 */ - if ((exponent == 0) && (arg->sigl == 0) && (arg->sigh == 0x80000000)) { - reg_move(&CONST_1, result); - return; - } - EXCEPTION(EX_Invalid); - reg_move(&CONST_QNaN, result); - return; - } -#endif /* PARANOID */ - - Xx.sigl = arg->sigl; - Xx.sigh = arg->sigh; - if (exponent < -1) { - /* shift the argument right by the required places */ - if (shrx(&(Xx.sigl), -1 - exponent) >= (unsigned)0x80000000) - (*((long long *) (&(Xx.sigl))))++; /* round up */ - } - mul64((long long *) &(Xx.sigl), (long long *) &(Xx.sigl), - (long long *) &(Xx2.sigl)); - mul64((long long *) &(Xx2.sigl), (long long *) &(Xx2.sigl), - (long long *) &(Xx4.sigl)); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(accum.sign) = 0; - accum.exp = 0; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &(accum.sigl), (u_int *)&(Xx4.sigl), lterms, HIPOWER - 1); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(negaccum.sign) = 0; - negaccum.exp = 0; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &(negaccum.sigl), (u_int *)&(Xx4.sigl), negterms, HIPOWER - 1); - mul64((long long *) &(Xx2.sigl), (long long *) &(negaccum.sigl), - (long long *) &(negaccum.sigl)); - - /* Subtract the mantissas */ - *((long long *) (&(accum.sigl))) -= *((long long *) (&(negaccum.sigl))); - - /* Convert to 64 bit signed-compatible */ - accum.exp = EXP_BIAS - 1 + accum.exp; - - *(short *) &(result->sign) = *(short *) &(accum.sign); - result->exp = accum.exp; - result->sigl = accum.sigl; - result->sigh = accum.sigh; - - normalize(result); - - reg_mul(result, arg, result, FULL_PRECISION); - reg_u_add(result, arg, result, FULL_PRECISION); - - /* A small overflow may be possible... but an illegal result. */ - if (result->exp >= EXP_BIAS) { - if ((result->exp > EXP_BIAS) /* Larger or equal 2.0 */ - ||(result->sigl > 1) /* Larger than 1.0+msb */ - ||(result->sigh != 0x80000000) /* Much > 1.0 */ - ) { -#ifdef DEBUGGING - RE_ENTRANT_CHECK_OFF - printk("\nEXP=%d, MS=%08x, LS=%08x\n", result->exp, - result->sigh, result->sigl); - RE_ENTRANT_CHECK_ON -#endif /* DEBUGGING */ - EXCEPTION(EX_INTERNAL | 0x103); - } -#ifdef DEBUGGING - RE_ENTRANT_CHECK_OFF - printk("\n***CORRECTING ILLEGAL RESULT*** in poly_sin() computation\n"); - printk("EXP=%d, MS=%08x, LS=%08x\n", result->exp, - result->sigh, result->sigl); - RE_ENTRANT_CHECK_ON -#endif /* DEBUGGING */ - - result->sigl = 0; /* Truncate the result to 1.00 */ - } -} diff --git a/sys/gnu/i386/fpemul/poly_tan.c b/sys/gnu/i386/fpemul/poly_tan.c deleted file mode 100644 index 7dbbddf..0000000 --- a/sys/gnu/i386/fpemul/poly_tan.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * poly_tan.c - * - * Compute the tan of a FPU_REG, using a polynomial approximation. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -#include <gnu/i386/fpemul/reg_constant.h> -#include <gnu/i386/fpemul/control_w.h> - - -#define HIPOWERop 3 /* odd poly, positive terms */ -static unsigned short oddplterms[HIPOWERop][4] = -{ - {0x846a, 0x42d1, 0xb544, 0x921f}, - {0x6fb2, 0x0215, 0x95c0, 0x099c}, - {0xfce6, 0x0cc8, 0x1c9a, 0x0000} -}; -#define HIPOWERon 2 /* odd poly, negative terms */ -static unsigned short oddnegterms[HIPOWERon][4] = -{ - {0x6906, 0xe205, 0x25c8, 0x8838}, - {0x1dd7, 0x3fe3, 0x944e, 0x002c} -}; -#define HIPOWERep 2 /* even poly, positive terms */ -static unsigned short evenplterms[HIPOWERep][4] = -{ - {0xdb8f, 0x3761, 0x1432, 0x2acf}, - {0x16eb, 0x13c1, 0x3099, 0x0003} -}; -#define HIPOWERen 2 /* even poly, negative terms */ -static unsigned short evennegterms[HIPOWERen][4] = -{ - {0x3a7c, 0xe4c5, 0x7f87, 0x2945}, - {0x572b, 0x664c, 0xc543, 0x018c} -}; - - -/*--- poly_tan() ------------------------------------------------------------+ - | | - +---------------------------------------------------------------------------*/ -void -poly_tan(FPU_REG * arg, FPU_REG * y_reg) -{ - char invert = 0; - short exponent; - FPU_REG odd_poly, even_poly, pos_poly, neg_poly; - FPU_REG argSq; - long long arg_signif, argSqSq; - - - exponent = arg->exp - EXP_BIAS; - - if (arg->tag == TW_Zero) { - /* Return 0.0 */ - reg_move(&CONST_Z, y_reg); - return; - } - if (exponent >= -1) { - /* argument is in the range [0.5 .. 1.0] */ - if (exponent >= 0) { -#ifdef PARANOID - if ((exponent == 0) && - (arg->sigl == 0) && (arg->sigh == 0x80000000)) -#endif /* PARANOID */ - { - arith_overflow(y_reg); - return; - } -#ifdef PARANOID - EXCEPTION(EX_INTERNAL | 0x104); /* There must be a logic - * error */ - return; -#endif /* PARANOID */ - } - /* The argument is in the range [0.5 .. 1.0) */ - /* Convert the argument to a number in the range (0.0 .. 0.5] */ - *((long long *) (&arg->sigl)) = -*((long long *) (&arg->sigl)); - normalize(arg); /* Needed later */ - exponent = arg->exp - EXP_BIAS; - invert = 1; - } -#ifdef PARANOID - if (arg->sign != 0) { /* Can't hack a number < 0.0 */ - arith_invalid(y_reg); - return; - } /* Need a positive number */ -#endif /* PARANOID */ - - *(long long *) &arg_signif = *(long long *) &(arg->sigl); - if (exponent < -1) { - /* shift the argument right by the required places */ - if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000) - arg_signif++; /* round up */ - } - mul64(&arg_signif, &arg_signif, (long long *) (&argSq.sigl)); - mul64((long long *) (&argSq.sigl), (long long *) (&argSq.sigl), &argSqSq); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(pos_poly.sign) = 0; - pos_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &pos_poly.sigl, (unsigned *) &argSqSq, oddplterms, HIPOWERop - 1); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(neg_poly.sign) = 0; - neg_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &neg_poly.sigl, (unsigned *) &argSqSq, oddnegterms, HIPOWERon - 1); - mul64((long long *) (&argSq.sigl), (long long *) (&neg_poly.sigl), - (long long *) (&neg_poly.sigl)); - - /* Subtract the mantissas */ - *((long long *) (&pos_poly.sigl)) -= *((long long *) (&neg_poly.sigl)); - - /* Convert to 64 bit signed-compatible */ - pos_poly.exp -= 1; - - reg_move(&pos_poly, &odd_poly); - normalize(&odd_poly); - - reg_mul(&odd_poly, arg, &odd_poly, FULL_PRECISION); - reg_u_add(&odd_poly, arg, &odd_poly, FULL_PRECISION); /* This is just the odd - * polynomial */ - - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(pos_poly.sign) = 0; - pos_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &pos_poly.sigl, (unsigned *) &argSqSq, evenplterms, HIPOWERep - 1); - mul64((long long *) (&argSq.sigl), - (long long *) (&pos_poly.sigl), (long long *) (&pos_poly.sigl)); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(neg_poly.sign) = 0; - neg_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &neg_poly.sigl, (unsigned *) &argSqSq, evennegterms, HIPOWERen - 1); - - /* Subtract the mantissas */ - *((long long *) (&neg_poly.sigl)) -= *((long long *) (&pos_poly.sigl)); - /* and multiply by argSq */ - - /* Convert argSq to a valid reg number */ - *(short *) &(argSq.sign) = 0; - argSq.exp = EXP_BIAS - 1; - normalize(&argSq); - - /* Convert to 64 bit signed-compatible */ - neg_poly.exp -= 1; - - reg_move(&neg_poly, &even_poly); - normalize(&even_poly); - - reg_mul(&even_poly, &argSq, &even_poly, FULL_PRECISION); - reg_add(&even_poly, &argSq, &even_poly, FULL_PRECISION); - reg_sub(&CONST_1, &even_poly, &even_poly, FULL_PRECISION); /* This is just the even - * polynomial */ - - /* Now ready to copy the results */ - if (invert) { - reg_div(&even_poly, &odd_poly, y_reg, FULL_PRECISION); - } else { - reg_div(&odd_poly, &even_poly, y_reg, FULL_PRECISION); - } - -} diff --git a/sys/gnu/i386/fpemul/polynomial.s b/sys/gnu/i386/fpemul/polynomial.s deleted file mode 100644 index 785c716..0000000 --- a/sys/gnu/i386/fpemul/polynomial.s +++ /dev/null @@ -1,190 +0,0 @@ -/* - * polynomial.S - * - * Fixed point arithmetic polynomial evaluation. - * - * Call from C as: - * void polynomial(unsigned accum[], unsigned x[], unsigned terms[][2], - * int n) - * - * Computes: - * terms[0] + (terms[1] + (terms[2] + ... + (terms[n-1]*x)*x)*x)*x) ... )*x - * The result is returned in accum. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - .file "fpolynom.s" - -#include <gnu/i386/fpemul/fpu_asm.h> - - -/* #define EXTRA_PRECISE*/ - -#define TERM_SIZE $8 - - -.text -ENTRY(polynomial) - pushl %ebp - movl %esp,%ebp - subl $32,%esp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi /* accum */ - movl PARAM2,%edi /* x */ - movl PARAM3,%ebx /* terms */ - movl PARAM4,%ecx /* n */ - - movl TERM_SIZE,%eax - mull %ecx - movl %eax,%ecx - - movl 4(%ebx,%ecx,1),%edx /* terms[n] */ - movl %edx,-20(%ebp) - movl (%ebx,%ecx,1),%edx /* terms[n] */ - movl %edx,-24(%ebp) - xor %eax,%eax - movl %eax,-28(%ebp) - - subl TERM_SIZE,%ecx - js L_accum_done - -L_accum_loop: - xor %eax,%eax - movl %eax,-4(%ebp) - movl %eax,-8(%ebp) - -#ifdef EXTRA_PRECISE - movl -28(%ebp),%eax - mull 4(%edi) /* x ms long */ - movl %edx,-12(%ebp) -#endif /* EXTRA_PRECISE */ - - movl -24(%ebp),%eax - mull (%edi) /* x ls long */ -/* movl %eax,-16(%ebp) */ /* Not needed */ - addl %edx,-12(%ebp) - adcl $0,-8(%ebp) - - movl -24(%ebp),%eax - mull 4(%edi) /* x ms long */ - addl %eax,-12(%ebp) - adcl %edx,-8(%ebp) - adcl $0,-4(%ebp) - - movl -20(%ebp),%eax - mull (%edi) - addl %eax,-12(%ebp) - adcl %edx,-8(%ebp) - adcl $0,-4(%ebp) - - movl -20(%ebp),%eax - mull 4(%edi) - addl %eax,-8(%ebp) - adcl %edx,-4(%ebp) - -/* Now add the next term */ - movl (%ebx,%ecx,1),%eax - addl %eax,-8(%ebp) - movl 4(%ebx,%ecx,1),%eax - adcl %eax,-4(%ebp) - -/* And put into the second register */ - movl -4(%ebp),%eax - movl %eax,-20(%ebp) - movl -8(%ebp),%eax - movl %eax,-24(%ebp) - -#ifdef EXTRA_PRECISE - movl -12(%ebp),%eax - movl %eax,-28(%ebp) -#else - testb $128,-25(%ebp) - je L_no_poly_round - - addl $1,-24(%ebp) - adcl $0,-20(%ebp) -L_no_poly_round: -#endif /* EXTRA_PRECISE */ - - subl TERM_SIZE,%ecx - jns L_accum_loop - -L_accum_done: -#ifdef EXTRA_PRECISE -/* And round the result */ - testb $128,-25(%ebp) - je L_poly_done - - addl $1,-24(%ebp) - adcl $0,-20(%ebp) -#endif /* EXTRA_PRECISE */ - -L_poly_done: - movl -24(%ebp),%eax - movl %eax,(%esi) - movl -20(%ebp),%eax - movl %eax,4(%esi) - - popl %ebx - popl %edi - popl %esi - leave - ret diff --git a/sys/gnu/i386/fpemul/reg_add_sub.c b/sys/gnu/i386/fpemul/reg_add_sub.c deleted file mode 100644 index df08bcd..0000000 --- a/sys/gnu/i386/fpemul/reg_add_sub.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * reg_add_sub.c - * - * Functions to add or subtract two registers and put the result in a third. - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -/*---------------------------------------------------------------------------+ - | For each function, the destination may be any FPU_REG, including one of | - | the source FPU_REGs. | - +---------------------------------------------------------------------------*/ - -#include <gnu/i386/fpemul/reg_constant.h> -#include <gnu/i386/fpemul/control_w.h> - - -void -reg_add(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w) -{ - int diff; - - if (!(a->tag | b->tag)) { - /* Both registers are valid */ - if (!(a->sign ^ b->sign)) { - /* signs are the same */ - reg_u_add(a, b, dest, control_w); - dest->sign = a->sign; - return; - } - /* The signs are different, so do a subtraction */ - diff = a->exp - b->exp; - if (!diff) { - diff = a->sigh - b->sigh; /* Works only if ms bits - * are identical */ - if (!diff) { - diff = a->sigl > b->sigl; - if (!diff) - diff = -(a->sigl < b->sigl); - } - } - if (diff > 0) { - reg_u_sub(a, b, dest, control_w); - dest->sign = a->sign; - } else - if (diff == 0) { - reg_move(&CONST_Z, dest); - /* sign depends upon rounding mode */ - dest->sign = ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG; - } else { - reg_u_sub(b, a, dest, control_w); - dest->sign = b->sign; - } - return; - } else { - if ((a->tag == TW_NaN) || (b->tag == TW_NaN)) { - real_2op_NaN(a, b, dest); - return; - } else - if (a->tag == TW_Zero) { - if (b->tag == TW_Zero) { - char different_signs = a->sign ^ b->sign; - /* Both are zero, result will be zero. */ - reg_move(a, dest); - if (different_signs) { - /* Signs are different. */ - /* Sign of answer depends upon - * rounding mode. */ - dest->sign = ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG; - } - } else { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - } - return; - } else - if (b->tag == TW_Zero) { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - return; - } else - if (a->tag == TW_Infinity) { - if (b->tag != TW_Infinity) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - return; - } - if (a->sign == b->sign) { - /* They are both + or - * - infinity */ - reg_move(a, dest); - return; - } - arith_invalid(dest); /* Infinity-Infinity is - * undefined. */ - return; - } else - if (b->tag == TW_Infinity) { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - return; - } - } -#ifdef PARANOID - EXCEPTION(EX_INTERNAL | 0x101); -#endif -} - - -/* Subtract b from a. (a-b) -> dest */ -void -reg_sub(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w) -{ - int diff; - - if (!(a->tag | b->tag)) { - /* Both registers are valid */ - diff = a->exp - b->exp; - if (!diff) { - diff = a->sigh - b->sigh; /* Works only if ms bits - * are identical */ - if (!diff) { - diff = a->sigl > b->sigl; - if (!diff) - diff = -(a->sigl < b->sigl); - } - } - switch (a->sign * 2 + b->sign) { - case 0: /* P - P */ - case 3: /* N - N */ - if (diff > 0) { - reg_u_sub(a, b, dest, control_w); - dest->sign = a->sign; - } else - if (diff == 0) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(&CONST_Z, dest); - /* sign depends upon rounding mode */ - dest->sign = ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG; - } else { - reg_u_sub(b, a, dest, control_w); - dest->sign = a->sign ^ SIGN_POS ^ SIGN_NEG; - } - return; - case 1: /* P - N */ - reg_u_add(a, b, dest, control_w); - dest->sign = SIGN_POS; - return; - case 2: /* N - P */ - reg_u_add(a, b, dest, control_w); - dest->sign = SIGN_NEG; - return; - } - } else { - if ((a->tag == TW_NaN) || (b->tag == TW_NaN)) { - real_2op_NaN(a, b, dest); - return; - } else - if (b->tag == TW_Zero) { - if (a->tag == TW_Zero) { - char same_signs = !(a->sign ^ b->sign); - /* Both are zero, result will be zero. */ - reg_move(a, dest); /* Answer for different - * signs. */ - if (same_signs) { - /* Sign depends upon rounding - * mode */ - dest->sign = ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG; - } - } else { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - } - return; - } else - if (a->tag == TW_Zero) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - dest->sign ^= SIGN_POS ^ SIGN_NEG; - return; - } else - if (a->tag == TW_Infinity) { - if (b->tag != TW_Infinity) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - return; - } - /* Both args are Infinity */ - if (a->sign == b->sign) { - arith_invalid(dest); /* Infinity-Infinity is - * undefined. */ - return; - } - reg_move(a, dest); - return; - } else - if (b->tag == TW_Infinity) { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - dest->sign ^= SIGN_POS ^ SIGN_NEG; - return; - } - } -#ifdef PARANOID - EXCEPTION(EX_INTERNAL | 0x110); -#endif -} diff --git a/sys/gnu/i386/fpemul/reg_compare.c b/sys/gnu/i386/fpemul/reg_compare.c deleted file mode 100644 index a23a7a5..0000000 --- a/sys/gnu/i386/fpemul/reg_compare.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * reg_compare.c - * - * Compare two floating point registers - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -/*---------------------------------------------------------------------------+ - | compare() is the core FPU_REG comparison function | - +---------------------------------------------------------------------------*/ -#include <sys/param.h> -#include <sys/proc.h> -#include <sys/systm.h> -#include <machine/pcb.h> - -#include <gnu/i386/fpemul/fpu_emu.h> -#include <gnu/i386/fpemul/fpu_system.h> -#include <gnu/i386/fpemul/exception.h> -#include <gnu/i386/fpemul/control_w.h> -#include <gnu/i386/fpemul/status_w.h> - - -int -compare(FPU_REG * b) -{ - int diff; - - if (FPU_st0_ptr->tag | b->tag) { - if (FPU_st0_ptr->tag == TW_Zero) { - if (b->tag == TW_Zero) - return COMP_A_eq_B; - if (b->tag == TW_Valid) { -#ifdef DENORM_OPERAND - if ((b->exp <= EXP_UNDER) && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - return (b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B; - } - } else - if (b->tag == TW_Zero) { - if (FPU_st0_ptr->tag == TW_Valid) { -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B; - } - } - if (FPU_st0_ptr->tag == TW_Infinity) { - if ((b->tag == TW_Valid) || (b->tag == TW_Zero)) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) - && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B; - } else - if (b->tag == TW_Infinity) { - /* The 80486 book says that infinities - * can be equal! */ - return (FPU_st0_ptr->sign == b->sign) ? COMP_A_eq_B : - ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B); - } - /* Fall through to the NaN code */ - } else - if (b->tag == TW_Infinity) { - if ((FPU_st0_ptr->tag == TW_Valid) || (FPU_st0_ptr->tag == TW_Zero)) { -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->tag == TW_Valid) - && (FPU_st0_ptr->exp <= EXP_UNDER) - && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - return (b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B; - } - /* Fall through to the NaN code */ - } - /* The only possibility now should be that one of the - * arguments is a NaN */ - if ((FPU_st0_ptr->tag == TW_NaN) || (b->tag == TW_NaN)) { - if (((FPU_st0_ptr->tag == TW_NaN) && !(FPU_st0_ptr->sigh & 0x40000000)) - || ((b->tag == TW_NaN) && !(b->sigh & 0x40000000))) - /* At least one arg is a signaling NaN */ - return COMP_No_Comp | COMP_SNaN | COMP_NaN; - else - /* Neither is a signaling NaN */ - return COMP_No_Comp | COMP_NaN; - } - EXCEPTION(EX_Invalid); - } -#ifdef PARANOID - if (!(FPU_st0_ptr->sigh & 0x80000000)) - EXCEPTION(EX_Invalid); - if (!(b->sigh & 0x80000000)) - EXCEPTION(EX_Invalid); -#endif /* PARANOID */ - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (b->exp <= EXP_UNDER)) && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign != b->sign) - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B; - - diff = FPU_st0_ptr->exp - b->exp; - if (diff == 0) { - diff = FPU_st0_ptr->sigh - b->sigh; /* Works only if ms bits - * are identical */ - if (diff == 0) { - diff = FPU_st0_ptr->sigl > b->sigl; - if (diff == 0) - diff = -(FPU_st0_ptr->sigl < b->sigl); - } - } - if (diff > 0) - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B; - if (diff < 0) - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B; - return COMP_A_eq_B; - -} - - -/* This function requires that st(0) is not empty */ -int -compare_st_data(void) -{ - int f = 0, c; - - c = compare(&FPU_loaded_data); - - if (c & (COMP_NaN | COMP_Denormal)) { - if (c & COMP_NaN) { - EXCEPTION(EX_Invalid); - f = SW_C3 | SW_C2 | SW_C0; - } else { - /* One of the operands is a de-normal */ - return 0; - } - } else - switch (c) { - case COMP_A_lt_B: - f = SW_C0; - break; - case COMP_A_eq_B: - f = SW_C3; - break; - case COMP_A_gt_B: - f = 0; - break; - case COMP_No_Comp: - f = SW_C3 | SW_C2 | SW_C0; - break; -#ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL | 0x121); - f = SW_C3 | SW_C2 | SW_C0; - break; -#endif /* PARANOID */ - } - setcc(f); - return 1; -} - - -static int -compare_st_st(int nr) -{ - int f = 0, c; - - if (!NOT_EMPTY_0 || !NOT_EMPTY(nr)) { - setcc(SW_C3 | SW_C2 | SW_C0); - /* Stack fault */ - EXCEPTION(EX_StackUnder); - return control_word & CW_Invalid; - } - c = compare(&st(nr)); - if (c & (COMP_NaN | COMP_Denormal)) { - if (c & COMP_NaN) { - setcc(SW_C3 | SW_C2 | SW_C0); - EXCEPTION(EX_Invalid); - return control_word & CW_Invalid; - } else { - /* One of the operands is a de-normal */ - return control_word & CW_Denormal; - } - } else - switch (c) { - case COMP_A_lt_B: - f = SW_C0; - break; - case COMP_A_eq_B: - f = SW_C3; - break; - case COMP_A_gt_B: - f = 0; - break; - case COMP_No_Comp: - f = SW_C3 | SW_C2 | SW_C0; - break; -#ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL | 0x122); - f = SW_C3 | SW_C2 | SW_C0; - break; -#endif /* PARANOID */ - } - setcc(f); - return 1; -} - - -static int -compare_u_st_st(int nr) -{ - int f = 0, c; - - if (!NOT_EMPTY_0 || !NOT_EMPTY(nr)) { - setcc(SW_C3 | SW_C2 | SW_C0); - /* Stack fault */ - EXCEPTION(EX_StackUnder); - return control_word & CW_Invalid; - } - c = compare(&st(nr)); - if (c & (COMP_NaN | COMP_Denormal)) { - if (c & COMP_NaN) { - setcc(SW_C3 | SW_C2 | SW_C0); - if (c & COMP_SNaN) { /* This is the only difference - * between un-ordered and - * ordinary comparisons */ - EXCEPTION(EX_Invalid); - return control_word & CW_Invalid; - } - return 1; - } else { - /* One of the operands is a de-normal */ - return control_word & CW_Denormal; - } - } else - switch (c) { - case COMP_A_lt_B: - f = SW_C0; - break; - case COMP_A_eq_B: - f = SW_C3; - break; - case COMP_A_gt_B: - f = 0; - break; - case COMP_No_Comp: - f = SW_C3 | SW_C2 | SW_C0; - break; -#ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL | 0x123); - f = SW_C3 | SW_C2 | SW_C0; - break; -#endif /* PARANOID */ - } - setcc(f); - return 1; -} -/*---------------------------------------------------------------------------*/ - -void -fcom_st() -{ - /* fcom st(i) */ - compare_st_st(FPU_rm); -} - - -void -fcompst() -{ - /* fcomp st(i) */ - if (compare_st_st(FPU_rm)) - pop(); -} - - -void -fcompp() -{ - /* fcompp */ - if (FPU_rm != 1) { - Un_impl(); - return; - } - if (compare_st_st(1)) { - pop(); - FPU_st0_ptr = &st(0); - pop(); - } -} - - -void -fucom_() -{ - /* fucom st(i) */ - compare_u_st_st(FPU_rm); - -} - - -void -fucomp() -{ - /* fucomp st(i) */ - if (compare_u_st_st(FPU_rm)) - pop(); -} - - -void -fucompp() -{ - /* fucompp */ - if (FPU_rm == 1) { - if (compare_u_st_st(1)) { - pop(); - FPU_st0_ptr = &st(0); - pop(); - } - } else - Un_impl(); -} diff --git a/sys/gnu/i386/fpemul/reg_constant.c b/sys/gnu/i386/fpemul/reg_constant.c deleted file mode 100644 index bd16fe4..0000000 --- a/sys/gnu/i386/fpemul/reg_constant.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * reg_constant.c - * - * All of the constant FPU_REGs - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * $FreeBSD$ - */ - - - -#include <sys/param.h> -#include <sys/proc.h> -#include <machine/pcb.h> - -#include <gnu/i386/fpemul/fpu_emu.h> -#include <gnu/i386/fpemul/fpu_system.h> -#include <gnu/i386/fpemul/status_w.h> - - -FPU_REG CONST_1 = {SIGN_POS, TW_Valid, EXP_BIAS, -0x00000000, 0x80000000}; -static FPU_REG CONST_L2T = {SIGN_POS, TW_Valid, EXP_BIAS + 1, -0xcd1b8afe, 0xd49a784b}; -static FPU_REG CONST_L2E = {SIGN_POS, TW_Valid, EXP_BIAS, -0x5c17f0bc, 0xb8aa3b29}; -FPU_REG CONST_PI = {SIGN_POS, TW_Valid, EXP_BIAS + 1, -0x2168c235, 0xc90fdaa2}; -FPU_REG CONST_PI2 = {SIGN_POS, TW_Valid, EXP_BIAS, -0x2168c235, 0xc90fdaa2}; -FPU_REG CONST_PI4 = {SIGN_POS, TW_Valid, EXP_BIAS - 1, -0x2168c235, 0xc90fdaa2}; -static FPU_REG CONST_LG2 = {SIGN_POS, TW_Valid, EXP_BIAS - 2, -0xfbcff799, 0x9a209a84}; -FPU_REG CONST_LN2 = {SIGN_POS, TW_Valid, EXP_BIAS - 1, -0xd1cf79ac, 0xb17217f7}; -/* Only the sign (and tag) is used in internal zeroes */ -FPU_REG CONST_Z = {SIGN_POS, TW_Zero, 0, 0x0, 0x0}; -/* Only the sign and significand (and tag) are used in internal NaNs */ -/* The 80486 never generates one of these -FPU_REG CONST_SNAN = { SIGN_POS, TW_NaN, EXP_OVER, 0x00000001, 0x80000000 }; - */ -/* This is the real indefinite QNaN */ -FPU_REG CONST_QNaN = {SIGN_NEG, TW_NaN, EXP_OVER, 0x00000000, 0xC0000000}; -/* Only the sign (and tag) is used in internal infinities */ -FPU_REG CONST_INF = {SIGN_POS, TW_Infinity, EXP_OVER, 0x00000000, 0x80000000}; - - - -static void -fld_const(FPU_REG * c) -{ - FPU_REG *st_new_ptr; - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - push(); - reg_move(c, FPU_st0_ptr); - status_word &= ~SW_C1; -} - - -static void -fld1(void) -{ - fld_const(&CONST_1); -} - -static void -fldl2t(void) -{ - fld_const(&CONST_L2T); -} - -static void -fldl2e(void) -{ - fld_const(&CONST_L2E); -} - -static void -fldpi(void) -{ - fld_const(&CONST_PI); -} - -static void -fldlg2(void) -{ - fld_const(&CONST_LG2); -} - -static void -fldln2(void) -{ - fld_const(&CONST_LN2); -} - -static void -fldz(void) -{ - fld_const(&CONST_Z); -} - -static FUNC constants_table[] = { - fld1, fldl2t, fldl2e, fldpi, fldlg2, fldln2, fldz, Un_impl -}; - -void -fconst(void) -{ - (constants_table[FPU_rm]) (); -} diff --git a/sys/gnu/i386/fpemul/reg_constant.h b/sys/gnu/i386/fpemul/reg_constant.h deleted file mode 100644 index 6c22cd7..0000000 --- a/sys/gnu/i386/fpemul/reg_constant.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * reg_constant.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -#ifndef _REG_CONSTANT_H_ -#define _REG_CONSTANT_H_ - -#include <gnu/i386/fpemul/fpu_emu.h> - -extern FPU_REG CONST_1; -extern FPU_REG CONST_2; -extern FPU_REG CONST_HALF; -extern FPU_REG CONST_L2T; -extern FPU_REG CONST_L2E; -extern FPU_REG CONST_PI; -extern FPU_REG CONST_PI2; -extern FPU_REG CONST_PI4; -extern FPU_REG CONST_LG2; -extern FPU_REG CONST_LN2; -extern FPU_REG CONST_Z; -extern FPU_REG CONST_PINF; -extern FPU_REG CONST_INF; -extern FPU_REG CONST_MINF; -extern FPU_REG CONST_QNaN; - -#endif /* _REG_CONSTANT_H_ */ diff --git a/sys/gnu/i386/fpemul/reg_div.s b/sys/gnu/i386/fpemul/reg_div.s deleted file mode 100644 index fe799f9..0000000 --- a/sys/gnu/i386/fpemul/reg_div.s +++ /dev/null @@ -1,290 +0,0 @@ - .file "reg_div.S" -/* - * reg_div.S - * - * Divide one FPU_REG by another and put the result in a destination FPU_REG. - * - * Call from C as: - * void reg_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest, - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -#include <gnu/i386/fpemul/fpu_asm.h> - -.text -ENTRY(reg_div) - pushl %ebp - movl %esp,%ebp - - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi - movl PARAM2,%ebx - movl PARAM3,%edi - - movb TAG(%esi),%al - orb TAG(%ebx),%al - - jne L_div_special /* Not (both numbers TW_Valid) */ - -#ifdef DENORM_OPERAND -/* Check for denormals */ - cmpl EXP_UNDER,EXP(%esi) - jg xL_arg1_not_denormal - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xL_arg1_not_denormal: - cmpl EXP_UNDER,EXP(%ebx) - jg xL_arg2_not_denormal - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xL_arg2_not_denormal: -#endif /* DENORM_OPERAND */ - -/* Both arguments are TW_Valid */ - movb TW_Valid,TAG(%edi) - - movb SIGN(%esi),%cl - cmpb %cl,SIGN(%ebx) - setne (%edi) /* Set the sign, requires SIGN_NEG=1, SIGN_POS=0 */ - - movl EXP(%esi),%edx - movl EXP(%ebx),%eax - subl %eax,%edx - addl EXP_BIAS,%edx - movl %edx,EXP(%edi) - - jmp divide_kernel - - -/*-----------------------------------------------------------------------*/ -L_div_special: - cmpb TW_NaN,TAG(%esi) /* A NaN with anything to give NaN */ - je L_arg1_NaN - - cmpb TW_NaN,TAG(%ebx) /* A NaN with anything to give NaN */ - jne L_no_NaN_arg - -/* Operations on NaNs */ -L_arg1_NaN: -L_arg2_NaN: - pushl %edi /* Destination */ - pushl %ebx - pushl %esi - call real_2op_NaN - jmp LDiv_exit - -/* Invalid operations */ -L_zero_zero: -L_inf_inf: - pushl %edi /* Destination */ - call arith_invalid /* 0/0 or Infinity/Infinity */ - jmp LDiv_exit - -L_no_NaN_arg: - cmpb TW_Infinity,TAG(%esi) - jne L_arg1_not_inf - - cmpb TW_Infinity,TAG(%ebx) - je L_inf_inf /* invalid operation */ - - cmpb TW_Valid,TAG(%ebx) - je L_inf_valid - -#ifdef PARANOID - /* arg2 must be zero or valid */ - cmpb TW_Zero,TAG(%ebx) - ja L_unknown_tags -#endif /* PARANOID */ - - /* Note that p16-9 says that infinity/0 returns infinity */ - jmp L_copy_arg1 /* Answer is Inf */ - -L_inf_valid: -#ifdef DENORM_OPERAND - cmpl EXP_UNDER,EXP(%ebx) - jg L_copy_arg1 /* Answer is Inf */ - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit -#endif /* DENORM_OPERAND */ - - jmp L_copy_arg1 /* Answer is Inf */ - -L_arg1_not_inf: - cmpb TW_Zero,TAG(%ebx) /* Priority to div-by-zero error */ - jne L_arg2_not_zero - - cmpb TW_Zero,TAG(%esi) - je L_zero_zero /* invalid operation */ - -#ifdef PARANOID - /* arg1 must be valid */ - cmpb TW_Valid,TAG(%esi) - ja L_unknown_tags -#endif /* PARANOID */ - -/* Division by zero error */ - pushl %edi /* destination */ - movb SIGN(%esi),%al - xorb SIGN(%ebx),%al - pushl %eax /* lower 8 bits have the sign */ - call divide_by_zero - jmp LDiv_exit - -L_arg2_not_zero: - cmpb TW_Infinity,TAG(%ebx) - jne L_arg2_not_inf - -#ifdef DENORM_OPERAND - cmpb TW_Valid,TAG(%esi) - jne L_return_zero - - cmpl EXP_UNDER,EXP(%esi) - jg L_return_zero /* Answer is zero */ - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit -#endif /* DENORM_OPERAND */ - - jmp L_return_zero /* Answer is zero */ - -L_arg2_not_inf: - -#ifdef PARANOID - cmpb TW_Zero,TAG(%esi) - jne L_unknown_tags -#endif /* PARANOID */ - - /* arg1 is zero, arg2 is not Infinity or a NaN */ - -#ifdef DENORM_OPERAND - cmpl EXP_UNDER,EXP(%ebx) - jg L_copy_arg1 /* Answer is zero */ - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit -#endif /* DENORM_OPERAND */ - -L_copy_arg1: - movb TAG(%esi),%al - movb %al,TAG(%edi) - movl EXP(%esi),%eax - movl %eax,EXP(%edi) - movl SIGL(%esi),%eax - movl %eax,SIGL(%edi) - movl SIGH(%esi),%eax - movl %eax,SIGH(%edi) - - movb SIGN(%esi),%cl - cmpb %cl,SIGN(%ebx) - jne LDiv_negative_result - - movb SIGN_POS,SIGN(%edi) - jmp LDiv_exit - -LDiv_set_result_sign: - movb SIGN(%esi),%cl - cmpb %cl,SIGN(%edi) - jne LDiv_negative_result - - movb SIGN_POS,SIGN(%ebx) - jmp LDiv_exit - -LDiv_negative_result: - movb SIGN_NEG,SIGN(%edi) - -LDiv_exit: - leal -12(%ebp),%esp - - popl %ebx - popl %edi - popl %esi - leave - ret - - -L_return_zero: - movb TW_Zero,TAG(%edi) - jmp LDiv_set_result_sign - -#ifdef PARANOID -L_unknown_tags: - push EX_INTERNAL | 0x208 - call EXCEPTION - - /* Generate a NaN for unknown tags */ - movl _CONST_QNaN,%eax - movl %eax,(%edi) - movl _CONST_QNaN+4,%eax - movl %eax,SIGL(%edi) - movl _CONST_QNaN+8,%eax - movl %eax,SIGH(%edi) - jmp LDiv_exit -#endif /* PARANOID */ diff --git a/sys/gnu/i386/fpemul/reg_ld_str.c b/sys/gnu/i386/fpemul/reg_ld_str.c deleted file mode 100644 index 9c13b11..0000000 --- a/sys/gnu/i386/fpemul/reg_ld_str.c +++ /dev/null @@ -1,1388 +0,0 @@ -/* - * reg_ld_str.c - * - * All of the functions which transfer data between user memory and FPU_REGs. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ -#include <sys/param.h> -#include <sys/proc.h> -#include <sys/systm.h> -#include <machine/pcb.h> - -#include <gnu/i386/fpemul/fpu_emu.h> -#include <gnu/i386/fpemul/fpu_system.h> -#include <gnu/i386/fpemul/exception.h> -#include <gnu/i386/fpemul/reg_constant.h> -#include <gnu/i386/fpemul/control_w.h> -#include <gnu/i386/fpemul/status_w.h> - - -#define EXTENDED_Emax 0x3fff /* largest valid exponent */ -#define EXTENDED_Ebias 0x3fff -#define EXTENDED_Emin (-0x3ffe) /* smallest valid exponent */ - -#define DOUBLE_Emax 1023 /* largest valid exponent */ -#define DOUBLE_Ebias 1023 -#define DOUBLE_Emin (-1022) /* smallest valid exponent */ - -#define SINGLE_Emax 127 /* largest valid exponent */ -#define SINGLE_Ebias 127 -#define SINGLE_Emin (-126) /* smallest valid exponent */ - -#define LOST_UP (EX_Precision | SW_C1) -#define LOST_DOWN EX_Precision - -FPU_REG FPU_loaded_data; - - -/* Get a long double from user memory */ -void -reg_load_extended(void) -{ - long double *s = (long double *) FPU_data_address; - unsigned long sigl, sigh, exp; - - REENTRANT_CHECK(OFF); - /* Use temporary variables here because FPU_loaded data is static and - * hence re-entrancy problems can arise */ - sigl = fuword((unsigned long *) s); - sigh = fuword(1 + (unsigned long *) s); - exp = fuword16(4 + (unsigned short *) s); - REENTRANT_CHECK(ON); - - FPU_loaded_data.sigl = sigl; - FPU_loaded_data.sigh = sigh; - FPU_loaded_data.exp = exp; - - if (FPU_loaded_data.exp & 0x8000) - FPU_loaded_data.sign = SIGN_NEG; - else - FPU_loaded_data.sign = SIGN_POS; - if ((FPU_loaded_data.exp &= 0x7fff) == 0) { - if (!(FPU_loaded_data.sigl | FPU_loaded_data.sigh)) { - FPU_loaded_data.tag = TW_Zero; - return; - } - /* The number is a de-normal or pseudodenormal. */ - /* The 80486 doesn't regard pseudodenormals as denormals here. */ - if (!(FPU_loaded_data.sigh & 0x80000000)) - EXCEPTION(EX_Denormal); - FPU_loaded_data.exp++; - - /* The default behaviour will now take care of it. */ - } else - if (FPU_loaded_data.exp == 0x7fff) { - FPU_loaded_data.exp = EXTENDED_Emax; - if ((FPU_loaded_data.sigh == 0x80000000) - && (FPU_loaded_data.sigl == 0)) { - FPU_loaded_data.tag = TW_Infinity; - return; - } else - if (!(FPU_loaded_data.sigh & 0x80000000)) { - /* Unsupported NaN data type */ - EXCEPTION(EX_Invalid); - FPU_loaded_data.tag = TW_NaN; - return; - } - FPU_loaded_data.tag = TW_NaN; - return; - } - FPU_loaded_data.exp = (FPU_loaded_data.exp & 0x7fff) - EXTENDED_Ebias - + EXP_BIAS; - FPU_loaded_data.tag = TW_Valid; - - if (!(sigh & 0x80000000)) { - /* Unsupported data type */ - EXCEPTION(EX_Invalid); - normalize_nuo(&FPU_loaded_data); - } -} - - -/* Get a double from user memory */ -void -reg_load_double(void) -{ - double *dfloat = (double *) FPU_data_address; - int exp; - unsigned m64, l64; - - REENTRANT_CHECK(OFF); - m64 = fuword(1 + (unsigned long *) dfloat); - l64 = fuword((unsigned long *) dfloat); - REENTRANT_CHECK(ON); - - if (m64 & 0x80000000) - FPU_loaded_data.sign = SIGN_NEG; - else - FPU_loaded_data.sign = SIGN_POS; - exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias; - m64 &= 0xfffff; - if (exp > DOUBLE_Emax) { - /* Infinity or NaN */ - if ((m64 == 0) && (l64 == 0)) { - /* +- infinity */ - FPU_loaded_data.exp = EXTENDED_Emax; - FPU_loaded_data.tag = TW_Infinity; - return; - } else { - /* Must be a signaling or quiet NaN */ - FPU_loaded_data.exp = EXTENDED_Emax; - FPU_loaded_data.tag = TW_NaN; - FPU_loaded_data.sigh = (m64 << 11) | 0x80000000; - FPU_loaded_data.sigh |= l64 >> 21; - FPU_loaded_data.sigl = l64 << 11; - return; - } - } else - if (exp < DOUBLE_Emin) { - /* Zero or de-normal */ - if ((m64 == 0) && (l64 == 0)) { - /* Zero */ - int c = FPU_loaded_data.sign; - reg_move(&CONST_Z, &FPU_loaded_data); - FPU_loaded_data.sign = c; - return; - } else { - /* De-normal */ - EXCEPTION(EX_Denormal); - FPU_loaded_data.exp = DOUBLE_Emin + EXP_BIAS; - FPU_loaded_data.tag = TW_Valid; - FPU_loaded_data.sigh = m64 << 11; - FPU_loaded_data.sigh |= l64 >> 21; - FPU_loaded_data.sigl = l64 << 11; - normalize_nuo(&FPU_loaded_data); - return; - } - } else { - FPU_loaded_data.exp = exp + EXP_BIAS; - FPU_loaded_data.tag = TW_Valid; - FPU_loaded_data.sigh = (m64 << 11) | 0x80000000; - FPU_loaded_data.sigh |= l64 >> 21; - FPU_loaded_data.sigl = l64 << 11; - - return; - } -} - - -/* Get a float from user memory */ -void -reg_load_single(void) -{ - float *single = (float *) FPU_data_address; - unsigned m32; - int exp; - - REENTRANT_CHECK(OFF); - m32 = fuword((unsigned long *) single); - REENTRANT_CHECK(ON); - - if (m32 & 0x80000000) - FPU_loaded_data.sign = SIGN_NEG; - else - FPU_loaded_data.sign = SIGN_POS; - if (!(m32 & 0x7fffffff)) { - /* Zero */ - int c = FPU_loaded_data.sign; - reg_move(&CONST_Z, &FPU_loaded_data); - FPU_loaded_data.sign = c; - return; - } - exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias; - m32 = (m32 & 0x7fffff) << 8; - if (exp < SINGLE_Emin) { - /* De-normals */ - EXCEPTION(EX_Denormal); - FPU_loaded_data.exp = SINGLE_Emin + EXP_BIAS; - FPU_loaded_data.tag = TW_Valid; - FPU_loaded_data.sigh = m32; - FPU_loaded_data.sigl = 0; - normalize_nuo(&FPU_loaded_data); - return; - } else - if (exp > SINGLE_Emax) { - /* Infinity or NaN */ - if (m32 == 0) { - /* +- infinity */ - FPU_loaded_data.exp = EXTENDED_Emax; - FPU_loaded_data.tag = TW_Infinity; - return; - } else { - /* Must be a signaling or quiet NaN */ - FPU_loaded_data.exp = EXTENDED_Emax; - FPU_loaded_data.tag = TW_NaN; - FPU_loaded_data.sigh = m32 | 0x80000000; - FPU_loaded_data.sigl = 0; - return; - } - } else { - FPU_loaded_data.exp = exp + EXP_BIAS; - FPU_loaded_data.sigh = m32 | 0x80000000; - FPU_loaded_data.sigl = 0; - FPU_loaded_data.tag = TW_Valid; - } -} - - -/* Get a long long from user memory */ -void -reg_load_int64(void) -{ - long long *_s = (long long *) FPU_data_address; - int e; - long long s; - - REENTRANT_CHECK(OFF); - ((unsigned long *) &s)[0] = fuword((unsigned long *) _s); - ((unsigned long *) &s)[1] = fuword(1 + (unsigned long *) _s); - REENTRANT_CHECK(ON); - - if (s == 0) { - reg_move(&CONST_Z, &FPU_loaded_data); - return; - } - if (s > 0) - FPU_loaded_data.sign = SIGN_POS; - else { - s = -s; - FPU_loaded_data.sign = SIGN_NEG; - } - - e = EXP_BIAS + 63; - *((long long *) &FPU_loaded_data.sigl) = s; - FPU_loaded_data.exp = e; - FPU_loaded_data.tag = TW_Valid; - normalize_nuo(&FPU_loaded_data); -} - - -/* Get a long from user memory */ -void -reg_load_int32(void) -{ - long *_s = (long *) FPU_data_address; - long s; - int e; - - REENTRANT_CHECK(OFF); - s = (long) fuword((unsigned long *) _s); - REENTRANT_CHECK(ON); - - if (s == 0) { - reg_move(&CONST_Z, &FPU_loaded_data); - return; - } - if (s > 0) - FPU_loaded_data.sign = SIGN_POS; - else { - s = -s; - FPU_loaded_data.sign = SIGN_NEG; - } - - e = EXP_BIAS + 31; - FPU_loaded_data.sigh = s; - FPU_loaded_data.sigl = 0; - FPU_loaded_data.exp = e; - FPU_loaded_data.tag = TW_Valid; - normalize_nuo(&FPU_loaded_data); -} - - -/* Get a short from user memory */ -void -reg_load_int16(void) -{ - short *_s = (short *) FPU_data_address; - int s, e; - - REENTRANT_CHECK(OFF); - /* Cast as short to get the sign extended. */ - s = (short) fuword16((unsigned short *) _s); - REENTRANT_CHECK(ON); - - if (s == 0) { - reg_move(&CONST_Z, &FPU_loaded_data); - return; - } - if (s > 0) - FPU_loaded_data.sign = SIGN_POS; - else { - s = -s; - FPU_loaded_data.sign = SIGN_NEG; - } - - e = EXP_BIAS + 15; - FPU_loaded_data.sigh = s << 16; - - FPU_loaded_data.sigl = 0; - FPU_loaded_data.exp = e; - FPU_loaded_data.tag = TW_Valid; - normalize_nuo(&FPU_loaded_data); -} - - -/* Get a packed bcd array from user memory */ -void -reg_load_bcd(void) -{ - char *s = (char *) FPU_data_address; - int pos; - unsigned char bcd; - long long l = 0; - - for (pos = 8; pos >= 0; pos--) { - l *= 10; - REENTRANT_CHECK(OFF); - bcd = (unsigned char) fubyte((unsigned char *) s + pos); - REENTRANT_CHECK(ON); - l += bcd >> 4; - l *= 10; - l += bcd & 0x0f; - } - - /* Finish all access to user memory before putting stuff into the - * static FPU_loaded_data */ - REENTRANT_CHECK(OFF); - FPU_loaded_data.sign = - ((unsigned char) fubyte((unsigned char *) s + 9)) & 0x80 ? - SIGN_NEG : SIGN_POS; - REENTRANT_CHECK(ON); - - if (l == 0) { - char sign = FPU_loaded_data.sign; - reg_move(&CONST_Z, &FPU_loaded_data); - FPU_loaded_data.sign = sign; - } else { - *((long long *) &FPU_loaded_data.sigl) = l; - FPU_loaded_data.exp = EXP_BIAS + 63; - FPU_loaded_data.tag = TW_Valid; - normalize_nuo(&FPU_loaded_data); - } -} -/*===========================================================================*/ - -/* Put a long double into user memory */ -int -reg_store_extended(void) -{ - long double *d = (long double *) FPU_data_address; - long e = FPU_st0_ptr->exp - EXP_BIAS + EXTENDED_Ebias; - unsigned short sign = FPU_st0_ptr->sign * 0x8000; - unsigned long ls, ms; - - - if (FPU_st0_tag == TW_Valid) { - if (e >= 0x7fff) { - EXCEPTION(EX_Overflow); /* Overflow */ - /* This is a special case: see sec 16.2.5.1 of the - * 80486 book */ - if (control_word & EX_Overflow) { - /* Overflow to infinity */ - ls = 0; - ms = 0x80000000; - e = 0x7fff; - } else - return 0; - } else - if (e <= 0) { - if (e > -63) { - /* Correctly format the de-normal */ - int precision_loss; - FPU_REG tmp; - - EXCEPTION(EX_Denormal); - reg_move(FPU_st0_ptr, &tmp); - tmp.exp += -EXTENDED_Emin + 63; /* largest exp to be 62 */ - if ((precision_loss = round_to_int(&tmp))) { - EXCEPTION(EX_Underflow | precision_loss); - /* This is a special case: see - * sec 16.2.5.1 of the 80486 - * book */ - if (!(control_word & EX_Underflow)) - return 0; - } - e = 0; - ls = tmp.sigl; - ms = tmp.sigh; - } else { - /* ****** ??? This should not be - * possible */ - EXCEPTION(EX_Underflow); /* Underflow */ - /* This is a special case: see sec - * 16.2.5.1 of the 80486 book */ - if (control_word & EX_Underflow) { - /* Underflow to zero */ - ls = 0; - ms = 0; - e = FPU_st0_ptr->sign == SIGN_POS ? 0x7fff : 0xffff; - } else - return 0; - } - } else { - ls = FPU_st0_ptr->sigl; - ms = FPU_st0_ptr->sigh; - } - } else - if (FPU_st0_tag == TW_Zero) { - ls = ms = 0; - e = 0; - } else - if (FPU_st0_tag == TW_Infinity) { - ls = 0; - ms = 0x80000000; - e = 0x7fff; - } else - if (FPU_st0_tag == TW_NaN) { - ls = FPU_st0_ptr->sigl; - ms = FPU_st0_ptr->sigh; - e = 0x7fff; - } else - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack - * underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN - * indefinite */ - ls = 0; - ms = 0xc0000000; - e = 0xffff; - } else - return 0; - } else { - /* We don't use TW_Denormal - * yet ... perhaps never! */ - EXCEPTION(EX_Invalid); - /* Store a NaN */ - e = 0x7fff; - ls = 1; - ms = 0x80000000; - } - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 10); */ - suword((unsigned long *) d, ls); - suword(1 + (unsigned long *) d, ms); - suword16(4 + (short *) d, (unsigned short) e | sign); - REENTRANT_CHECK(ON); - - return 1; - -} - - -/* Put a double into user memory */ -int -reg_store_double(void) -{ - double *dfloat = (double *) FPU_data_address; - unsigned long l[2]; - if (FPU_st0_tag == TW_Valid) { - int exp; - FPU_REG tmp; - - reg_move(FPU_st0_ptr, &tmp); - exp = tmp.exp - EXP_BIAS; - - if (exp < DOUBLE_Emin) { /* It may be a denormal */ - /* Make a de-normal */ - int precision_loss; - - if (exp <= -EXTENDED_Ebias) - EXCEPTION(EX_Denormal); - - tmp.exp += -DOUBLE_Emin + 52; /* largest exp to be 51 */ - - if ((precision_loss = round_to_int(&tmp))) { -#ifdef PECULIAR_486 - /* Did it round to a non-denormal ? */ - /* This behaviour might be regarded as - * peculiar, it appears that the 80486 rounds - * to the dest precision, then converts to - * decide underflow. */ - if ((tmp.sigh == 0x00100000) && (tmp.sigl == 0) && - (FPU_st0_ptr->sigl & 0x000007ff)) - EXCEPTION(precision_loss); - else -#endif /* PECULIAR_486 */ - { - EXCEPTION(EX_Underflow | precision_loss); - /* This is a special case: see sec - * 16.2.5.1 of the 80486 book */ - if (!(control_word & EX_Underflow)) - return 0; - } - } - l[0] = tmp.sigl; - l[1] = tmp.sigh; - } else { - if (tmp.sigl & 0x000007ff) { - unsigned long increment = 0; /* avoid gcc warnings */ - - switch (control_word & CW_RC) { - case RC_RND: - /* Rounding can get a little messy.. */ - increment = ((tmp.sigl & 0x7ff) > 0x400) | /* nearest */ - ((tmp.sigl & 0xc00) == 0xc00); /* odd -> even */ - break; - case RC_DOWN: /* towards -infinity */ - increment = (tmp.sign == SIGN_POS) ? 0 : tmp.sigl & 0x7ff; - break; - case RC_UP: /* towards +infinity */ - increment = (tmp.sign == SIGN_POS) ? tmp.sigl & 0x7ff : 0; - break; - case RC_CHOP: - increment = 0; - break; - } - - /* Truncate the mantissa */ - tmp.sigl &= 0xfffff800; - - if (increment) { - set_precision_flag_up(); - - if (tmp.sigl >= 0xfffff800) { - /* the sigl part overflows */ - if (tmp.sigh == 0xffffffff) { - /* The sigh part - * overflows */ - tmp.sigh = 0x80000000; - exp++; - if (exp >= EXP_OVER) - goto overflow; - } else { - tmp.sigh++; - } - tmp.sigl = 0x00000000; - } else { - /* We only need to increment - * sigl */ - tmp.sigl += 0x00000800; - } - } else - set_precision_flag_down(); - } - l[0] = (tmp.sigl >> 11) | (tmp.sigh << 21); - l[1] = ((tmp.sigh >> 11) & 0xfffff); - - if (exp > DOUBLE_Emax) { - overflow: - EXCEPTION(EX_Overflow); - /* This is a special case: see sec 16.2.5.1 of - * the 80486 book */ - if (control_word & EX_Overflow) { - /* Overflow to infinity */ - l[0] = 0x00000000; /* Set to */ - l[1] = 0x7ff00000; /* + INF */ - } else - return 0; - } else { - /* Add the exponent */ - l[1] |= (((exp + DOUBLE_Ebias) & 0x7ff) << 20); - } - } - } else - if (FPU_st0_tag == TW_Zero) { - /* Number is zero */ - l[0] = 0; - l[1] = 0; - } else - if (FPU_st0_tag == TW_Infinity) { - l[0] = 0; - l[1] = 0x7ff00000; - } else - if (FPU_st0_tag == TW_NaN) { - /* See if we can get a valid NaN from - * the FPU_REG */ - l[0] = (FPU_st0_ptr->sigl >> 11) | (FPU_st0_ptr->sigh << 21); - l[1] = ((FPU_st0_ptr->sigh >> 11) & 0xfffff); - if (!(l[0] | l[1])) { - /* This case does not seem to - * be handled by the 80486 - * specs */ - EXCEPTION(EX_Invalid); - /* Make the quiet NaN "real - * indefinite" */ - goto put_indefinite; - } - l[1] |= 0x7ff00000; - } else - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack - * underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN - * indefinite */ - put_indefinite: - REENTRANT_CHECK(OFF); - /* verify_area(VERIFY_W - * RITE, (void *) - * dfloat, 8); */ - suword((unsigned long *) dfloat, 0); - suword(1 + (unsigned long *) dfloat, 0xfff80000); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } -#if 0 /* TW_Denormal is not used yet, and probably - * won't be */ - else - if (FPU_st0_tag == TW_Denormal) { - /* Extended real -> - * double real will - * always underflow */ - l[0] = l[1] = 0; - EXCEPTION(EX_Underflow); - } -#endif - if (FPU_st0_ptr->sign) - l[1] |= 0x80000000; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, (void *) dfloat, 8);*/ - suword((u_long *) dfloat, l[0]); - suword((u_long *) dfloat + 1, l[1]); -/* - suword(l[0], (unsigned long *) dfloat); - suword(l[1], 1 + (unsigned long *) dfloat);*/ - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a float into user memory */ -int -reg_store_single(void) -{ - float *single = (float *) FPU_data_address; - long templ = 0; - - if (FPU_st0_tag == TW_Valid) { - int exp; - FPU_REG tmp; - - reg_move(FPU_st0_ptr, &tmp); - exp = tmp.exp - EXP_BIAS; - - if (exp < SINGLE_Emin) { - /* Make a de-normal */ - int precision_loss; - - if (exp <= -EXTENDED_Ebias) - EXCEPTION(EX_Denormal); - - tmp.exp += -SINGLE_Emin + 23; /* largest exp to be 22 */ - - if ((precision_loss = round_to_int(&tmp))) { -#ifdef PECULIAR_486 - /* Did it round to a non-denormal ? */ - /* This behaviour might be regarded as - * peculiar, it appears that the 80486 rounds - * to the dest precision, then converts to - * decide underflow. */ - if ((tmp.sigl == 0x00800000) && - ((FPU_st0_ptr->sigh & 0x000000ff) || FPU_st0_ptr->sigl)) - EXCEPTION(precision_loss); - else -#endif /* PECULIAR_486 */ - { - EXCEPTION(EX_Underflow | precision_loss); - /* This is a special case: see sec - * 16.2.5.1 of the 80486 book */ - if (!(control_word & EX_Underflow)) - return 0; - } - } - templ = tmp.sigl; - } else { - if (tmp.sigl | (tmp.sigh & 0x000000ff)) { - unsigned long increment = 0; /* avoid gcc warnings */ - unsigned long sigh = tmp.sigh; - unsigned long sigl = tmp.sigl; - - switch (control_word & CW_RC) { - case RC_RND: - increment = ((sigh & 0xff) > 0x80) /* more than half */ - ||(((sigh & 0xff) == 0x80) && sigl) /* more than half */ - ||((sigh & 0x180) == 0x180); /* round to even */ - break; - case RC_DOWN: /* towards -infinity */ - increment = (tmp.sign == SIGN_POS) - ? 0 : (sigl | (sigh & 0xff)); - break; - case RC_UP: /* towards +infinity */ - increment = (tmp.sign == SIGN_POS) - ? (sigl | (sigh & 0xff)) : 0; - break; - case RC_CHOP: - increment = 0; - break; - } - - /* Truncate part of the mantissa */ - tmp.sigl = 0; - - if (increment) { - set_precision_flag_up(); - - if (sigh >= 0xffffff00) { - /* The sigh part overflows */ - tmp.sigh = 0x80000000; - exp++; - if (exp >= EXP_OVER) - goto overflow; - } else { - tmp.sigh &= 0xffffff00; - tmp.sigh += 0x100; - } - } else { - set_precision_flag_down(); - tmp.sigh &= 0xffffff00; /* Finish the truncation */ - } - } - templ = (tmp.sigh >> 8) & 0x007fffff; - - if (exp > SINGLE_Emax) { - overflow: - EXCEPTION(EX_Overflow); - /* This is a special case: see sec 16.2.5.1 of - * the 80486 book */ - if (control_word & EX_Overflow) { - /* Overflow to infinity */ - templ = 0x7f800000; - } else - return 0; - } else - templ |= ((exp + SINGLE_Ebias) & 0xff) << 23; - } - } else - if (FPU_st0_tag == TW_Zero) { - templ = 0; - } else - if (FPU_st0_tag == TW_Infinity) { - templ = 0x7f800000; - } else - if (FPU_st0_tag == TW_NaN) { - /* See if we can get a valid NaN from - * the FPU_REG */ - templ = FPU_st0_ptr->sigh >> 8; - if (!(templ & 0x3fffff)) { - /* This case does not seem to - * be handled by the 80486 - * specs */ - EXCEPTION(EX_Invalid); - /* Make the quiet NaN "real - * indefinite" */ - goto put_indefinite; - } - templ |= 0x7f800000; - } else - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack - * underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN - * indefinite */ - put_indefinite: - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, (void *) single, 4); */ - suword((unsigned long *) single, 0xffc00000); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } -#if 0 /* TW_Denormal is not used yet, and probably - * won't be */ - else - if (FPU_st0_tag == TW_Denormal) { - /* Extended real -> - * real will always - * underflow */ - templ = 0; - EXCEPTION(EX_Underflow); - } -#endif -#ifdef PARANOID - else { - EXCEPTION(EX_INTERNAL | 0x106); - return 0; - } -#endif - if (FPU_st0_ptr->sign) - templ |= 0x80000000; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, (void *) single, 4); */ - suword((unsigned long *) single, templ); - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a long long into user memory */ -int -reg_store_int64(void) -{ - long long *d = (long long *) FPU_data_address; - FPU_REG t; - long long tll; - - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN indefinite */ - goto put_indefinite; - } else - return 0; - } - reg_move(FPU_st0_ptr, &t); - round_to_int(&t); - ((long *) &tll)[0] = t.sigl; - ((long *) &tll)[1] = t.sigh; - if ((t.sigh & 0x80000000) && - !((t.sigh == 0x80000000) && (t.sigl == 0) && (t.sign == SIGN_NEG))) { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - if (control_word & EX_Invalid) { - /* Produce "indefinite" */ - put_indefinite: - ((long *) &tll)[1] = 0x80000000; - ((long *) &tll)[0] = 0; - } else - return 0; - } else - if (t.sign) - tll = -tll; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, (void *) d, 8); */ - suword((unsigned long *) d, ((long *) &tll)[0]); - suword(1 + (unsigned long *) d, ((long *) &tll)[1]); - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a long into user memory */ -int -reg_store_int32(void) -{ - long *d = (long *) FPU_data_address; - FPU_REG t; - - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN indefinite */ - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 4);*/ - suword((unsigned long *) d, 0x80000000); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } - reg_move(FPU_st0_ptr, &t); - round_to_int(&t); - if (t.sigh || - ((t.sigl & 0x80000000) && - !((t.sigl == 0x80000000) && (t.sign == SIGN_NEG)))) { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - if (control_word & EX_Invalid) { - /* Produce "indefinite" */ - t.sigl = 0x80000000; - } else - return 0; - } else - if (t.sign) - t.sigl = -(long) t.sigl; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 4); */ - suword((unsigned long *) d, t.sigl); - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a short into user memory */ -int -reg_store_int16(void) -{ - short *d = (short *) FPU_data_address; - FPU_REG t; - short ts; - - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN indefinite */ - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 2);*/ - suword16((unsigned short *) d, 0x8000); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } - reg_move(FPU_st0_ptr, &t); - round_to_int(&t); - if (t.sigh || - ((t.sigl & 0xffff8000) && - !((t.sigl == 0x8000) && (t.sign == SIGN_NEG)))) { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - if (control_word & EX_Invalid) { - /* Produce "indefinite" */ - ts = 0x8000; - } else - return 0; - } else - if (t.sign) - t.sigl = -t.sigl; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 2); */ - suword16((short *) d, (short) t.sigl); - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a packed bcd array into user memory */ -int -reg_store_bcd(void) -{ - char *d = (char *) FPU_data_address; - FPU_REG t; - long long ll; - unsigned char b; - int i; - unsigned char sign = (FPU_st0_ptr->sign == SIGN_NEG) ? 0x80 : 0; - - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN indefinite */ - goto put_indefinite; - } else - return 0; - } - reg_move(FPU_st0_ptr, &t); - round_to_int(&t); - ll = *(long long *) (&t.sigl); - - /* Check for overflow, by comparing with 999999999999999999 decimal. */ - if ((t.sigh > 0x0de0b6b3) || - ((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff))) { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - if (control_word & EX_Invalid) { - put_indefinite: - /* Produce "indefinite" */ - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 10);*/ - subyte((unsigned char *) d + 7, 0xff); - subyte((unsigned char *) d + 8, 0xff); - subyte((unsigned char *) d + 9, 0xff); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } -/* verify_area(VERIFY_WRITE, d, 10);*/ - for (i = 0; i < 9; i++) { - b = div_small(&ll, 10); - b |= (div_small(&ll, 10)) << 4; - REENTRANT_CHECK(OFF); - subyte((unsigned char *) d + i, b); - REENTRANT_CHECK(ON); - } - REENTRANT_CHECK(OFF); - subyte((unsigned char *) d + 9, sign); - REENTRANT_CHECK(ON); - - return 1; -} -/*===========================================================================*/ - -/* r gets mangled such that sig is int, sign: - it is NOT normalized */ -/* The return value (in eax) is zero if the result is exact, - if bits are changed due to rounding, truncation, etc, then - a non-zero value is returned */ -/* Overflow is signalled by a non-zero return value (in eax). - In the case of overflow, the returned significand always has the - the largest possible value */ -/* The value returned in eax is never actually needed :-) */ -int -round_to_int(FPU_REG * r) -{ - char very_big; - unsigned eax; - - if (r->tag == TW_Zero) { - /* Make sure that zero is returned */ - *(long long *) &r->sigl = 0; - return 0; /* o.k. */ - } - if (r->exp > EXP_BIAS + 63) { - r->sigl = r->sigh = ~0; /* The largest representable number */ - return 1; /* overflow */ - } - eax = shrxs(&r->sigl, EXP_BIAS + 63 - r->exp); - very_big = !(~(r->sigh) | ~(r->sigl)); /* test for 0xfff...fff */ -#define half_or_more (eax & 0x80000000) -#define frac_part (eax) -#define more_than_half ((eax & 0x80000001) == 0x80000001) - switch (control_word & CW_RC) { - case RC_RND: - if (more_than_half /* nearest */ - || (half_or_more && (r->sigl & 1))) { /* odd -> even */ - if (very_big) - return 1; /* overflow */ - (*(long long *) (&r->sigl))++; - return LOST_UP; - } - break; - case RC_DOWN: - if (frac_part && r->sign) { - if (very_big) - return 1; /* overflow */ - (*(long long *) (&r->sigl))++; - return LOST_UP; - } - break; - case RC_UP: - if (frac_part && !r->sign) { - if (very_big) - return 1; /* overflow */ - (*(long long *) (&r->sigl))++; - return LOST_UP; - } - break; - case RC_CHOP: - break; - } - - return eax ? LOST_DOWN : 0; - -} -/*===========================================================================*/ - -char * -fldenv(void) -{ - char *s = (char *) FPU_data_address; - unsigned short tag_word = 0; - unsigned char tag; - int i; - - REENTRANT_CHECK(OFF); - control_word = fuword16((unsigned short *) s); - status_word = fuword16((unsigned short *) (s + 4)); - tag_word = fuword16((unsigned short *) (s + 8)); - ip_offset = fuword((unsigned long *) (s + 0x0c)); - cs_selector = fuword((unsigned long *) (s + 0x10)); - data_operand_offset = fuword((unsigned long *) (s + 0x14)); - operand_selector = fuword((unsigned long *) (s + 0x18)); - REENTRANT_CHECK(ON); - - top = (status_word >> SW_Top_Shift) & 7; - - for (i = 0; i < 8; i++) { - tag = tag_word & 3; - tag_word >>= 2; - - switch (tag) { - case 0: - regs[i].tag = TW_Valid; - break; - case 1: - regs[i].tag = TW_Zero; - break; - case 2: - regs[i].tag = TW_NaN; - break; - case 3: - regs[i].tag = TW_Empty; - break; - } - } - - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - - return s + 0x1c; -} - - -void -frstor(void) -{ - int i, stnr; - unsigned char tag; - unsigned short saved_status, saved_control; - char *s = (char *) fldenv(); - - saved_status = status_word; - saved_control = control_word; - control_word = 0x037f; /* Mask all interrupts while we load. */ - for (i = 0; i < 8; i++) { - /* load each register */ - FPU_data_address = (void *) (s + i * 10); - reg_load_extended(); - stnr = (i + top) & 7; - tag = regs[stnr].tag; /* derived from the loaded tag word */ - reg_move(&FPU_loaded_data, ®s[stnr]); - if (tag == TW_NaN) { - /* The current data is a special, i.e. NaN, - * unsupported, infinity, or denormal */ - unsigned char t = regs[stnr].tag; /* derived from the new - * data */ - if ( /* (t == TW_Valid) || *** */ (t == TW_Zero)) - regs[stnr].tag = TW_NaN; - } else - regs[stnr].tag = tag; - } - control_word = saved_control; - status_word = saved_status; - - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; -} - - -unsigned short -tag_word(void) -{ - unsigned short word = 0; - unsigned char tag; - int i; - - for (i = 7; i >= 0; i--) { - switch (tag = regs[i].tag) { -#if 0 /* TW_Denormal is not used yet, and probably - * won't be */ - case TW_Denormal: -#endif - case TW_Valid: - if (regs[i].exp <= (EXP_BIAS - EXTENDED_Ebias)) - tag = 2; - break; - case TW_Infinity: - case TW_NaN: - tag = 2; - break; - case TW_Empty: - tag = 3; - break; - /* TW_Valid and TW_Zero already have the correct value */ - } - word <<= 2; - word |= tag; - } - return word; -} - - -char * -fstenv(void) -{ - char *d = (char *) FPU_data_address; - -/* verify_area(VERIFY_WRITE, d, 28);*/ - -#if 0 /****/ - *(unsigned short *) &cs_selector = fpu_cs; - *(unsigned short *) &operand_selector = fpu_os; -#endif /****/ - - REENTRANT_CHECK(OFF); - suword16((unsigned short *) d, control_word); - suword16((unsigned short *) (d + 4), (status_word & ~SW_Top) | ((top & 7) << SW_Top_Shift)); - suword16((unsigned short *) (d + 8), tag_word()); - suword((unsigned long *) (d + 0x0c), ip_offset); - suword((unsigned long *) (d + 0x10), cs_selector); - suword((unsigned long *) (d + 0x14), data_operand_offset); - suword((unsigned long *) (d + 0x18), operand_selector); - REENTRANT_CHECK(ON); - - return d + 0x1c; -} - - -void -fsave(void) -{ - char *d; - FPU_REG tmp, *rp; - int i; - short e; - - d = fstenv(); -/* verify_area(VERIFY_WRITE, d, 80);*/ - for (i = 0; i < 8; i++) { - /* Store each register in the order: st(0), st(1), ... */ - rp = ®s[(top + i) & 7]; - - e = rp->exp - EXP_BIAS + EXTENDED_Ebias; - - if (rp->tag == TW_Valid) { - if (e >= 0x7fff) { - /* Overflow to infinity */ - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), 0); - suword((unsigned long *) (d + i * 10 + 4), 0); - REENTRANT_CHECK(ON); - e = 0x7fff; - } else - if (e <= 0) { - if (e > -63) { - /* Make a de-normal */ - reg_move(rp, &tmp); - tmp.exp += -EXTENDED_Emin + 63; /* largest exp to be 62 */ - round_to_int(&tmp); - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), tmp.sigl); - suword((unsigned long *) (d + i * 10 + 4), tmp.sigh); - REENTRANT_CHECK(ON); - } else { - /* Underflow to zero */ - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), 0); - suword((unsigned long *) (d + i * 10 + 4), 0); - REENTRANT_CHECK(ON); - } - e = 0; - } else { - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), rp->sigl); - suword((unsigned long *) (d + i * 10 + 4), rp->sigh); - REENTRANT_CHECK(ON); - } - } else - if (rp->tag == TW_Zero) { - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), 0); - suword((unsigned long *) (d + i * 10 + 4), 0); - REENTRANT_CHECK(ON); - e = 0; - } else - if (rp->tag == TW_Infinity) { - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), 0); - suword((unsigned long *) (d + i * 10 + 4), 0x80000000); - REENTRANT_CHECK(ON); - e = 0x7fff; - } else - if (rp->tag == TW_NaN) { - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), rp->sigl); - suword((unsigned long *) (d + i * 10 + 4), rp->sigh); - REENTRANT_CHECK(ON); - e = 0x7fff; - } else - if (rp->tag == TW_Empty) { - /* just copy the reg */ - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), rp->sigl); - suword((unsigned long *) (d + i * 10 + 4), rp->sigh); - REENTRANT_CHECK(ON); - } - e |= rp->sign == SIGN_POS ? 0 : 0x8000; - REENTRANT_CHECK(OFF); - suword16((unsigned short *) (d + i * 10 + 8), e); - REENTRANT_CHECK(ON); - } - - finit(); - -} -/*===========================================================================*/ diff --git a/sys/gnu/i386/fpemul/reg_mul.c b/sys/gnu/i386/fpemul/reg_mul.c deleted file mode 100644 index 1b9cf2b..0000000 --- a/sys/gnu/i386/fpemul/reg_mul.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * reg_mul.c - * - * Multiply one FPU_REG by another, put the result in a destination FPU_REG. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -/*---------------------------------------------------------------------------+ - | The destination may be any FPU_REG, including one of the source FPU_REGs. | - +---------------------------------------------------------------------------*/ - -#include <gnu/i386/fpemul/reg_constant.h> - - -/* This routine must be called with non-empty source registers */ -void -reg_mul(FPU_REG * a, FPU_REG * b, FPU_REG * dest, unsigned int control_w) -{ - char sign = (a->sign ^ b->sign); - - if (!(a->tag | b->tag)) { - /* This should be the most common case */ - reg_u_mul(a, b, dest, control_w); - dest->sign = sign; - return; - } else - if ((a->tag <= TW_Zero) && (b->tag <= TW_Zero)) { -#ifdef DENORM_OPERAND - if (((b->tag == TW_Valid) && (b->exp <= EXP_UNDER)) || - ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER))) { - if (denormal_operand()) - return; - } -#endif /* DENORM_OPERAND */ - /* Must have either both arguments == zero, or one - * valid and the other zero. The result is therefore - * zero. */ - reg_move(&CONST_Z, dest); -#ifdef PECULIAR_486 - /* The 80486 book says that the answer is +0, but a - * real 80486 appears to behave this way... */ - dest->sign = sign; -#endif /* PECULIAR_486 */ - return; - } -#if 0 /* TW_Denormal is not used yet... perhaps - * never will be. */ - else - if ((a->tag <= TW_Denormal) && (b->tag <= TW_Denormal)) { - /* One or both arguments are de-normalized */ - /* Internal de-normalized numbers are not - * supported yet */ - EXCEPTION(EX_INTERNAL | 0x105); - reg_move(&CONST_Z, dest); - } -#endif - else { - /* Must have infinities, NaNs, etc */ - if ((a->tag == TW_NaN) || (b->tag == TW_NaN)) { - real_2op_NaN(a, b, dest); - return; - } else - if (a->tag == TW_Infinity) { - if (b->tag == TW_Zero) { - arith_invalid(dest); - return; - } - /* Zero*Infinity is invalid */ - else { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - dest->sign = sign; - } - return; - } else - if (b->tag == TW_Infinity) { - if (a->tag == TW_Zero) { - arith_invalid(dest); - return; - } - /* Zero*Infinity is - * invalid */ - else { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - dest->sign = sign; - } - return; - } -#ifdef PARANOID - else { - EXCEPTION(EX_INTERNAL | 0x102); - } -#endif /* PARANOID */ - } -} diff --git a/sys/gnu/i386/fpemul/reg_norm.s b/sys/gnu/i386/fpemul/reg_norm.s deleted file mode 100644 index f940327..0000000 --- a/sys/gnu/i386/fpemul/reg_norm.s +++ /dev/null @@ -1,176 +0,0 @@ -/* - * reg_norm.s - * - * Normalize the value in a FPU_REG. - * - * Call from C as: - * void normalize(FPU_REG *n) - * - * void normalize_nuo(FPU_REG *n) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - -#include <gnu/i386/fpemul/fpu_asm.h> - - -.text - -ENTRY(normalize) - pushl %ebp - movl %esp,%ebp - pushl %ebx - - movl PARAM1,%ebx - - movl SIGH(%ebx),%edx - movl SIGL(%ebx),%eax - - orl %edx,%edx /* ms bits */ - js L_done /* Already normalized */ - jnz L_shift_1 /* Shift left 1 - 31 bits */ - - orl %eax,%eax - jz L_zero /* The contents are zero */ - -/* L_shift_32: */ - movl %eax,%edx - xorl %eax,%eax - subl $32,EXP(%ebx) /* This can cause an underflow */ - -/* We need to shift left by 1 - 31 bits */ -L_shift_1: - bsrl %edx,%ecx /* get the required shift in %ecx */ - subl $31,%ecx - negl %ecx - shld %cl,%eax,%edx - shl %cl,%eax - subl %ecx,EXP(%ebx) /* This can cause an underflow */ - - movl %edx,SIGH(%ebx) - movl %eax,SIGL(%ebx) - -L_done: - cmpl EXP_OVER,EXP(%ebx) - jge L_overflow - - cmpl EXP_UNDER,EXP(%ebx) - jle L_underflow - -L_exit: - popl %ebx - leave - ret - - -L_zero: - movl EXP_UNDER,EXP(%ebx) - movb TW_Zero,TAG(%ebx) - jmp L_exit - -L_underflow: - push %ebx - call arith_underflow - pop %ebx - jmp L_exit - -L_overflow: - push %ebx - call arith_overflow - pop %ebx - jmp L_exit - - - -/* Normalise without reporting underflow or overflow */ -ENTRY(normalize_nuo) - pushl %ebp - movl %esp,%ebp - pushl %ebx - - movl PARAM1,%ebx - - movl SIGH(%ebx),%edx - movl SIGL(%ebx),%eax - - orl %edx,%edx /* ms bits */ - js L_exit /* Already normalized */ - jnz L_nuo_shift_1 /* Shift left 1 - 31 bits */ - - orl %eax,%eax - jz L_zero /* The contents are zero */ - -/* L_nuo_shift_32: */ - movl %eax,%edx - xorl %eax,%eax - subl $32,EXP(%ebx) /* This can cause an underflow */ - -/* We need to shift left by 1 - 31 bits */ -L_nuo_shift_1: - bsrl %edx,%ecx /* get the required shift in %ecx */ - subl $31,%ecx - negl %ecx - shld %cl,%eax,%edx - shl %cl,%eax - subl %ecx,EXP(%ebx) /* This can cause an underflow */ - - movl %edx,SIGH(%ebx) - movl %eax,SIGL(%ebx) - jmp L_exit - - diff --git a/sys/gnu/i386/fpemul/reg_round.s b/sys/gnu/i386/fpemul/reg_round.s deleted file mode 100644 index dd1fa91..0000000 --- a/sys/gnu/i386/fpemul/reg_round.s +++ /dev/null @@ -1,650 +0,0 @@ - .file "reg_round.S" -/* - * reg_round.S - * - * Rounding/truncation/etc for FPU basic arithmetic functions. - * - * This code has four possible entry points. - * The following must be entered by a jmp intruction: - * FPU_round, FPU_round_sqrt, and FPU_Arith_exit. - * - * The _round_reg entry point is intended to be used by C code. - * From C, call as: - * void round_reg(FPU_REG *arg, unsigned int extent, unsigned int control_w) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - -/*---------------------------------------------------------------------------+ - | Four entry points. | - | | - | Needed by both the FPU_round and FPU_round_sqrt entry points: | - | %eax:%ebx 64 bit significand | - | %edx 32 bit extension of the significand | - | %edi pointer to an FPU_REG for the result to be stored | - | stack calling function must have set up a C stack frame and | - | pushed %esi, %edi, and %ebx | - | | - | Needed just for the FPU_round_sqrt entry point: | - | %cx A control word in the same format as the FPU control word. | - | Otherwise, PARAM4 must give such a value. | - | | - | | - | The significand and its extension are assumed to be exact in the | - | following sense: | - | If the significand by itself is the exact result then the significand | - | extension (%edx) must contain 0, otherwise the significand extension | - | must be non-zero. | - | If the significand extension is non-zero then the significand is | - | smaller than the magnitude of the correct exact result by an amount | - | greater than zero and less than one ls bit of the significand. | - | The significand extension is only required to have three possible | - | non-zero values: | - | less than 0x80000000 <=> the significand is less than 1/2 an ls | - | bit smaller than the magnitude of the | - | true exact result. | - | exactly 0x80000000 <=> the significand is exactly 1/2 an ls bit | - | smaller than the magnitude of the true | - | exact result. | - | greater than 0x80000000 <=> the significand is more than 1/2 an ls | - | bit smaller than the magnitude of the | - | true exact result. | - | | - +---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------+ - | The code in this module has become quite complex, but it should handle | - | all of the FPU flags which are set at this stage of the basic arithmetic | - | computations. | - | There are a few rare cases where the results are not set identically to | - | a real FPU. These require a bit more thought because at this stage the | - | results of the code here appear to be more consistent... | - | This may be changed in a future version. | - +---------------------------------------------------------------------------*/ - - -#include <gnu/i386/fpemul/exception.h> -#include <gnu/i386/fpemul/control_w.h> - -#define LOST_DOWN $1 -#define LOST_UP $2 -#define DENORMAL $1 -#define UNMASKED_UNDERFLOW $2 - -.data - ALIGN_DATA -FPU_bits_lost: - .byte 0 -FPU_denormal: - .byte 0 - -.text -.globl FPU_round -.globl FPU_round_sqrt -.globl FPU_Arith_exit - -/* Entry point when called from C */ -ENTRY(round_reg) - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%edi - movl SIGH(%edi),%eax - movl SIGL(%edi),%ebx - movl PARAM2,%edx - movl PARAM3,%ecx - jmp FPU_round_sqrt - -FPU_round: /* Normal entry point */ - movl PARAM4,%ecx - -FPU_round_sqrt: /* Entry point from wm_sqrt.S */ - -#ifdef PARANOID -/* Cannot use this here yet */ -/* orl %eax,%eax */ -/* jns L_entry_bugged */ -#endif /* PARANOID */ - - cmpl EXP_UNDER,EXP(%edi) - jle xMake_denorm /* The number is a de-normal*/ - - movb $0,FPU_denormal /* 0 -> not a de-normal*/ - -xDenorm_done: - movb $0,FPU_bits_lost /*No bits yet lost in rounding*/ - - movl %ecx,%esi - andl CW_PC,%ecx - cmpl PR_64_BITS,%ecx - je LRound_To_64 - - cmpl PR_53_BITS,%ecx - je LRound_To_53 - - cmpl PR_24_BITS,%ecx - je LRound_To_24 - -#ifdef PARANOID - jmp L_bugged /* There is no bug, just a bad control word */ -#endif /* PARANOID */ - - -/* Round etc to 24 bit precision */ -LRound_To_24: - movl %esi,%ecx - andl CW_RC,%ecx - cmpl RC_RND,%ecx - je LRound_nearest_24 - - cmpl RC_CHOP,%ecx - je LCheck_truncate_24 - - cmpl RC_UP,%ecx /* Towards +infinity */ - je LUp_24 - - cmpl RC_DOWN,%ecx /* Towards -infinity */ - je LDown_24 - -#ifdef PARANOID - jmp L_bugged -#endif /* PARANOID */ - -LUp_24: - cmpb SIGN_POS,SIGN(%edi) - jne LCheck_truncate_24 /* If negative then up==truncate */ - - jmp LCheck_24_round_up - -LDown_24: - cmpb SIGN_POS,SIGN(%edi) - je LCheck_truncate_24 /* If positive then down==truncate */ - -LCheck_24_round_up: - movl %eax,%ecx - andl $0x000000ff,%ecx - orl %ebx,%ecx - orl %edx,%ecx - jnz LDo_24_round_up - jmp LRe_normalise - -LRound_nearest_24: - /* Do rounding of the 24th bit if needed (nearest or even) */ - movl %eax,%ecx - andl $0x000000ff,%ecx - cmpl $0x00000080,%ecx - jc LCheck_truncate_24 /*less than half, no increment needed*/ - - jne LGreater_Half_24 /* greater than half, increment needed*/ - - /* Possibly half, we need to check the ls bits */ - orl %ebx,%ebx - jnz LGreater_Half_24 /* greater than half, increment needed*/ - - orl %edx,%edx - jnz LGreater_Half_24 /* greater than half, increment needed*/ - - /* Exactly half, increment only if 24th bit is 1 (round to even)*/ - testl $0x00000100,%eax - jz LDo_truncate_24 - -LGreater_Half_24: /*Rounding: increment at the 24th bit*/ -LDo_24_round_up: - andl $0xffffff00,%eax /*Truncate to 24 bits*/ - xorl %ebx,%ebx - movb LOST_UP,FPU_bits_lost - addl $0x00000100,%eax - jmp LCheck_Round_Overflow - -LCheck_truncate_24: - movl %eax,%ecx - andl $0x000000ff,%ecx - orl %ebx,%ecx - orl %edx,%ecx - jz LRe_normalise /* No truncation needed*/ - -LDo_truncate_24: - andl $0xffffff00,%eax /* Truncate to 24 bits*/ - xorl %ebx,%ebx - movb LOST_DOWN,FPU_bits_lost - jmp LRe_normalise - - -/* Round etc to 53 bit precision */ -LRound_To_53: - movl %esi,%ecx - andl CW_RC,%ecx - cmpl RC_RND,%ecx - je LRound_nearest_53 - - cmpl RC_CHOP,%ecx - je LCheck_truncate_53 - - cmpl RC_UP,%ecx /* Towards +infinity*/ - je LUp_53 - - cmpl RC_DOWN,%ecx /* Towards -infinity*/ - je LDown_53 - -#ifdef PARANOID - jmp L_bugged -#endif /* PARANOID */ - -LUp_53: - cmpb SIGN_POS,SIGN(%edi) - jne LCheck_truncate_53 /* If negative then up==truncate*/ - - jmp LCheck_53_round_up - -LDown_53: - cmpb SIGN_POS,SIGN(%edi) - je LCheck_truncate_53 /* If positive then down==truncate*/ - -LCheck_53_round_up: - movl %ebx,%ecx - andl $0x000007ff,%ecx - orl %edx,%ecx - jnz LDo_53_round_up - jmp LRe_normalise - -LRound_nearest_53: - /*Do rounding of the 53rd bit if needed (nearest or even)*/ - movl %ebx,%ecx - andl $0x000007ff,%ecx - cmpl $0x00000400,%ecx - jc LCheck_truncate_53 /* less than half, no increment needed*/ - - jnz LGreater_Half_53 /* greater than half, increment needed*/ - - /*Possibly half, we need to check the ls bits*/ - orl %edx,%edx - jnz LGreater_Half_53 /* greater than half, increment needed*/ - - /* Exactly half, increment only if 53rd bit is 1 (round to even)*/ - testl $0x00000800,%ebx - jz LTruncate_53 - -LGreater_Half_53: /*Rounding: increment at the 53rd bit*/ -LDo_53_round_up: - movb LOST_UP,FPU_bits_lost - andl $0xfffff800,%ebx /* Truncate to 53 bits*/ - addl $0x00000800,%ebx - adcl $0,%eax - jmp LCheck_Round_Overflow - -LCheck_truncate_53: - movl %ebx,%ecx - andl $0x000007ff,%ecx - orl %edx,%ecx - jz LRe_normalise - -LTruncate_53: - movb LOST_DOWN,FPU_bits_lost - andl $0xfffff800,%ebx /* Truncate to 53 bits*/ - jmp LRe_normalise - - -/* Round etc to 64 bit precision*/ -LRound_To_64: - movl %esi,%ecx - andl CW_RC,%ecx - cmpl RC_RND,%ecx - je LRound_nearest_64 - - cmpl RC_CHOP,%ecx - je LCheck_truncate_64 - - cmpl RC_UP,%ecx /* Towards +infinity*/ - je LUp_64 - - cmpl RC_DOWN,%ecx /* Towards -infinity*/ - je LDown_64 - -#ifdef PARANOID - jmp L_bugged -#endif /* PARANOID */ - -LUp_64: - cmpb SIGN_POS,SIGN(%edi) - jne LCheck_truncate_64 /* If negative then up==truncate*/ - - orl %edx,%edx - jnz LDo_64_round_up - jmp LRe_normalise - -LDown_64: - cmpb SIGN_POS,SIGN(%edi) - je LCheck_truncate_64 /*If positive then down==truncate*/ - - orl %edx,%edx - jnz LDo_64_round_up - jmp LRe_normalise - -LRound_nearest_64: - cmpl $0x80000000,%edx - jc LCheck_truncate_64 - - jne LDo_64_round_up - - /* Now test for round-to-even */ - testb $1,%bl - jz LCheck_truncate_64 - -LDo_64_round_up: - movb LOST_UP,FPU_bits_lost - addl $1,%ebx - adcl $0,%eax - -LCheck_Round_Overflow: - jnc LRe_normalise /* Rounding done, no overflow */ - - /* Overflow, adjust the result (to 1.0) */ - rcrl $1,%eax - rcrl $1,%ebx - incl EXP(%edi) - jmp LRe_normalise - -LCheck_truncate_64: - orl %edx,%edx - jz LRe_normalise - -LTruncate_64: - movb LOST_DOWN,FPU_bits_lost - -LRe_normalise: - testb $0xff,FPU_denormal - jnz xNormalise_result - -xL_Normalised: - cmpb LOST_UP,FPU_bits_lost - je xL_precision_lost_up - - cmpb LOST_DOWN,FPU_bits_lost - je xL_precision_lost_down - -xL_no_precision_loss: - cmpl EXP_OVER,EXP(%edi) - jge L_overflow - - /* store the result */ - movb TW_Valid,TAG(%edi) - -xL_Store_significand: - movl %eax,SIGH(%edi) - movl %ebx,SIGL(%edi) - -FPU_Arith_exit: - popl %ebx - popl %edi - popl %esi - leave - ret - - -/* Set the FPU status flags to represent precision loss due to*/ -/* round-up.*/ -xL_precision_lost_up: - push %eax - call set_precision_flag_up - popl %eax - jmp xL_no_precision_loss - -/* Set the FPU status flags to represent precision loss due to*/ -/* truncation.*/ -xL_precision_lost_down: - push %eax - call set_precision_flag_down - popl %eax - jmp xL_no_precision_loss - - -/* The number is a denormal (which might get rounded up to a normal) -// Shift the number right the required number of bits, which will -// have to be undone later...*/ -xMake_denorm: - /* The action to be taken depends upon whether the underflow - // exception is masked*/ - testb CW_Underflow,%cl /* Underflow mask.*/ - jz xUnmasked_underflow /* Do not make a denormal.*/ - - movb DENORMAL,FPU_denormal - - pushl %ecx /* Save*/ - movl EXP(%edi),%ecx - subl EXP_UNDER+1,%ecx - negl %ecx - - cmpl $64,%ecx /* shrd only works for 0..31 bits */ - jnc xDenorm_shift_more_than_63 - - cmpl $32,%ecx /* shrd only works for 0..31 bits */ - jnc xDenorm_shift_more_than_32 - -/* We got here without jumps by assuming that the most common requirement -// is for a small de-normalising shift. -// Shift by [1..31] bits */ - addl %ecx,EXP(%edi) - orl %edx,%edx /* extension*/ - setne %ch - xorl %edx,%edx - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - orb %ch,%dl - popl %ecx - jmp xDenorm_done - -/* Shift by [32..63] bits*/ -xDenorm_shift_more_than_32: - addl %ecx,EXP(%edi) - subb $32,%cl - orl %edx,%edx - setne %ch - orb %ch,%bl - xorl %edx,%edx - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - orl %edx,%edx /*test these 32 bits*/ - setne %cl - orb %ch,%bl - orb %cl,%bl - movl %ebx,%edx - movl %eax,%ebx - xorl %eax,%eax - popl %ecx - jmp xDenorm_done - -/* Shift by [64..) bits*/ -xDenorm_shift_more_than_63: - cmpl $64,%ecx - jne xDenorm_shift_more_than_64 - -/* Exactly 64 bit shift*/ - addl %ecx,EXP(%edi) - xorl %ecx,%ecx - orl %edx,%edx - setne %cl - orl %ebx,%ebx - setne %ch - orb %ch,%cl - orb %cl,%al - movl %eax,%edx - xorl %eax,%eax - xorl %ebx,%ebx - popl %ecx - jmp xDenorm_done - -xDenorm_shift_more_than_64: - movl EXP_UNDER+1,EXP(%edi) -/* This is easy, %eax must be non-zero, so..*/ - movl $1,%edx - xorl %eax,%eax - xorl %ebx,%ebx - popl %ecx - jmp xDenorm_done - - -xUnmasked_underflow: - /* Increase the exponent by the magic number*/ - addl $(3*(1<<13)),EXP(%edi) - movb UNMASKED_UNDERFLOW,FPU_denormal - jmp xDenorm_done - - -/* Undo the de-normalisation.*/ -xNormalise_result: - cmpb UNMASKED_UNDERFLOW,FPU_denormal - je xSignal_underflow - -/* The number must be a denormal if we got here.*/ -#ifdef PARANOID - /* But check it... just in case.*/ - cmpl EXP_UNDER+1,EXP(%edi) - jne L_norm_bugged -#endif /* PARANOID */ - - orl %eax,%eax /* ms bits*/ - jnz LNormalise_shift_up_to_31 /* Shift left 0 - 31 bits*/ - - orl %ebx,%ebx - jz L_underflow_to_zero /* The contents are zero*/ - -/* Shift left 32 - 63 bits*/ - movl %ebx,%eax - xorl %ebx,%ebx - subl $32,EXP(%edi) - -LNormalise_shift_up_to_31: - bsrl %eax,%ecx /* get the required shift in %ecx */ - subl $31,%ecx - negl %ecx - shld %cl,%ebx,%eax - shl %cl,%ebx - subl %ecx,EXP(%edi) - -LNormalise_shift_done: - testb $0xff,FPU_bits_lost /* bits lost == underflow*/ - jz xL_Normalised - - /* There must be a masked underflow*/ - push %eax - pushl EX_Underflow - call exception - popl %eax - popl %eax - jmp xL_Normalised - - -/* The operations resulted in a number too small to represent. -// Masked response.*/ -L_underflow_to_zero: - push %eax - call set_precision_flag_down - popl %eax - - push %eax - pushl EX_Underflow - call exception - popl %eax - popl %eax - - movb TW_Zero,TAG(%edi) - jmp xL_Store_significand - - -/* The operations resulted in a number too large to represent.*/ -L_overflow: - push %edi - call arith_overflow - pop %edi - jmp FPU_Arith_exit - - -xSignal_underflow: - push %eax - pushl EX_Underflow - call EXCEPTION - popl %eax - popl %eax - jmp xL_Normalised - - -#ifdef PARANOID -/* If we ever get here then we have problems! */ -L_bugged: - pushl EX_INTERNAL|0x201 - call EXCEPTION - popl %ebx - jmp FPU_Arith_exit - -L_norm_bugged: - pushl EX_INTERNAL|0x216 - call EXCEPTION - popl %ebx - jmp FPU_Arith_exit - -L_entry_bugged: - pushl EX_INTERNAL|0x217 - call EXCEPTION - popl %ebx - jmp FPU_Arith_exit -#endif /* PARANOID */ diff --git a/sys/gnu/i386/fpemul/reg_u_add.s b/sys/gnu/i386/fpemul/reg_u_add.s deleted file mode 100644 index 79852be..0000000 --- a/sys/gnu/i386/fpemul/reg_u_add.s +++ /dev/null @@ -1,240 +0,0 @@ - .file "reg_u_add.S" -/* - * reg_u_add.S - * - * Add two valid (TW_Valid) FPU_REG numbers, of the same sign, and put the - * result in a destination FPU_REG. - * - * Call from C as: - * void reg_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, - * int control_w) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - -/* - | Kernel addition routine reg_u_add(reg *arg1, reg *arg2, reg *answ). - | Takes two valid reg f.p. numbers (TW_Valid), which are - | treated as unsigned numbers, - | and returns their sum as a TW_Valid or TW_S f.p. number. - | The returned number is normalized. - | Basic checks are performed if PARANOID is defined. - */ - -#include <gnu/i386/fpemul/fpu_asm.h> - -.text -ENTRY(reg_u_add) - pushl %ebp - movl %esp,%ebp -/* subl $16,%esp*/ - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi /* source 1 */ - movl PARAM2,%edi /* source 2 */ - -#ifdef DENORM_OPERAND - cmpl EXP_UNDER,EXP(%esi) - jg xOp1_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp1_not_denorm: - cmpl EXP_UNDER,EXP(%edi) - jg xOp2_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp2_not_denorm: -#endif /* DENORM_OPERAND */ - -/* xorl %ecx,%ecx*/ - movl EXP(%esi),%ecx - subl EXP(%edi),%ecx /* exp1 - exp2 */ -/* jnc L_arg1_larger*/ - jge L_arg1_larger - - /* num1 is smaller */ - movl SIGL(%esi),%ebx - movl SIGH(%esi),%eax - - movl %edi,%esi - negw %cx - jmp L_accum_loaded - -L_arg1_larger: - /* num1 has larger or equal exponent */ - movl SIGL(%edi),%ebx - movl SIGH(%edi),%eax - -L_accum_loaded: - movl PARAM3,%edi /* destination */ - movb SIGN(%esi),%dl - movb %dl,SIGN(%edi) /* Copy the sign from the first arg */ - - - movl EXP(%esi),%edx - movl %edx,EXP(%edi) /* Copy exponent to destination */ - - xorl %edx,%edx /* clear the extension */ - -#ifdef PARANOID - testl $0x80000000,%eax - je L_bugged - - testl $0x80000000,SIGH(%esi) - je L_bugged -#endif /* PARANOID */ - -/* The number to be shifted is in %eax:%ebx:%edx*/ - cmpw $32,%cx /* shrd only works for 0..31 bits */ - jnc L_more_than_31 - -/* less than 32 bits */ - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - jmp L_shift_done - -L_more_than_31: - cmpw $64,%cx - jnc L_more_than_63 - - subb $32,%cl - jz L_exactly_32 - - shrd %cl,%eax,%edx - shr %cl,%eax - orl %ebx,%ebx - jz L_more_31_no_low /* none of the lowest bits is set*/ - - orl $1,%edx /* record the fact in the extension*/ - -L_more_31_no_low: - movl %eax,%ebx - xorl %eax,%eax - jmp L_shift_done - -L_exactly_32: - movl %ebx,%edx - movl %eax,%ebx - xorl %eax,%eax - jmp L_shift_done - -L_more_than_63: - cmpw $65,%cx - jnc L_more_than_64 - - movl %eax,%edx - orl %ebx,%ebx - jz L_more_63_no_low - - orl $1,%edx - jmp L_more_63_no_low - -L_more_than_64: - movl $1,%edx /* The shifted nr always at least one '1'*/ - -L_more_63_no_low: - xorl %ebx,%ebx - xorl %eax,%eax - -L_shift_done: - /* Now do the addition */ - addl SIGL(%esi),%ebx - adcl SIGH(%esi),%eax - jnc L_round_the_result - - /* Overflow, adjust the result */ - rcrl $1,%eax - rcrl $1,%ebx - rcrl $1,%edx - jnc L_no_bit_lost - - orl $1,%edx - -L_no_bit_lost: - incl EXP(%edi) - -L_round_the_result: - jmp FPU_round /* Round the result*/ - - - -#ifdef PARANOID -/* If we ever get here then we have problems! */ -L_bugged: - pushl EX_INTERNAL|0x201 - call EXCEPTION - pop %ebx - jmp L_exit -#endif /* PARANOID */ - - -L_exit: - popl %ebx - popl %edi - popl %esi - leave - ret diff --git a/sys/gnu/i386/fpemul/reg_u_div.s b/sys/gnu/i386/fpemul/reg_u_div.s deleted file mode 100644 index 6a0850d..0000000 --- a/sys/gnu/i386/fpemul/reg_u_div.s +++ /dev/null @@ -1,501 +0,0 @@ - .file "reg_u_div.S" -/* - * reg_u_div.S - * - * Core division routines - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -/*---------------------------------------------------------------------------+ - | Kernel for the division routines. | - | | - | void reg_u_div(FPU_REG *a, FPU_REG *a, | - | FPU_REG *dest, unsigned int control_word) | - | | - | Does not compute the destination exponent, but does adjust it. | - +---------------------------------------------------------------------------*/ - -#include <gnu/i386/fpemul/fpu_asm.h> - - -/* #define dSIGL(x) (x) */ -/* #define dSIGH(x) 4(x) */ - - -.data -/* - Local storage: - Result: accum_3:accum_2:accum_1:accum_0 - Overflow flag: ovfl_flag - */ - ALIGN_DATA -accum_3: - .long 0 -accum_2: - .long 0 -accum_1: - .long 0 -accum_0: - .long 0 -result_1: - .long 0 -result_2: - .long 0 -ovfl_flag: - .byte 0 - - -.text - -.globl divide_kernel - -ENTRY(reg_u_div) - pushl %ebp - movl %esp,%ebp - - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi /* pointer to num */ - movl PARAM2,%ebx /* pointer to denom */ - movl PARAM3,%edi /* pointer to answer */ - -#ifdef DENORM_OPERAND - movl EXP(%esi),%eax - cmpl EXP_UNDER,%eax - jg xOp1_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp1_not_denorm: - movl EXP(%ebx),%eax - cmpl EXP_UNDER,%eax - jg xOp2_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp2_not_denorm: -#endif /* DENORM_OPERAND */ - -divide_kernel: -#ifdef PARANOID -/* testl $0x80000000, SIGH(%esi) *//* Dividend */ -/* je L_bugged */ - testl $0x80000000, SIGH(%ebx) /* Divisor*/ - je L_bugged -#endif /* PARANOID */ - -/* Check if the divisor can be treated as having just 32 bits */ - cmpl $0,SIGL(%ebx) - jnz L_Full_Division /* Can't do a quick divide */ - -/* We should be able to zip through the division here */ - movl SIGH(%ebx),%ecx /* The divisor */ - movl SIGH(%esi),%edx /* Dividend */ - movl SIGL(%esi),%eax /* Dividend */ - - cmpl %ecx,%edx - setaeb ovfl_flag /* Keep a record */ - jb L_no_adjust - - subl %ecx,%edx /* Prevent the overflow */ - -L_no_adjust: - /* Divide the 64 bit number by the 32 bit denominator */ - divl %ecx - movl %eax,result_2 - - /* Work on the remainder of the first division */ - xorl %eax,%eax - divl %ecx - movl %eax,result_1 - - /* Work on the remainder of the 64 bit division */ - xorl %eax,%eax - divl %ecx - - testb $255,ovfl_flag /* was the num > denom ? */ - je L_no_overflow - - /* Do the shifting here */ - /* increase the exponent */ - incl EXP(%edi) - - /* shift the mantissa right one bit */ - stc /* To set the ms bit */ - rcrl result_2 - rcrl result_1 - rcrl %eax - -L_no_overflow: - jmp LRound_precision /* Do the rounding as required*/ - - -/*---------------------------------------------------------------------------+ - | Divide: Return arg1/arg2 to arg3. | - | | - | This routine does not use the exponents of arg1 and arg2, but does | - | adjust the exponent of arg3. | - | | - | The maximum returned value is (ignoring exponents) | - | .ffffffff ffffffff | - | ------------------ = 1.ffffffff fffffffe | - | .80000000 00000000 | - | and the minimum is | - | .80000000 00000000 | - | ------------------ = .80000000 00000001 (rounded) | - | .ffffffff ffffffff | - | | - +---------------------------------------------------------------------------*/ - - -L_Full_Division: - /* Save extended dividend in local register*/ - movl SIGL(%esi),%eax - movl %eax,accum_2 - movl SIGH(%esi),%eax - movl %eax,accum_3 - xorl %eax,%eax - movl %eax,accum_1 /* zero the extension */ - movl %eax,accum_0 /* zero the extension */ - - movl SIGL(%esi),%eax /* Get the current num */ - movl SIGH(%esi),%edx - -/*----------------------------------------------------------------------*/ -/* Initialization done */ -/* Do the first 32 bits */ - - movb $0,ovfl_flag - cmpl SIGH(%ebx),%edx /* Test for imminent overflow */ - jb LLess_than_1 - ja LGreater_than_1 - - cmpl SIGL(%ebx),%eax - jb LLess_than_1 - -LGreater_than_1: -/* The dividend is greater or equal, would cause overflow */ - setaeb ovfl_flag /* Keep a record */ - - subl SIGL(%ebx),%eax - sbbl SIGH(%ebx),%edx /* Prevent the overflow */ - movl %eax,accum_2 - movl %edx,accum_3 - -LLess_than_1: -/* At this point, we have a dividend < divisor, with a record of - adjustment in ovfl_flag */ - - /* We will divide by a number which is too large */ - movl SIGH(%ebx),%ecx - addl $1,%ecx - jnc LFirst_div_not_1 - - /* here we need to divide by 100000000h, - i.e., no division at all.. */ - mov %edx,%eax - jmp LFirst_div_done - -LFirst_div_not_1: - divl %ecx /* Divide the numerator by the augmented - denom ms dw */ - -LFirst_div_done: - movl %eax,result_2 /* Put the result in the answer */ - - mull SIGH(%ebx) /* mul by the ms dw of the denom */ - - subl %eax,accum_2 /* Subtract from the num local reg */ - sbbl %edx,accum_3 - - movl result_2,%eax /* Get the result back */ - mull SIGL(%ebx) /* now mul the ls dw of the denom */ - - subl %eax,accum_1 /* Subtract from the num local reg */ - sbbl %edx,accum_2 - sbbl $0,accum_3 - je LDo_2nd_32_bits /* Must check for non-zero result here */ - -#ifdef PARANOID - jb L_bugged_1 -#endif /* PARANOID */ - - /* need to subtract another once of the denom */ - incl result_2 /* Correct the answer */ - - movl SIGL(%ebx),%eax - movl SIGH(%ebx),%edx - subl %eax,accum_1 /* Subtract from the num local reg */ - sbbl %edx,accum_2 - -#ifdef PARANOID - sbbl $0,accum_3 - jne L_bugged_1 /* Must check for non-zero result here */ -#endif /* PARANOID */ - -/*----------------------------------------------------------------------*/ -/* Half of the main problem is done, there is just a reduced numerator - to handle now */ -/* Work with the second 32 bits, accum_0 not used from now on */ -LDo_2nd_32_bits: - movl accum_2,%edx /* get the reduced num */ - movl accum_1,%eax - - /* need to check for possible subsequent overflow */ - cmpl SIGH(%ebx),%edx - jb LDo_2nd_div - ja LPrevent_2nd_overflow - - cmpl SIGL(%ebx),%eax - jb LDo_2nd_div - -LPrevent_2nd_overflow: -/* The numerator is greater or equal, would cause overflow */ - /* prevent overflow */ - subl SIGL(%ebx),%eax - sbbl SIGH(%ebx),%edx - movl %edx,accum_2 - movl %eax,accum_1 - - incl result_2 /* Reflect the subtraction in the answer */ - -#ifdef PARANOID - je L_bugged_2 /* Can't bump the result to 1.0 */ -#endif /* PARANOID */ - -LDo_2nd_div: - cmpl $0,%ecx /* augmented denom msw*/ - jnz LSecond_div_not_1 - - /* %ecx == 0, we are dividing by 1.0 */ - mov %edx,%eax - jmp LSecond_div_done - -LSecond_div_not_1: - divl %ecx /* Divide the numerator by the denom ms dw */ - -LSecond_div_done: - movl %eax,result_1 /* Put the result in the answer */ - - mull SIGH(%ebx) /* mul by the ms dw of the denom */ - - subl %eax,accum_1 /* Subtract from the num local reg */ - sbbl %edx,accum_2 - -#ifdef PARANOID - jc L_bugged_2 -#endif /* PARANOID */ - - movl result_1,%eax /* Get the result back */ - mull SIGL(%ebx) /* now mul the ls dw of the denom */ - - subl %eax,accum_0 /* Subtract from the num local reg */ - sbbl %edx,accum_1 /* Subtract from the num local reg */ - sbbl $0,accum_2 - -#ifdef PARANOID - jc L_bugged_2 -#endif /* PARANOID */ - - jz LDo_3rd_32_bits - -#ifdef PARANOID - cmpl $1,accum_2 - jne L_bugged_2 -#endif /* PARANOID */ - - /* need to subtract another once of the denom */ - movl SIGL(%ebx),%eax - movl SIGH(%ebx),%edx - subl %eax,accum_0 /* Subtract from the num local reg */ - sbbl %edx,accum_1 - sbbl $0,accum_2 - -#ifdef PARANOID - jc L_bugged_2 - jne L_bugged_2 -#endif /* PARANOID */ - - addl $1,result_1 /* Correct the answer */ - adcl $0,result_2 - -#ifdef PARANOID - jc L_bugged_2 /* Must check for non-zero result here */ -#endif /* PARANOID */ - -/*----------------------------------------------------------------------*/ -/* The division is essentially finished here, we just need to perform - tidying operations. */ -/* deal with the 3rd 32 bits */ -LDo_3rd_32_bits: - movl accum_1,%edx /* get the reduced num */ - movl accum_0,%eax - - /* need to check for possible subsequent overflow */ - cmpl SIGH(%ebx),%edx /* denom*/ - jb LRound_prep - ja LPrevent_3rd_overflow - - cmpl SIGL(%ebx),%eax /* denom */ - jb LRound_prep - -LPrevent_3rd_overflow: - /* prevent overflow */ - subl SIGL(%ebx),%eax - sbbl SIGH(%ebx),%edx - movl %edx,accum_1 - movl %eax,accum_0 - - addl $1,result_1 /* Reflect the subtraction in the answer */ - adcl $0,result_2 - jne LRound_prep - jnc LRound_prep - - /* This is a tricky spot, there is an overflow of the answer */ - movb $255,ovfl_flag /* Overflow -> 1.000 */ - -LRound_prep: -/* Prepare for rounding. -// To test for rounding, we just need to compare 2*accum with the -// denom. */ - movl accum_0,%ecx - movl accum_1,%edx - movl %ecx,%eax - orl %edx,%eax - jz LRound_ovfl /* The accumulator contains zero.*/ - - /* Multiply by 2 */ - clc - rcll $1,%ecx - rcll $1,%edx - jc LRound_large /* No need to compare, denom smaller */ - - subl SIGL(%ebx),%ecx - sbbl SIGH(%ebx),%edx - jnc LRound_not_small - - movl $0x70000000,%eax /* Denom was larger */ - jmp LRound_ovfl - -LRound_not_small: - jnz LRound_large - - movl $0x80000000,%eax /* Remainder was exactly 1/2 denom */ - jmp LRound_ovfl - -LRound_large: - movl $0xff000000,%eax /* Denom was smaller */ - -LRound_ovfl: -/* We are now ready to deal with rounding, but first we must get - the bits properly aligned */ - testb $255,ovfl_flag /* was the num > denom ? */ - je LRound_precision - - incl EXP(%edi) - - /* shift the mantissa right one bit */ - stc /* Will set the ms bit */ - rcrl result_2 - rcrl result_1 - rcrl %eax - -/* Round the result as required */ -LRound_precision: - decl EXP(%edi) /* binary point between 1st & 2nd bits */ - - movl %eax,%edx - movl result_1,%ebx - movl result_2,%eax - jmp FPU_round - - -#ifdef PARANOID -/* The logic is wrong if we got here */ -L_bugged: - pushl EX_INTERNAL|0x202 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_1: - pushl EX_INTERNAL|0x203 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_2: - pushl EX_INTERNAL|0x204 - call EXCEPTION - pop %ebx - jmp L_exit - -L_exit: - popl %ebx - popl %edi - popl %esi - - leave - ret -#endif /* PARANOID */ diff --git a/sys/gnu/i386/fpemul/reg_u_mul.s b/sys/gnu/i386/fpemul/reg_u_mul.s deleted file mode 100644 index d4c20a7..0000000 --- a/sys/gnu/i386/fpemul/reg_u_mul.s +++ /dev/null @@ -1,194 +0,0 @@ - .file "reg_u_mul.S" -/* - * reg_u_mul.S - * - * Core multiplication routine - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -/*---------------------------------------------------------------------------+ - | Basic multiplication routine. | - | Does not check the resulting exponent for overflow/underflow | - | | - | reg_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw); | - | | - | Internal working is at approx 128 bits. | - | Result is rounded to nearest 53 or 64 bits, using "nearest or even". | - +---------------------------------------------------------------------------*/ - -#include <gnu/i386/fpemul/fpu_asm.h> - - -.data - ALIGN_DATA -accum_0: - .long 0 -accum_1: - .long 0 - - -.text -ENTRY(reg_u_mul) - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi - movl PARAM2,%edi - -#ifdef PARANOID - testl $0x80000000,SIGH(%esi) - jz L_bugged - testl $0x80000000,SIGH(%edi) - jz L_bugged -#endif /* PARANOID */ - -#ifdef DENORM_OPERAND - movl EXP(%esi),%eax - cmpl EXP_UNDER,%eax - jg xOp1_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp1_not_denorm: - movl EXP(%edi),%eax - cmpl EXP_UNDER,%eax - jg xOp2_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp2_not_denorm: -#endif /* DENORM_OPERAND */ - - xorl %ecx,%ecx - xorl %ebx,%ebx - - movl SIGL(%esi),%eax - mull SIGL(%edi) - movl %eax,accum_0 - movl %edx,accum_1 - - movl SIGL(%esi),%eax - mull SIGH(%edi) - addl %eax,accum_1 - adcl %edx,%ebx -/* adcl $0,%ecx *//* overflow here is not possible */ - - movl SIGH(%esi),%eax - mull SIGL(%edi) - addl %eax,accum_1 - adcl %edx,%ebx - adcl $0,%ecx - - movl SIGH(%esi),%eax - mull SIGH(%edi) - addl %eax,%ebx - adcl %edx,%ecx - - movl EXP(%esi),%eax /* Compute the exponent */ - addl EXP(%edi),%eax - subl EXP_BIAS-1,%eax -/* Have now finished with the sources */ - movl PARAM3,%edi /* Point to the destination */ - movl %eax,EXP(%edi) - -/* Now make sure that the result is normalized */ - testl $0x80000000,%ecx - jnz LResult_Normalised - - /* Normalize by shifting left one bit */ - shll $1,accum_0 - rcll $1,accum_1 - rcll $1,%ebx - rcll $1,%ecx - decl EXP(%edi) - -LResult_Normalised: - movl accum_0,%eax - movl accum_1,%edx - orl %eax,%eax - jz L_extent_zero - - orl $1,%edx - -L_extent_zero: - movl %ecx,%eax - jmp FPU_round - - -#ifdef PARANOID -L_bugged: - pushl EX_INTERNAL|0x205 - call EXCEPTION - pop %ebx - jmp L_exit - -L_exit: - popl %ebx - popl %edi - popl %esi - leave - ret -#endif /* PARANOID */ - diff --git a/sys/gnu/i386/fpemul/reg_u_sub.s b/sys/gnu/i386/fpemul/reg_u_sub.s deleted file mode 100644 index 2a3903a..0000000 --- a/sys/gnu/i386/fpemul/reg_u_sub.s +++ /dev/null @@ -1,357 +0,0 @@ - .file "reg_u_sub.S" -/* - * reg_u_sub.S - * - * Core floating point subtraction routine. - * - * Call from C as: - * void reg_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, - * int control_w) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -/* - | Kernel subtraction routine reg_u_sub(reg *arg1, reg *arg2, reg *answ). - | Takes two valid reg f.p. numbers (TW_Valid), which are - | treated as unsigned numbers, - | and returns their difference as a TW_Valid or TW_Zero f.p. - | number. - | The first number (arg1) must be the larger. - | The returned number is normalized. - | Basic checks are performed if PARANOID is defined. - */ - -#include <gnu/i386/fpemul/fpu_asm.h> - -.text -ENTRY(reg_u_sub) - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi /* source 1 */ - movl PARAM2,%edi /* source 2 */ - -#ifdef DENORM_OPERAND - cmpl EXP_UNDER,EXP(%esi) - jg xOp1_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp1_not_denorm: - cmpl EXP_UNDER,EXP(%edi) - jg xOp2_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp2_not_denorm: -#endif /* DENORM_OPERAND */ - -/* xorl %ecx,%ecx */ - movl EXP(%esi),%ecx - subl EXP(%edi),%ecx /* exp1 - exp2 */ - -#ifdef PARANOID - /* source 2 is always smaller than source 1 */ -/* jc L_bugged */ - js L_bugged_1 - - testl $0x80000000,SIGH(%edi) /* The args are assumed to be be normalized */ - je L_bugged_2 - - testl $0x80000000,SIGH(%esi) - je L_bugged_2 -#endif /* PARANOID */ - -/*--------------------------------------+ - | Form a register holding the | - | smaller number | - +--------------------------------------*/ - movl SIGH(%edi),%eax /* register ms word */ - movl SIGL(%edi),%ebx /* register ls word */ - - movl PARAM3,%edi /* destination */ - movl EXP(%esi),%edx - movl %edx,EXP(%edi) /* Copy exponent to destination */ - movb SIGN(%esi),%dl - movb %dl,SIGN(%edi) /* Copy the sign from the first arg */ - - xorl %edx,%edx /* register extension */ - -/*--------------------------------------+ - | Shift the temporary register | - | right the required number of | - | places. | - +--------------------------------------*/ -L_shift_r: - cmpl $32,%ecx /* shrd only works for 0..31 bits */ - jnc L_more_than_31 - -/* less than 32 bits */ - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - jmp L_shift_done - -L_more_than_31: - cmpl $64,%ecx - jnc L_more_than_63 - - subb $32,%cl - jz L_exactly_32 - - shrd %cl,%eax,%edx - shr %cl,%eax - orl %ebx,%ebx - jz L_more_31_no_low /* none of the lowest bits is set */ - - orl $1,%edx /* record the fact in the extension */ - -L_more_31_no_low: - movl %eax,%ebx - xorl %eax,%eax - jmp L_shift_done - -L_exactly_32: - movl %ebx,%edx - movl %eax,%ebx - xorl %eax,%eax - jmp L_shift_done - -L_more_than_63: - cmpw $65,%cx - jnc L_more_than_64 - - /* Shift right by 64 bits */ - movl %eax,%edx - orl %ebx,%ebx - jz L_more_63_no_low - - orl $1,%edx - jmp L_more_63_no_low - -L_more_than_64: - jne L_more_than_65 - - /* Shift right by 65 bits */ - /* Carry is clear if we get here */ - movl %eax,%edx - rcrl %edx - jnc L_shift_65_nc - - orl $1,%edx - jmp L_more_63_no_low - -L_shift_65_nc: - orl %ebx,%ebx - jz L_more_63_no_low - - orl $1,%edx - jmp L_more_63_no_low - -L_more_than_65: - movl $1,%edx /* The shifted nr always at least one '1' */ - -L_more_63_no_low: - xorl %ebx,%ebx - xorl %eax,%eax - -L_shift_done: -L_subtr: -/*------------------------------+ - | Do the subtraction | - +------------------------------*/ - xorl %ecx,%ecx - subl %edx,%ecx - movl %ecx,%edx - movl SIGL(%esi),%ecx - sbbl %ebx,%ecx - movl %ecx,%ebx - movl SIGH(%esi),%ecx - sbbl %eax,%ecx - movl %ecx,%eax - -#ifdef PARANOID - /* We can never get a borrow */ - jc L_bugged -#endif /* PARANOID */ - -/*--------------------------------------+ - | Normalize the result | - +--------------------------------------*/ - testl $0x80000000,%eax - jnz L_round /* no shifting needed */ - - orl %eax,%eax - jnz L_shift_1 /* shift left 1 - 31 bits */ - - orl %ebx,%ebx - jnz L_shift_32 /* shift left 32 - 63 bits */ - -/* A rare case, the only one which is non-zero if we got here -// is: 1000000 .... 0000 -// -0111111 .... 1111 1 -// -------------------- -// 0000000 .... 0000 1 */ - - cmpl $0x80000000,%edx - jnz L_must_be_zero - - /* Shift left 64 bits */ - subl $64,EXP(%edi) - movl %edx,%eax - jmp L_store - -L_must_be_zero: -#ifdef PARANOID - orl %edx,%edx - jnz L_bugged_3 -#endif /* PARANOID */ - - /* The result is zero */ - movb TW_Zero,TAG(%edi) - movl $0,EXP(%edi) /* exponent */ - movl $0,SIGL(%edi) - movl $0,SIGH(%edi) - jmp L_exit /* Does not underflow */ - -L_shift_32: - movl %ebx,%eax - movl %edx,%ebx - movl $0,%edx - subl $32,EXP(%edi) /* Can get underflow here */ - -/* We need to shift left by 1 - 31 bits */ -L_shift_1: - bsrl %eax,%ecx /* get the required shift in %ecx */ - subl $31,%ecx - negl %ecx - shld %cl,%ebx,%eax - shld %cl,%edx,%ebx - shl %cl,%edx - subl %ecx,EXP(%edi) /* Can get underflow here */ - -L_round: - jmp FPU_round /* Round the result */ - - -#ifdef PARANOID -L_bugged_1: - pushl EX_INTERNAL|0x206 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_2: - pushl EX_INTERNAL|0x209 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_3: - pushl EX_INTERNAL|0x210 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_4: - pushl EX_INTERNAL|0x211 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged: - pushl EX_INTERNAL|0x212 - call EXCEPTION - pop %ebx - jmp L_exit -#endif /* PARANOID */ - - -L_store: -/*------------------------------+ - | Store the result | - +------------------------------*/ - movl %eax,SIGH(%edi) - movl %ebx,SIGL(%edi) - - movb TW_Valid,TAG(%edi) /* Set the tags to TW_Valid */ - - cmpl EXP_UNDER,EXP(%edi) - jle L_underflow - -L_exit: - popl %ebx - popl %edi - popl %esi - leave - ret - - -L_underflow: - push %edi - call arith_underflow - pop %ebx - jmp L_exit - diff --git a/sys/gnu/i386/fpemul/status_w.h b/sys/gnu/i386/fpemul/status_w.h deleted file mode 100644 index 4d15641..0000000 --- a/sys/gnu/i386/fpemul/status_w.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * status_w.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - -#ifndef _STATUS_H_ -#define _STATUS_H_ - - -#ifdef LOCORE -#define Const__(x) $/**/x -#else -#define Const__(x) x -#endif - -#define SW_Backward Const__(0x8000) /* backward compatibility */ -#define SW_C3 Const__(0x4000) /* condition bit 3 */ -#define SW_Top Const__(0x3800) /* top of stack */ -#define SW_Top_Shift Const__(11) /* shift for top of stack bits */ -#define SW_C2 Const__(0x0400) /* condition bit 2 */ -#define SW_C1 Const__(0x0200) /* condition bit 1 */ -#define SW_C0 Const__(0x0100) /* condition bit 0 */ -#define SW_Summary Const__(0x0080) /* exception summary */ -#define SW_Stack_Fault Const__(0x0040) /* stack fault */ -#define SW_Precision Const__(0x0020) /* loss of precision */ -#define SW_Underflow Const__(0x0010) /* underflow */ -#define SW_Overflow Const__(0x0008) /* overflow */ -#define SW_Zero_Div Const__(0x0004) /* divide by zero */ -#define SW_Denorm_Op Const__(0x0002) /* denormalized operand */ -#define SW_Invalid Const__(0x0001) /* invalid operation */ - -#define SW_Exc_Mask Const__(0x27f) /* Status word exception bit mask */ - -#ifndef LOCORE - -#define COMP_A_gt_B 1 -#define COMP_A_eq_B 2 -#define COMP_A_lt_B 3 -#define COMP_No_Comp 4 -#define COMP_Denormal 0x20 -#define COMP_NaN 0x40 -#define COMP_SNaN 0x80 - -#define setcc(cc) ({ \ - status_word &= ~(SW_C0|SW_C1|SW_C2|SW_C3); \ - status_word |= (cc) & (SW_C0|SW_C1|SW_C2|SW_C3); }) - -#endif /* LOCORE */ - -#endif /* _STATUS_H_ */ diff --git a/sys/gnu/i386/fpemul/version.h b/sys/gnu/i386/fpemul/version.h deleted file mode 100644 index 38f6b93..0000000 --- a/sys/gnu/i386/fpemul/version.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * version.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - -#define FPU_VERSION "wm-FPU-emu version BETA 1.4" diff --git a/sys/gnu/i386/fpemul/wm_shrx.s b/sys/gnu/i386/fpemul/wm_shrx.s deleted file mode 100644 index 19bdb7e..0000000 --- a/sys/gnu/i386/fpemul/wm_shrx.s +++ /dev/null @@ -1,258 +0,0 @@ - .file "wm_shrx.S" -/* - * wm_shrx.S - * - * 64 bit right shift functions - * - * Call from C as: - * unsigned shrx(void *arg1, unsigned arg2) - * and - * unsigned shrxs(void *arg1, unsigned arg2) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - -#include <gnu/i386/fpemul/fpu_asm.h> - -.text - -/*---------------------------------------------------------------------------+ - | unsigned shrx(void *arg1, unsigned arg2) | - | | - | Extended shift right function. | - | Fastest for small shifts. | - | Shifts the 64 bit quantity pointed to by the first arg (arg1) | - | right by the number of bits specified by the second arg (arg2). | - | Forms a 96 bit quantity from the 64 bit arg and eax: | - | [ 64 bit arg ][ eax ] | - | shift right ---------> | - | The eax register is initialized to 0 before the shifting. | - | Results returned in the 64 bit arg and eax. | - +---------------------------------------------------------------------------*/ - -ENTRY(shrx) - push %ebp - movl %esp,%ebp - pushl %esi - movl PARAM2,%ecx - movl PARAM1,%esi - cmpl $32,%ecx /* shrd only works for 0..31 bits */ - jnc L_more_than_31 - -/* less than 32 bits */ - pushl %ebx - movl (%esi),%ebx /* lsl */ - movl 4(%esi),%edx /* msl */ - xorl %eax,%eax /* extension */ - shrd %cl,%ebx,%eax - shrd %cl,%edx,%ebx - shr %cl,%edx - movl %ebx,(%esi) - movl %edx,4(%esi) - popl %ebx - popl %esi - leave - ret - -L_more_than_31: - cmpl $64,%ecx - jnc L_more_than_63 - - subb $32,%cl - movl (%esi),%eax /* lsl */ - movl 4(%esi),%edx /* msl */ - shrd %cl,%edx,%eax - shr %cl,%edx - movl %edx,(%esi) - movl $0,4(%esi) - popl %esi - leave - ret - -L_more_than_63: - cmpl $96,%ecx - jnc L_more_than_95 - - subb $64,%cl - movl 4(%esi),%eax /* msl */ - shr %cl,%eax - xorl %edx,%edx - movl %edx,(%esi) - movl %edx,4(%esi) - popl %esi - leave - ret - -L_more_than_95: - xorl %eax,%eax - movl %eax,(%esi) - movl %eax,4(%esi) - popl %esi - leave - ret - - -/*---------------------------------------------------------------------------+ - | unsigned shrxs(void *arg1, unsigned arg2) | - | | - | Extended shift right function (optimized for small floating point | - | integers). | - | Shifts the 64 bit quantity pointed to by the first arg (arg1) | - | right by the number of bits specified by the second arg (arg2). | - | Forms a 96 bit quantity from the 64 bit arg and eax: | - | [ 64 bit arg ][ eax ] | - | shift right ---------> | - | The eax register is initialized to 0 before the shifting. | - | The lower 8 bits of eax are lost and replaced by a flag which is | - | set (to 0x01) if any bit, apart from the first one, is set in the | - | part which has been shifted out of the arg. | - | Results returned in the 64 bit arg and eax. | - +---------------------------------------------------------------------------*/ - .globl shrxs -shrxs: - push %ebp - movl %esp,%ebp - pushl %esi - pushl %ebx - movl PARAM2,%ecx - movl PARAM1,%esi - cmpl $64,%ecx /* shrd only works for 0..31 bits */ - jnc Ls_more_than_63 - - cmpl $32,%ecx /* shrd only works for 0..31 bits */ - jc Ls_less_than_32 - -/* We got here without jumps by assuming that the most common requirement - is for small integers */ -/* Shift by [32..63] bits */ - subb $32,%cl - movl (%esi),%eax /* lsl */ - movl 4(%esi),%edx /* msl */ - xorl %ebx,%ebx - shrd %cl,%eax,%ebx - shrd %cl,%edx,%eax - shr %cl,%edx - orl %ebx,%ebx /* test these 32 bits */ - setne %bl - test $0x7fffffff,%eax /* and 31 bits here */ - setne %bh - orw %bx,%bx /* Any of the 63 bit set ? */ - setne %al - movl %edx,(%esi) - movl $0,4(%esi) - popl %ebx - popl %esi - leave - ret - -/* Shift by [0..31] bits */ -Ls_less_than_32: - movl (%esi),%ebx /* lsl */ - movl 4(%esi),%edx /* msl */ - xorl %eax,%eax /* extension */ - shrd %cl,%ebx,%eax - shrd %cl,%edx,%ebx - shr %cl,%edx - test $0x7fffffff,%eax /* only need to look at eax here */ - setne %al - movl %ebx,(%esi) - movl %edx,4(%esi) - popl %ebx - popl %esi - leave - ret - -/* Shift by [64..95] bits */ -Ls_more_than_63: - cmpl $96,%ecx - jnc Ls_more_than_95 - - subb $64,%cl - movl (%esi),%ebx /* lsl */ - movl 4(%esi),%eax /* msl */ - xorl %edx,%edx /* extension */ - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - orl %ebx,%edx - setne %bl - test $0x7fffffff,%eax /* only need to look at eax here */ - setne %bh - orw %bx,%bx - setne %al - xorl %edx,%edx - movl %edx,(%esi) /* set to zero */ - movl %edx,4(%esi) /* set to zero */ - popl %ebx - popl %esi - leave - ret - -Ls_more_than_95: -/* Shift by [96..inf) bits */ - xorl %eax,%eax - movl (%esi),%ebx - orl 4(%esi),%ebx - setne %al - xorl %ebx,%ebx - movl %ebx,(%esi) - movl %ebx,4(%esi) - popl %ebx - popl %esi - leave - ret diff --git a/sys/gnu/i386/fpemul/wm_sqrt.s b/sys/gnu/i386/fpemul/wm_sqrt.s deleted file mode 100644 index d0cd415..0000000 --- a/sys/gnu/i386/fpemul/wm_sqrt.s +++ /dev/null @@ -1,492 +0,0 @@ - .file "wm_sqrt.S" -/* - * wm_sqrt.S - * - * Fixed point arithmetic square root evaluation. - * - * Call from C as: - * void wm_sqrt(FPU_REG *n, unsigned int control_word) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD$ - * - */ - - -/*---------------------------------------------------------------------------+ - | wm_sqrt(FPU_REG *n, unsigned int control_word) | - | returns the square root of n in n. | - | | - | Use Newton's method to compute the square root of a number, which must | - | be in the range [1.0 .. 4.0), to 64 bits accuracy. | - | Does not check the sign or tag of the argument. | - | Sets the exponent, but not the sign or tag of the result. | - | | - | The guess is kept in %esi:%edi | - +---------------------------------------------------------------------------*/ - -#include <gnu/i386/fpemul/fpu_asm.h> - - -.data -/* - Local storage: - */ - ALIGN_DATA -accum_3: - .long 0 /* ms word */ -accum_2: - .long 0 -accum_1: - .long 0 -accum_0: - .long 0 - -/* The de-normalised argument: -// sq_2 sq_1 sq_0 -// b b b b b b b ... b b b b b b .... b b b b 0 0 0 ... 0 -// ^ binary point here */ -fsqrt_arg_2: - .long 0 /* ms word */ -fsqrt_arg_1: - .long 0 -fsqrt_arg_0: - .long 0 /* ls word, at most the ms bit is set */ - -.text - -ENTRY(wm_sqrt) - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi - - movl SIGH(%esi),%eax - movl SIGL(%esi),%ecx - xorl %edx,%edx - -/* We use a rough linear estimate for the first guess.. */ - - cmpl EXP_BIAS,EXP(%esi) - jnz sqrt_arg_ge_2 - - shrl $1,%eax /* arg is in the range [1.0 .. 2.0) */ - rcrl $1,%ecx - rcrl $1,%edx - -sqrt_arg_ge_2: -/* From here on, n is never accessed directly again until it is -// replaced by the answer. */ - - movl %eax,fsqrt_arg_2 /* ms word of n */ - movl %ecx,fsqrt_arg_1 - movl %edx,fsqrt_arg_0 - -/* Make a linear first estimate */ - shrl $1,%eax - addl $0x40000000,%eax - movl $0xaaaaaaaa,%ecx - mull %ecx - shll %edx /* max result was 7fff... */ - testl $0x80000000,%edx /* but min was 3fff... */ - jnz sqrt_prelim_no_adjust - - movl $0x80000000,%edx /* round up */ - -sqrt_prelim_no_adjust: - movl %edx,%esi /* Our first guess */ - -/* We have now computed (approx) (2 + x) / 3, which forms the basis - for a few iterations of Newton's method */ - - movl fsqrt_arg_2,%ecx /* ms word */ - -/* From our initial estimate, three iterations are enough to get us -// to 30 bits or so. This will then allow two iterations at better -// precision to complete the process. - -// Compute (g + n/g)/2 at each iteration (g is the guess). */ - shrl %ecx /* Doing this first will prevent a divide */ - /* overflow later. */ - - movl %ecx,%edx /* msw of the arg / 2 */ - divl %esi /* current estimate */ - shrl %esi /* divide by 2 */ - addl %eax,%esi /* the new estimate */ - - movl %ecx,%edx - divl %esi - shrl %esi - addl %eax,%esi - - movl %ecx,%edx - divl %esi - shrl %esi - addl %eax,%esi - -/* Now that an estimate accurate to about 30 bits has been obtained (in %esi), -// we improve it to 60 bits or so. - -// The strategy from now on is to compute new estimates from -// guess := guess + (n - guess^2) / (2 * guess) */ - -/* First, find the square of the guess */ - movl %esi,%eax - mull %esi -/* guess^2 now in %edx:%eax */ - - movl fsqrt_arg_1,%ecx - subl %ecx,%eax - movl fsqrt_arg_2,%ecx /* ms word of normalized n */ - sbbl %ecx,%edx - jnc sqrt_stage_2_positive -/* subtraction gives a negative result -// negate the result before division */ - notl %edx - notl %eax - addl $1,%eax - adcl $0,%edx - - divl %esi - movl %eax,%ecx - - movl %edx,%eax - divl %esi - jmp sqrt_stage_2_finish - -sqrt_stage_2_positive: - divl %esi - movl %eax,%ecx - - movl %edx,%eax - divl %esi - - notl %ecx - notl %eax - addl $1,%eax - adcl $0,%ecx - -sqrt_stage_2_finish: - sarl $1,%ecx /* divide by 2 */ - rcrl $1,%eax - - /* Form the new estimate in %esi:%edi */ - movl %eax,%edi - addl %ecx,%esi - - jnz sqrt_stage_2_done /* result should be [1..2) */ - -#ifdef PARANOID -/* It should be possible to get here only if the arg is ffff....ffff*/ - cmp $0xffffffff,fsqrt_arg_1 - jnz sqrt_stage_2_error -#endif /* PARANOID */ - -/* The best rounded result.*/ - xorl %eax,%eax - decl %eax - movl %eax,%edi - movl %eax,%esi - movl $0x7fffffff,%eax - jmp sqrt_round_result - -#ifdef PARANOID -sqrt_stage_2_error: - pushl EX_INTERNAL|0x213 - call EXCEPTION -#endif /* PARANOID */ - -sqrt_stage_2_done: - -/* Now the square root has been computed to better than 60 bits */ - -/* Find the square of the guess*/ - movl %edi,%eax /* ls word of guess*/ - mull %edi - movl %edx,accum_1 - - movl %esi,%eax - mull %esi - movl %edx,accum_3 - movl %eax,accum_2 - - movl %edi,%eax - mull %esi - addl %eax,accum_1 - adcl %edx,accum_2 - adcl $0,accum_3 - -/* movl %esi,%eax*/ -/* mull %edi*/ - addl %eax,accum_1 - adcl %edx,accum_2 - adcl $0,accum_3 - -/* guess^2 now in accum_3:accum_2:accum_1*/ - - movl fsqrt_arg_0,%eax /* get normalized n*/ - subl %eax,accum_1 - movl fsqrt_arg_1,%eax - sbbl %eax,accum_2 - movl fsqrt_arg_2,%eax /* ms word of normalized n*/ - sbbl %eax,accum_3 - jnc sqrt_stage_3_positive - -/* subtraction gives a negative result*/ -/* negate the result before division */ - notl accum_1 - notl accum_2 - notl accum_3 - addl $1,accum_1 - adcl $0,accum_2 - -#ifdef PARANOID - adcl $0,accum_3 /* This must be zero */ - jz sqrt_stage_3_no_error - -sqrt_stage_3_error: - pushl EX_INTERNAL|0x207 - call EXCEPTION - -sqrt_stage_3_no_error: -#endif /* PARANOID */ - - movl accum_2,%edx - movl accum_1,%eax - divl %esi - movl %eax,%ecx - - movl %edx,%eax - divl %esi - - sarl $1,%ecx /* divide by 2*/ - rcrl $1,%eax - - /* prepare to round the result*/ - - addl %ecx,%edi - adcl $0,%esi - - jmp sqrt_stage_3_finished - -sqrt_stage_3_positive: - movl accum_2,%edx - movl accum_1,%eax - divl %esi - movl %eax,%ecx - - movl %edx,%eax - divl %esi - - sarl $1,%ecx /* divide by 2*/ - rcrl $1,%eax - - /* prepare to round the result*/ - - notl %eax /* Negate the correction term*/ - notl %ecx - addl $1,%eax - adcl $0,%ecx /* carry here ==> correction == 0*/ - adcl $0xffffffff,%esi - - addl %ecx,%edi - adcl $0,%esi - -sqrt_stage_3_finished: - -/* The result in %esi:%edi:%esi should be good to about 90 bits here, -// and the rounding information here does not have sufficient accuracy -// in a few rare cases. */ - cmpl $0xffffffe0,%eax - ja sqrt_near_exact_x - - cmpl $0x00000020,%eax - jb sqrt_near_exact - - cmpl $0x7fffffe0,%eax - jb sqrt_round_result - - cmpl $0x80000020,%eax - jb sqrt_get_more_precision - -sqrt_round_result: -/* Set up for rounding operations*/ - movl %eax,%edx - movl %esi,%eax - movl %edi,%ebx - movl PARAM1,%edi - movl EXP_BIAS,EXP(%edi) /* Result is in [1.0 .. 2.0)*/ - movl PARAM2,%ecx - jmp FPU_round_sqrt - - -sqrt_near_exact_x: -/* First, the estimate must be rounded up.*/ - addl $1,%edi - adcl $0,%esi - -sqrt_near_exact: -/* This is an easy case because x^1/2 is monotonic. -// We need just find the square of our estimate, compare it -// with the argument, and deduce whether our estimate is -// above, below, or exact. We use the fact that the estimate -// is known to be accurate to about 90 bits. */ - movl %edi,%eax /* ls word of guess*/ - mull %edi - movl %edx,%ebx /* 2nd ls word of square*/ - movl %eax,%ecx /* ls word of square*/ - - movl %edi,%eax - mull %esi - addl %eax,%ebx - addl %eax,%ebx - -#ifdef PARANOID - cmp $0xffffffb0,%ebx - jb sqrt_near_exact_ok - - cmp $0x00000050,%ebx - ja sqrt_near_exact_ok - - pushl EX_INTERNAL|0x214 - call EXCEPTION - -sqrt_near_exact_ok: -#endif /* PARANOID */ - - or %ebx,%ebx - js sqrt_near_exact_small - - jnz sqrt_near_exact_large - - or %ebx,%edx - jnz sqrt_near_exact_large - -/* Our estimate is exactly the right answer*/ - xorl %eax,%eax - jmp sqrt_round_result - -sqrt_near_exact_small: -/* Our estimate is too small*/ - movl $0x000000ff,%eax - jmp sqrt_round_result - -sqrt_near_exact_large: -/* Our estimate is too large, we need to decrement it*/ - subl $1,%edi - sbbl $0,%esi - movl $0xffffff00,%eax - jmp sqrt_round_result - - -sqrt_get_more_precision: -/* This case is almost the same as the above, except we start*/ -/* with an extra bit of precision in the estimate.*/ - stc /* The extra bit.*/ - rcll $1,%edi /* Shift the estimate left one bit*/ - rcll $1,%esi - - movl %edi,%eax /* ls word of guess*/ - mull %edi - movl %edx,%ebx /* 2nd ls word of square*/ - movl %eax,%ecx /* ls word of square*/ - - movl %edi,%eax - mull %esi - addl %eax,%ebx - addl %eax,%ebx - -/* Put our estimate back to its original value*/ - stc /* The ms bit.*/ - rcrl $1,%esi /* Shift the estimate left one bit*/ - rcrl $1,%edi - -#ifdef PARANOID - cmp $0xffffff60,%ebx - jb sqrt_more_prec_ok - - cmp $0x000000a0,%ebx - ja sqrt_more_prec_ok - - pushl EX_INTERNAL|0x215 - call EXCEPTION - -sqrt_more_prec_ok: -#endif /* PARANOID */ - - or %ebx,%ebx - js sqrt_more_prec_small - - jnz sqrt_more_prec_large - - or %ebx,%ecx - jnz sqrt_more_prec_large - -/* Our estimate is exactly the right answer*/ - movl $0x80000000,%eax - jmp sqrt_round_result - -sqrt_more_prec_small: -/* Our estimate is too small*/ - movl $0x800000ff,%eax - jmp sqrt_round_result - -sqrt_more_prec_large: -/* Our estimate is too large*/ - movl $0x7fffff00,%eax - jmp sqrt_round_result diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index f1cc29c..15e2cb9 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -186,16 +186,6 @@ options CYRIX_CACHE_REALLY_WORKS #options NO_F00F_HACK options CPU_DISABLE_CMPXCHG -# -# A math emulator is mandatory if you wish to run on hardware which -# does not have a floating-point processor. Pick either the original, -# bogus (but freely-distributable) math emulator, or a much more -# fully-featured but GPL-licensed emulator taken from Linux. -# -options MATH_EMULATE #Support for x87 emulation -# Don't enable both of these in a real config. -options GPL_MATH_EMULATE #Support for x87 emulation via - # Debug options options NPX_DEBUG # enable npx debugging (FPU/math emu) #new math emulator diff --git a/sys/i386/i386/math_emu.h b/sys/i386/i386/math_emu.h deleted file mode 100644 index bc28dc1..0000000 --- a/sys/i386/i386/math_emu.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * linux/include/linux/math_emu.h - * - * (C) 1991 Linus Torvalds - * - * $FreeBSD$ - */ -#ifndef _LINUX_MATH_EMU_H -#define _LINUX_MATH_EMU_H - -/*#define math_abort(x,y) \ -(((volatile void (*)(struct info *,unsigned int)) __math_abort)((x),(y)))*/ - -/* - * Gcc forces this stupid alignment problem: I want to use only two int32_t's - * for the temporary real 64-bit mantissa, but then gcc aligns out the - * structure to 12 bytes which breaks things in math_emulate.c. Shit. I - * want some kind of "no-alignt" pragma or something. - */ - -typedef struct { - int32_t a,b; - short exponent; -} temp_real; - -typedef struct { - short m0,m1,m2,m3; - short exponent; -} temp_real_unaligned; - -#define real_to_real(a,b) \ -((*(long long *) (b) = *(long long *) (a)),((b)->exponent = (a)->exponent)) - -typedef struct { - int32_t a,b; -} long_real; - -typedef int32_t short_real; - -typedef struct { - int32_t a,b; - short sign; -} temp_int; - -struct swd { - int ie:1; - int de:1; - int ze:1; - int oe:1; - int ue:1; - int pe:1; - int sf:1; - int ir:1; - int c0:1; - int c1:1; - int c2:1; - int top:3; - int c3:1; - int b:1; -}; -struct i387_struct { - int32_t cwd; - int32_t swd; - int32_t twd; - int32_t fip; - int32_t fcs; - int32_t foo; - int32_t fos; - int32_t st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ -}; - -#define I387 (*(struct i387_struct *)&(curthread->td_pcb->pcb_save.sv_87)) -#define SWD (*(struct swd *) &I387.swd) -#define ROUNDING ((I387.cwd >> 10) & 3) -#define PRECISION ((I387.cwd >> 8) & 3) - -#define BITS24 0 -#define BITS53 2 -#define BITS64 3 - -#define ROUND_NEAREST 0 -#define ROUND_DOWN 1 -#define ROUND_UP 2 -#define ROUND_0 3 - -#define CONSTZ (temp_real_unaligned) {0x0000,0x0000,0x0000,0x0000,0x0000} -#define CONST1 (temp_real_unaligned) {0x0000,0x0000,0x0000,0x8000,0x3FFF} -#define CONSTPI (temp_real_unaligned) {0xC235,0x2168,0xDAA2,0xC90F,0x4000} -#define CONSTLN2 (temp_real_unaligned) {0x79AC,0xD1CF,0x17F7,0xB172,0x3FFE} -#define CONSTLG2 (temp_real_unaligned) {0xF799,0xFBCF,0x9A84,0x9A20,0x3FFD} -#define CONSTL2E (temp_real_unaligned) {0xF0BC,0x5C17,0x3B29,0xB8AA,0x3FFF} -#define CONSTL2T (temp_real_unaligned) {0x8AFE,0xCD1B,0x784B,0xD49A,0x4000} - -#define set_IE() (I387.swd |= 1) -#define set_DE() (I387.swd |= 2) -#define set_ZE() (I387.swd |= 4) -#define set_OE() (I387.swd |= 8) -#define set_UE() (I387.swd |= 16) -#define set_PE() (I387.swd |= 32) - -#define set_C0() (I387.swd |= 0x0100) -#define set_C1() (I387.swd |= 0x0200) -#define set_C2() (I387.swd |= 0x0400) -#define set_C3() (I387.swd |= 0x4000) - -/* ea.c */ - -static char * ea(struct trapframe *, unsigned short); - -/* convert.c */ - -static void frndint(const temp_real * __a, temp_real * __b); -static void Fscale(const temp_real *, const temp_real *, temp_real *); -static void short_to_temp(const short_real * __a, temp_real * __b); -static void long_to_temp(const long_real * __a, temp_real * __b); -static void temp_to_short(const temp_real * __a, short_real * __b); -static void temp_to_long(const temp_real * __a, long_real * __b); -static void real_to_int(const temp_real * __a, temp_int * __b); -static void int_to_real(const temp_int * __a, temp_real * __b); - -/* get_put.c */ - -static void get_short_real(temp_real *, struct trapframe *, unsigned short); -static void get_long_real(temp_real *, struct trapframe *, unsigned short); -static void get_temp_real(temp_real *, struct trapframe *, unsigned short); -static void get_short_int(temp_real *, struct trapframe *, unsigned short); -static void get_long_int(temp_real *, struct trapframe *, unsigned short); -static void get_longlong_int(temp_real *, struct trapframe *, unsigned short); -static void get_BCD(temp_real *, struct trapframe *, unsigned short); -static void put_short_real(const temp_real *, struct trapframe *, unsigned short); -static void put_long_real(const temp_real *, struct trapframe *, unsigned short); -static void put_temp_real(const temp_real *, struct trapframe *, unsigned short); -static void put_short_int(const temp_real *, struct trapframe *, unsigned short); -static void put_long_int(const temp_real *, struct trapframe *, unsigned short); -static void put_longlong_int(const temp_real *, struct trapframe *, unsigned short); -static void put_BCD(const temp_real *, struct trapframe *, unsigned short); - -/* add.c */ - -static void fadd(const temp_real *, const temp_real *, temp_real *); - -/* mul.c */ - -static void fmul(const temp_real *, const temp_real *, temp_real *); - -/* div.c */ - -static void fdiv(const temp_real *, const temp_real *, temp_real *); - -/* compare.c */ - -static void fcom(const temp_real *, const temp_real *); -static void fucom(const temp_real *, const temp_real *); -static void ftst(const temp_real *); - -#endif diff --git a/sys/i386/i386/math_emulate.c b/sys/i386/i386/math_emulate.c deleted file mode 100644 index 696b768..0000000 --- a/sys/i386/i386/math_emulate.c +++ /dev/null @@ -1,1582 +0,0 @@ -/* - * linux/kernel/math/math_emulate.c - * - * (C) 1991 Linus Torvalds - * - * [expediant "port" of linux 8087 emulator to 386BSD, with apologies -wfj] - * - * from: 386BSD 0.1 - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * Limited emulation 27.12.91 - mostly loads/stores, which gcc wants - * even for soft-float, unless you use bruce evans' patches. The patches - * are great, but they have to be re-applied for every version, and the - * library is different for soft-float and 80387. So emulation is more - * practical, even though it's slower. - * - * 28.12.91 - loads/stores work, even BCD. I'll have to start thinking - * about add/sub/mul/div. Urgel. I should find some good source, but I'll - * just fake up something. - * - * 30.12.91 - add/sub/mul/div/com seem to work mostly. I should really - * test every possible combination. - */ - -/* - * This file is full of ugly macros etc: one problem was that gcc simply - * didn't want to make the structures as they should be: it has to try to - * align them. Sickening code, but at least I've hidden the ugly things - * in this one file: the other files don't need to know about these things. - * - * The other files also don't care about ST(x) etc - they just get addresses - * to 80-bit temporary reals, and do with them as they please. I wanted to - * hide most of the 387-specific things here. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/proc.h> -#include <sys/user.h> - -#include <machine/frame.h> -#include <machine/reg.h> - -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_map.h> - -#define __ALIGNED_TEMP_REAL 1 -#include <i386/i386/math_emu.h> - -#define bswapw(x) __asm__("xchgb %%al,%%ah":"+a" ((short)(x))) -#define ST(x) (*__st((x))) -#define PST(x) ((const temp_real *) __st((x))) -#define math_abort(tfp, signo) \ - do { tfp->tf_eip = oldeip; return (signo);} while(0) - -/* - * We don't want these inlined - it gets too messy in the machine-code. - */ -static void fpop(void); -static void fpush(void); -static void fxchg(temp_real_unaligned * a, temp_real_unaligned * b); -static temp_real_unaligned * __st(int i); - -static unsigned char -get_fs_byte(char *adr) - { return(fubyte(adr)); } - -static unsigned short -get_fs_word(unsigned short *adr) - { return(fuword16(adr)); } - -static u_int32_t -get_fs_long(u_int32_t *adr) - { return(fuword(adr)); } - -static void -put_fs_byte(unsigned char val, char *adr) - { (void)subyte(adr,val); } - -static void -put_fs_word(unsigned short val, short *adr) - { (void)suword16(adr,val); } - -static void -put_fs_long(u_long val, u_int32_t *adr) - { (void)suword(adr,val); } - -static int -math_emulate(struct trapframe * info) -{ - unsigned short code; - temp_real tmp; - char * address; - u_int32_t oldeip; - - /* ever used fp? */ - if ((curthread->td_pcb->pcb_flags & FP_SOFTFP) == 0) { - curthread->td_pcb->pcb_flags |= FP_SOFTFP; - I387.cwd = 0x037f; - I387.swd = 0x0000; - I387.twd = 0x0000; - } - - if (I387.cwd & I387.swd & 0x3f) - I387.swd |= 0x8000; - else - I387.swd &= 0x7fff; - oldeip = info->tf_eip; -/* 0x001f means user code space */ - if ((u_short)info->tf_cs != 0x001F) { - printf("math_emulate: %04x:%08lx\n", (u_short)info->tf_cs, - (u_long)oldeip); - panic("?Math emulation needed in kernel?"); - } - /* completely ignore an operand-size prefix */ - if (get_fs_byte((char *) info->tf_eip) == 0x66) - info->tf_eip++; - code = get_fs_word((unsigned short *) info->tf_eip); - bswapw(code); - code &= 0x7ff; - I387.fip = oldeip; - *(unsigned short *) &I387.fcs = (u_short) info->tf_cs; - *(1+(unsigned short *) &I387.fcs) = code; - info->tf_eip += 2; - switch (code) { - case 0x1d0: /* fnop */ - return(0); - case 0x1d1: case 0x1d2: case 0x1d3: /* fst to 32-bit mem */ - case 0x1d4: case 0x1d5: case 0x1d6: case 0x1d7: - math_abort(info,SIGILL); - case 0x1e0: /* fchs */ - ST(0).exponent ^= 0x8000; - return(0); - case 0x1e1: /* fabs */ - ST(0).exponent &= 0x7fff; - return(0); - case 0x1e2: case 0x1e3: - math_abort(info,SIGILL); - case 0x1e4: /* ftst */ - ftst(PST(0)); - return(0); - case 0x1e5: /* fxam */ - printf("fxam not implemented\n"); - math_abort(info,SIGILL); - case 0x1e6: case 0x1e7: /* fldenv */ - math_abort(info,SIGILL); - case 0x1e8: /* fld1 */ - fpush(); - ST(0) = CONST1; - return(0); - case 0x1e9: /* fld2t */ - fpush(); - ST(0) = CONSTL2T; - return(0); - case 0x1ea: /* fld2e */ - fpush(); - ST(0) = CONSTL2E; - return(0); - case 0x1eb: /* fldpi */ - fpush(); - ST(0) = CONSTPI; - return(0); - case 0x1ec: /* fldlg2 */ - fpush(); - ST(0) = CONSTLG2; - return(0); - case 0x1ed: /* fldln2 */ - fpush(); - ST(0) = CONSTLN2; - return(0); - case 0x1ee: /* fldz */ - fpush(); - ST(0) = CONSTZ; - return(0); - case 0x1ef: - math_abort(info,SIGILL); - case 0x1f0: /* f2xm1 */ - case 0x1f1: /* fyl2x */ - case 0x1f2: /* fptan */ - case 0x1f3: /* fpatan */ - case 0x1f4: /* fxtract */ - case 0x1f5: /* fprem1 */ - case 0x1f6: /* fdecstp */ - case 0x1f7: /* fincstp */ - case 0x1f8: /* fprem */ - case 0x1f9: /* fyl2xp1 */ - case 0x1fa: /* fsqrt */ - case 0x1fb: /* fsincos */ - case 0x1fe: /* fsin */ - case 0x1ff: /* fcos */ - uprintf( - "math_emulate: instruction %04x not implemented\n", - code + 0xd800); - math_abort(info,SIGILL); - case 0x1fc: /* frndint */ - frndint(PST(0),&tmp); - real_to_real(&tmp,&ST(0)); - return(0); - case 0x1fd: /* fscale */ - /* incomplete and totally inadequate -wfj */ - Fscale(PST(0), PST(1), &tmp); - real_to_real(&tmp,&ST(0)); - return(0); /* 19 Sep 92*/ - case 0x2e9: /* ????? */ -/* if this should be a fucomp ST(0),ST(1) , it must be a 0x3e9 ATS */ - fucom(PST(1),PST(0)); - fpop(); fpop(); - return(0); - case 0x3d0: case 0x3d1: /* fist ?? */ - return(0); - case 0x3e2: /* fclex */ - I387.swd &= 0x7f00; - return(0); - case 0x3e3: /* fninit */ - I387.cwd = 0x037f; - I387.swd = 0x0000; - I387.twd = 0x0000; - return(0); - case 0x3e4: - return(0); - case 0x6d9: /* fcompp */ - fcom(PST(1),PST(0)); - fpop(); fpop(); - return(0); - case 0x7e0: /* fstsw ax */ - *(short *) &info->tf_eax = I387.swd; - return(0); - } - switch (code >> 3) { - case 0x18: /* fadd */ - fadd(PST(0),PST(code & 7),&tmp); - real_to_real(&tmp,&ST(0)); - return(0); - case 0x19: /* fmul */ - fmul(PST(0),PST(code & 7),&tmp); - real_to_real(&tmp,&ST(0)); - return(0); - case 0x1a: /* fcom */ - fcom(PST(code & 7),PST(0)); - return(0); - case 0x1b: /* fcomp */ - fcom(PST(code & 7),PST(0)); - fpop(); - return(0); - case 0x1c: /* fsubr */ - real_to_real(&ST(code & 7),&tmp); - tmp.exponent ^= 0x8000; - fadd(PST(0),&tmp,&tmp); - real_to_real(&tmp,&ST(0)); - return(0); - case 0x1d: /* fsub */ - ST(0).exponent ^= 0x8000; - fadd(PST(0),PST(code & 7),&tmp); - real_to_real(&tmp,&ST(0)); - return(0); - case 0x1e: /* fdivr */ - fdiv(PST(0),PST(code & 7),&tmp); - real_to_real(&tmp,&ST(0)); - return(0); - case 0x1f: /* fdiv */ - fdiv(PST(code & 7),PST(0),&tmp); - real_to_real(&tmp,&ST(0)); - return(0); - case 0x38: /* fld */ - fpush(); - ST(0) = ST((code & 7)+1); /* why plus 1 ????? ATS */ - return(0); - case 0x39: /* fxch */ - fxchg(&ST(0),&ST(code & 7)); - return(0); - case 0x3b: /* ??? ??? wrong ???? ATS */ - ST(code & 7) = ST(0); - fpop(); - return(0); - case 0x98: /* fadd */ - fadd(PST(0),PST(code & 7),&tmp); - real_to_real(&tmp,&ST(code & 7)); - return(0); - case 0x99: /* fmul */ - fmul(PST(0),PST(code & 7),&tmp); - real_to_real(&tmp,&ST(code & 7)); - return(0); - case 0x9a: /* ???? , my manual don't list a direction bit -for fcom , ??? ATS */ - fcom(PST(code & 7),PST(0)); - return(0); - case 0x9b: /* same as above , ATS */ - fcom(PST(code & 7),PST(0)); - fpop(); - return(0); - case 0x9c: /* fsubr */ - ST(code & 7).exponent ^= 0x8000; - fadd(PST(0),PST(code & 7),&tmp); - real_to_real(&tmp,&ST(code & 7)); - return(0); - case 0x9d: /* fsub */ - real_to_real(&ST(0),&tmp); - tmp.exponent ^= 0x8000; - fadd(PST(code & 7),&tmp,&tmp); - real_to_real(&tmp,&ST(code & 7)); - return(0); - case 0x9e: /* fdivr */ - fdiv(PST(0),PST(code & 7),&tmp); - real_to_real(&tmp,&ST(code & 7)); - return(0); - case 0x9f: /* fdiv */ - fdiv(PST(code & 7),PST(0),&tmp); - real_to_real(&tmp,&ST(code & 7)); - return(0); - case 0xb8: /* ffree */ - printf("ffree not implemented\n"); - math_abort(info,SIGILL); - case 0xb9: /* fstp ???? where is the pop ? ATS */ - fxchg(&ST(0),&ST(code & 7)); - return(0); - case 0xba: /* fst */ - ST(code & 7) = ST(0); - return(0); - case 0xbb: /* ????? encoding of fstp to mem ? ATS */ - ST(code & 7) = ST(0); - fpop(); - return(0); - case 0xbc: /* fucom */ - fucom(PST(code & 7),PST(0)); - return(0); - case 0xbd: /* fucomp */ - fucom(PST(code & 7),PST(0)); - fpop(); - return(0); - case 0xd8: /* faddp */ - fadd(PST(code & 7),PST(0),&tmp); - real_to_real(&tmp,&ST(code & 7)); - fpop(); - return(0); - case 0xd9: /* fmulp */ - fmul(PST(code & 7),PST(0),&tmp); - real_to_real(&tmp,&ST(code & 7)); - fpop(); - return(0); - case 0xda: /* ??? encoding of ficom with 16 bit mem ? ATS */ - fcom(PST(code & 7),PST(0)); - fpop(); - return(0); - case 0xdc: /* fsubrp */ - ST(code & 7).exponent ^= 0x8000; - fadd(PST(0),PST(code & 7),&tmp); - real_to_real(&tmp,&ST(code & 7)); - fpop(); - return(0); - case 0xdd: /* fsubp */ - real_to_real(&ST(0),&tmp); - tmp.exponent ^= 0x8000; - fadd(PST(code & 7),&tmp,&tmp); - real_to_real(&tmp,&ST(code & 7)); - fpop(); - return(0); - case 0xde: /* fdivrp */ - fdiv(PST(0),PST(code & 7),&tmp); - real_to_real(&tmp,&ST(code & 7)); - fpop(); - return(0); - case 0xdf: /* fdivp */ - fdiv(PST(code & 7),PST(0),&tmp); - real_to_real(&tmp,&ST(code & 7)); - fpop(); - return(0); - case 0xf8: /* fild 16-bit mem ???? ATS */ - printf("ffree not implemented\n"); - math_abort(info,SIGILL); - fpop(); - return(0); - case 0xf9: /* ????? ATS */ - fxchg(&ST(0),&ST(code & 7)); - return(0); - case 0xfa: /* fist 16-bit mem ? ATS */ - case 0xfb: /* fistp 16-bit mem ? ATS */ - ST(code & 7) = ST(0); - fpop(); - return(0); - } - switch ((code>>3) & 0xe7) { - case 0x22: - put_short_real(PST(0),info,code); - return(0); - case 0x23: - put_short_real(PST(0),info,code); - fpop(); - return(0); - case 0x24: - address = ea(info,code); - for (code = 0 ; code < 7 ; code++) { - ((int32_t *) & I387)[code] = - get_fs_long((u_int32_t *) address); - address += 4; - } - return(0); - case 0x25: - address = ea(info,code); - *(unsigned short *) &I387.cwd = - get_fs_word((unsigned short *) address); - return(0); - case 0x26: - address = ea(info,code); - /*verify_area(address,28);*/ - for (code = 0 ; code < 7 ; code++) { - put_fs_long( ((int32_t *) & I387)[code], - (u_int32_t *) address); - address += 4; - } - return(0); - case 0x27: - address = ea(info,code); - /*verify_area(address,2);*/ - put_fs_word(I387.cwd,(short *) address); - return(0); - case 0x62: - put_long_int(PST(0),info,code); - return(0); - case 0x63: - put_long_int(PST(0),info,code); - fpop(); - return(0); - case 0x65: - fpush(); - get_temp_real(&tmp,info,code); - real_to_real(&tmp,&ST(0)); - return(0); - case 0x67: - put_temp_real(PST(0),info,code); - fpop(); - return(0); - case 0xa2: - put_long_real(PST(0),info,code); - return(0); - case 0xa3: - put_long_real(PST(0),info,code); - fpop(); - return(0); - case 0xa4: - address = ea(info,code); - for (code = 0 ; code < 27 ; code++) { - ((int32_t *) & I387)[code] = - get_fs_long((u_int32_t *) address); - address += 4; - } - return(0); - case 0xa6: - address = ea(info,code); - /*verify_area(address,108);*/ - for (code = 0 ; code < 27 ; code++) { - put_fs_long( ((int32_t *) & I387)[code], - (u_int32_t *) address); - address += 4; - } - I387.cwd = 0x037f; - I387.swd = 0x0000; - I387.twd = 0x0000; - return(0); - case 0xa7: - address = ea(info,code); - /*verify_area(address,2);*/ - put_fs_word(I387.swd,(short *) address); - return(0); - case 0xe2: - put_short_int(PST(0),info,code); - return(0); - case 0xe3: - put_short_int(PST(0),info,code); - fpop(); - return(0); - case 0xe4: - fpush(); - get_BCD(&tmp,info,code); - real_to_real(&tmp,&ST(0)); - return(0); - case 0xe5: - fpush(); - get_longlong_int(&tmp,info,code); - real_to_real(&tmp,&ST(0)); - return(0); - case 0xe6: - put_BCD(PST(0),info,code); - fpop(); - return(0); - case 0xe7: - put_longlong_int(PST(0),info,code); - fpop(); - return(0); - } - switch (code >> 9) { - case 0: - get_short_real(&tmp,info,code); - break; - case 1: - get_long_int(&tmp,info,code); - break; - case 2: - get_long_real(&tmp,info,code); - break; - case 4: - get_short_int(&tmp,info,code); - } - switch ((code>>3) & 0x27) { - case 0: - fadd(&tmp,PST(0),&tmp); - real_to_real(&tmp,&ST(0)); - return(0); - case 1: - fmul(&tmp,PST(0),&tmp); - real_to_real(&tmp,&ST(0)); - return(0); - case 2: - fcom(&tmp,PST(0)); - return(0); - case 3: - fcom(&tmp,PST(0)); - fpop(); - return(0); - case 4: - tmp.exponent ^= 0x8000; - fadd(&tmp,PST(0),&tmp); - real_to_real(&tmp,&ST(0)); - return(0); - case 5: - ST(0).exponent ^= 0x8000; - fadd(&tmp,PST(0),&tmp); - real_to_real(&tmp,&ST(0)); - return(0); - case 6: - fdiv(PST(0),&tmp,&tmp); - real_to_real(&tmp,&ST(0)); - return(0); - case 7: - fdiv(&tmp,PST(0),&tmp); - real_to_real(&tmp,&ST(0)); - return(0); - } - if ((code & 0x138) == 0x100) { - fpush(); - real_to_real(&tmp,&ST(0)); - return(0); - } - printf("Unknown math-insns: %04x:%08x %04x\n",(u_short)info->tf_cs, - info->tf_eip,code); - math_abort(info,SIGFPE); -} - -static void -fpop(void) -{ - u_int32_t tmp; - - tmp = I387.swd & 0xffffc7ffUL; - I387.swd += 0x00000800; - I387.swd &= 0x00003800; - I387.swd |= tmp; -} - -static void -fpush(void) -{ - u_int32_t tmp; - - tmp = I387.swd & 0xffffc7ffUL; - I387.swd += 0x00003800; - I387.swd &= 0x00003800; - I387.swd |= tmp; -} - -static void -fxchg(temp_real_unaligned * a, temp_real_unaligned * b) -{ - temp_real_unaligned c; - - c = *a; - *a = *b; - *b = c; -} - -static temp_real_unaligned * -__st(int i) -{ - i += I387.swd >> 11; - i &= 7; - return (temp_real_unaligned *) (i*10 + (char *)(I387.st_space)); -} - -/* - * linux/kernel/math/ea.c - * - * (C) 1991 Linus Torvalds - */ - -/* - * Calculate the effective address. - */ - - -static int __regoffset[] = { - tEAX, tECX, tEDX, tEBX, tESP, tEBP, tESI, tEDI -}; - -#define REG(x) (((int *)curthread->td_frame)[__regoffset[(x)]]) - -static char * -sib(struct trapframe * info, int mod) -{ - unsigned char ss,index,base; - int32_t offset = 0; - - base = get_fs_byte((char *) info->tf_eip); - info->tf_eip++; - ss = base >> 6; - index = (base >> 3) & 7; - base &= 7; - if (index == 4) - offset = 0; - else - offset = REG(index); - offset <<= ss; - if (mod || base != 5) - offset += REG(base); - if (mod == 1) { - offset += (signed char) get_fs_byte((char *) info->tf_eip); - info->tf_eip++; - } else if (mod == 2 || base == 5) { - offset += (signed) get_fs_long((u_int32_t *) info->tf_eip); - info->tf_eip += 4; - } - I387.foo = offset; - I387.fos = 0x17; - return (char *) offset; -} - -static char * -ea(struct trapframe * info, unsigned short code) -{ - unsigned char mod,rm; - int32_t * tmp; - int offset = 0; - - mod = (code >> 6) & 3; - rm = code & 7; - if (rm == 4 && mod != 3) - return sib(info,mod); - if (rm == 5 && !mod) { - offset = get_fs_long((u_int32_t *) info->tf_eip); - info->tf_eip += 4; - I387.foo = offset; - I387.fos = 0x17; - return (char *) offset; - } - tmp = (int32_t *) ®(rm); - switch (mod) { - case 0: offset = 0; break; - case 1: - offset = (signed char) get_fs_byte((char *) info->tf_eip); - info->tf_eip++; - break; - case 2: - offset = (signed) get_fs_long((u_int32_t *) info->tf_eip); - info->tf_eip += 4; - break; -#ifdef notyet - case 3: - math_abort(info,1<<(SIGILL-1)); -#endif - } - I387.foo = offset; - I387.fos = 0x17; - return offset + (char *) *tmp; -} -/* - * linux/kernel/math/get_put.c - * - * (C) 1991 Linus Torvalds - */ - -/* - * This file handles all accesses to user memory: getting and putting - * ints/reals/BCD etc. This is the only part that concerns itself with - * other than temporary real format. All other cals are strictly temp_real. - */ - -static void -get_short_real(temp_real * tmp, struct trapframe * info, unsigned short code) -{ - char * addr; - short_real sr; - - addr = ea(info,code); - sr = get_fs_long((u_int32_t *) addr); - short_to_temp(&sr,tmp); -} - -static void -get_long_real(temp_real * tmp, struct trapframe * info, unsigned short code) -{ - char * addr; - long_real lr; - - addr = ea(info,code); - lr.a = get_fs_long((u_int32_t *) addr); - lr.b = get_fs_long(1 + (u_int32_t *) addr); - long_to_temp(&lr,tmp); -} - -static void -get_temp_real(temp_real * tmp, struct trapframe * info, unsigned short code) -{ - char * addr; - - addr = ea(info,code); - tmp->a = get_fs_long((u_int32_t *) addr); - tmp->b = get_fs_long(1 + (u_int32_t *) addr); - tmp->exponent = get_fs_word(4 + (unsigned short *) addr); -} - -static void -get_short_int(temp_real * tmp, struct trapframe * info, unsigned short code) -{ - char * addr; - temp_int ti; - - addr = ea(info,code); - ti.a = (signed short) get_fs_word((unsigned short *) addr); - ti.b = 0; - if ((ti.sign = (ti.a < 0)) != 0) - ti.a = - ti.a; - int_to_real(&ti,tmp); -} - -static void -get_long_int(temp_real * tmp, struct trapframe * info, unsigned short code) -{ - char * addr; - temp_int ti; - - addr = ea(info,code); - ti.a = get_fs_long((u_int32_t *) addr); - ti.b = 0; - if ((ti.sign = (ti.a < 0)) != 0) - ti.a = - ti.a; - int_to_real(&ti,tmp); -} - -static void -get_longlong_int(temp_real * tmp, struct trapframe * info, unsigned short code) -{ - char * addr; - temp_int ti; - - addr = ea(info,code); - ti.a = get_fs_long((u_int32_t *) addr); - ti.b = get_fs_long(1 + (u_int32_t *) addr); - if ((ti.sign = (ti.b < 0)) != 0) - __asm__("notl %0 ; notl %1\n\t" - "addl $1,%0 ; adcl $0,%1" - :"=r" (ti.a),"=r" (ti.b) - :"0" (ti.a),"1" (ti.b)); - int_to_real(&ti,tmp); -} - -#define MUL10(low, high) \ - __asm__("addl %0,%0 ; adcl %1,%1\n\t" \ - "movl %0,%%ecx ; movl %1,%%ebx\n\t" \ - "addl %0,%0 ; adcl %1,%1\n\t" \ - "addl %0,%0 ; adcl %1,%1\n\t" \ - "addl %%ecx,%0 ; adcl %%ebx,%1" \ - : "=a" (low), "=d" (high) \ - : "0" (low), "1" (high) \ - : "cx", "bx") - -#define ADD64(val, low, high) \ - __asm__("addl %4,%0 ; adcl $0,%1" \ - :"=r" (low),"=r" (high) \ - :"0" (low),"1" (high),"r" ((u_int32_t) (val))) - -static void -get_BCD(temp_real * tmp, struct trapframe * info, unsigned short code) -{ - int k; - char * addr; - temp_int i; - unsigned char c; - - addr = ea(info,code); - addr += 9; - i.sign = 0x80 & get_fs_byte(addr--); - i.a = i.b = 0; - for (k = 0; k < 9; k++) { - c = get_fs_byte(addr--); - MUL10(i.a, i.b); - ADD64((c>>4), i.a, i.b); - MUL10(i.a, i.b); - ADD64((c&0xf), i.a, i.b); - } - int_to_real(&i,tmp); -} - -static void -put_short_real(const temp_real * tmp, - struct trapframe * info, unsigned short code) -{ - char * addr; - short_real sr; - - addr = ea(info,code); - /*verify_area(addr,4);*/ - temp_to_short(tmp,&sr); - put_fs_long(sr,(u_int32_t *) addr); -} - -static void -put_long_real(const temp_real * tmp, - struct trapframe * info, unsigned short code) -{ - char * addr; - long_real lr; - - addr = ea(info,code); - /*verify_area(addr,8);*/ - temp_to_long(tmp,&lr); - put_fs_long(lr.a, (u_int32_t *) addr); - put_fs_long(lr.b, 1 + (u_int32_t *) addr); -} - -static void -put_temp_real(const temp_real * tmp, - struct trapframe * info, unsigned short code) -{ - char * addr; - - addr = ea(info,code); - /*verify_area(addr,10);*/ - put_fs_long(tmp->a, (u_int32_t *) addr); - put_fs_long(tmp->b, 1 + (u_int32_t *) addr); - put_fs_word(tmp->exponent, 4 + (short *) addr); -} - -static void -put_short_int(const temp_real * tmp, - struct trapframe * info, unsigned short code) -{ - char * addr; - temp_int ti; - - addr = ea(info,code); - real_to_int(tmp,&ti); - /*verify_area(addr,2);*/ - if (ti.sign) - ti.a = -ti.a; - put_fs_word(ti.a,(short *) addr); -} - -static void -put_long_int(const temp_real * tmp, - struct trapframe * info, unsigned short code) -{ - char * addr; - temp_int ti; - - addr = ea(info,code); - real_to_int(tmp,&ti); - /*verify_area(addr,4);*/ - if (ti.sign) - ti.a = -ti.a; - put_fs_long(ti.a,(u_int32_t *) addr); -} - -static void -put_longlong_int(const temp_real * tmp, - struct trapframe * info, unsigned short code) -{ - char * addr; - temp_int ti; - - addr = ea(info,code); - real_to_int(tmp,&ti); - /*verify_area(addr,8);*/ - if (ti.sign) - __asm__("notl %0 ; notl %1\n\t" - "addl $1,%0 ; adcl $0,%1" - :"=r" (ti.a),"=r" (ti.b) - :"0" (ti.a),"1" (ti.b)); - put_fs_long(ti.a,(u_int32_t *) addr); - put_fs_long(ti.b,1 + (u_int32_t *) addr); -} - -#define DIV10(low,high,rem) \ - __asm__("divl %6 ; xchgl %1,%2 ; divl %6" \ - :"=d" (rem),"=a" (low),"=r" (high) \ - :"0" (0),"1" (high),"2" (low),"c" (10)) - -static void -put_BCD(const temp_real * tmp,struct trapframe * info, unsigned short code) -{ - int k,rem; - char * addr; - temp_int i; - unsigned char c; - - addr = ea(info,code); - /*verify_area(addr,10);*/ - real_to_int(tmp,&i); - if (i.sign) - put_fs_byte(0x80, addr+9); - else - put_fs_byte(0, addr+9); - for (k = 0; k < 9; k++) { - DIV10(i.a,i.b,rem); - c = rem; - DIV10(i.a,i.b,rem); - c += rem<<4; - put_fs_byte(c,addr++); - } -} - -/* - * linux/kernel/math/mul.c - * - * (C) 1991 Linus Torvalds - */ - -/* - * temporary real multiplication routine. - */ - - -static void -shift(int * c) -{ - __asm__("movl (%0),%%eax ; addl %%eax,(%0)\n\t" - "movl 4(%0),%%eax ; adcl %%eax,4(%0)\n\t" - "movl 8(%0),%%eax ; adcl %%eax,8(%0)\n\t" - "movl 12(%0),%%eax ; adcl %%eax,12(%0)" - ::"r" (c):"ax"); -} - -static void -mul64(const temp_real * a, const temp_real * b, int * c) -{ - __asm__("movl (%0),%%eax\n\t" - "mull (%1)\n\t" - "movl %%eax,(%2)\n\t" - "movl %%edx,4(%2)\n\t" - "movl 4(%0),%%eax\n\t" - "mull 4(%1)\n\t" - "movl %%eax,8(%2)\n\t" - "movl %%edx,12(%2)\n\t" - "movl (%0),%%eax\n\t" - "mull 4(%1)\n\t" - "addl %%eax,4(%2)\n\t" - "adcl %%edx,8(%2)\n\t" - "adcl $0,12(%2)\n\t" - "movl 4(%0),%%eax\n\t" - "mull (%1)\n\t" - "addl %%eax,4(%2)\n\t" - "adcl %%edx,8(%2)\n\t" - "adcl $0,12(%2)" - ::"S" (a),"c" (b),"D" (c) - :"ax","dx"); -} - -static void -fmul(const temp_real * src1, const temp_real * src2, temp_real * result) -{ - int i,sign; - int tmp[4] = {0,0,0,0}; - - sign = (src1->exponent ^ src2->exponent) & 0x8000; - i = (src1->exponent & 0x7fff) + (src2->exponent & 0x7fff) - 16383 + 1; - if (i<0) { - result->exponent = sign; - result->a = result->b = 0; - return; - } - if (i>0x7fff) { - set_OE(); - return; - } - mul64(src1,src2,tmp); - if (tmp[0] || tmp[1] || tmp[2] || tmp[3]) - while (i && tmp[3] >= 0) { - i--; - shift(tmp); - } - else - i = 0; - result->exponent = i | sign; - result->a = tmp[2]; - result->b = tmp[3]; -} - -/* - * linux/kernel/math/div.c - * - * (C) 1991 Linus Torvalds - */ - -/* - * temporary real division routine. - */ - -static void -shift_left(int * c) -{ - __asm__ __volatile__("movl (%0),%%eax ; addl %%eax,(%0)\n\t" - "movl 4(%0),%%eax ; adcl %%eax,4(%0)\n\t" - "movl 8(%0),%%eax ; adcl %%eax,8(%0)\n\t" - "movl 12(%0),%%eax ; adcl %%eax,12(%0)" - ::"r" (c):"ax"); -} - -static void -shift_right(int * c) -{ - __asm__("shrl $1,12(%0) ; rcrl $1,8(%0) ; rcrl $1,4(%0) ; rcrl $1,(%0)" - ::"r" (c)); -} - -static int -try_sub(int * a, int * b) -{ - char ok; - - __asm__ __volatile__("movl (%1),%%eax ; subl %%eax,(%2)\n\t" - "movl 4(%1),%%eax ; sbbl %%eax,4(%2)\n\t" - "movl 8(%1),%%eax ; sbbl %%eax,8(%2)\n\t" - "movl 12(%1),%%eax ; sbbl %%eax,12(%2)\n\t" - "setae %%al":"=a" (ok):"c" (a),"d" (b)); - return ok; -} - -static void -div64(int * a, int * b, int * c) -{ - int tmp[4]; - int i; - unsigned int mask = 0; - - c += 4; - for (i = 0 ; i<64 ; i++) { - if (!(mask >>= 1)) { - c--; - mask = 0x80000000UL; - } - tmp[0] = a[0]; tmp[1] = a[1]; - tmp[2] = a[2]; tmp[3] = a[3]; - if (try_sub(b,tmp)) { - *c |= mask; - a[0] = tmp[0]; a[1] = tmp[1]; - a[2] = tmp[2]; a[3] = tmp[3]; - } - shift_right(b); - } -} - -static void -fdiv(const temp_real * src1, const temp_real * src2, temp_real * result) -{ - int i,sign; - int a[4],b[4],tmp[4] = {0,0,0,0}; - - sign = (src1->exponent ^ src2->exponent) & 0x8000; - if (!(src2->a || src2->b)) { - set_ZE(); - return; - } - i = (src1->exponent & 0x7fff) - (src2->exponent & 0x7fff) + 16383; - if (i<0) { - set_UE(); - result->exponent = sign; - result->a = result->b = 0; - return; - } - a[0] = a[1] = 0; - a[2] = src1->a; - a[3] = src1->b; - b[0] = b[1] = 0; - b[2] = src2->a; - b[3] = src2->b; - while (b[3] >= 0) { - i++; - shift_left(b); - } - div64(a,b,tmp); - if (tmp[0] || tmp[1] || tmp[2] || tmp[3]) { - while (i && tmp[3] >= 0) { - i--; - shift_left(tmp); - } - if (tmp[3] >= 0) - set_DE(); - } else - i = 0; - if (i>0x7fff) { - set_OE(); - return; - } - if (tmp[0] || tmp[1]) - set_PE(); - result->exponent = i | sign; - result->a = tmp[2]; - result->b = tmp[3]; -} - -/* - * linux/kernel/math/add.c - * - * (C) 1991 Linus Torvalds - */ - -/* - * temporary real addition routine. - * - * NOTE! These aren't exact: they are only 62 bits wide, and don't do - * correct rounding. Fast hack. The reason is that we shift right the - * values by two, in order not to have overflow (1 bit), and to be able - * to move the sign into the mantissa (1 bit). Much simpler algorithms, - * and 62 bits (61 really - no rounding) accuracy is usually enough. The - * only time you should notice anything weird is when adding 64-bit - * integers together. When using doubles (52 bits accuracy), the - * 61-bit accuracy never shows at all. - */ - -#define NEGINT(a) \ - __asm__("notl %0 ; notl %1 ; addl $1,%0 ; adcl $0,%1" \ - : "=r" (a->a), "=r" (a->b) \ - : "0" (a->a), "1" (a->b)) - -static void signify(temp_real * a) -{ - a->exponent += 2; - __asm__("shrdl $2,%1,%0 ; shrl $2,%1" - :"=r" (a->a),"=r" (a->b) - :"0" (a->a),"1" (a->b)); - if (a->exponent < 0) - NEGINT(a); - a->exponent &= 0x7fff; -} - -static void unsignify(temp_real * a) -{ - if (!(a->a || a->b)) { - a->exponent = 0; - return; - } - a->exponent &= 0x7fff; - if (a->b < 0) { - NEGINT(a); - a->exponent |= 0x8000; - } - while (a->b >= 0) { - a->exponent--; - __asm__("addl %0,%0 ; adcl %1,%1" - :"=r" (a->a),"=r" (a->b) - :"0" (a->a),"1" (a->b)); - } -} - -static void -fadd(const temp_real * src1, const temp_real * src2, temp_real * result) -{ - temp_real a,b; - int x1,x2,shift; - - x1 = src1->exponent & 0x7fff; - x2 = src2->exponent & 0x7fff; - if (x1 > x2) { - a = *src1; - b = *src2; - shift = x1-x2; - } else { - a = *src2; - b = *src1; - shift = x2-x1; - } - if (shift >= 64) { - *result = a; - return; - } - if (shift >= 32) { - b.a = b.b; - b.b = 0; - shift -= 32; - } - __asm__("shrdl %4,%1,%0 ; shrl %4,%1" - :"=r" (b.a),"=r" (b.b) - :"0" (b.a),"1" (b.b),"c" ((char) shift)); - signify(&a); - signify(&b); - __asm__("addl %4,%0 ; adcl %5,%1" - :"=r" (a.a),"=r" (a.b) - :"0" (a.a),"1" (a.b),"g" (b.a),"g" (b.b)); - unsignify(&a); - *result = a; -} - -/* - * linux/kernel/math/compare.c - * - * (C) 1991 Linus Torvalds - */ - -/* - * temporary real comparison routines - */ - - -#define clear_Cx() (I387.swd &= ~0x4500) - -static void -normalize(temp_real * a) -{ - int i = a->exponent & 0x7fff; - int sign = a->exponent & 0x8000; - - if (!(a->a || a->b)) { - a->exponent = 0; - return; - } - while (i && a->b >= 0) { - i--; - __asm__("addl %0,%0 ; adcl %1,%1" - :"=r" (a->a),"=r" (a->b) - :"0" (a->a),"1" (a->b)); - } - a->exponent = i | sign; -} - -static void -ftst(const temp_real * a) -{ - temp_real b; - - clear_Cx(); - b = *a; - normalize(&b); - if (b.a || b.b || b.exponent) { - if (b.exponent < 0) - set_C0(); - } else - set_C3(); -} - -static void -fcom(const temp_real * src1, const temp_real * src2) -{ - temp_real a; - - a = *src1; - a.exponent ^= 0x8000; - fadd(&a,src2,&a); - ftst(&a); -} - -static void -fucom(const temp_real * src1, const temp_real * src2) -{ - fcom(src1,src2); -} - -/* - * linux/kernel/math/convert.c - * - * (C) 1991 Linus Torvalds - */ - - -/* - * NOTE!!! There is some "non-obvious" optimisations in the temp_to_long - * and temp_to_short conversion routines: don't touch them if you don't - * know what's going on. They are the adding of one in the rounding: the - * overflow bit is also used for adding one into the exponent. Thus it - * looks like the overflow would be incorrectly handled, but due to the - * way the IEEE numbers work, things are correct. - * - * There is no checking for total overflow in the conversions, though (ie - * if the temp-real number simply won't fit in a short- or long-real.) - */ - -static void -short_to_temp(const short_real * a, temp_real * b) -{ - if (!(*a & 0x7fffffff)) { - b->a = b->b = 0; - if (*a) - b->exponent = 0x8000; - else - b->exponent = 0; - return; - } - b->exponent = ((*a>>23) & 0xff)-127+16383; - if (*a<0) - b->exponent |= 0x8000; - b->b = (*a<<8) | 0x80000000UL; - b->a = 0; -} - -static void -long_to_temp(const long_real * a, temp_real * b) -{ - if (!a->a && !(a->b & 0x7fffffff)) { - b->a = b->b = 0; - if (a->b) - b->exponent = 0x8000; - else - b->exponent = 0; - return; - } - b->exponent = ((a->b >> 20) & 0x7ff)-1023+16383; - if (a->b<0) - b->exponent |= 0x8000; - b->b = 0x80000000UL | (a->b<<11) | (((u_int32_t)a->a)>>21); - b->a = a->a<<11; -} - -static void -temp_to_short(const temp_real * a, short_real * b) -{ - if (!(a->exponent & 0x7fff)) { - *b = (a->exponent)?0x80000000UL:0; - return; - } - *b = ((((int32_t) a->exponent)-16383+127) << 23) & 0x7f800000; - if (a->exponent < 0) - *b |= 0x80000000UL; - *b |= (a->b >> 8) & 0x007fffff; - switch ((int)ROUNDING) { - case ROUND_NEAREST: - if ((a->b & 0xff) > 0x80) - ++*b; - break; - case ROUND_DOWN: - if ((a->exponent & 0x8000) && (a->b & 0xff)) - ++*b; - break; - case ROUND_UP: - if (!(a->exponent & 0x8000) && (a->b & 0xff)) - ++*b; - break; - } -} - -static void -temp_to_long(const temp_real * a, long_real * b) -{ - if (!(a->exponent & 0x7fff)) { - b->a = 0; - b->b = (a->exponent)?0x80000000UL:0; - return; - } - b->b = (((0x7fff & (int32_t) a->exponent)-16383+1023) << 20) & - 0x7ff00000; - if (a->exponent < 0) - b->b |= 0x80000000UL; - b->b |= (a->b >> 11) & 0x000fffff; - b->a = a->b << 21; - b->a |= (a->a >> 11) & 0x001fffff; - switch ((int)ROUNDING) { - case ROUND_NEAREST: - if ((a->a & 0x7ff) > 0x400) - __asm__("addl $1,%0 ; adcl $0,%1" - :"=r" (b->a),"=r" (b->b) - :"0" (b->a),"1" (b->b)); - break; - case ROUND_DOWN: - if ((a->exponent & 0x8000) && (a->b & 0xff)) - __asm__("addl $1,%0 ; adcl $0,%1" - :"=r" (b->a),"=r" (b->b) - :"0" (b->a),"1" (b->b)); - break; - case ROUND_UP: - if (!(a->exponent & 0x8000) && (a->b & 0xff)) - __asm__("addl $1,%0 ; adcl $0,%1" - :"=r" (b->a),"=r" (b->b) - :"0" (b->a),"1" (b->b)); - break; - } -} - -static void -frndint(const temp_real * a, temp_real * b) -{ - int shift = 16383 + 63 - (a->exponent & 0x7fff); - u_int32_t underflow; - - if ((shift < 0) || (shift == 16383+63)) { - *b = *a; - return; - } - b->a = b->b = underflow = 0; - b->exponent = a->exponent; - if (shift < 32) { - b->b = a->b; b->a = a->a; - } else if (shift < 64) { - b->a = a->b; underflow = a->a; - shift -= 32; - b->exponent += 32; - } else if (shift < 96) { - underflow = a->b; - shift -= 64; - b->exponent += 64; - } else { - underflow = 1; - shift = 0; - } - b->exponent += shift; - __asm__("shrdl %2,%1,%0" - :"=r" (underflow),"=r" (b->a) - :"c" ((char) shift),"0" (underflow),"1" (b->a)); - __asm__("shrdl %2,%1,%0" - :"=r" (b->a),"=r" (b->b) - :"c" ((char) shift),"0" (b->a),"1" (b->b)); - __asm__("shrl %1,%0" - :"=r" (b->b) - :"c" ((char) shift),"0" (b->b)); - switch ((int)ROUNDING) { - case ROUND_NEAREST: - __asm__("addl %4,%5 ; adcl $0,%0 ; adcl $0,%1" - :"=r" (b->a),"=r" (b->b) - :"0" (b->a),"1" (b->b) - ,"r" (0x7fffffff + (b->a & 1)) - ,"m" (*&underflow)); - break; - case ROUND_UP: - if ((b->exponent >= 0) && underflow) - __asm__("addl $1,%0 ; adcl $0,%1" - :"=r" (b->a),"=r" (b->b) - :"0" (b->a),"1" (b->b)); - break; - case ROUND_DOWN: - if ((b->exponent < 0) && underflow) - __asm__("addl $1,%0 ; adcl $0,%1" - :"=r" (b->a),"=r" (b->b) - :"0" (b->a),"1" (b->b)); - break; - } - if (b->a || b->b) - while (b->b >= 0) { - b->exponent--; - __asm__("addl %0,%0 ; adcl %1,%1" - :"=r" (b->a),"=r" (b->b) - :"0" (b->a),"1" (b->b)); - } - else - b->exponent = 0; -} - -static void -Fscale(const temp_real *a, const temp_real *b, temp_real *c) -{ - temp_int ti; - - *c = *a; - if(!c->a && !c->b) { /* 19 Sep 92*/ - c->exponent = 0; - return; - } - real_to_int(b, &ti); - if(ti.sign) - c->exponent -= ti.a; - else - c->exponent += ti.a; -} - -static void -real_to_int(const temp_real * a, temp_int * b) -{ - int shift = 16383 + 63 - (a->exponent & 0x7fff); - u_int32_t underflow; - - b->a = b->b = underflow = 0; - b->sign = (a->exponent < 0); - if (shift < 0) { - set_OE(); - return; - } - if (shift < 32) { - b->b = a->b; b->a = a->a; - } else if (shift < 64) { - b->a = a->b; underflow = a->a; - shift -= 32; - } else if (shift < 96) { - underflow = a->b; - shift -= 64; - } else { - underflow = 1; - shift = 0; - } - __asm__("shrdl %2,%1,%0" - :"=r" (underflow),"=r" (b->a) - :"c" ((char) shift),"0" (underflow),"1" (b->a)); - __asm__("shrdl %2,%1,%0" - :"=r" (b->a),"=r" (b->b) - :"c" ((char) shift),"0" (b->a),"1" (b->b)); - __asm__("shrl %1,%0" - :"=r" (b->b) - :"c" ((char) shift),"0" (b->b)); - switch ((int)ROUNDING) { - case ROUND_NEAREST: - __asm__("addl %4,%5 ; adcl $0,%0 ; adcl $0,%1" - :"=r" (b->a),"=r" (b->b) - :"0" (b->a),"1" (b->b) - ,"r" (0x7fffffff + (b->a & 1)) - ,"m" (*&underflow)); - break; - case ROUND_UP: - if (!b->sign && underflow) - __asm__("addl $1,%0 ; adcl $0,%1" - :"=r" (b->a),"=r" (b->b) - :"0" (b->a),"1" (b->b)); - break; - case ROUND_DOWN: - if (b->sign && underflow) - __asm__("addl $1,%0 ; adcl $0,%1" - :"=r" (b->a),"=r" (b->b) - :"0" (b->a),"1" (b->b)); - break; - } -} - -static void -int_to_real(const temp_int * a, temp_real * b) -{ - b->a = a->a; - b->b = a->b; - if (b->a || b->b) - b->exponent = 16383 + 63 + (a->sign? 0x8000:0); - else { - b->exponent = 0; - return; - } - while (b->b >= 0) { - b->exponent--; - __asm__("addl %0,%0 ; adcl %1,%1" - :"=r" (b->a),"=r" (b->b) - :"0" (b->a),"1" (b->b)); - } -} - -static int -fpu_modevent(module_t mod, int type, void *unused) -{ - switch (type) { - case MOD_LOAD: - if (pmath_emulate) { - printf("Another Math emulator already present\n"); - return EBUSY; - } - pmath_emulate = math_emulate; - if (bootverbose) - printf("Math emulator present\n"); - break; - case MOD_UNLOAD: - if (pmath_emulate != math_emulate) { - printf("Cannot unload another math emulator\n"); - return EACCES; - } - pmath_emulate = 0; - if (bootverbose) - printf("Math emulator unloaded\n"); - break; - default: - break; - } - return 0; -} -static moduledata_t fpumod = { - "fpu", - fpu_modevent, - 0 -}; -DECLARE_MODULE(fpu, fpumod, SI_SUB_DRIVERS, SI_ORDER_ANY); diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index 1f165f2..30112ed 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -102,8 +102,6 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> -int (*pmath_emulate)(struct trapframe *); - extern void trap(struct trapframe frame); #ifdef I386_CPU extern int trapwrite(unsigned addr); @@ -398,21 +396,8 @@ trap(frame) if (npxdna()) goto userout; #endif - if (!pmath_emulate) { - i = SIGFPE; - ucode = FPE_FPU_NP_TRAP; - break; - } - mtx_lock(&Giant); - i = (*pmath_emulate)(&frame); - mtx_unlock(&Giant); - if (i == 0) { - if (!(frame.tf_eflags & PSL_T)) - goto userout; - frame.tf_eflags &= ~PSL_T; - i = SIGTRAP; - } - /* else ucode = emulator_only_knows() XXX */ + i = SIGFPE; + ucode = FPE_FPU_NP_TRAP; break; case T_FPOPFLT: /* FPU operand fetch fault */ diff --git a/sys/i386/include/frame.h b/sys/i386/include/frame.h index c32afc4..6112545 100644 --- a/sys/i386/include/frame.h +++ b/sys/i386/include/frame.h @@ -154,7 +154,6 @@ struct clockframe { }; int kdb_trap(int, int, struct trapframe *); -extern int (*pmath_emulate)(struct trapframe *); #define INTR_TO_TRAPFRAME(frame) ((struct trapframe *)&(frame)->if_fs) diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c index c44f789..a254d47 100644 --- a/sys/i386/isa/npx.c +++ b/sys/i386/isa/npx.c @@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$"); #include "opt_cpu.h" #include "opt_debug_npx.h" #include "opt_isa.h" -#include "opt_math_emulate.h" #include "opt_npx.h" #include <sys/param.h> @@ -106,7 +105,6 @@ __FBSDID("$FreeBSD$"); #define NPX_DISABLE_I586_OPTIMIZED_BCOPY (1 << 0) #define NPX_DISABLE_I586_OPTIMIZED_BZERO (1 << 1) #define NPX_DISABLE_I586_OPTIMIZED_COPYIO (1 << 2) -#define NPX_PREFER_EMULATOR (1 << 3) #if defined(__GNUC__) && !defined(lint) @@ -470,30 +468,10 @@ npx_attach(dev) if (npx_irq13) { device_printf(dev, "using IRQ 13 interface\n"); } else { -#if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE) - if (npx_ex16) { - if (!(flags & NPX_PREFER_EMULATOR)) - device_printf(dev, "INT 16 interface\n"); - else { - device_printf(dev, "FPU exists, but flags request " - "emulator\n"); - hw_float = npx_exists = 0; - } - } else if (npx_exists) { - device_printf(dev, "error reporting broken; using 387 emulator\n"); - hw_float = npx_exists = 0; - } else - device_printf(dev, "387 emulator\n"); -#else - if (npx_ex16) { + if (npx_ex16) device_printf(dev, "INT 16 interface\n"); - if (flags & NPX_PREFER_EMULATOR) { - device_printf(dev, "emulator requested, but none compiled " - "into kernel, using FPU\n"); - } - } else - device_printf(dev, "no 387 emulator in kernel and no FPU!\n"); -#endif + else + device_printf(dev, "WARNING: no FPU!\n"); } npxinit(__INITIAL_NPXCW__); diff --git a/sys/modules/Makefile b/sys/modules/Makefile index e44c8a0..2ed67c0 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -187,8 +187,6 @@ SUBDIR+=3dfx \ em \ ep \ fe \ - fpu \ - gnufpu \ hea \ hfa \ i2c \ @@ -251,7 +249,7 @@ SUBDIR+=canbepm \ .if ${MACHINE_ARCH} == "ia64" # Modules not enabled on ia64 (as compared to i386) include: -# aac acpi aout apm atspeaker drm fpu gnufpu ibcs2 linprocfs linux ncv +# aac acpi aout apm atspeaker drm ibcs2 linprocfs linux ncv # nsp oltr pecoff s3 sbni stg vesa SUBDIR+=aic \ ar \ diff --git a/sys/modules/fpu/Makefile b/sys/modules/fpu/Makefile deleted file mode 100644 index a8e78b7..0000000 --- a/sys/modules/fpu/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../i386/i386 - -KMOD= fpu -SRCS= math_emulate.c - -.include <bsd.kmod.mk> diff --git a/sys/modules/gnufpu/Makefile b/sys/modules/gnufpu/Makefile deleted file mode 100644 index f3767f7..0000000 --- a/sys/modules/gnufpu/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../gnu/i386/fpemul - -KMOD= gnufpu -SRCS= div_small.s errors.c fpu_arith.c fpu_aux.c fpu_entry.c fpu_etc.c \ - fpu_trig.c get_address.c load_store.c poly_2xm1.c poly_atan.c \ - poly_div.s poly_l2.c poly_mul64.s poly_sin.c poly_tan.c \ - polynomial.s reg_add_sub.c reg_compare.c reg_constant.c reg_div.s \ - reg_ld_str.c reg_u_mul.s reg_u_sub.s wm_shrx.s wm_sqrt.s - -EXPORT_SYMS= math_emulate - -.s.o: - ${CC} -x assembler-with-cpp -DLOCORE ${CFLAGS} -c \ - ${.IMPSRC} -o ${.TARGET} - -.include <bsd.kmod.mk> diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC index 60efee4..10f462d 100644 --- a/sys/pc98/conf/GENERIC +++ b/sys/pc98/conf/GENERIC @@ -31,7 +31,6 @@ ident GENERIC makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols options PC98 #PC98 -options MATH_EMULATE #Support for x87 emulation options SCHED_4BSD #4BSD scheduler options INET #InterNETworking options INET6 #IPv6 communications protocols diff --git a/sys/pc98/conf/NOTES b/sys/pc98/conf/NOTES index ecf3816..f62eb2e 100644 --- a/sys/pc98/conf/NOTES +++ b/sys/pc98/conf/NOTES @@ -176,16 +176,6 @@ options CYRIX_CACHE_REALLY_WORKS #options NO_F00F_HACK options CPU_DISABLE_CMPXCHG -# -# A math emulator is mandatory if you wish to run on hardware which -# does not have a floating-point processor. Pick either the original, -# bogus (but freely-distributable) math emulator, or a much more -# fully-featured but GPL-licensed emulator taken from Linux. -# -options MATH_EMULATE #Support for x87 emulation -# Don't enable both of these in a real config. -options GPL_MATH_EMULATE #Support for x87 emulation via - # Debug options options NPX_DEBUG # enable npx debugging (FPU/math emu) #new math emulator |