Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / i386 / gnu / fpemul / fpu_etc.c
1 /*
2  *  fpu_etc.c
3  *
4  * Implement a few FPU instructions.
5  *
6  *
7  * Copyright (C) 1992,1993,1994
8  *                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,
9  *                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au
10  * All rights reserved.
11  *
12  * This copyright notice covers the redistribution and use of the
13  * FPU emulator developed by W. Metzenthen. It covers only its use
14  * in the 386BSD, FreeBSD and NetBSD operating systems. Any other
15  * use is not permitted under this copyright.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  *    notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must include information specifying
23  *    that source code for the emulator is freely available and include
24  *    either:
25  *      a) an offer to provide the source code for a nominal distribution
26  *         fee, or
27  *      b) list at least two alternative methods whereby the source
28  *         can be obtained, e.g. a publically accessible bulletin board
29  *         and an anonymous ftp site from which the software can be
30  *         downloaded.
31  * 3. All advertising materials specifically mentioning features or use of
32  *    this emulator must acknowledge that it was developed by W. Metzenthen.
33  * 4. The name of W. Metzenthen may not be used to endorse or promote
34  *    products derived from this software without specific prior written
35  *    permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
38  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
39  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
40  * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
41  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
42  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
44  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
45  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  *
48  *
49  * The purpose of this copyright, based upon the Berkeley copyright, is to
50  * ensure that the covered software remains freely available to everyone.
51  *
52  * The software (with necessary differences) is also available, but under
53  * the terms of the GNU copyleft, for the Linux operating system and for
54  * the djgpp ms-dos extender.
55  *
56  * W. Metzenthen   June 1994.
57  *
58  *
59  * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_etc.c,v 1.8 1999/08/28 00:42:51 peter Exp $
60  *
61  */
62
63 #include <sys/param.h>
64 #ifdef DEBUG
65 #include <sys/systm.h>          /* for printf() in EXCEPTION() */
66 #endif
67 #include <sys/proc.h>
68 #include <machine/pcb.h>
69
70 #include <gnu/i386/fpemul/fpu_emu.h>
71 #include <gnu/i386/fpemul/fpu_system.h>
72 #include <gnu/i386/fpemul/exception.h>
73 #include <gnu/i386/fpemul/status_w.h>
74
75
76 static void
77 fchs(void)
78 {
79         if (NOT_EMPTY_0) {
80                 FPU_st0_ptr->sign ^= SIGN_POS ^ SIGN_NEG;
81                 status_word &= ~SW_C1;
82         } else
83                 stack_underflow();
84 }
85
86 static void
87 fabs(void)
88 {
89         if (FPU_st0_tag ^ TW_Empty) {
90                 FPU_st0_ptr->sign = SIGN_POS;
91                 status_word &= ~SW_C1;
92         } else
93                 stack_underflow();
94 }
95
96
97 static void
98 ftst_(void)
99 {
100         switch (FPU_st0_tag) {
101                 case TW_Zero:
102                 setcc(SW_C3);
103                 break;
104         case TW_Valid:
105
106 #ifdef DENORM_OPERAND
107                 if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
108                         return;
109 #endif                          /* DENORM_OPERAND */
110
111                 if (FPU_st0_ptr->sign == SIGN_POS)
112                         setcc(0);
113                 else
114                         setcc(SW_C0);
115                 break;
116         case TW_NaN:
117                 setcc(SW_C0 | SW_C2 | SW_C3);   /* Operand is not comparable */
118                 EXCEPTION(EX_Invalid);
119                 break;
120         case TW_Infinity:
121                 if (FPU_st0_ptr->sign == SIGN_POS)
122                         setcc(0);
123                 else
124                         setcc(SW_C0);
125                 EXCEPTION(EX_Invalid);
126                 break;
127         case TW_Empty:
128                 setcc(SW_C0 | SW_C2 | SW_C3);
129                 EXCEPTION(EX_StackUnder);
130                 break;
131         default:
132                 setcc(SW_C0 | SW_C2 | SW_C3);   /* Operand is not comparable */
133                 EXCEPTION(EX_INTERNAL | 0x14);
134                 break;
135         }
136 }
137
138 static void
139 fxam(void)
140 {
141         int     c = 0;
142         switch (FPU_st0_tag) {
143         case TW_Empty:
144                 c = SW_C3 | SW_C0;
145                 break;
146         case TW_Zero:
147                 c = SW_C3;
148                 break;
149         case TW_Valid:
150                 /* This will need to be changed if TW_Denormal is ever used. */
151                 if (FPU_st0_ptr->exp <= EXP_UNDER)
152                         c = SW_C2 | SW_C3;      /* Denormal */
153                 else
154                         c = SW_C3;
155                 break;
156         case TW_NaN:
157                 c = SW_C0;
158                 break;
159         case TW_Infinity:
160                 c = SW_C2 | SW_C0;
161                 break;
162         }
163         if (FPU_st0_ptr->sign == SIGN_NEG)
164                 c |= SW_C1;
165         setcc(c);
166 }
167
168 static FUNC fp_etc_table[] = {
169         fchs, fabs, Un_impl, Un_impl, ftst_, fxam, Un_impl, Un_impl
170 };
171
172 void
173 fp_etc()
174 {
175         (fp_etc_table[FPU_rm]) ();
176 }