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