1 /*---------------------------------------------------------------------------+
4 | All of the functions which transfer data between user memory and FPU_REGs.|
6 | Copyright (C) 1992,1993,1994,1996,1997 |
7 | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
8 | E-mail billm@suburbia.net |
11 +---------------------------------------------------------------------------*/
13 /*---------------------------------------------------------------------------+
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 +---------------------------------------------------------------------------*/
22 #include <asm/uaccess.h>
24 #include "fpu_system.h"
25 #include "exception.h"
26 #include "reg_constant.h"
27 #include "control_w.h"
31 #define DOUBLE_Emax 1023 /* largest valid exponent */
32 #define DOUBLE_Ebias 1023
33 #define DOUBLE_Emin (-1022) /* smallest valid exponent */
35 #define SINGLE_Emax 127 /* largest valid exponent */
36 #define SINGLE_Ebias 127
37 #define SINGLE_Emin (-126) /* smallest valid exponent */
40 static u_char
normalize_no_excep(FPU_REG
*r
, int exp
, int sign
)
44 setexponent16(r
, exp
);
46 tag
= FPU_normalize_nuo(r
);
55 int FPU_tagof(FPU_REG
*ptr
)
59 exp
= exponent16(ptr
) & 0x7fff;
62 if ( !(ptr
->sigh
| ptr
->sigl
) )
66 /* The number is a de-normal or pseudodenormal. */
72 /* Is an Infinity, a NaN, or an unsupported data type. */
76 if ( !(ptr
->sigh
& 0x80000000) )
78 /* Unsupported data type. */
79 /* Valid numbers have the ms bit set to 1. */
88 /* Get a long double from user memory */
89 int FPU_load_extended(long double __user
*s
, int stnr
)
91 FPU_REG
*sti_ptr
= &st(stnr
);
94 FPU_access_ok(VERIFY_READ
, s
, 10);
95 __copy_from_user(sti_ptr
, s
, 10);
98 return FPU_tagof(sti_ptr
);
102 /* Get a double from user memory */
103 int FPU_load_double(double __user
*dfloat
, FPU_REG
*loaded_data
)
105 int exp
, tag
, negative
;
108 RE_ENTRANT_CHECK_OFF
;
109 FPU_access_ok(VERIFY_READ
, dfloat
, 8);
110 FPU_get_user(m64
, 1 + (unsigned long __user
*) dfloat
);
111 FPU_get_user(l64
, (unsigned long __user
*) dfloat
);
114 negative
= (m64
& 0x80000000) ? SIGN_Negative
: SIGN_Positive
;
115 exp
= ((m64
& 0x7ff00000) >> 20) - DOUBLE_Ebias
+ EXTENDED_Ebias
;
117 if ( exp
> DOUBLE_Emax
+ EXTENDED_Ebias
)
119 /* Infinity or NaN */
120 if ((m64
== 0) && (l64
== 0))
123 loaded_data
->sigh
= 0x80000000;
124 loaded_data
->sigl
= 0x00000000;
125 exp
= EXP_Infinity
+ EXTENDED_Ebias
;
130 /* Must be a signaling or quiet NaN */
131 exp
= EXP_NaN
+ EXTENDED_Ebias
;
132 loaded_data
->sigh
= (m64
<< 11) | 0x80000000;
133 loaded_data
->sigh
|= l64
>> 21;
134 loaded_data
->sigl
= l64
<< 11;
135 tag
= TAG_Special
; /* The calling function must look for NaNs */
138 else if ( exp
< DOUBLE_Emin
+ EXTENDED_Ebias
)
140 /* Zero or de-normal */
141 if ((m64
== 0) && (l64
== 0))
144 reg_copy(&CONST_Z
, loaded_data
);
151 loaded_data
->sigh
= m64
<< 11;
152 loaded_data
->sigh
|= l64
>> 21;
153 loaded_data
->sigl
= l64
<< 11;
155 return normalize_no_excep(loaded_data
, DOUBLE_Emin
, negative
)
156 | (denormal_operand() < 0 ? FPU_Exception
: 0);
161 loaded_data
->sigh
= (m64
<< 11) | 0x80000000;
162 loaded_data
->sigh
|= l64
>> 21;
163 loaded_data
->sigl
= l64
<< 11;
168 setexponent16(loaded_data
, exp
| negative
);
174 /* Get a float from user memory */
175 int FPU_load_single(float __user
*single
, FPU_REG
*loaded_data
)
178 int exp
, tag
, negative
;
180 RE_ENTRANT_CHECK_OFF
;
181 FPU_access_ok(VERIFY_READ
, single
, 4);
182 FPU_get_user(m32
, (unsigned long __user
*) single
);
185 negative
= (m32
& 0x80000000) ? SIGN_Negative
: SIGN_Positive
;
187 if (!(m32
& 0x7fffffff))
190 reg_copy(&CONST_Z
, loaded_data
);
191 addexponent(loaded_data
, negative
);
194 exp
= ((m32
& 0x7f800000) >> 23) - SINGLE_Ebias
+ EXTENDED_Ebias
;
195 m32
= (m32
& 0x7fffff) << 8;
196 if ( exp
< SINGLE_Emin
+ EXTENDED_Ebias
)
199 loaded_data
->sigh
= m32
;
200 loaded_data
->sigl
= 0;
202 return normalize_no_excep(loaded_data
, SINGLE_Emin
, negative
)
203 | (denormal_operand() < 0 ? FPU_Exception
: 0);
205 else if ( exp
> SINGLE_Emax
+ EXTENDED_Ebias
)
207 /* Infinity or NaN */
211 loaded_data
->sigh
= 0x80000000;
212 loaded_data
->sigl
= 0x00000000;
213 exp
= EXP_Infinity
+ EXTENDED_Ebias
;
218 /* Must be a signaling or quiet NaN */
219 exp
= EXP_NaN
+ EXTENDED_Ebias
;
220 loaded_data
->sigh
= m32
| 0x80000000;
221 loaded_data
->sigl
= 0;
222 tag
= TAG_Special
; /* The calling function must look for NaNs */
227 loaded_data
->sigh
= m32
| 0x80000000;
228 loaded_data
->sigl
= 0;
232 setexponent16(loaded_data
, exp
| negative
); /* Set the sign. */
238 /* Get a long long from user memory */
239 int FPU_load_int64(long long __user
*_s
)
243 FPU_REG
*st0_ptr
= &st(0);
245 RE_ENTRANT_CHECK_OFF
;
246 FPU_access_ok(VERIFY_READ
, _s
, 8);
247 copy_from_user(&s
,_s
,8);
252 reg_copy(&CONST_Z
, st0_ptr
);
257 sign
= SIGN_Positive
;
261 sign
= SIGN_Negative
;
264 significand(st0_ptr
) = s
;
266 return normalize_no_excep(st0_ptr
, 63, sign
);
270 /* Get a long from user memory */
271 int FPU_load_int32(long __user
*_s
, FPU_REG
*loaded_data
)
276 RE_ENTRANT_CHECK_OFF
;
277 FPU_access_ok(VERIFY_READ
, _s
, 4);
282 { reg_copy(&CONST_Z
, loaded_data
); return TAG_Zero
; }
285 negative
= SIGN_Positive
;
289 negative
= SIGN_Negative
;
292 loaded_data
->sigh
= s
;
293 loaded_data
->sigl
= 0;
295 return normalize_no_excep(loaded_data
, 31, negative
);
299 /* Get a short from user memory */
300 int FPU_load_int16(short __user
*_s
, FPU_REG
*loaded_data
)
304 RE_ENTRANT_CHECK_OFF
;
305 FPU_access_ok(VERIFY_READ
, _s
, 2);
306 /* Cast as short to get the sign extended. */
311 { reg_copy(&CONST_Z
, loaded_data
); return TAG_Zero
; }
314 negative
= SIGN_Positive
;
318 negative
= SIGN_Negative
;
321 loaded_data
->sigh
= s
<< 16;
322 loaded_data
->sigl
= 0;
324 return normalize_no_excep(loaded_data
, 15, negative
);
328 /* Get a packed bcd array from user memory */
329 int FPU_load_bcd(u_char __user
*s
)
331 FPU_REG
*st0_ptr
= &st(0);
337 RE_ENTRANT_CHECK_OFF
;
338 FPU_access_ok(VERIFY_READ
, s
, 10);
340 for ( pos
= 8; pos
>= 0; pos
--)
343 RE_ENTRANT_CHECK_OFF
;
344 FPU_get_user(bcd
, s
+pos
);
351 RE_ENTRANT_CHECK_OFF
;
352 FPU_get_user(sign
, s
+9);
353 sign
= sign
& 0x80 ? SIGN_Negative
: SIGN_Positive
;
358 reg_copy(&CONST_Z
, st0_ptr
);
359 addexponent(st0_ptr
, sign
); /* Set the sign. */
364 significand(st0_ptr
) = l
;
365 return normalize_no_excep(st0_ptr
, 63, sign
);
369 /*===========================================================================*/
371 /* Put a long double into user memory */
372 int FPU_store_extended(FPU_REG
*st0_ptr
, u_char st0_tag
, long double __user
*d
)
375 The only exception raised by an attempt to store to an
376 extended format is the Invalid Stack exception, i.e.
377 attempting to store from an empty register.
380 if ( st0_tag
!= TAG_Empty
)
382 RE_ENTRANT_CHECK_OFF
;
383 FPU_access_ok(VERIFY_WRITE
, d
, 10);
385 FPU_put_user(st0_ptr
->sigl
, (unsigned long __user
*) d
);
386 FPU_put_user(st0_ptr
->sigh
, (unsigned long __user
*) ((u_char __user
*)d
+ 4));
387 FPU_put_user(exponent16(st0_ptr
), (unsigned short __user
*) ((u_char __user
*)d
+ 8));
393 /* Empty register (stack underflow) */
394 EXCEPTION(EX_StackUnder
);
395 if ( control_word
& CW_Invalid
)
397 /* The masked response */
398 /* Put out the QNaN indefinite */
399 RE_ENTRANT_CHECK_OFF
;
400 FPU_access_ok(VERIFY_WRITE
,d
,10);
401 FPU_put_user(0, (unsigned long __user
*) d
);
402 FPU_put_user(0xc0000000, 1 + (unsigned long __user
*) d
);
403 FPU_put_user(0xffff, 4 + (short __user
*) d
);
413 /* Put a double into user memory */
414 int FPU_store_double(FPU_REG
*st0_ptr
, u_char st0_tag
, double __user
*dfloat
)
417 unsigned long increment
= 0; /* avoid gcc warnings */
422 if ( st0_tag
== TAG_Valid
)
424 reg_copy(st0_ptr
, &tmp
);
425 exp
= exponent(&tmp
);
427 if ( exp
< DOUBLE_Emin
) /* It may be a denormal */
429 addexponent(&tmp
, -DOUBLE_Emin
+ 52); /* largest exp to be 51 */
433 if ( (precision_loss
= FPU_round_to_int(&tmp
, st0_tag
)) )
436 /* Did it round to a non-denormal ? */
437 /* This behaviour might be regarded as peculiar, it appears
438 that the 80486 rounds to the dest precision, then
439 converts to decide underflow. */
440 if ( !((tmp
.sigh
== 0x00100000) && (tmp
.sigl
== 0) &&
441 (st0_ptr
->sigl
& 0x000007ff)) )
442 #endif /* PECULIAR_486 */
444 EXCEPTION(EX_Underflow
);
445 /* This is a special case: see sec 16.2.5.1 of
447 if ( !(control_word
& CW_Underflow
) )
450 EXCEPTION(precision_loss
);
451 if ( !(control_word
& CW_Precision
) )
459 if ( tmp
.sigl
& 0x000007ff )
462 switch (control_word
& CW_RC
)
465 /* Rounding can get a little messy.. */
466 increment
= ((tmp
.sigl
& 0x7ff) > 0x400) | /* nearest */
467 ((tmp
.sigl
& 0xc00) == 0xc00); /* odd -> even */
469 case RC_DOWN
: /* towards -infinity */
470 increment
= signpositive(&tmp
) ? 0 : tmp
.sigl
& 0x7ff;
472 case RC_UP
: /* towards +infinity */
473 increment
= signpositive(&tmp
) ? tmp
.sigl
& 0x7ff : 0;
480 /* Truncate the mantissa */
481 tmp
.sigl
&= 0xfffff800;
485 if ( tmp
.sigl
>= 0xfffff800 )
487 /* the sigl part overflows */
488 if ( tmp
.sigh
== 0xffffffff )
490 /* The sigh part overflows */
491 tmp
.sigh
= 0x80000000;
500 tmp
.sigl
= 0x00000000;
504 /* We only need to increment sigl */
505 tmp
.sigl
+= 0x00000800;
512 l
[0] = (tmp
.sigl
>> 11) | (tmp
.sigh
<< 21);
513 l
[1] = ((tmp
.sigh
>> 11) & 0xfffff);
515 if ( exp
> DOUBLE_Emax
)
518 EXCEPTION(EX_Overflow
);
519 if ( !(control_word
& CW_Overflow
) )
521 set_precision_flag_up();
522 if ( !(control_word
& CW_Precision
) )
525 /* This is a special case: see sec 16.2.5.1 of the 80486 book */
526 /* Overflow to infinity */
527 l
[0] = 0x00000000; /* Set to */
528 l
[1] = 0x7ff00000; /* + INF */
532 if ( precision_loss
)
535 set_precision_flag_up();
537 set_precision_flag_down();
539 /* Add the exponent */
540 l
[1] |= (((exp
+DOUBLE_Ebias
) & 0x7ff) << 20);
544 else if (st0_tag
== TAG_Zero
)
550 else if ( st0_tag
== TAG_Special
)
552 st0_tag
= FPU_Special(st0_ptr
);
553 if ( st0_tag
== TW_Denormal
)
555 /* A denormal will always underflow. */
557 /* An 80486 is supposed to be able to generate
558 a denormal exception here, but... */
559 /* Underflow has priority. */
560 if ( control_word
& CW_Underflow
)
562 #endif /* PECULIAR_486 */
563 reg_copy(st0_ptr
, &tmp
);
566 else if (st0_tag
== TW_Infinity
)
571 else if (st0_tag
== TW_NaN
)
573 /* Is it really a NaN ? */
574 if ( (exponent(st0_ptr
) == EXP_OVER
)
575 && (st0_ptr
->sigh
& 0x80000000) )
577 /* See if we can get a valid NaN from the FPU_REG */
578 l
[0] = (st0_ptr
->sigl
>> 11) | (st0_ptr
->sigh
<< 21);
579 l
[1] = ((st0_ptr
->sigh
>> 11) & 0xfffff);
580 if ( !(st0_ptr
->sigh
& 0x40000000) )
582 /* It is a signalling NaN */
583 EXCEPTION(EX_Invalid
);
584 if ( !(control_word
& CW_Invalid
) )
586 l
[1] |= (0x40000000 >> 11);
592 /* It is an unsupported data type */
593 EXCEPTION(EX_Invalid
);
594 if ( !(control_word
& CW_Invalid
) )
601 else if ( st0_tag
== TAG_Empty
)
603 /* Empty register (stack underflow) */
604 EXCEPTION(EX_StackUnder
);
605 if ( control_word
& CW_Invalid
)
607 /* The masked response */
608 /* Put out the QNaN indefinite */
609 RE_ENTRANT_CHECK_OFF
;
610 FPU_access_ok(VERIFY_WRITE
,dfloat
,8);
611 FPU_put_user(0, (unsigned long __user
*) dfloat
);
612 FPU_put_user(0xfff80000, 1 + (unsigned long __user
*) dfloat
);
619 if ( getsign(st0_ptr
) )
622 RE_ENTRANT_CHECK_OFF
;
623 FPU_access_ok(VERIFY_WRITE
,dfloat
,8);
624 FPU_put_user(l
[0], (unsigned long __user
*)dfloat
);
625 FPU_put_user(l
[1], 1 + (unsigned long __user
*)dfloat
);
632 /* Put a float into user memory */
633 int FPU_store_single(FPU_REG
*st0_ptr
, u_char st0_tag
, float __user
*single
)
636 unsigned long increment
= 0; /* avoid gcc warnings */
641 if ( st0_tag
== TAG_Valid
)
644 reg_copy(st0_ptr
, &tmp
);
645 exp
= exponent(&tmp
);
647 if ( exp
< SINGLE_Emin
)
649 addexponent(&tmp
, -SINGLE_Emin
+ 23); /* largest exp to be 22 */
653 if ( (precision_loss
= FPU_round_to_int(&tmp
, st0_tag
)) )
656 /* Did it round to a non-denormal ? */
657 /* This behaviour might be regarded as peculiar, it appears
658 that the 80486 rounds to the dest precision, then
659 converts to decide underflow. */
660 if ( !((tmp
.sigl
== 0x00800000) &&
661 ((st0_ptr
->sigh
& 0x000000ff) || st0_ptr
->sigl
)) )
662 #endif /* PECULIAR_486 */
664 EXCEPTION(EX_Underflow
);
665 /* This is a special case: see sec 16.2.5.1 of
667 if ( !(control_word
& CW_Underflow
) )
670 EXCEPTION(precision_loss
);
671 if ( !(control_word
& CW_Precision
) )
678 if ( tmp
.sigl
| (tmp
.sigh
& 0x000000ff) )
680 unsigned long sigh
= tmp
.sigh
;
681 unsigned long sigl
= tmp
.sigl
;
684 switch (control_word
& CW_RC
)
687 increment
= ((sigh
& 0xff) > 0x80) /* more than half */
688 || (((sigh
& 0xff) == 0x80) && sigl
) /* more than half */
689 || ((sigh
& 0x180) == 0x180); /* round to even */
691 case RC_DOWN
: /* towards -infinity */
692 increment
= signpositive(&tmp
)
693 ? 0 : (sigl
| (sigh
& 0xff));
695 case RC_UP
: /* towards +infinity */
696 increment
= signpositive(&tmp
)
697 ? (sigl
| (sigh
& 0xff)) : 0;
704 /* Truncate part of the mantissa */
709 if ( sigh
>= 0xffffff00 )
711 /* The sigh part overflows */
712 tmp
.sigh
= 0x80000000;
714 if ( exp
>= EXP_OVER
)
719 tmp
.sigh
&= 0xffffff00;
725 tmp
.sigh
&= 0xffffff00; /* Finish the truncation */
731 templ
= (tmp
.sigh
>> 8) & 0x007fffff;
733 if ( exp
> SINGLE_Emax
)
736 EXCEPTION(EX_Overflow
);
737 if ( !(control_word
& CW_Overflow
) )
739 set_precision_flag_up();
740 if ( !(control_word
& CW_Precision
) )
743 /* This is a special case: see sec 16.2.5.1 of the 80486 book. */
744 /* Masked response is overflow to infinity. */
749 if ( precision_loss
)
752 set_precision_flag_up();
754 set_precision_flag_down();
756 /* Add the exponent */
757 templ
|= ((exp
+SINGLE_Ebias
) & 0xff) << 23;
761 else if (st0_tag
== TAG_Zero
)
765 else if ( st0_tag
== TAG_Special
)
767 st0_tag
= FPU_Special(st0_ptr
);
768 if (st0_tag
== TW_Denormal
)
770 reg_copy(st0_ptr
, &tmp
);
772 /* A denormal will always underflow. */
774 /* An 80486 is supposed to be able to generate
775 a denormal exception here, but... */
776 /* Underflow has priority. */
777 if ( control_word
& CW_Underflow
)
779 #endif /* PECULIAR_486 */
782 else if (st0_tag
== TW_Infinity
)
786 else if (st0_tag
== TW_NaN
)
788 /* Is it really a NaN ? */
789 if ( (exponent(st0_ptr
) == EXP_OVER
) && (st0_ptr
->sigh
& 0x80000000) )
791 /* See if we can get a valid NaN from the FPU_REG */
792 templ
= st0_ptr
->sigh
>> 8;
793 if ( !(st0_ptr
->sigh
& 0x40000000) )
795 /* It is a signalling NaN */
796 EXCEPTION(EX_Invalid
);
797 if ( !(control_word
& CW_Invalid
) )
799 templ
|= (0x40000000 >> 8);
805 /* It is an unsupported data type */
806 EXCEPTION(EX_Invalid
);
807 if ( !(control_word
& CW_Invalid
) )
815 EXCEPTION(EX_INTERNAL
|0x164);
820 else if ( st0_tag
== TAG_Empty
)
822 /* Empty register (stack underflow) */
823 EXCEPTION(EX_StackUnder
);
824 if ( control_word
& EX_Invalid
)
826 /* The masked response */
827 /* Put out the QNaN indefinite */
828 RE_ENTRANT_CHECK_OFF
;
829 FPU_access_ok(VERIFY_WRITE
,single
,4);
830 FPU_put_user(0xffc00000, (unsigned long __user
*) single
);
840 EXCEPTION(EX_INTERNAL
|0x163);
844 if ( getsign(st0_ptr
) )
847 RE_ENTRANT_CHECK_OFF
;
848 FPU_access_ok(VERIFY_WRITE
,single
,4);
849 FPU_put_user(templ
,(unsigned long __user
*) single
);
856 /* Put a long long into user memory */
857 int FPU_store_int64(FPU_REG
*st0_ptr
, u_char st0_tag
, long long __user
*d
)
863 if ( st0_tag
== TAG_Empty
)
865 /* Empty register (stack underflow) */
866 EXCEPTION(EX_StackUnder
);
867 goto invalid_operand
;
869 else if ( st0_tag
== TAG_Special
)
871 st0_tag
= FPU_Special(st0_ptr
);
872 if ( (st0_tag
== TW_Infinity
) ||
873 (st0_tag
== TW_NaN
) )
875 EXCEPTION(EX_Invalid
);
876 goto invalid_operand
;
880 reg_copy(st0_ptr
, &t
);
881 precision_loss
= FPU_round_to_int(&t
, st0_tag
);
882 ((long *)&tll
)[0] = t
.sigl
;
883 ((long *)&tll
)[1] = t
.sigh
;
884 if ( (precision_loss
== 1) ||
885 ((t
.sigh
& 0x80000000) &&
886 !((t
.sigh
== 0x80000000) && (t
.sigl
== 0) &&
889 EXCEPTION(EX_Invalid
);
890 /* This is a special case: see sec 16.2.5.1 of the 80486 book */
892 if ( control_word
& EX_Invalid
)
894 /* Produce something like QNaN "indefinite" */
895 tll
= 0x8000000000000000LL
;
902 if ( precision_loss
)
903 set_precision_flag(precision_loss
);
904 if ( signnegative(&t
) )
908 RE_ENTRANT_CHECK_OFF
;
909 FPU_access_ok(VERIFY_WRITE
,d
,8);
910 copy_to_user(d
, &tll
, 8);
917 /* Put a long into user memory */
918 int FPU_store_int32(FPU_REG
*st0_ptr
, u_char st0_tag
, long __user
*d
)
923 if ( st0_tag
== TAG_Empty
)
925 /* Empty register (stack underflow) */
926 EXCEPTION(EX_StackUnder
);
927 goto invalid_operand
;
929 else if ( st0_tag
== TAG_Special
)
931 st0_tag
= FPU_Special(st0_ptr
);
932 if ( (st0_tag
== TW_Infinity
) ||
933 (st0_tag
== TW_NaN
) )
935 EXCEPTION(EX_Invalid
);
936 goto invalid_operand
;
940 reg_copy(st0_ptr
, &t
);
941 precision_loss
= FPU_round_to_int(&t
, st0_tag
);
943 ((t
.sigl
& 0x80000000) &&
944 !((t
.sigl
== 0x80000000) && signnegative(&t
))) )
946 EXCEPTION(EX_Invalid
);
947 /* This is a special case: see sec 16.2.5.1 of the 80486 book */
949 if ( control_word
& EX_Invalid
)
951 /* Produce something like QNaN "indefinite" */
959 if ( precision_loss
)
960 set_precision_flag(precision_loss
);
961 if ( signnegative(&t
) )
962 t
.sigl
= -(long)t
.sigl
;
965 RE_ENTRANT_CHECK_OFF
;
966 FPU_access_ok(VERIFY_WRITE
,d
,4);
967 FPU_put_user(t
.sigl
, (unsigned long __user
*) d
);
974 /* Put a short into user memory */
975 int FPU_store_int16(FPU_REG
*st0_ptr
, u_char st0_tag
, short __user
*d
)
980 if ( st0_tag
== TAG_Empty
)
982 /* Empty register (stack underflow) */
983 EXCEPTION(EX_StackUnder
);
984 goto invalid_operand
;
986 else if ( st0_tag
== TAG_Special
)
988 st0_tag
= FPU_Special(st0_ptr
);
989 if ( (st0_tag
== TW_Infinity
) ||
990 (st0_tag
== TW_NaN
) )
992 EXCEPTION(EX_Invalid
);
993 goto invalid_operand
;
997 reg_copy(st0_ptr
, &t
);
998 precision_loss
= FPU_round_to_int(&t
, st0_tag
);
1000 ((t
.sigl
& 0xffff8000) &&
1001 !((t
.sigl
== 0x8000) && signnegative(&t
))) )
1003 EXCEPTION(EX_Invalid
);
1004 /* This is a special case: see sec 16.2.5.1 of the 80486 book */
1006 if ( control_word
& EX_Invalid
)
1008 /* Produce something like QNaN "indefinite" */
1016 if ( precision_loss
)
1017 set_precision_flag(precision_loss
);
1018 if ( signnegative(&t
) )
1022 RE_ENTRANT_CHECK_OFF
;
1023 FPU_access_ok(VERIFY_WRITE
,d
,2);
1024 FPU_put_user((short)t
.sigl
, d
);
1025 RE_ENTRANT_CHECK_ON
;
1031 /* Put a packed bcd array into user memory */
1032 int FPU_store_bcd(FPU_REG
*st0_ptr
, u_char st0_tag
, u_char __user
*d
)
1035 unsigned long long ll
;
1037 int i
, precision_loss
;
1038 u_char sign
= (getsign(st0_ptr
) == SIGN_NEG
) ? 0x80 : 0;
1040 if ( st0_tag
== TAG_Empty
)
1042 /* Empty register (stack underflow) */
1043 EXCEPTION(EX_StackUnder
);
1044 goto invalid_operand
;
1046 else if ( st0_tag
== TAG_Special
)
1048 st0_tag
= FPU_Special(st0_ptr
);
1049 if ( (st0_tag
== TW_Infinity
) ||
1050 (st0_tag
== TW_NaN
) )
1052 EXCEPTION(EX_Invalid
);
1053 goto invalid_operand
;
1057 reg_copy(st0_ptr
, &t
);
1058 precision_loss
= FPU_round_to_int(&t
, st0_tag
);
1059 ll
= significand(&t
);
1061 /* Check for overflow, by comparing with 999999999999999999 decimal. */
1062 if ( (t
.sigh
> 0x0de0b6b3) ||
1063 ((t
.sigh
== 0x0de0b6b3) && (t
.sigl
> 0xa763ffff)) )
1065 EXCEPTION(EX_Invalid
);
1066 /* This is a special case: see sec 16.2.5.1 of the 80486 book */
1068 if ( control_word
& CW_Invalid
)
1070 /* Produce the QNaN "indefinite" */
1071 RE_ENTRANT_CHECK_OFF
;
1072 FPU_access_ok(VERIFY_WRITE
,d
,10);
1073 for ( i
= 0; i
< 7; i
++)
1074 FPU_put_user(0, d
+i
); /* These bytes "undefined" */
1075 FPU_put_user(0xc0, d
+7); /* This byte "undefined" */
1076 FPU_put_user(0xff, d
+8);
1077 FPU_put_user(0xff, d
+9);
1078 RE_ENTRANT_CHECK_ON
;
1084 else if ( precision_loss
)
1086 /* Precision loss doesn't stop the data transfer */
1087 set_precision_flag(precision_loss
);
1090 RE_ENTRANT_CHECK_OFF
;
1091 FPU_access_ok(VERIFY_WRITE
,d
,10);
1092 RE_ENTRANT_CHECK_ON
;
1093 for ( i
= 0; i
< 9; i
++)
1095 b
= FPU_div_small(&ll
, 10);
1096 b
|= (FPU_div_small(&ll
, 10)) << 4;
1097 RE_ENTRANT_CHECK_OFF
;
1098 FPU_put_user(b
, d
+i
);
1099 RE_ENTRANT_CHECK_ON
;
1101 RE_ENTRANT_CHECK_OFF
;
1102 FPU_put_user(sign
, d
+9);
1103 RE_ENTRANT_CHECK_ON
;
1108 /*===========================================================================*/
1110 /* r gets mangled such that sig is int, sign:
1111 it is NOT normalized */
1112 /* The return value (in eax) is zero if the result is exact,
1113 if bits are changed due to rounding, truncation, etc, then
1114 a non-zero value is returned */
1115 /* Overflow is signalled by a non-zero return value (in eax).
1116 In the case of overflow, the returned significand always has the
1117 largest possible value */
1118 int FPU_round_to_int(FPU_REG
*r
, u_char tag
)
1123 if (tag
== TAG_Zero
)
1125 /* Make sure that zero is returned */
1127 return 0; /* o.k. */
1130 if (exponent(r
) > 63)
1132 r
->sigl
= r
->sigh
= ~0; /* The largest representable number */
1133 return 1; /* overflow */
1136 eax
= FPU_shrxs(&r
->sigl
, 63 - exponent(r
));
1137 very_big
= !(~(r
->sigh
) | ~(r
->sigl
)); /* test for 0xfff...fff */
1138 #define half_or_more (eax & 0x80000000)
1139 #define frac_part (eax)
1140 #define more_than_half ((eax & 0x80000001) == 0x80000001)
1141 switch (control_word
& CW_RC
)
1144 if ( more_than_half
/* nearest */
1145 || (half_or_more
&& (r
->sigl
& 1)) ) /* odd -> even */
1147 if ( very_big
) return 1; /* overflow */
1149 return PRECISION_LOST_UP
;
1153 if (frac_part
&& getsign(r
))
1155 if ( very_big
) return 1; /* overflow */
1157 return PRECISION_LOST_UP
;
1161 if (frac_part
&& !getsign(r
))
1163 if ( very_big
) return 1; /* overflow */
1165 return PRECISION_LOST_UP
;
1172 return eax
? PRECISION_LOST_DOWN
: 0;
1176 /*===========================================================================*/
1178 u_char __user
*fldenv(fpu_addr_modes addr_modes
, u_char __user
*s
)
1180 unsigned short tag_word
= 0;
1184 if ( (addr_modes
.default_mode
== VM86
) ||
1185 ((addr_modes
.default_mode
== PM16
)
1186 ^ (addr_modes
.override
.operand_size
== OP_SIZE_PREFIX
)) )
1188 RE_ENTRANT_CHECK_OFF
;
1189 FPU_access_ok(VERIFY_READ
, s
, 0x0e);
1190 FPU_get_user(control_word
, (unsigned short __user
*) s
);
1191 FPU_get_user(partial_status
, (unsigned short __user
*) (s
+2));
1192 FPU_get_user(tag_word
, (unsigned short __user
*) (s
+4));
1193 FPU_get_user(instruction_address
.offset
, (unsigned short __user
*) (s
+6));
1194 FPU_get_user(instruction_address
.selector
, (unsigned short __user
*) (s
+8));
1195 FPU_get_user(operand_address
.offset
, (unsigned short __user
*) (s
+0x0a));
1196 FPU_get_user(operand_address
.selector
, (unsigned short __user
*) (s
+0x0c));
1197 RE_ENTRANT_CHECK_ON
;
1199 if ( addr_modes
.default_mode
== VM86
)
1201 instruction_address
.offset
1202 += (instruction_address
.selector
& 0xf000) << 4;
1203 operand_address
.offset
+= (operand_address
.selector
& 0xf000) << 4;
1208 RE_ENTRANT_CHECK_OFF
;
1209 FPU_access_ok(VERIFY_READ
, s
, 0x1c);
1210 FPU_get_user(control_word
, (unsigned short __user
*) s
);
1211 FPU_get_user(partial_status
, (unsigned short __user
*) (s
+4));
1212 FPU_get_user(tag_word
, (unsigned short __user
*) (s
+8));
1213 FPU_get_user(instruction_address
.offset
, (unsigned long __user
*) (s
+0x0c));
1214 FPU_get_user(instruction_address
.selector
, (unsigned short __user
*) (s
+0x10));
1215 FPU_get_user(instruction_address
.opcode
, (unsigned short __user
*) (s
+0x12));
1216 FPU_get_user(operand_address
.offset
, (unsigned long __user
*) (s
+0x14));
1217 FPU_get_user(operand_address
.selector
, (unsigned long __user
*) (s
+0x18));
1218 RE_ENTRANT_CHECK_ON
;
1223 control_word
&= ~0xe080;
1224 #endif /* PECULIAR_486 */
1226 top
= (partial_status
>> SW_Top_Shift
) & 7;
1228 if ( partial_status
& ~control_word
& CW_Exceptions
)
1229 partial_status
|= (SW_Summary
| SW_Backward
);
1231 partial_status
&= ~(SW_Summary
| SW_Backward
);
1233 for ( i
= 0; i
< 8; i
++ )
1238 if ( tag
== TAG_Empty
)
1239 /* New tag is empty. Accept it */
1240 FPU_settag(i
, TAG_Empty
);
1241 else if ( FPU_gettag(i
) == TAG_Empty
)
1243 /* Old tag is empty and new tag is not empty. New tag is determined
1244 by old reg contents */
1245 if ( exponent(&fpu_register(i
)) == - EXTENDED_Ebias
)
1247 if ( !(fpu_register(i
).sigl
| fpu_register(i
).sigh
) )
1248 FPU_settag(i
, TAG_Zero
);
1250 FPU_settag(i
, TAG_Special
);
1252 else if ( exponent(&fpu_register(i
)) == 0x7fff - EXTENDED_Ebias
)
1254 FPU_settag(i
, TAG_Special
);
1256 else if ( fpu_register(i
).sigh
& 0x80000000 )
1257 FPU_settag(i
, TAG_Valid
);
1259 FPU_settag(i
, TAG_Special
); /* An Un-normal */
1261 /* Else old tag is not empty and new tag is not empty. Old tag
1269 void frstor(fpu_addr_modes addr_modes
, u_char __user
*data_address
)
1272 u_char __user
*s
= fldenv(addr_modes
, data_address
);
1273 int offset
= (top
& 7) * 10, other
= 80 - offset
;
1275 /* Copy all registers in stack order. */
1276 RE_ENTRANT_CHECK_OFF
;
1277 FPU_access_ok(VERIFY_READ
,s
,80);
1278 __copy_from_user(register_base
+offset
, s
, other
);
1280 __copy_from_user(register_base
, s
+other
, offset
);
1281 RE_ENTRANT_CHECK_ON
;
1283 for ( i
= 0; i
< 8; i
++ )
1285 regnr
= (i
+top
) & 7;
1286 if ( FPU_gettag(regnr
) != TAG_Empty
)
1287 /* The loaded data over-rides all other cases. */
1288 FPU_settag(regnr
, FPU_tagof(&st(i
)));
1294 u_char __user
*fstenv(fpu_addr_modes addr_modes
, u_char __user
*d
)
1296 if ( (addr_modes
.default_mode
== VM86
) ||
1297 ((addr_modes
.default_mode
== PM16
)
1298 ^ (addr_modes
.override
.operand_size
== OP_SIZE_PREFIX
)) )
1300 RE_ENTRANT_CHECK_OFF
;
1301 FPU_access_ok(VERIFY_WRITE
,d
,14);
1303 FPU_put_user(control_word
& ~0xe080, (unsigned long __user
*) d
);
1305 FPU_put_user(control_word
, (unsigned short __user
*) d
);
1306 #endif /* PECULIAR_486 */
1307 FPU_put_user(status_word(), (unsigned short __user
*) (d
+2));
1308 FPU_put_user(fpu_tag_word
, (unsigned short __user
*) (d
+4));
1309 FPU_put_user(instruction_address
.offset
, (unsigned short __user
*) (d
+6));
1310 FPU_put_user(operand_address
.offset
, (unsigned short __user
*) (d
+0x0a));
1311 if ( addr_modes
.default_mode
== VM86
)
1313 FPU_put_user((instruction_address
.offset
& 0xf0000) >> 4,
1314 (unsigned short __user
*) (d
+8));
1315 FPU_put_user((operand_address
.offset
& 0xf0000) >> 4,
1316 (unsigned short __user
*) (d
+0x0c));
1320 FPU_put_user(instruction_address
.selector
, (unsigned short __user
*) (d
+8));
1321 FPU_put_user(operand_address
.selector
, (unsigned short __user
*) (d
+0x0c));
1323 RE_ENTRANT_CHECK_ON
;
1328 RE_ENTRANT_CHECK_OFF
;
1329 FPU_access_ok(VERIFY_WRITE
, d
, 7*4);
1331 control_word
&= ~0xe080;
1332 /* An 80486 sets nearly all of the reserved bits to 1. */
1333 control_word
|= 0xffff0040;
1334 partial_status
= status_word() | 0xffff0000;
1335 fpu_tag_word
|= 0xffff0000;
1336 I387
.soft
.fcs
&= ~0xf8000000;
1337 I387
.soft
.fos
|= 0xffff0000;
1338 #endif /* PECULIAR_486 */
1339 __copy_to_user(d
, &control_word
, 7*4);
1340 RE_ENTRANT_CHECK_ON
;
1344 control_word
|= CW_Exceptions
;
1345 partial_status
&= ~(SW_Summary
| SW_Backward
);
1351 void fsave(fpu_addr_modes addr_modes
, u_char __user
*data_address
)
1354 int offset
= (top
& 7) * 10, other
= 80 - offset
;
1356 d
= fstenv(addr_modes
, data_address
);
1358 RE_ENTRANT_CHECK_OFF
;
1359 FPU_access_ok(VERIFY_WRITE
,d
,80);
1361 /* Copy all registers in stack order. */
1362 __copy_to_user(d
, register_base
+offset
, other
);
1364 __copy_to_user(d
+other
, register_base
, offset
);
1365 RE_ENTRANT_CHECK_ON
;
1370 /*===========================================================================*/