Initial import from FreeBSD RELENG_4:
[games.git] / sys / platform / pc32 / gnu / fpemul / fpu_aux.c
1 /*
2  *  fpu_aux.c
3  *
4  * Code to implement some of the FPU auxiliary 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_aux.c,v 1.11 1999/10/12 02:23:14 msmith Exp $
60  *
61  */
62
63
64 #include <sys/param.h>
65 #ifdef DEBUG
66 #include <sys/systm.h>          /* for printf() in EXCEPTION() */
67 #endif
68 #include <sys/proc.h>
69 #include <machine/cpu.h>
70 #include <machine/pcb.h>
71
72 #include <gnu/i386/fpemul/fpu_emu.h>
73 #include <gnu/i386/fpemul/fpu_system.h>
74 #include <gnu/i386/fpemul/exception.h>
75 #include <gnu/i386/fpemul/status_w.h>
76
77
78 static void
79 fclex(void)
80 {
81         status_word &= ~(SW_Backward | SW_Summary | SW_Stack_Fault | SW_Precision |
82             SW_Underflow | SW_Overflow | SW_Zero_Div | SW_Denorm_Op |
83             SW_Invalid);
84         FPU_entry_eip = ip_offset;      /* We want no net effect */
85 }
86 /* Needs to be externally visible */
87 void
88 finit()
89 {
90         int     r;
91         control_word = 0x037f;
92         status_word = 0;
93         top = 0;                /* We don't keep top in the status word
94                                  * internally. */
95         for (r = 0; r < 8; r++) {
96                 regs[r].tag = TW_Empty;
97         }
98         FPU_entry_eip = ip_offset = 0;
99 }
100
101 static FUNC finit_table[] = {
102         Un_impl, Un_impl, fclex, finit, Un_impl, Un_impl, Un_impl, Un_impl
103 };
104
105 void
106 finit_()
107 {
108         (finit_table[FPU_rm]) ();
109 }
110
111
112 static void
113 fstsw_ax(void)
114 {
115
116         status_word &= ~SW_Top;
117         status_word |= (top & 7) << SW_Top_Shift;
118
119         *(short *) &FPU_EAX = status_word;
120
121 }
122
123 static FUNC fstsw_table[] = {
124         fstsw_ax, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl
125 };
126
127 void
128 fstsw_()
129 {
130         (fstsw_table[FPU_rm]) ();
131 }
132
133
134
135 static void
136 fnop(void)
137 {
138 }
139
140 static FUNC    fp_nop_table[] = {
141         fnop, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl
142 };
143
144 void
145 fp_nop()
146 {
147         (fp_nop_table[FPU_rm]) ();
148 }
149
150
151 void
152 fld_i_()
153 {
154         FPU_REG *st_new_ptr;
155
156         if (STACK_OVERFLOW) {
157                 stack_overflow();
158                 return;
159         }
160         /* fld st(i) */
161         if (NOT_EMPTY(FPU_rm)) {
162                 reg_move(&st(FPU_rm), st_new_ptr);
163                 push();
164         } else {
165                 if (control_word & EX_Invalid) {
166                         /* The masked response */
167                         push();
168                         stack_underflow();
169                 } else
170                         EXCEPTION(EX_StackUnder);
171         }
172
173 }
174
175
176 void
177 fxch_i()
178 {
179         /* fxch st(i) */
180         FPU_REG t;
181         register FPU_REG *sti_ptr = &st(FPU_rm);
182
183         if (FPU_st0_tag == TW_Empty) {
184                 if (sti_ptr->tag == TW_Empty) {
185                         stack_underflow();
186                         stack_underflow_i(FPU_rm);
187                         return;
188                 }
189                 reg_move(sti_ptr, FPU_st0_ptr);
190                 stack_underflow_i(FPU_rm);
191                 return;
192         }
193         if (sti_ptr->tag == TW_Empty) {
194                 reg_move(FPU_st0_ptr, sti_ptr);
195                 stack_underflow();
196                 return;
197         }
198         reg_move(FPU_st0_ptr, &t);
199         reg_move(sti_ptr, FPU_st0_ptr);
200         reg_move(&t, sti_ptr);
201 }
202
203
204 void
205 ffree_()
206 {
207         /* ffree st(i) */
208         st(FPU_rm).tag = TW_Empty;
209 }
210
211
212 void
213 ffreep()
214 {
215         /* ffree st(i) + pop - unofficial code */
216         st(FPU_rm).tag = TW_Empty;
217         pop();
218 }
219
220
221 void
222 fst_i_()
223 {
224         /* fst st(i) */
225         reg_move(FPU_st0_ptr, &st(FPU_rm));
226 }
227
228
229 void
230 fstp_i()
231 {
232         /* fstp st(i) */
233         reg_move(FPU_st0_ptr, &st(FPU_rm));
234         pop();
235 }