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