Rev 548 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
548 | serge | 1 | /**************************************************************************** |
2 | * |
||
3 | * Open Watcom Project |
||
4 | * |
||
5 | * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. |
||
6 | * |
||
7 | * ======================================================================== |
||
8 | * |
||
9 | * This file contains Original Code and/or Modifications of Original |
||
10 | * Code as defined in and that are subject to the Sybase Open Watcom |
||
11 | * Public License version 1.0 (the 'License'). You may not use this file |
||
12 | * except in compliance with the License. BY USING THIS FILE YOU AGREE TO |
||
13 | * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is |
||
14 | * provided with the Original Code and Modifications, and is also |
||
15 | * available at www.sybase.com/developer/opensource. |
||
16 | * |
||
17 | * The Original Code and all software distributed under the License are |
||
18 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
||
19 | * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM |
||
20 | * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF |
||
21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR |
||
22 | * NON-INFRINGEMENT. Please see the License for the specific language |
||
23 | * governing rights and limitations under the License. |
||
24 | * |
||
25 | * ======================================================================== |
||
26 | * |
||
27 | * Description: __chk8087 and other FPU related functions. |
||
28 | * |
||
29 | ****************************************************************************/ |
||
30 | |||
31 | |||
32 | #include "variety.h" |
||
33 | #include |
||
34 | #include |
||
35 | #if defined( __OS2__ ) |
||
36 | #endif |
||
37 | #if defined( __WINDOWS__ ) |
||
38 | #include |
||
39 | #endif |
||
40 | |||
41 | #include "rtdata.h" |
||
42 | #include "exitwmsg.h" |
||
43 | #include "87state.h" |
||
44 | |||
45 | extern void __GrabFP87( void ); |
||
46 | |||
47 | extern unsigned short __8087cw; |
||
48 | #pragma aux __8087cw "*"; |
||
49 | |||
50 | #if defined( __DOS_086__ ) |
||
51 | extern unsigned char __dos87real; |
||
52 | #pragma aux __dos87real "*"; |
||
53 | |||
54 | extern unsigned short __dos87emucall; |
||
55 | #pragma aux __dos87emucall "*"; |
||
56 | #endif |
||
57 | |||
58 | extern void __init_80x87( void ); |
||
59 | #if defined( __DOS_086__ ) |
||
60 | #pragma aux __init_80x87 "*" = \ |
||
61 | ".8087" \ |
||
62 | "cmp __dos87real,0" \ |
||
63 | "jz l1" \ |
||
64 | "finit" \ |
||
65 | "fldcw __8087cw" \ |
||
66 | "l1: cmp __dos87emucall,0" \ |
||
67 | "jz l2" \ |
||
68 | "mov ax,1" \ |
||
69 | "call __dos87emucall" \ |
||
70 | "l2:" ; |
||
71 | #else |
||
72 | #pragma aux __init_80x87 "*" = \ |
||
73 | ".8087" \ |
||
74 | "finit" \ |
||
75 | "fldcw __8087cw" ; |
||
76 | #endif |
||
77 | |||
78 | /* 0 => no 8087; 2 => 8087,287; 3=>387 */ |
||
79 | extern unsigned char _WCI86NEAR __x87id( void ); |
||
80 | #pragma aux __x87id "*"; |
||
81 | |||
82 | #if !defined( __UNIX__ ) && !defined( __OS2_386__ ) |
||
83 | |||
84 | extern void __fsave( _87state * ); |
||
85 | extern void __frstor( _87state * ); |
||
86 | |||
87 | #if defined( __386__ ) |
||
88 | |||
89 | #pragma aux __fsave = \ |
||
90 | 0x9b 0xdd 0x30 /* fsave [eax] ; save the 8087 state */ \ |
||
91 | 0x9b /* wait */ \ |
||
92 | parm routine [eax]; |
||
93 | |||
94 | #pragma aux __frstor = \ |
||
95 | 0xdd 0x20 /* frstor [eax] ; restore the 8087 */ \ |
||
96 | 0x9b /* wait ; wait */ \ |
||
97 | parm routine [eax]; |
||
98 | |||
99 | #else /* __286__ */ |
||
100 | |||
101 | #if defined( __BIG_DATA__ ) |
||
102 | #pragma aux __fsave = \ |
||
103 | 0x53 /* push bx */ \ |
||
104 | 0x1e /* push ds */ \ |
||
105 | 0x8e 0xda /* mov ds,dx */ \ |
||
106 | 0x8b 0xd8 /* mov bx,ax */ \ |
||
107 | 0x9b 0xdd 0x37 /* fsave [bx] */ \ |
||
108 | 0x90 0x9b /* fwait */ \ |
||
109 | 0x1f /* pop ds */ \ |
||
110 | 0x5b /* pop bx */ \ |
||
111 | parm routine [dx ax]; |
||
112 | #else |
||
113 | #pragma aux __fsave = \ |
||
114 | 0x53 /* push bx */ \ |
||
115 | 0x8b 0xd8 /* mov bx,ax */ \ |
||
116 | 0x9b 0xdd 0x37 /* fsave [bx] */ \ |
||
117 | 0x90 0x9b /* fwait */ \ |
||
118 | 0x5b /* pop bx */ \ |
||
119 | parm routine [ax]; |
||
120 | #endif |
||
121 | |||
122 | #if defined( __BIG_DATA__ ) |
||
123 | #pragma aux __frstor = \ |
||
124 | 0x53 /* push bx */ \ |
||
125 | 0x1e /* push ds */ \ |
||
126 | 0x8e 0xda /* mov ds,dx */ \ |
||
127 | 0x8b 0xd8 /* mov bx,ax */ \ |
||
128 | 0x9b 0xdd 0x27 /* frstor [bx] */ \ |
||
129 | 0x90 0x9b /* fwait */ \ |
||
130 | 0x1f /* pop ds */ \ |
||
131 | 0x5b /* pop bx */ \ |
||
132 | parm routine [dx ax]; |
||
133 | #else |
||
134 | #pragma aux __frstor = \ |
||
135 | 0x53 /* push bx */ \ |
||
136 | 0x8b 0xd8 /* mov bx,ax */ \ |
||
137 | 0x9b 0xdd 0x27 /* frstor [bx] */ \ |
||
138 | 0x90 0x9b /* fwait */ \ |
||
139 | 0x5b /* pop bx */ \ |
||
140 | parm routine [ax]; |
||
141 | #endif |
||
142 | |||
143 | #endif |
||
144 | |||
145 | static void __save_8087( _87state * __fs ) |
||
146 | { |
||
147 | __fsave( __fs ); |
||
148 | } |
||
149 | |||
150 | static void __rest_8087( _87state * __fs ) |
||
151 | { |
||
152 | __frstor( __fs ); |
||
153 | } |
||
154 | #endif /* !__UNIX__ && && !__OS2__ */ |
||
155 | |||
156 | _WCRTLINK void _fpreset( void ) |
||
157 | { |
||
158 | if( _RWD_8087 != 0 ) { |
||
159 | __init_80x87(); |
||
160 | } |
||
161 | } |
||
162 | |||
163 | void __init_8087( void ) |
||
164 | { |
||
165 | #if !defined( __UNIX__ ) && !defined( __OS2_386__ ) |
||
166 | if( _RWD_real87 != 0 ) |
||
167 | { /* if our emulator, don't worry */ |
||
168 | _RWD_Save8087 = __save_8087; /* point to real save 8087 routine */ |
||
169 | _RWD_Rest8087 = __rest_8087; /* point to real restore 8087 routine */ |
||
170 | } |
||
171 | #endif |
||
172 | _fpreset(); |
||
173 | } |
||
174 | |||
175 | #if defined( __DOS__ ) || defined( __OS2_286__ ) |
||
176 | |||
177 | void _WCI86FAR __default_sigfpe_handler( int fpe_sig ) |
||
178 | { |
||
179 | __fatal_runtime_error( "Floating point exception\r\n", EXIT_FAILURE ); |
||
180 | } |
||
181 | #endif |
||
182 | |||
183 | #if defined( __OS2__ ) |
||
184 | |||
185 | void __chk8087( void ) |
||
186 | /********************/ |
||
187 | { |
||
188 | char devinfo; |
||
189 | |||
190 | #if defined( __386__ ) |
||
191 | DosDevConfig( &devinfo, DEVINFO_COPROCESSOR ); |
||
192 | if( devinfo == 0 ) { |
||
193 | _RWD_real87 = 0; |
||
194 | } else { |
||
195 | _RWD_real87 = __x87id(); |
||
196 | } |
||
197 | _RWD_8087 = _RWD_real87; |
||
198 | #else |
||
199 | if( _RWD_8087 == 0 ) { |
||
200 | DosDevConfig( &devinfo, 3, 0 ); |
||
201 | if( devinfo == 0 ) { |
||
202 | _RWD_real87 = 0; |
||
203 | } else { |
||
204 | _RWD_real87 = __x87id(); |
||
205 | } |
||
206 | _RWD_8087 = _RWD_real87; |
||
207 | } |
||
208 | if( _RWD_real87 ) { |
||
209 | __GrabFP87(); |
||
210 | } |
||
211 | if( _RWD_8087 ) { |
||
212 | _RWD_FPE_handler = __default_sigfpe_handler; |
||
213 | } |
||
214 | #endif |
||
215 | _fpreset(); |
||
216 | } |
||
217 | |||
218 | #elif defined( __QNX__ ) |
||
219 | |||
220 | void __chk8087( void ) |
||
221 | /********************/ |
||
222 | { |
||
223 | extern char __87; |
||
224 | extern char __r87; |
||
225 | |||
226 | _RWD_real87 = __r87; |
||
227 | _RWD_8087 = __87; |
||
228 | _fpreset(); |
||
229 | } |
||
230 | |||
231 | #elif defined( __LINUX__ ) |
||
232 | |||
233 | void __chk8087( void ) |
||
234 | /********************/ |
||
235 | { |
||
236 | // TODO: We really need to call Linux and determine if the machine |
||
237 | // has a real FPU or not, so we can properly work with an FPU |
||
238 | // emulator. |
||
239 | _RWD_real87 = __x87id(); |
||
240 | _RWD_8087 = _RWD_real87; |
||
241 | _fpreset(); |
||
242 | } |
||
243 | |||
244 | #elif defined( __NETWARE__ ) |
||
245 | |||
246 | extern short __87present( void ); |
||
247 | #pragma aux __87present = \ |
||
248 | "smsw ax ", \ |
||
249 | "test ax, 4 ", \ |
||
250 | "jne no_emu ", \ |
||
251 | "xor ax, ax ", \ |
||
252 | "no_emu: ", \ |
||
253 | "mov ax, 1 " \ |
||
254 | value [ ax ]; |
||
255 | |||
256 | extern void __chk8087( void ) |
||
257 | /*****************************/ |
||
258 | { |
||
259 | if( _RWD_8087 == 0 ) { |
||
260 | if( __87present() ) { |
||
261 | _RWD_8087 = 3; /* 387 */ |
||
262 | _RWD_real87 = 3; |
||
263 | } |
||
264 | __init_80x87(); |
||
265 | } |
||
266 | } |
||
267 | |||
268 | #elif defined( __NT__ ) |
||
269 | |||
270 | void __chk8087( void ) |
||
271 | /********************/ |
||
272 | { |
||
702 | serge | 273 | _RWD_real87 = __x87id(); |
548 | serge | 274 | _RWD_8087 = _RWD_real87; |
275 | __init_8087(); |
||
276 | } |
||
277 | |||
278 | #elif defined( __DOS__ ) |
||
279 | |||
280 | void __chk8087( void ) |
||
281 | /********************/ |
||
282 | { |
||
283 | if( _RWD_8087 != 0 ) { /* if we already know we have an 80x87 */ |
||
284 | #if !defined( __386__ ) |
||
285 | if( __dos87real ) |
||
286 | __GrabFP87(); |
||
287 | #endif |
||
288 | _RWD_FPE_handler = __default_sigfpe_handler; |
||
289 | return; /* this prevents real87 from being set */ |
||
290 | } /* when we have an emulator */ |
||
291 | _RWD_real87 = __x87id(); /* if a coprocessor is present then we */ |
||
292 | _RWD_8087 = _RWD_real87; /* initialize even when NO87 is defined */ |
||
293 | #if !defined( __386__ ) |
||
294 | __dos87real = _RWD_real87; |
||
295 | #endif |
||
296 | __init_8087(); /* this handles the fpi87 and NO87 case */ |
||
297 | if( _RWD_no87 != 0 ) { /* if NO87 environment var is defined */ |
||
298 | _RWD_8087 = 0; /* then we want to pretend that the */ |
||
299 | _RWD_real87 = 0; /* coprocessor doesn't exist */ |
||
300 | } |
||
301 | if( _RWD_real87 ) { |
||
302 | __GrabFP87(); |
||
303 | } |
||
304 | if( _RWD_8087 ) { |
||
305 | _RWD_FPE_handler = __default_sigfpe_handler; |
||
306 | } |
||
307 | } |
||
308 | |||
309 | #elif defined( __WINDOWS__ ) |
||
310 | |||
311 | void __chk8087( void ) |
||
312 | /********************/ |
||
313 | { |
||
314 | if( _RWD_8087 != 0 ) /* if we already know we have an 80x87 */ |
||
315 | return; /* this prevents real87 from being set */ |
||
316 | /* when we have an emulator */ |
||
317 | if( GetWinFlags() & WF_80x87 ) { /* if a coprocessor is present then we */ |
||
318 | #if defined( __386__ ) |
||
319 | extern void pascal _FloatingPoint( void ); |
||
320 | _FloatingPoint(); |
||
321 | #endif |
||
322 | _RWD_real87 = __x87id(); /* initialize even when NO87 is defined */ |
||
323 | _RWD_8087 = _RWD_real87; /* this handles the fpi87 and NO87 case */ |
||
324 | __init_8087(); |
||
325 | } else { |
||
326 | #if defined( __386__ ) |
||
327 | // check to see if emulator is loaded |
||
328 | union REGS regs; |
||
329 | regs.w.ax = 0xfa00; |
||
330 | int86( 0x2f, ®s, ®s ); |
||
331 | if( regs.w.ax == 0x0666 ) { /* check for emulator present */ |
||
332 | _RWD_real87 = __x87id(); /* initialize even when NO87 is defined */ |
||
333 | _RWD_8087 = _RWD_real87; /* this handles the fpi87 and NO87 case */ |
||
334 | __init_8087(); |
||
335 | } |
||
336 | #endif |
||
337 | } |
||
338 | if( _RWD_no87 != 0 ) { /* if NO87 environment var is defined */ |
||
339 | _RWD_8087 = 0; /* then we want to pretend that the */ |
||
340 | _RWD_real87 = 0; /* coprocessor doesn't exist */ |
||
341 | } |
||
342 | } |
||
343 | |||
344 | #endif |