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,0
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 if ( n & EX_INTERNAL )
225 {
226 int_type = n - EX_INTERNAL;
227 n = EX_INTERNAL;
228
229 status_word |= (0x3f | EX_ErrorSummary | FPU_BUSY);
230 }
231 else
232 {
233
234 status_word |= (n | EX_ErrorSummary | FPU_BUSY);
235 if (n == EX_StackUnder)
236
237 status_word &= ~SW_C1;
238 }
239
240 RE_ENTRANT_CHECK_OFF
241 if ( (~control_word & n & CW_EXM) || (n == EX_INTERNAL) )
242 {
243 #ifdef PRINT_MESSAGES
244
245 printk(FPU_VERSION" "__DATE__" (C) W. Metzenthen.\r\n");
246 #endif PRINT_MESSAGES
247
248
249 for (i=0; exception_names[i].type; i++)
250 if (exception_names[i].type == n)
251 break;
252
253 if (exception_names[i].type)
254 {
255 #ifdef PRINT_MESSAGES
256 printk("FP Exception: %s!\n", exception_names[i].name);
257 #endif PRINT_MESSAGES
258 }
259 else
260 printk("FP emulator: Unknown Exception: 0x%04x!\n", n);
261
262 if ( n == EX_INTERNAL )
263 {
264 printk("FP emulator: Internal error type 0x%04x\n", int_type);
265 emu_printall();
266 }
267 #ifdef PRINT_MESSAGES
268 else
269 emu_printall();
270 #endif PRINT_MESSAGES
271
272 send_sig(SIGFPE, current, 1);
273 }
274 RE_ENTRANT_CHECK_ON
275
276 #ifdef __DEBUG__
277 math_abort(FPU_info,SIGFPE);
278 #endif __DEBUG__
279
280
281 FPU_lookahead = 0;
282 }
283
284
285
286 void real_2op_NaN(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
287 {
288 FPU_REG *x;
289
290 x = a;
291 if (a->tag == TW_NaN)
292 {
293 if (b->tag == TW_NaN)
294 {
295
296 if ( *(long long *)&(a->sigl) < *(long long *)&(b->sigl) )
297 x = b;
298 }
299
300 }
301 else if (b->tag == TW_NaN)
302 {
303 x = b;
304 }
305 #ifdef PARANOID
306 else
307 {
308 EXCEPTION(EX_INTERNAL|0x113);
309 x = &CONST_QNaN;
310 }
311 #endif PARANOID
312
313 if ( control_word & EX_Invalid )
314 {
315
316 reg_move(x, dest);
317
318 dest->sigh |= 0x40000000;
319 }
320
321 EXCEPTION(EX_Invalid);
322
323 return;
324 }
325
326
327 void arith_invalid(FPU_REG *dest)
328 {
329
330 if ( control_word & EX_Invalid )
331 {
332
333 reg_move(&CONST_QNaN, dest);
334 }
335
336 EXCEPTION(EX_Invalid);
337
338 return;
339
340 }
341
342
343
344 void divide_by_zero(int sign, FPU_REG *dest)
345 {
346
347 if ( control_word & EX_ZeroDiv )
348 {
349
350 reg_move(&CONST_INF, dest);
351 dest->sign = (unsigned char)sign;
352 }
353
354 EXCEPTION(EX_ZeroDiv);
355
356 return;
357
358 }
359
360
361 void arith_overflow(FPU_REG *dest)
362 {
363
364 if ( control_word & EX_Overflow )
365 {
366 char sign;
367
368 sign = dest->sign;
369 reg_move(&CONST_INF, dest);
370 dest->sign = sign;
371 }
372 else
373 {
374
375 dest->exp -= (3 * (1 << 13));
376 }
377
378 EXCEPTION(EX_Overflow);
379
380 return;
381
382 }
383
384
385 void arith_underflow(FPU_REG *dest)
386 {
387
388 if ( control_word & EX_Underflow )
389 {
390
391 if ( dest->exp <= EXP_UNDER - 63 )
392 reg_move(&CONST_Z, dest);
393 }
394 else
395 {
396
397 dest->exp += (3 * (1 << 13));
398 }
399
400 EXCEPTION(EX_Underflow);
401
402 return;
403 }
404
405
406 void stack_overflow(void)
407 {
408
409 if ( control_word & EX_Invalid )
410 {
411
412 top--;
413 reg_move(&CONST_QNaN, FPU_st0_ptr = &st(0));
414 }
415
416 EXCEPTION(EX_StackOver);
417
418 return;
419
420 }
421
422
423 void stack_underflow(void)
424 {
425
426 if ( control_word & EX_Invalid )
427 {
428
429 reg_move(&CONST_QNaN, FPU_st0_ptr);
430 }
431
432 EXCEPTION(EX_StackUnder);
433
434 return;
435
436 }
437