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