Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
errors.c
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------+
2  | errors.c |
3  | |
4  | The error handling functions for wm-FPU-emu |
5  | |
6  | Copyright (C) 1992,1993,1994,1996 |
7  | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
8  | E-mail [email protected] |
9  | |
10  | |
11  +---------------------------------------------------------------------------*/
12 
13 /*---------------------------------------------------------------------------+
14  | Note: |
15  | The file contains code which accesses user memory. |
16  | Emulator static data may change when user memory is accessed, due to |
17  | other processes using the emulator while swapping is in progress. |
18  +---------------------------------------------------------------------------*/
19 
20 #include <linux/signal.h>
21 
22 #include <asm/uaccess.h>
23 
24 #include "fpu_emu.h"
25 #include "fpu_system.h"
26 #include "exception.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 #if 0
37 void Un_impl(void)
38 {
39  u_char byte1, FPU_modrm;
40  unsigned long address = FPU_ORIG_EIP;
41 
43  /* No need to check access_ok(), we have previously fetched these bytes. */
44  printk("Unimplemented FPU Opcode at eip=%p : ", (void __user *)address);
45  if (FPU_CS == __USER_CS) {
46  while (1) {
47  FPU_get_user(byte1, (u_char __user *) address);
48  if ((byte1 & 0xf8) == 0xd8)
49  break;
50  printk("[%02x]", byte1);
51  address++;
52  }
53  printk("%02x ", byte1);
54  FPU_get_user(FPU_modrm, 1 + (u_char __user *) address);
55 
56  if (FPU_modrm >= 0300)
57  printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8,
58  FPU_modrm & 7);
59  else
60  printk("/%d\n", (FPU_modrm >> 3) & 7);
61  } else {
62  printk("cs selector = %04x\n", FPU_CS);
63  }
64 
66 
68 
69 }
70 #endif /* 0 */
71 
72 /*
73  Called for opcodes which are illegal and which are known to result in a
74  SIGILL with a real 80486.
75  */
76 void FPU_illegal(void)
77 {
79 }
80 
81 void FPU_printall(void)
82 {
83  int i;
84  static const char *tag_desc[] = { "Valid", "Zero", "ERROR", "Empty",
85  "DeNorm", "Inf", "NaN"
86  };
87  u_char byte1, FPU_modrm;
88  unsigned long address = FPU_ORIG_EIP;
89 
91  /* No need to check access_ok(), we have previously fetched these bytes. */
92  printk("At %p:", (void *)address);
93  if (FPU_CS == __USER_CS) {
94 #define MAX_PRINTED_BYTES 20
95  for (i = 0; i < MAX_PRINTED_BYTES; i++) {
96  FPU_get_user(byte1, (u_char __user *) address);
97  if ((byte1 & 0xf8) == 0xd8) {
98  printk(" %02x", byte1);
99  break;
100  }
101  printk(" [%02x]", byte1);
102  address++;
103  }
104  if (i == MAX_PRINTED_BYTES)
105  printk(" [more..]\n");
106  else {
107  FPU_get_user(FPU_modrm, 1 + (u_char __user *) address);
108 
109  if (FPU_modrm >= 0300)
110  printk(" %02x (%02x+%d)\n", FPU_modrm,
111  FPU_modrm & 0xf8, FPU_modrm & 7);
112  else
113  printk(" /%d, mod=%d rm=%d\n",
114  (FPU_modrm >> 3) & 7,
115  (FPU_modrm >> 6) & 3, FPU_modrm & 7);
116  }
117  } else {
118  printk("%04x\n", FPU_CS);
119  }
120 
122 
123 #ifdef DEBUGGING
125  printk("SW: backward compatibility\n");
126  if (partial_status & SW_C3)
127  printk("SW: condition bit 3\n");
128  if (partial_status & SW_C2)
129  printk("SW: condition bit 2\n");
130  if (partial_status & SW_C1)
131  printk("SW: condition bit 1\n");
132  if (partial_status & SW_C0)
133  printk("SW: condition bit 0\n");
135  printk("SW: exception summary\n");
137  printk("SW: stack fault\n");
139  printk("SW: loss of precision\n");
141  printk("SW: underflow\n");
143  printk("SW: overflow\n");
145  printk("SW: divide by zero\n");
147  printk("SW: denormalized operand\n");
149  printk("SW: invalid operation\n");
150 #endif /* DEBUGGING */
151 
152  printk(" SW: b=%d st=%d es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n", partial_status & 0x8000 ? 1 : 0, /* busy */
153  (partial_status & 0x3800) >> 11, /* stack top pointer */
154  partial_status & 0x80 ? 1 : 0, /* Error summary status */
155  partial_status & 0x40 ? 1 : 0, /* Stack flag */
156  partial_status & SW_C3 ? 1 : 0, partial_status & SW_C2 ? 1 : 0, /* cc */
157  partial_status & SW_C1 ? 1 : 0, partial_status & SW_C0 ? 1 : 0, /* cc */
158  partial_status & SW_Precision ? 1 : 0,
159  partial_status & SW_Underflow ? 1 : 0,
160  partial_status & SW_Overflow ? 1 : 0,
161  partial_status & SW_Zero_Div ? 1 : 0,
162  partial_status & SW_Denorm_Op ? 1 : 0,
163  partial_status & SW_Invalid ? 1 : 0);
164 
165  printk(" CW: ic=%d rc=%d%d pc=%d%d iem=%d ef=%d%d%d%d%d%d\n",
166  control_word & 0x1000 ? 1 : 0,
167  (control_word & 0x800) >> 11, (control_word & 0x400) >> 10,
168  (control_word & 0x200) >> 9, (control_word & 0x100) >> 8,
169  control_word & 0x80 ? 1 : 0,
170  control_word & SW_Precision ? 1 : 0,
171  control_word & SW_Underflow ? 1 : 0,
172  control_word & SW_Overflow ? 1 : 0,
173  control_word & SW_Zero_Div ? 1 : 0,
174  control_word & SW_Denorm_Op ? 1 : 0,
175  control_word & SW_Invalid ? 1 : 0);
176 
177  for (i = 0; i < 8; i++) {
178  FPU_REG *r = &st(i);
179  u_char tagi = FPU_gettagi(i);
180  switch (tagi) {
181  case TAG_Empty:
182  continue;
183  break;
184  case TAG_Zero:
185  case TAG_Special:
186  tagi = FPU_Special(r);
187  case TAG_Valid:
188  printk("st(%d) %c .%04lx %04lx %04lx %04lx e%+-6d ", i,
189  getsign(r) ? '-' : '+',
190  (long)(r->sigh >> 16),
191  (long)(r->sigh & 0xFFFF),
192  (long)(r->sigl >> 16),
193  (long)(r->sigl & 0xFFFF),
194  exponent(r) - EXP_BIAS + 1);
195  break;
196  default:
197  printk("Whoops! Error in errors.c: tag%d is %d ", i,
198  tagi);
199  continue;
200  break;
201  }
202  printk("%s\n", tag_desc[(int)(unsigned)tagi]);
203  }
204 
206 
207 }
208 
209 static struct {
210  int type;
211  const char *name;
212 } exception_names[] = {
213  {
214  EX_StackOver, "stack overflow"}, {
215  EX_StackUnder, "stack underflow"}, {
216  EX_Precision, "loss of precision"}, {
217  EX_Underflow, "underflow"}, {
218  EX_Overflow, "overflow"}, {
219  EX_ZeroDiv, "divide by zero"}, {
220  EX_Denormal, "denormalized operand"}, {
221  EX_Invalid, "invalid operation"}, {
222  EX_INTERNAL, "INTERNAL BUG in " FPU_VERSION}, {
223  0, NULL}
224 };
225 
226 /*
227  EX_INTERNAL is always given with a code which indicates where the
228  error was detected.
229 
230  Internal error types:
231  0x14 in fpu_etc.c
232  0x1nn in a *.c file:
233  0x101 in reg_add_sub.c
234  0x102 in reg_mul.c
235  0x104 in poly_atan.c
236  0x105 in reg_mul.c
237  0x107 in fpu_trig.c
238  0x108 in reg_compare.c
239  0x109 in reg_compare.c
240  0x110 in reg_add_sub.c
241  0x111 in fpe_entry.c
242  0x112 in fpu_trig.c
243  0x113 in errors.c
244  0x115 in fpu_trig.c
245  0x116 in fpu_trig.c
246  0x117 in fpu_trig.c
247  0x118 in fpu_trig.c
248  0x119 in fpu_trig.c
249  0x120 in poly_atan.c
250  0x121 in reg_compare.c
251  0x122 in reg_compare.c
252  0x123 in reg_compare.c
253  0x125 in fpu_trig.c
254  0x126 in fpu_entry.c
255  0x127 in poly_2xm1.c
256  0x128 in fpu_entry.c
257  0x129 in fpu_entry.c
258  0x130 in get_address.c
259  0x131 in get_address.c
260  0x132 in get_address.c
261  0x133 in get_address.c
262  0x140 in load_store.c
263  0x141 in load_store.c
264  0x150 in poly_sin.c
265  0x151 in poly_sin.c
266  0x160 in reg_ld_str.c
267  0x161 in reg_ld_str.c
268  0x162 in reg_ld_str.c
269  0x163 in reg_ld_str.c
270  0x164 in reg_ld_str.c
271  0x170 in fpu_tags.c
272  0x171 in fpu_tags.c
273  0x172 in fpu_tags.c
274  0x180 in reg_convert.c
275  0x2nn in an *.S file:
276  0x201 in reg_u_add.S
277  0x202 in reg_u_div.S
278  0x203 in reg_u_div.S
279  0x204 in reg_u_div.S
280  0x205 in reg_u_mul.S
281  0x206 in reg_u_sub.S
282  0x207 in wm_sqrt.S
283  0x208 in reg_div.S
284  0x209 in reg_u_sub.S
285  0x210 in reg_u_sub.S
286  0x211 in reg_u_sub.S
287  0x212 in reg_u_sub.S
288  0x213 in wm_sqrt.S
289  0x214 in wm_sqrt.S
290  0x215 in wm_sqrt.S
291  0x220 in reg_norm.S
292  0x221 in reg_norm.S
293  0x230 in reg_round.S
294  0x231 in reg_round.S
295  0x232 in reg_round.S
296  0x233 in reg_round.S
297  0x234 in reg_round.S
298  0x235 in reg_round.S
299  0x236 in reg_round.S
300  0x240 in div_Xsig.S
301  0x241 in div_Xsig.S
302  0x242 in div_Xsig.S
303  */
304 
306 {
307  int i, int_type;
308 
309  int_type = 0; /* Needed only to stop compiler warnings */
310  if (n & EX_INTERNAL) {
311  int_type = n - EX_INTERNAL;
312  n = EX_INTERNAL;
313  /* Set lots of exception bits! */
315  } else {
316  /* Extract only the bits which we use to set the status word */
317  n &= (SW_Exc_Mask);
318  /* Set the corresponding exception bit */
319  partial_status |= n;
320  /* Set summary bits iff exception isn't masked */
323  if (n & (SW_Stack_Fault | EX_Precision)) {
324  if (!(n & SW_C1))
325  /* This bit distinguishes over- from underflow for a stack fault,
326  and roundup from round-down for precision loss. */
327  partial_status &= ~SW_C1;
328  }
329  }
330 
332  if ((~control_word & n & CW_Exceptions) || (n == EX_INTERNAL)) {
333 #ifdef PRINT_MESSAGES
334  /* My message from the sponsor */
335  printk(FPU_VERSION " " __DATE__ " (C) W. Metzenthen.\n");
336 #endif /* PRINT_MESSAGES */
337 
338  /* Get a name string for error reporting */
339  for (i = 0; exception_names[i].type; i++)
340  if ((exception_names[i].type & n) ==
341  exception_names[i].type)
342  break;
343 
344  if (exception_names[i].type) {
345 #ifdef PRINT_MESSAGES
346  printk("FP Exception: %s!\n", exception_names[i].name);
347 #endif /* PRINT_MESSAGES */
348  } else
349  printk("FPU emulator: Unknown Exception: 0x%04x!\n", n);
350 
351  if (n == EX_INTERNAL) {
352  printk("FPU emulator: Internal error type 0x%04x\n",
353  int_type);
354  FPU_printall();
355  }
356 #ifdef PRINT_MESSAGES
357  else
358  FPU_printall();
359 #endif /* PRINT_MESSAGES */
360 
361  /*
362  * The 80486 generates an interrupt on the next non-control FPU
363  * instruction. So we need some means of flagging it.
364  * We use the ES (Error Summary) bit for this.
365  */
366  }
368 
369 #ifdef __DEBUG__
371 #endif /* __DEBUG__ */
372 
373 }
374 
375 /* Real operation attempted on a NaN. */
376 /* Returns < 0 if the exception is unmasked */
378 {
379  int signalling, isNaN;
380 
381  isNaN = (exponent(a) == EXP_OVER) && (a->sigh & 0x80000000);
382 
383  /* The default result for the case of two "equal" NaNs (signs may
384  differ) is chosen to reproduce 80486 behaviour */
385  signalling = isNaN && !(a->sigh & 0x40000000);
386 
387  if (!signalling) {
388  if (!isNaN) { /* pseudo-NaN, or other unsupported? */
389  if (control_word & CW_Invalid) {
390  /* Masked response */
391  reg_copy(&CONST_QNaN, a);
392  }
394  return (!(control_word & CW_Invalid) ? FPU_Exception :
395  0) | TAG_Special;
396  }
397  return TAG_Special;
398  }
399 
400  if (control_word & CW_Invalid) {
401  /* The masked response */
402  if (!(a->sigh & 0x80000000)) { /* pseudo-NaN ? */
403  reg_copy(&CONST_QNaN, a);
404  }
405  /* ensure a Quiet NaN */
406  a->sigh |= 0x40000000;
407  }
408 
410 
411  return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
412 }
413 
414 /* Real operation attempted on two operands, one a NaN. */
415 /* Returns < 0 if the exception is unmasked */
416 int real_2op_NaN(FPU_REG const *b, u_char tagb,
417  int deststnr, FPU_REG const *defaultNaN)
418 {
419  FPU_REG *dest = &st(deststnr);
420  FPU_REG const *a = dest;
421  u_char taga = FPU_gettagi(deststnr);
422  FPU_REG const *x;
423  int signalling, unsupported;
424 
425  if (taga == TAG_Special)
426  taga = FPU_Special(a);
427  if (tagb == TAG_Special)
428  tagb = FPU_Special(b);
429 
430  /* TW_NaN is also used for unsupported data types. */
431  unsupported = ((taga == TW_NaN)
432  && !((exponent(a) == EXP_OVER)
433  && (a->sigh & 0x80000000)))
434  || ((tagb == TW_NaN)
435  && !((exponent(b) == EXP_OVER) && (b->sigh & 0x80000000)));
436  if (unsupported) {
437  if (control_word & CW_Invalid) {
438  /* Masked response */
440  }
442  return (!(control_word & CW_Invalid) ? FPU_Exception : 0) |
443  TAG_Special;
444  }
445 
446  if (taga == TW_NaN) {
447  x = a;
448  if (tagb == TW_NaN) {
449  signalling = !(a->sigh & b->sigh & 0x40000000);
450  if (significand(b) > significand(a))
451  x = b;
452  else if (significand(b) == significand(a)) {
453  /* The default result for the case of two "equal" NaNs (signs may
454  differ) is chosen to reproduce 80486 behaviour */
455  x = defaultNaN;
456  }
457  } else {
458  /* return the quiet version of the NaN in a */
459  signalling = !(a->sigh & 0x40000000);
460  }
461  } else
462 #ifdef PARANOID
463  if (tagb == TW_NaN)
464 #endif /* PARANOID */
465  {
466  signalling = !(b->sigh & 0x40000000);
467  x = b;
468  }
469 #ifdef PARANOID
470  else {
471  signalling = 0;
472  EXCEPTION(EX_INTERNAL | 0x113);
473  x = &CONST_QNaN;
474  }
475 #endif /* PARANOID */
476 
477  if ((!signalling) || (control_word & CW_Invalid)) {
478  if (!x)
479  x = b;
480 
481  if (!(x->sigh & 0x80000000)) /* pseudo-NaN ? */
482  x = &CONST_QNaN;
483 
484  FPU_copy_to_regi(x, TAG_Special, deststnr);
485 
486  if (!signalling)
487  return TAG_Special;
488 
489  /* ensure a Quiet NaN */
490  dest->sigh |= 0x40000000;
491  }
492 
494 
495  return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
496 }
497 
498 /* Invalid arith operation on Valid registers */
499 /* Returns < 0 if the exception is unmasked */
500 asmlinkage int arith_invalid(int deststnr)
501 {
502 
504 
505  if (control_word & CW_Invalid) {
506  /* The masked response */
508  }
509 
510  return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Valid;
511 
512 }
513 
514 /* Divide a finite number by zero */
516 {
517  FPU_REG *dest = &st(deststnr);
518  int tag = TAG_Valid;
519 
520  if (control_word & CW_ZeroDiv) {
521  /* The masked response */
523  setsign(dest, sign);
524  tag = TAG_Special;
525  }
526 
528 
529  return (!(control_word & CW_ZeroDiv) ? FPU_Exception : 0) | tag;
530 
531 }
532 
533 /* This may be called often, so keep it lean */
535 {
536  if (control_word & CW_Precision) {
537  partial_status &= ~(SW_C1 & flags);
538  partial_status |= flags; /* The masked response */
539  return 0;
540  } else {
541  EXCEPTION(flags);
542  return 1;
543  }
544 }
545 
546 /* This may be called often, so keep it lean */
548 {
550  partial_status |= (SW_Precision | SW_C1); /* The masked response */
551  else
553 }
554 
555 /* This may be called often, so keep it lean */
557 {
558  if (control_word & CW_Precision) { /* The masked response */
559  partial_status &= ~SW_C1;
561  } else
563 }
564 
566 {
567  if (control_word & CW_Denormal) { /* The masked response */
569  return TAG_Special;
570  } else {
572  return TAG_Special | FPU_Exception;
573  }
574 }
575 
577 {
578  int tag = TAG_Valid;
579 
580  if (control_word & CW_Overflow) {
581  /* The masked response */
582 /* ###### The response here depends upon the rounding mode */
583  reg_copy(&CONST_INF, dest);
584  tag = TAG_Special;
585  } else {
586  /* Subtract the magic number from the exponent */
587  addexponent(dest, (-3 * (1 << 13)));
588  }
589 
591  if (control_word & CW_Overflow) {
592  /* The overflow exception is masked. */
593  /* By definition, precision is lost.
594  The roundup bit (C1) is also set because we have
595  "rounded" upwards to Infinity. */
597  return tag;
598  }
599 
600  return tag;
601 
602 }
603 
605 {
606  int tag = TAG_Valid;
607 
608  if (control_word & CW_Underflow) {
609  /* The masked response */
610  if (exponent16(dest) <= EXP_UNDER - 63) {
611  reg_copy(&CONST_Z, dest);
612  partial_status &= ~SW_C1; /* Round down. */
613  tag = TAG_Zero;
614  } else {
615  stdexp(dest);
616  }
617  } else {
618  /* Add the magic number to the exponent. */
619  addexponent(dest, (3 * (1 << 13)) + EXTENDED_Ebias);
620  }
621 
623  if (control_word & CW_Underflow) {
624  /* The underflow exception is masked. */
626  return tag;
627  }
628 
629  return tag;
630 
631 }
632 
634 {
635 
636  if (control_word & CW_Invalid) {
637  /* The masked response */
638  top--;
640  }
641 
643 
644  return;
645 
646 }
647 
649 {
650 
651  if (control_word & CW_Invalid) {
652  /* The masked response */
654  }
655 
657 
658  return;
659 
660 }
661 
663 {
664 
665  if (control_word & CW_Invalid) {
666  /* The masked response */
668  }
669 
671 
672  return;
673 
674 }
675 
677 {
678 
679  if (control_word & CW_Invalid) {
680  /* The masked response */
682  FPU_pop();
683  }
684 
686 
687  return;
688 
689 }