Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / x86 / math-emu / errors.c
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   billm@jacobi.maths.monash.edu.au                |
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
42         RE_ENTRANT_CHECK_OFF;
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
65         RE_ENTRANT_CHECK_ON;
66
67         EXCEPTION(EX_Invalid);
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 {
78         math_abort(FPU_info, SIGILL);
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
90         RE_ENTRANT_CHECK_OFF;
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
121         partial_status = status_word();
122
123 #ifdef DEBUGGING
124         if (partial_status & SW_Backward)
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");
134         if (partial_status & SW_Summary)
135                 printk("SW: exception summary\n");
136         if (partial_status & SW_Stack_Fault)
137                 printk("SW: stack fault\n");
138         if (partial_status & SW_Precision)
139                 printk("SW: loss of precision\n");
140         if (partial_status & SW_Underflow)
141                 printk("SW: underflow\n");
142         if (partial_status & SW_Overflow)
143                 printk("SW: overflow\n");
144         if (partial_status & SW_Zero_Div)
145                 printk("SW: divide by zero\n");
146         if (partial_status & SW_Denorm_Op)
147                 printk("SW: denormalized operand\n");
148         if (partial_status & SW_Invalid)
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
205         RE_ENTRANT_CHECK_ON;
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
305 asmlinkage __visible void FPU_exception(int n)
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! */
314                 partial_status |= (SW_Exc_Mask | SW_Summary | SW_Backward);
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 */
321                 if (partial_status & ~control_word & CW_Exceptions)
322                         partial_status |= (SW_Summary | SW_Backward);
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
331         RE_ENTRANT_CHECK_OFF;
332         if ((~control_word & n & CW_Exceptions) || (n == EX_INTERNAL)) {
333                 /* Get a name string for error reporting */
334                 for (i = 0; exception_names[i].type; i++)
335                         if ((exception_names[i].type & n) ==
336                             exception_names[i].type)
337                                 break;
338
339                 if (exception_names[i].type) {
340 #ifdef PRINT_MESSAGES
341                         printk("FP Exception: %s!\n", exception_names[i].name);
342 #endif /* PRINT_MESSAGES */
343                 } else
344                         printk("FPU emulator: Unknown Exception: 0x%04x!\n", n);
345
346                 if (n == EX_INTERNAL) {
347                         printk("FPU emulator: Internal error type 0x%04x\n",
348                                int_type);
349                         FPU_printall();
350                 }
351 #ifdef PRINT_MESSAGES
352                 else
353                         FPU_printall();
354 #endif /* PRINT_MESSAGES */
355
356                 /*
357                  * The 80486 generates an interrupt on the next non-control FPU
358                  * instruction. So we need some means of flagging it.
359                  * We use the ES (Error Summary) bit for this.
360                  */
361         }
362         RE_ENTRANT_CHECK_ON;
363
364 #ifdef __DEBUG__
365         math_abort(FPU_info, SIGFPE);
366 #endif /* __DEBUG__ */
367
368 }
369
370 /* Real operation attempted on a NaN. */
371 /* Returns < 0 if the exception is unmasked */
372 int real_1op_NaN(FPU_REG *a)
373 {
374         int signalling, isNaN;
375
376         isNaN = (exponent(a) == EXP_OVER) && (a->sigh & 0x80000000);
377
378         /* The default result for the case of two "equal" NaNs (signs may
379            differ) is chosen to reproduce 80486 behaviour */
380         signalling = isNaN && !(a->sigh & 0x40000000);
381
382         if (!signalling) {
383                 if (!isNaN) {   /* pseudo-NaN, or other unsupported? */
384                         if (control_word & CW_Invalid) {
385                                 /* Masked response */
386                                 reg_copy(&CONST_QNaN, a);
387                         }
388                         EXCEPTION(EX_Invalid);
389                         return (!(control_word & CW_Invalid) ? FPU_Exception :
390                                 0) | TAG_Special;
391                 }
392                 return TAG_Special;
393         }
394
395         if (control_word & CW_Invalid) {
396                 /* The masked response */
397                 if (!(a->sigh & 0x80000000)) {  /* pseudo-NaN ? */
398                         reg_copy(&CONST_QNaN, a);
399                 }
400                 /* ensure a Quiet NaN */
401                 a->sigh |= 0x40000000;
402         }
403
404         EXCEPTION(EX_Invalid);
405
406         return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
407 }
408
409 /* Real operation attempted on two operands, one a NaN. */
410 /* Returns < 0 if the exception is unmasked */
411 int real_2op_NaN(FPU_REG const *b, u_char tagb,
412                  int deststnr, FPU_REG const *defaultNaN)
413 {
414         FPU_REG *dest = &st(deststnr);
415         FPU_REG const *a = dest;
416         u_char taga = FPU_gettagi(deststnr);
417         FPU_REG const *x;
418         int signalling, unsupported;
419
420         if (taga == TAG_Special)
421                 taga = FPU_Special(a);
422         if (tagb == TAG_Special)
423                 tagb = FPU_Special(b);
424
425         /* TW_NaN is also used for unsupported data types. */
426         unsupported = ((taga == TW_NaN)
427                        && !((exponent(a) == EXP_OVER)
428                             && (a->sigh & 0x80000000)))
429             || ((tagb == TW_NaN)
430                 && !((exponent(b) == EXP_OVER) && (b->sigh & 0x80000000)));
431         if (unsupported) {
432                 if (control_word & CW_Invalid) {
433                         /* Masked response */
434                         FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr);
435                 }
436                 EXCEPTION(EX_Invalid);
437                 return (!(control_word & CW_Invalid) ? FPU_Exception : 0) |
438                     TAG_Special;
439         }
440
441         if (taga == TW_NaN) {
442                 x = a;
443                 if (tagb == TW_NaN) {
444                         signalling = !(a->sigh & b->sigh & 0x40000000);
445                         if (significand(b) > significand(a))
446                                 x = b;
447                         else if (significand(b) == significand(a)) {
448                                 /* The default result for the case of two "equal" NaNs (signs may
449                                    differ) is chosen to reproduce 80486 behaviour */
450                                 x = defaultNaN;
451                         }
452                 } else {
453                         /* return the quiet version of the NaN in a */
454                         signalling = !(a->sigh & 0x40000000);
455                 }
456         } else
457 #ifdef PARANOID
458         if (tagb == TW_NaN)
459 #endif /* PARANOID */
460         {
461                 signalling = !(b->sigh & 0x40000000);
462                 x = b;
463         }
464 #ifdef PARANOID
465         else {
466                 signalling = 0;
467                 EXCEPTION(EX_INTERNAL | 0x113);
468                 x = &CONST_QNaN;
469         }
470 #endif /* PARANOID */
471
472         if ((!signalling) || (control_word & CW_Invalid)) {
473                 if (!x)
474                         x = b;
475
476                 if (!(x->sigh & 0x80000000))    /* pseudo-NaN ? */
477                         x = &CONST_QNaN;
478
479                 FPU_copy_to_regi(x, TAG_Special, deststnr);
480
481                 if (!signalling)
482                         return TAG_Special;
483
484                 /* ensure a Quiet NaN */
485                 dest->sigh |= 0x40000000;
486         }
487
488         EXCEPTION(EX_Invalid);
489
490         return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
491 }
492
493 /* Invalid arith operation on Valid registers */
494 /* Returns < 0 if the exception is unmasked */
495 asmlinkage __visible int arith_invalid(int deststnr)
496 {
497
498         EXCEPTION(EX_Invalid);
499
500         if (control_word & CW_Invalid) {
501                 /* The masked response */
502                 FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr);
503         }
504
505         return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Valid;
506
507 }
508
509 /* Divide a finite number by zero */
510 asmlinkage __visible int FPU_divide_by_zero(int deststnr, u_char sign)
511 {
512         FPU_REG *dest = &st(deststnr);
513         int tag = TAG_Valid;
514
515         if (control_word & CW_ZeroDiv) {
516                 /* The masked response */
517                 FPU_copy_to_regi(&CONST_INF, TAG_Special, deststnr);
518                 setsign(dest, sign);
519                 tag = TAG_Special;
520         }
521
522         EXCEPTION(EX_ZeroDiv);
523
524         return (!(control_word & CW_ZeroDiv) ? FPU_Exception : 0) | tag;
525
526 }
527
528 /* This may be called often, so keep it lean */
529 int set_precision_flag(int flags)
530 {
531         if (control_word & CW_Precision) {
532                 partial_status &= ~(SW_C1 & flags);
533                 partial_status |= flags;        /* The masked response */
534                 return 0;
535         } else {
536                 EXCEPTION(flags);
537                 return 1;
538         }
539 }
540
541 /* This may be called often, so keep it lean */
542 asmlinkage __visible void set_precision_flag_up(void)
543 {
544         if (control_word & CW_Precision)
545                 partial_status |= (SW_Precision | SW_C1);       /* The masked response */
546         else
547                 EXCEPTION(EX_Precision | SW_C1);
548 }
549
550 /* This may be called often, so keep it lean */
551 asmlinkage __visible void set_precision_flag_down(void)
552 {
553         if (control_word & CW_Precision) {      /* The masked response */
554                 partial_status &= ~SW_C1;
555                 partial_status |= SW_Precision;
556         } else
557                 EXCEPTION(EX_Precision);
558 }
559
560 asmlinkage __visible int denormal_operand(void)
561 {
562         if (control_word & CW_Denormal) {       /* The masked response */
563                 partial_status |= SW_Denorm_Op;
564                 return TAG_Special;
565         } else {
566                 EXCEPTION(EX_Denormal);
567                 return TAG_Special | FPU_Exception;
568         }
569 }
570
571 asmlinkage __visible int arith_overflow(FPU_REG *dest)
572 {
573         int tag = TAG_Valid;
574
575         if (control_word & CW_Overflow) {
576                 /* The masked response */
577 /* ###### The response here depends upon the rounding mode */
578                 reg_copy(&CONST_INF, dest);
579                 tag = TAG_Special;
580         } else {
581                 /* Subtract the magic number from the exponent */
582                 addexponent(dest, (-3 * (1 << 13)));
583         }
584
585         EXCEPTION(EX_Overflow);
586         if (control_word & CW_Overflow) {
587                 /* The overflow exception is masked. */
588                 /* By definition, precision is lost.
589                    The roundup bit (C1) is also set because we have
590                    "rounded" upwards to Infinity. */
591                 EXCEPTION(EX_Precision | SW_C1);
592                 return tag;
593         }
594
595         return tag;
596
597 }
598
599 asmlinkage __visible int arith_underflow(FPU_REG *dest)
600 {
601         int tag = TAG_Valid;
602
603         if (control_word & CW_Underflow) {
604                 /* The masked response */
605                 if (exponent16(dest) <= EXP_UNDER - 63) {
606                         reg_copy(&CONST_Z, dest);
607                         partial_status &= ~SW_C1;       /* Round down. */
608                         tag = TAG_Zero;
609                 } else {
610                         stdexp(dest);
611                 }
612         } else {
613                 /* Add the magic number to the exponent. */
614                 addexponent(dest, (3 * (1 << 13)) + EXTENDED_Ebias);
615         }
616
617         EXCEPTION(EX_Underflow);
618         if (control_word & CW_Underflow) {
619                 /* The underflow exception is masked. */
620                 EXCEPTION(EX_Precision);
621                 return tag;
622         }
623
624         return tag;
625
626 }
627
628 void FPU_stack_overflow(void)
629 {
630
631         if (control_word & CW_Invalid) {
632                 /* The masked response */
633                 top--;
634                 FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
635         }
636
637         EXCEPTION(EX_StackOver);
638
639         return;
640
641 }
642
643 void FPU_stack_underflow(void)
644 {
645
646         if (control_word & CW_Invalid) {
647                 /* The masked response */
648                 FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
649         }
650
651         EXCEPTION(EX_StackUnder);
652
653         return;
654
655 }
656
657 void FPU_stack_underflow_i(int i)
658 {
659
660         if (control_word & CW_Invalid) {
661                 /* The masked response */
662                 FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i);
663         }
664
665         EXCEPTION(EX_StackUnder);
666
667         return;
668
669 }
670
671 void FPU_stack_underflow_pop(int i)
672 {
673
674         if (control_word & CW_Invalid) {
675                 /* The masked response */
676                 FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i);
677                 FPU_pop();
678         }
679
680         EXCEPTION(EX_StackUnder);
681
682         return;
683
684 }