This source file includes following definitions.
- Un_impl
- emu_printall
- exception
- real_2op_NaN
- arith_invalid
- divide_by_zero
- arith_overflow
- arith_underflow
- stack_overflow
- stack_underflow
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <linux/signal.h>
21
22 #include <asm/segment.h>
23
24 #include "fpu_system.h"
25 #include "exception.h"
26 #include "fpu_emu.h"
27 #include "status_w.h"
28 #include "control_w.h"
29 #include "reg_constant.h"
30 #include "version.h"
31
32
33 #undef PRINT_MESSAGES
34
35
36 void Un_impl(void)
37 {
38 unsigned char byte1, FPU_modrm;
39
40 RE_ENTRANT_CHECK_OFF
41 byte1 = get_fs_byte((unsigned char *) FPU_ORIG_EIP);
42 FPU_modrm = get_fs_byte(1 + (unsigned char *) FPU_ORIG_EIP);
43
44 printk("Unimplemented FPU Opcode at eip=%p : %02x ",
45 FPU_ORIG_EIP, byte1);
46
47 if (FPU_modrm >= 0300)
48 printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
49 else
50 printk("/%d\n", (FPU_modrm >> 3) & 7);
51 RE_ENTRANT_CHECK_ON
52
53 EXCEPTION(EX_Invalid);
54
55 }
56
57
58
59
60 void emu_printall()
61 {
62 int i;
63 static char *tag_desc[] = { "Valid", "Zero", "ERROR", "ERROR",
64 "DeNorm", "Inf", "NaN", "Empty" };
65 unsigned char byte1, FPU_modrm;
66
67 RE_ENTRANT_CHECK_OFF
68 byte1 = get_fs_byte((unsigned char *) FPU_ORIG_EIP);
69 FPU_modrm = get_fs_byte(1 + (unsigned char *) FPU_ORIG_EIP);
70
71 #ifdef DEBUGGING
72 if ( status_word & SW_B ) printk("SW: backward compatibility (=ES)\n");
73 if ( status_word & SW_C3 ) printk("SW: condition bit 3\n");
74 if ( status_word & SW_C2 ) printk("SW: condition bit 2\n");
75 if ( status_word & SW_C1 ) printk("SW: condition bit 1\n");
76 if ( status_word & SW_C0 ) printk("SW: condition bit 0\n");
77 if ( status_word & SW_ES ) printk("SW: exception summary\n");
78 if ( status_word & SW_SF ) printk("SW: stack fault\n");
79 if ( status_word & SW_PE ) printk("SW: loss of precision\n");
80 if ( status_word & SW_UE ) printk("SW: underflow\n");
81 if ( status_word & SW_OE ) printk("SW: overflow\n");
82 if ( status_word & SW_ZE ) printk("SW: divide by zero\n");
83 if ( status_word & SW_DE ) printk("SW: denormalized operand\n");
84 if ( status_word & SW_IE ) printk("SW: invalid operation\n");
85 #endif DEBUGGING
86
87 status_word = status_word & ~SW_TOP;
88 status_word |= (top&7) << SW_TOPS;
89
90 printk("At %p: %02x ", FPU_ORIG_EIP, byte1);
91 if (FPU_modrm >= 0300)
92 printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
93 else
94 printk("/%d, mod=%d rm=%d\n",
95 (FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7);
96
97 printk(" SW: b=%d st=%d es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n",
98 status_word & 0x8000 ? 1 : 0,
99 (status_word & 0x3800) >> 11,
100 status_word & 0x80 ? 1 : 0,
101 status_word & 0x40 ? 1 : 0,
102 status_word & SW_C3?1:0, status_word & SW_C2?1:0,
103 status_word & SW_C1?1:0, status_word & SW_C0?1:0,
104 status_word & SW_PE?1:0, status_word & SW_UE?1:0,
105 status_word & SW_OE?1:0, status_word & SW_ZE?1:0,
106 status_word & SW_DE?1:0, status_word & SW_IE?1:0);
107
108 printk(" CW: ic=%d rc=%d%d pc=%d%d iem=%d ef=%d%d%d%d%d%d\n",
109 control_word & 0x1000 ? 1 : 0,
110 (control_word & 0x800) >> 11, (control_word & 0x400) >> 10,
111 (control_word & 0x200) >> 9, (control_word & 0x100) >> 8,
112 control_word & 0x80 ? 1 : 0,
113 control_word & SW_PE?1:0, control_word & SW_UE?1:0,
114 control_word & SW_OE?1:0, control_word & SW_ZE?1:0,
115 control_word & SW_DE?1:0, control_word & SW_IE?1:0);
116
117 for ( i = 0; i < 8; i++ )
118 {
119 FPU_REG *r = &st(i);
120 switch (r->tag)
121 {
122 case TW_Empty:
123 continue;
124 break;
125 case TW_Zero:
126 printk("st(%d) %c .0000 0000 0000 0000 ",
127 i, r->sign ? '-' : '+');
128 break;
129 case TW_Valid:
130 case TW_NaN:
131 case TW_Denormal:
132 case TW_Infinity:
133 printk("st(%d) %c .%04x %04x %04x %04x e%+-6d ", i,
134 r->sign ? '-' : '+',
135 (long)(r->sigh >> 16),
136 (long)(r->sigh & 0xFFFF),
137 (long)(r->sigl >> 16),
138 (long)(r->sigl & 0xFFFF),
139 r->exp - EXP_BIAS + 1);
140 break;
141 default:
142 printk("Whoops! Error in errors.c ");
143 break;
144 }
145 printk("%s\n", tag_desc[(int) (unsigned) r->tag]);
146 }
147
148 printk("[data] %c .%04x %04x %04x %04x e%+-6d ",
149 FPU_loaded_data.sign ? '-' : '+',
150 (long)(FPU_loaded_data.sigh >> 16),
151 (long)(FPU_loaded_data.sigh & 0xFFFF),
152 (long)(FPU_loaded_data.sigl >> 16),
153 (long)(FPU_loaded_data.sigl & 0xFFFF),
154 FPU_loaded_data.exp - EXP_BIAS + 1);
155 printk("%s\n", tag_desc[(int) (unsigned) FPU_loaded_data.tag]);
156 RE_ENTRANT_CHECK_ON
157
158 }
159
160 static struct {
161 int type;
162 char *name;
163 } exception_names[] = {
164 { EX_StackOver, "stack overflow" },
165 { EX_StackUnder, "stack underflow" },
166 { EX_Precision, "loss of precision" },
167 { EX_Underflow, "underflow" },
168 { EX_Overflow, "overflow" },
169 { EX_ZeroDiv, "divide by zero" },
170 { EX_Denormal, "denormalized operand" },
171 { EX_Invalid, "invalid operation" },
172 { EX_INTERNAL, "INTERNAL BUG in "FPU_VERSION },
173 { 0, NULL }
174 };
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221 void exception(int n)
222 {
223 int i, int_type;
224
225 int_type = 0;
226 if ( n & EX_INTERNAL )
227 {
228 int_type = n - EX_INTERNAL;
229 n = EX_INTERNAL;
230
231 status_word |= (0x3f | EX_ErrorSummary | FPU_BUSY);
232 }
233 else
234 {
235
236 status_word |= (n | EX_ErrorSummary | FPU_BUSY);
237 if (n == EX_StackUnder)
238
239 status_word &= ~SW_C1;
240 }
241
242 RE_ENTRANT_CHECK_OFF
243 if ( (~control_word & n & CW_EXM) || (n == EX_INTERNAL) )
244 {
245 #ifdef PRINT_MESSAGES
246
247 printk(FPU_VERSION" "__DATE__" (C) W. Metzenthen.\n");
248 #endif PRINT_MESSAGES
249
250
251 for (i=0; exception_names[i].type; i++)
252 if (exception_names[i].type == n)
253 break;
254
255 if (exception_names[i].type)
256 {
257 #ifdef PRINT_MESSAGES
258 printk("FP Exception: %s!\n", exception_names[i].name);
259 #endif PRINT_MESSAGES
260 }
261 else
262 printk("FP emulator: Unknown Exception: 0x%04x!\n", n);
263
264 if ( n == EX_INTERNAL )
265 {
266 printk("FP emulator: Internal error type 0x%04x\n", int_type);
267 emu_printall();
268 }
269 #ifdef PRINT_MESSAGES
270 else
271 emu_printall();
272 #endif PRINT_MESSAGES
273
274 send_sig(SIGFPE, current, 1);
275 }
276 RE_ENTRANT_CHECK_ON
277
278 #ifdef __DEBUG__
279 math_abort(FPU_info,SIGFPE);
280 #endif __DEBUG__
281
282
283 FPU_lookahead = 0;
284 }
285
286
287
288 void real_2op_NaN(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
289 {
290 FPU_REG *x;
291
292 x = a;
293 if (a->tag == TW_NaN)
294 {
295 if (b->tag == TW_NaN)
296 {
297
298 if ( *(long long *)&(a->sigl) < *(long long *)&(b->sigl) )
299 x = b;
300 }
301
302 }
303 else if (b->tag == TW_NaN)
304 {
305 x = b;
306 }
307 #ifdef PARANOID
308 else
309 {
310 EXCEPTION(EX_INTERNAL|0x113);
311 x = &CONST_QNaN;
312 }
313 #endif PARANOID
314
315 if ( control_word & EX_Invalid )
316 {
317
318 reg_move(x, dest);
319
320 dest->sigh |= 0x40000000;
321 }
322
323 EXCEPTION(EX_Invalid);
324
325 return;
326 }
327
328
329 void arith_invalid(FPU_REG *dest)
330 {
331
332 if ( control_word & EX_Invalid )
333 {
334
335 reg_move(&CONST_QNaN, dest);
336 }
337
338 EXCEPTION(EX_Invalid);
339
340 return;
341
342 }
343
344
345
346 void divide_by_zero(int sign, FPU_REG *dest)
347 {
348
349 if ( control_word & EX_ZeroDiv )
350 {
351
352 reg_move(&CONST_INF, dest);
353 dest->sign = (unsigned char)sign;
354 }
355
356 EXCEPTION(EX_ZeroDiv);
357
358 return;
359
360 }
361
362
363 void arith_overflow(FPU_REG *dest)
364 {
365
366 if ( control_word & EX_Overflow )
367 {
368 char sign;
369
370 sign = dest->sign;
371 reg_move(&CONST_INF, dest);
372 dest->sign = sign;
373 }
374 else
375 {
376
377 dest->exp -= (3 * (1 << 13));
378 }
379
380 EXCEPTION(EX_Overflow);
381
382 return;
383
384 }
385
386
387 void arith_underflow(FPU_REG *dest)
388 {
389
390 if ( control_word & EX_Underflow )
391 {
392
393 if ( dest->exp <= EXP_UNDER - 63 )
394 reg_move(&CONST_Z, dest);
395 }
396 else
397 {
398
399 dest->exp += (3 * (1 << 13));
400 }
401
402 EXCEPTION(EX_Underflow);
403
404 return;
405 }
406
407
408 void stack_overflow(void)
409 {
410
411 if ( control_word & EX_Invalid )
412 {
413
414 top--;
415 reg_move(&CONST_QNaN, FPU_st0_ptr = &st(0));
416 }
417
418 EXCEPTION(EX_StackOver);
419
420 return;
421
422 }
423
424
425 void stack_underflow(void)
426 {
427
428 if ( control_word & EX_Invalid )
429 {
430
431 reg_move(&CONST_QNaN, FPU_st0_ptr);
432 }
433
434 EXCEPTION(EX_StackUnder);
435
436 return;
437
438 }
439