Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
reg_ld_str.c
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------+
2  | reg_ld_str.c |
3  | |
4  | All of the functions which transfer data between user memory and FPU_REGs.|
5  | |
6  | Copyright (C) 1992,1993,1994,1996,1997 |
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 "fpu_emu.h"
21 
22 #include <asm/uaccess.h>
23 
24 #include "fpu_system.h"
25 #include "exception.h"
26 #include "reg_constant.h"
27 #include "control_w.h"
28 #include "status_w.h"
29 
30 #define DOUBLE_Emax 1023 /* largest valid exponent */
31 #define DOUBLE_Ebias 1023
32 #define DOUBLE_Emin (-1022) /* smallest valid exponent */
33 
34 #define SINGLE_Emax 127 /* largest valid exponent */
35 #define SINGLE_Ebias 127
36 #define SINGLE_Emin (-126) /* smallest valid exponent */
37 
38 static u_char normalize_no_excep(FPU_REG *r, int exp, int sign)
39 {
40  u_char tag;
41 
42  setexponent16(r, exp);
43 
44  tag = FPU_normalize_nuo(r);
45  stdexp(r);
46  if (sign)
47  setnegative(r);
48 
49  return tag;
50 }
51 
53 {
54  int exp;
55 
56  exp = exponent16(ptr) & 0x7fff;
57  if (exp == 0) {
58  if (!(ptr->sigh | ptr->sigl)) {
59  return TAG_Zero;
60  }
61  /* The number is a de-normal or pseudodenormal. */
62  return TAG_Special;
63  }
64 
65  if (exp == 0x7fff) {
66  /* Is an Infinity, a NaN, or an unsupported data type. */
67  return TAG_Special;
68  }
69 
70  if (!(ptr->sigh & 0x80000000)) {
71  /* Unsupported data type. */
72  /* Valid numbers have the ms bit set to 1. */
73  /* Unnormal. */
74  return TAG_Special;
75  }
76 
77  return TAG_Valid;
78 }
79 
80 /* Get a long double from user memory */
81 int FPU_load_extended(long double __user *s, int stnr)
82 {
83  FPU_REG *sti_ptr = &st(stnr);
84 
86  FPU_access_ok(VERIFY_READ, s, 10);
87  __copy_from_user(sti_ptr, s, 10);
89 
90  return FPU_tagof(sti_ptr);
91 }
92 
93 /* Get a double from user memory */
94 int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data)
95 {
96  int exp, tag, negative;
97  unsigned m64, l64;
98 
100  FPU_access_ok(VERIFY_READ, dfloat, 8);
101  FPU_get_user(m64, 1 + (unsigned long __user *)dfloat);
102  FPU_get_user(l64, (unsigned long __user *)dfloat);
104 
105  negative = (m64 & 0x80000000) ? SIGN_Negative : SIGN_Positive;
106  exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias + EXTENDED_Ebias;
107  m64 &= 0xfffff;
108  if (exp > DOUBLE_Emax + EXTENDED_Ebias) {
109  /* Infinity or NaN */
110  if ((m64 == 0) && (l64 == 0)) {
111  /* +- infinity */
112  loaded_data->sigh = 0x80000000;
113  loaded_data->sigl = 0x00000000;
115  tag = TAG_Special;
116  } else {
117  /* Must be a signaling or quiet NaN */
118  exp = EXP_NaN + EXTENDED_Ebias;
119  loaded_data->sigh = (m64 << 11) | 0x80000000;
120  loaded_data->sigh |= l64 >> 21;
121  loaded_data->sigl = l64 << 11;
122  tag = TAG_Special; /* The calling function must look for NaNs */
123  }
124  } else if (exp < DOUBLE_Emin + EXTENDED_Ebias) {
125  /* Zero or de-normal */
126  if ((m64 == 0) && (l64 == 0)) {
127  /* Zero */
128  reg_copy(&CONST_Z, loaded_data);
129  exp = 0;
130  tag = TAG_Zero;
131  } else {
132  /* De-normal */
133  loaded_data->sigh = m64 << 11;
134  loaded_data->sigh |= l64 >> 21;
135  loaded_data->sigl = l64 << 11;
136 
137  return normalize_no_excep(loaded_data, DOUBLE_Emin,
138  negative)
139  | (denormal_operand() < 0 ? FPU_Exception : 0);
140  }
141  } else {
142  loaded_data->sigh = (m64 << 11) | 0x80000000;
143  loaded_data->sigh |= l64 >> 21;
144  loaded_data->sigl = l64 << 11;
145 
146  tag = TAG_Valid;
147  }
148 
149  setexponent16(loaded_data, exp | negative);
150 
151  return tag;
152 }
153 
154 /* Get a float from user memory */
155 int FPU_load_single(float __user *single, FPU_REG *loaded_data)
156 {
157  unsigned m32;
158  int exp, tag, negative;
159 
161  FPU_access_ok(VERIFY_READ, single, 4);
162  FPU_get_user(m32, (unsigned long __user *)single);
164 
165  negative = (m32 & 0x80000000) ? SIGN_Negative : SIGN_Positive;
166 
167  if (!(m32 & 0x7fffffff)) {
168  /* Zero */
169  reg_copy(&CONST_Z, loaded_data);
170  addexponent(loaded_data, negative);
171  return TAG_Zero;
172  }
173  exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias + EXTENDED_Ebias;
174  m32 = (m32 & 0x7fffff) << 8;
175  if (exp < SINGLE_Emin + EXTENDED_Ebias) {
176  /* De-normals */
177  loaded_data->sigh = m32;
178  loaded_data->sigl = 0;
179 
180  return normalize_no_excep(loaded_data, SINGLE_Emin, negative)
181  | (denormal_operand() < 0 ? FPU_Exception : 0);
182  } else if (exp > SINGLE_Emax + EXTENDED_Ebias) {
183  /* Infinity or NaN */
184  if (m32 == 0) {
185  /* +- infinity */
186  loaded_data->sigh = 0x80000000;
187  loaded_data->sigl = 0x00000000;
189  tag = TAG_Special;
190  } else {
191  /* Must be a signaling or quiet NaN */
192  exp = EXP_NaN + EXTENDED_Ebias;
193  loaded_data->sigh = m32 | 0x80000000;
194  loaded_data->sigl = 0;
195  tag = TAG_Special; /* The calling function must look for NaNs */
196  }
197  } else {
198  loaded_data->sigh = m32 | 0x80000000;
199  loaded_data->sigl = 0;
200  tag = TAG_Valid;
201  }
202 
203  setexponent16(loaded_data, exp | negative); /* Set the sign. */
204 
205  return tag;
206 }
207 
208 /* Get a long long from user memory */
209 int FPU_load_int64(long long __user *_s)
210 {
211  long long s;
212  int sign;
213  FPU_REG *st0_ptr = &st(0);
214 
216  FPU_access_ok(VERIFY_READ, _s, 8);
217  if (copy_from_user(&s, _s, 8))
218  FPU_abort;
220 
221  if (s == 0) {
222  reg_copy(&CONST_Z, st0_ptr);
223  return TAG_Zero;
224  }
225 
226  if (s > 0)
227  sign = SIGN_Positive;
228  else {
229  s = -s;
230  sign = SIGN_Negative;
231  }
232 
233  significand(st0_ptr) = s;
234 
235  return normalize_no_excep(st0_ptr, 63, sign);
236 }
237 
238 /* Get a long from user memory */
239 int FPU_load_int32(long __user *_s, FPU_REG *loaded_data)
240 {
241  long s;
242  int negative;
243 
245  FPU_access_ok(VERIFY_READ, _s, 4);
246  FPU_get_user(s, _s);
248 
249  if (s == 0) {
250  reg_copy(&CONST_Z, loaded_data);
251  return TAG_Zero;
252  }
253 
254  if (s > 0)
255  negative = SIGN_Positive;
256  else {
257  s = -s;
258  negative = SIGN_Negative;
259  }
260 
261  loaded_data->sigh = s;
262  loaded_data->sigl = 0;
263 
264  return normalize_no_excep(loaded_data, 31, negative);
265 }
266 
267 /* Get a short from user memory */
268 int FPU_load_int16(short __user *_s, FPU_REG *loaded_data)
269 {
270  int s, negative;
271 
273  FPU_access_ok(VERIFY_READ, _s, 2);
274  /* Cast as short to get the sign extended. */
275  FPU_get_user(s, _s);
277 
278  if (s == 0) {
279  reg_copy(&CONST_Z, loaded_data);
280  return TAG_Zero;
281  }
282 
283  if (s > 0)
284  negative = SIGN_Positive;
285  else {
286  s = -s;
287  negative = SIGN_Negative;
288  }
289 
290  loaded_data->sigh = s << 16;
291  loaded_data->sigl = 0;
292 
293  return normalize_no_excep(loaded_data, 15, negative);
294 }
295 
296 /* Get a packed bcd array from user memory */
297 int FPU_load_bcd(u_char __user *s)
298 {
299  FPU_REG *st0_ptr = &st(0);
300  int pos;
301  u_char bcd;
302  long long l = 0;
303  int sign;
304 
306  FPU_access_ok(VERIFY_READ, s, 10);
308  for (pos = 8; pos >= 0; pos--) {
309  l *= 10;
311  FPU_get_user(bcd, s + pos);
313  l += bcd >> 4;
314  l *= 10;
315  l += bcd & 0x0f;
316  }
317 
319  FPU_get_user(sign, s + 9);
320  sign = sign & 0x80 ? SIGN_Negative : SIGN_Positive;
322 
323  if (l == 0) {
324  reg_copy(&CONST_Z, st0_ptr);
325  addexponent(st0_ptr, sign); /* Set the sign. */
326  return TAG_Zero;
327  } else {
328  significand(st0_ptr) = l;
329  return normalize_no_excep(st0_ptr, 63, sign);
330  }
331 }
332 
333 /*===========================================================================*/
334 
335 /* Put a long double into user memory */
336 int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag,
337  long double __user * d)
338 {
339  /*
340  The only exception raised by an attempt to store to an
341  extended format is the Invalid Stack exception, i.e.
342  attempting to store from an empty register.
343  */
344 
345  if (st0_tag != TAG_Empty) {
347  FPU_access_ok(VERIFY_WRITE, d, 10);
348 
349  FPU_put_user(st0_ptr->sigl, (unsigned long __user *)d);
350  FPU_put_user(st0_ptr->sigh,
351  (unsigned long __user *)((u_char __user *) d + 4));
352  FPU_put_user(exponent16(st0_ptr),
353  (unsigned short __user *)((u_char __user *) d +
354  8));
356 
357  return 1;
358  }
359 
360  /* Empty register (stack underflow) */
362  if (control_word & CW_Invalid) {
363  /* The masked response */
364  /* Put out the QNaN indefinite */
366  FPU_access_ok(VERIFY_WRITE, d, 10);
367  FPU_put_user(0, (unsigned long __user *)d);
368  FPU_put_user(0xc0000000, 1 + (unsigned long __user *)d);
369  FPU_put_user(0xffff, 4 + (short __user *)d);
371  return 1;
372  } else
373  return 0;
374 
375 }
376 
377 /* Put a double into user memory */
378 int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
379 {
380  unsigned long l[2];
381  unsigned long increment = 0; /* avoid gcc warnings */
382  int precision_loss;
383  int exp;
384  FPU_REG tmp;
385 
386  l[0] = 0;
387  l[1] = 0;
388  if (st0_tag == TAG_Valid) {
389  reg_copy(st0_ptr, &tmp);
390  exp = exponent(&tmp);
391 
392  if (exp < DOUBLE_Emin) { /* It may be a denormal */
393  addexponent(&tmp, -DOUBLE_Emin + 52); /* largest exp to be 51 */
394 denormal_arg:
395  if ((precision_loss = FPU_round_to_int(&tmp, st0_tag))) {
396 #ifdef PECULIAR_486
397  /* Did it round to a non-denormal ? */
398  /* This behaviour might be regarded as peculiar, it appears
399  that the 80486 rounds to the dest precision, then
400  converts to decide underflow. */
401  if (!
402  ((tmp.sigh == 0x00100000) && (tmp.sigl == 0)
403  && (st0_ptr->sigl & 0x000007ff)))
404 #endif /* PECULIAR_486 */
405  {
407  /* This is a special case: see sec 16.2.5.1 of
408  the 80486 book */
409  if (!(control_word & CW_Underflow))
410  return 0;
411  }
412  EXCEPTION(precision_loss);
413  if (!(control_word & CW_Precision))
414  return 0;
415  }
416  l[0] = tmp.sigl;
417  l[1] = tmp.sigh;
418  } else {
419  if (tmp.sigl & 0x000007ff) {
420  precision_loss = 1;
421  switch (control_word & CW_RC) {
422  case RC_RND:
423  /* Rounding can get a little messy.. */
424  increment = ((tmp.sigl & 0x7ff) > 0x400) | /* nearest */
425  ((tmp.sigl & 0xc00) == 0xc00); /* odd -> even */
426  break;
427  case RC_DOWN: /* towards -infinity */
428  increment =
429  signpositive(&tmp) ? 0 : tmp.
430  sigl & 0x7ff;
431  break;
432  case RC_UP: /* towards +infinity */
433  increment =
434  signpositive(&tmp) ? tmp.
435  sigl & 0x7ff : 0;
436  break;
437  case RC_CHOP:
438  increment = 0;
439  break;
440  }
441 
442  /* Truncate the mantissa */
443  tmp.sigl &= 0xfffff800;
444 
445  if (increment) {
446  if (tmp.sigl >= 0xfffff800) {
447  /* the sigl part overflows */
448  if (tmp.sigh == 0xffffffff) {
449  /* The sigh part overflows */
450  tmp.sigh = 0x80000000;
451  exp++;
452  if (exp >= EXP_OVER)
453  goto overflow;
454  } else {
455  tmp.sigh++;
456  }
457  tmp.sigl = 0x00000000;
458  } else {
459  /* We only need to increment sigl */
460  tmp.sigl += 0x00000800;
461  }
462  }
463  } else
464  precision_loss = 0;
465 
466  l[0] = (tmp.sigl >> 11) | (tmp.sigh << 21);
467  l[1] = ((tmp.sigh >> 11) & 0xfffff);
468 
469  if (exp > DOUBLE_Emax) {
470  overflow:
472  if (!(control_word & CW_Overflow))
473  return 0;
475  if (!(control_word & CW_Precision))
476  return 0;
477 
478  /* This is a special case: see sec 16.2.5.1 of the 80486 book */
479  /* Overflow to infinity */
480  l[1] = 0x7ff00000; /* Set to + INF */
481  } else {
482  if (precision_loss) {
483  if (increment)
485  else
487  }
488  /* Add the exponent */
489  l[1] |= (((exp + DOUBLE_Ebias) & 0x7ff) << 20);
490  }
491  }
492  } else if (st0_tag == TAG_Zero) {
493  /* Number is zero */
494  } else if (st0_tag == TAG_Special) {
495  st0_tag = FPU_Special(st0_ptr);
496  if (st0_tag == TW_Denormal) {
497  /* A denormal will always underflow. */
498 #ifndef PECULIAR_486
499  /* An 80486 is supposed to be able to generate
500  a denormal exception here, but... */
501  /* Underflow has priority. */
504 #endif /* PECULIAR_486 */
505  reg_copy(st0_ptr, &tmp);
506  goto denormal_arg;
507  } else if (st0_tag == TW_Infinity) {
508  l[1] = 0x7ff00000;
509  } else if (st0_tag == TW_NaN) {
510  /* Is it really a NaN ? */
511  if ((exponent(st0_ptr) == EXP_OVER)
512  && (st0_ptr->sigh & 0x80000000)) {
513  /* See if we can get a valid NaN from the FPU_REG */
514  l[0] =
515  (st0_ptr->sigl >> 11) | (st0_ptr->
516  sigh << 21);
517  l[1] = ((st0_ptr->sigh >> 11) & 0xfffff);
518  if (!(st0_ptr->sigh & 0x40000000)) {
519  /* It is a signalling NaN */
521  if (!(control_word & CW_Invalid))
522  return 0;
523  l[1] |= (0x40000000 >> 11);
524  }
525  l[1] |= 0x7ff00000;
526  } else {
527  /* It is an unsupported data type */
529  if (!(control_word & CW_Invalid))
530  return 0;
531  l[1] = 0xfff80000;
532  }
533  }
534  } else if (st0_tag == TAG_Empty) {
535  /* Empty register (stack underflow) */
537  if (control_word & CW_Invalid) {
538  /* The masked response */
539  /* Put out the QNaN indefinite */
541  FPU_access_ok(VERIFY_WRITE, dfloat, 8);
542  FPU_put_user(0, (unsigned long __user *)dfloat);
543  FPU_put_user(0xfff80000,
544  1 + (unsigned long __user *)dfloat);
546  return 1;
547  } else
548  return 0;
549  }
550  if (getsign(st0_ptr))
551  l[1] |= 0x80000000;
552 
554  FPU_access_ok(VERIFY_WRITE, dfloat, 8);
555  FPU_put_user(l[0], (unsigned long __user *)dfloat);
556  FPU_put_user(l[1], 1 + (unsigned long __user *)dfloat);
558 
559  return 1;
560 }
561 
562 /* Put a float into user memory */
563 int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single)
564 {
565  long templ = 0;
566  unsigned long increment = 0; /* avoid gcc warnings */
567  int precision_loss;
568  int exp;
569  FPU_REG tmp;
570 
571  if (st0_tag == TAG_Valid) {
572 
573  reg_copy(st0_ptr, &tmp);
574  exp = exponent(&tmp);
575 
576  if (exp < SINGLE_Emin) {
577  addexponent(&tmp, -SINGLE_Emin + 23); /* largest exp to be 22 */
578 
579  denormal_arg:
580 
581  if ((precision_loss = FPU_round_to_int(&tmp, st0_tag))) {
582 #ifdef PECULIAR_486
583  /* Did it round to a non-denormal ? */
584  /* This behaviour might be regarded as peculiar, it appears
585  that the 80486 rounds to the dest precision, then
586  converts to decide underflow. */
587  if (!((tmp.sigl == 0x00800000) &&
588  ((st0_ptr->sigh & 0x000000ff)
589  || st0_ptr->sigl)))
590 #endif /* PECULIAR_486 */
591  {
593  /* This is a special case: see sec 16.2.5.1 of
594  the 80486 book */
595  if (!(control_word & CW_Underflow))
596  return 0;
597  }
598  EXCEPTION(precision_loss);
599  if (!(control_word & CW_Precision))
600  return 0;
601  }
602  templ = tmp.sigl;
603  } else {
604  if (tmp.sigl | (tmp.sigh & 0x000000ff)) {
605  unsigned long sigh = tmp.sigh;
606  unsigned long sigl = tmp.sigl;
607 
608  precision_loss = 1;
609  switch (control_word & CW_RC) {
610  case RC_RND:
611  increment = ((sigh & 0xff) > 0x80) /* more than half */
612  ||(((sigh & 0xff) == 0x80) && sigl) /* more than half */
613  ||((sigh & 0x180) == 0x180); /* round to even */
614  break;
615  case RC_DOWN: /* towards -infinity */
616  increment = signpositive(&tmp)
617  ? 0 : (sigl | (sigh & 0xff));
618  break;
619  case RC_UP: /* towards +infinity */
620  increment = signpositive(&tmp)
621  ? (sigl | (sigh & 0xff)) : 0;
622  break;
623  case RC_CHOP:
624  increment = 0;
625  break;
626  }
627 
628  /* Truncate part of the mantissa */
629  tmp.sigl = 0;
630 
631  if (increment) {
632  if (sigh >= 0xffffff00) {
633  /* The sigh part overflows */
634  tmp.sigh = 0x80000000;
635  exp++;
636  if (exp >= EXP_OVER)
637  goto overflow;
638  } else {
639  tmp.sigh &= 0xffffff00;
640  tmp.sigh += 0x100;
641  }
642  } else {
643  tmp.sigh &= 0xffffff00; /* Finish the truncation */
644  }
645  } else
646  precision_loss = 0;
647 
648  templ = (tmp.sigh >> 8) & 0x007fffff;
649 
650  if (exp > SINGLE_Emax) {
651  overflow:
653  if (!(control_word & CW_Overflow))
654  return 0;
656  if (!(control_word & CW_Precision))
657  return 0;
658 
659  /* This is a special case: see sec 16.2.5.1 of the 80486 book. */
660  /* Masked response is overflow to infinity. */
661  templ = 0x7f800000;
662  } else {
663  if (precision_loss) {
664  if (increment)
666  else
668  }
669  /* Add the exponent */
670  templ |= ((exp + SINGLE_Ebias) & 0xff) << 23;
671  }
672  }
673  } else if (st0_tag == TAG_Zero) {
674  templ = 0;
675  } else if (st0_tag == TAG_Special) {
676  st0_tag = FPU_Special(st0_ptr);
677  if (st0_tag == TW_Denormal) {
678  reg_copy(st0_ptr, &tmp);
679 
680  /* A denormal will always underflow. */
681 #ifndef PECULIAR_486
682  /* An 80486 is supposed to be able to generate
683  a denormal exception here, but... */
684  /* Underflow has priority. */
687 #endif /* PECULIAR_486 */
688  goto denormal_arg;
689  } else if (st0_tag == TW_Infinity) {
690  templ = 0x7f800000;
691  } else if (st0_tag == TW_NaN) {
692  /* Is it really a NaN ? */
693  if ((exponent(st0_ptr) == EXP_OVER)
694  && (st0_ptr->sigh & 0x80000000)) {
695  /* See if we can get a valid NaN from the FPU_REG */
696  templ = st0_ptr->sigh >> 8;
697  if (!(st0_ptr->sigh & 0x40000000)) {
698  /* It is a signalling NaN */
700  if (!(control_word & CW_Invalid))
701  return 0;
702  templ |= (0x40000000 >> 8);
703  }
704  templ |= 0x7f800000;
705  } else {
706  /* It is an unsupported data type */
708  if (!(control_word & CW_Invalid))
709  return 0;
710  templ = 0xffc00000;
711  }
712  }
713 #ifdef PARANOID
714  else {
715  EXCEPTION(EX_INTERNAL | 0x164);
716  return 0;
717  }
718 #endif
719  } else if (st0_tag == TAG_Empty) {
720  /* Empty register (stack underflow) */
722  if (control_word & EX_Invalid) {
723  /* The masked response */
724  /* Put out the QNaN indefinite */
726  FPU_access_ok(VERIFY_WRITE, single, 4);
727  FPU_put_user(0xffc00000,
728  (unsigned long __user *)single);
730  return 1;
731  } else
732  return 0;
733  }
734 #ifdef PARANOID
735  else {
736  EXCEPTION(EX_INTERNAL | 0x163);
737  return 0;
738  }
739 #endif
740  if (getsign(st0_ptr))
741  templ |= 0x80000000;
742 
744  FPU_access_ok(VERIFY_WRITE, single, 4);
745  FPU_put_user(templ, (unsigned long __user *)single);
747 
748  return 1;
749 }
750 
751 /* Put a long long into user memory */
752 int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d)
753 {
754  FPU_REG t;
755  long long tll;
756  int precision_loss;
757 
758  if (st0_tag == TAG_Empty) {
759  /* Empty register (stack underflow) */
761  goto invalid_operand;
762  } else if (st0_tag == TAG_Special) {
763  st0_tag = FPU_Special(st0_ptr);
764  if ((st0_tag == TW_Infinity) || (st0_tag == TW_NaN)) {
766  goto invalid_operand;
767  }
768  }
769 
770  reg_copy(st0_ptr, &t);
771  precision_loss = FPU_round_to_int(&t, st0_tag);
772  ((long *)&tll)[0] = t.sigl;
773  ((long *)&tll)[1] = t.sigh;
774  if ((precision_loss == 1) ||
775  ((t.sigh & 0x80000000) &&
776  !((t.sigh == 0x80000000) && (t.sigl == 0) && signnegative(&t)))) {
778  /* This is a special case: see sec 16.2.5.1 of the 80486 book */
779  invalid_operand:
780  if (control_word & EX_Invalid) {
781  /* Produce something like QNaN "indefinite" */
782  tll = 0x8000000000000000LL;
783  } else
784  return 0;
785  } else {
786  if (precision_loss)
787  set_precision_flag(precision_loss);
788  if (signnegative(&t))
789  tll = -tll;
790  }
791 
794  if (copy_to_user(d, &tll, 8))
795  FPU_abort;
797 
798  return 1;
799 }
800 
801 /* Put a long into user memory */
802 int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d)
803 {
804  FPU_REG t;
805  int precision_loss;
806 
807  if (st0_tag == TAG_Empty) {
808  /* Empty register (stack underflow) */
810  goto invalid_operand;
811  } else if (st0_tag == TAG_Special) {
812  st0_tag = FPU_Special(st0_ptr);
813  if ((st0_tag == TW_Infinity) || (st0_tag == TW_NaN)) {
815  goto invalid_operand;
816  }
817  }
818 
819  reg_copy(st0_ptr, &t);
820  precision_loss = FPU_round_to_int(&t, st0_tag);
821  if (t.sigh ||
822  ((t.sigl & 0x80000000) &&
823  !((t.sigl == 0x80000000) && signnegative(&t)))) {
825  /* This is a special case: see sec 16.2.5.1 of the 80486 book */
826  invalid_operand:
827  if (control_word & EX_Invalid) {
828  /* Produce something like QNaN "indefinite" */
829  t.sigl = 0x80000000;
830  } else
831  return 0;
832  } else {
833  if (precision_loss)
834  set_precision_flag(precision_loss);
835  if (signnegative(&t))
836  t.sigl = -(long)t.sigl;
837  }
838 
841  FPU_put_user(t.sigl, (unsigned long __user *)d);
843 
844  return 1;
845 }
846 
847 /* Put a short into user memory */
848 int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d)
849 {
850  FPU_REG t;
851  int precision_loss;
852 
853  if (st0_tag == TAG_Empty) {
854  /* Empty register (stack underflow) */
856  goto invalid_operand;
857  } else if (st0_tag == TAG_Special) {
858  st0_tag = FPU_Special(st0_ptr);
859  if ((st0_tag == TW_Infinity) || (st0_tag == TW_NaN)) {
861  goto invalid_operand;
862  }
863  }
864 
865  reg_copy(st0_ptr, &t);
866  precision_loss = FPU_round_to_int(&t, st0_tag);
867  if (t.sigh ||
868  ((t.sigl & 0xffff8000) &&
869  !((t.sigl == 0x8000) && signnegative(&t)))) {
871  /* This is a special case: see sec 16.2.5.1 of the 80486 book */
872  invalid_operand:
873  if (control_word & EX_Invalid) {
874  /* Produce something like QNaN "indefinite" */
875  t.sigl = 0x8000;
876  } else
877  return 0;
878  } else {
879  if (precision_loss)
880  set_precision_flag(precision_loss);
881  if (signnegative(&t))
882  t.sigl = -t.sigl;
883  }
884 
887  FPU_put_user((short)t.sigl, d);
889 
890  return 1;
891 }
892 
893 /* Put a packed bcd array into user memory */
894 int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d)
895 {
896  FPU_REG t;
897  unsigned long long ll;
898  u_char b;
899  int i, precision_loss;
900  u_char sign = (getsign(st0_ptr) == SIGN_NEG) ? 0x80 : 0;
901 
902  if (st0_tag == TAG_Empty) {
903  /* Empty register (stack underflow) */
905  goto invalid_operand;
906  } else if (st0_tag == TAG_Special) {
907  st0_tag = FPU_Special(st0_ptr);
908  if ((st0_tag == TW_Infinity) || (st0_tag == TW_NaN)) {
910  goto invalid_operand;
911  }
912  }
913 
914  reg_copy(st0_ptr, &t);
915  precision_loss = FPU_round_to_int(&t, st0_tag);
916  ll = significand(&t);
917 
918  /* Check for overflow, by comparing with 999999999999999999 decimal. */
919  if ((t.sigh > 0x0de0b6b3) ||
920  ((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff))) {
922  /* This is a special case: see sec 16.2.5.1 of the 80486 book */
923  invalid_operand:
924  if (control_word & CW_Invalid) {
925  /* Produce the QNaN "indefinite" */
927  FPU_access_ok(VERIFY_WRITE, d, 10);
928  for (i = 0; i < 7; i++)
929  FPU_put_user(0, d + i); /* These bytes "undefined" */
930  FPU_put_user(0xc0, d + 7); /* This byte "undefined" */
931  FPU_put_user(0xff, d + 8);
932  FPU_put_user(0xff, d + 9);
934  return 1;
935  } else
936  return 0;
937  } else if (precision_loss) {
938  /* Precision loss doesn't stop the data transfer */
939  set_precision_flag(precision_loss);
940  }
941 
943  FPU_access_ok(VERIFY_WRITE, d, 10);
945  for (i = 0; i < 9; i++) {
946  b = FPU_div_small(&ll, 10);
947  b |= (FPU_div_small(&ll, 10)) << 4;
949  FPU_put_user(b, d + i);
951  }
953  FPU_put_user(sign, d + 9);
955 
956  return 1;
957 }
958 
959 /*===========================================================================*/
960 
961 /* r gets mangled such that sig is int, sign:
962  it is NOT normalized */
963 /* The return value (in eax) is zero if the result is exact,
964  if bits are changed due to rounding, truncation, etc, then
965  a non-zero value is returned */
966 /* Overflow is signalled by a non-zero return value (in eax).
967  In the case of overflow, the returned significand always has the
968  largest possible value */
970 {
971  u_char very_big;
972  unsigned eax;
973 
974  if (tag == TAG_Zero) {
975  /* Make sure that zero is returned */
976  significand(r) = 0;
977  return 0; /* o.k. */
978  }
979 
980  if (exponent(r) > 63) {
981  r->sigl = r->sigh = ~0; /* The largest representable number */
982  return 1; /* overflow */
983  }
984 
985  eax = FPU_shrxs(&r->sigl, 63 - exponent(r));
986  very_big = !(~(r->sigh) | ~(r->sigl)); /* test for 0xfff...fff */
987 #define half_or_more (eax & 0x80000000)
988 #define frac_part (eax)
989 #define more_than_half ((eax & 0x80000001) == 0x80000001)
990  switch (control_word & CW_RC) {
991  case RC_RND:
992  if (more_than_half /* nearest */
993  || (half_or_more && (r->sigl & 1))) { /* odd -> even */
994  if (very_big)
995  return 1; /* overflow */
996  significand(r)++;
997  return PRECISION_LOST_UP;
998  }
999  break;
1000  case RC_DOWN:
1001  if (frac_part && getsign(r)) {
1002  if (very_big)
1003  return 1; /* overflow */
1004  significand(r)++;
1005  return PRECISION_LOST_UP;
1006  }
1007  break;
1008  case RC_UP:
1009  if (frac_part && !getsign(r)) {
1010  if (very_big)
1011  return 1; /* overflow */
1012  significand(r)++;
1013  return PRECISION_LOST_UP;
1014  }
1015  break;
1016  case RC_CHOP:
1017  break;
1018  }
1019 
1020  return eax ? PRECISION_LOST_DOWN : 0;
1021 
1022 }
1023 
1024 /*===========================================================================*/
1025 
1027 {
1028  unsigned short tag_word = 0;
1029  u_char tag;
1030  int i;
1031 
1032  if ((addr_modes.default_mode == VM86) ||
1033  ((addr_modes.default_mode == PM16)
1034  ^ (addr_modes.override.operand_size == OP_SIZE_PREFIX))) {
1036  FPU_access_ok(VERIFY_READ, s, 0x0e);
1037  FPU_get_user(control_word, (unsigned short __user *)s);
1038  FPU_get_user(partial_status, (unsigned short __user *)(s + 2));
1039  FPU_get_user(tag_word, (unsigned short __user *)(s + 4));
1041  (unsigned short __user *)(s + 6));
1043  (unsigned short __user *)(s + 8));
1045  (unsigned short __user *)(s + 0x0a));
1046  FPU_get_user(operand_address.selector,
1047  (unsigned short __user *)(s + 0x0c));
1049  s += 0x0e;
1050  if (addr_modes.default_mode == VM86) {
1051  instruction_address.offset
1052  += (instruction_address.selector & 0xf000) << 4;
1053  operand_address.offset +=
1054  (operand_address.selector & 0xf000) << 4;
1055  }
1056  } else {
1058  FPU_access_ok(VERIFY_READ, s, 0x1c);
1059  FPU_get_user(control_word, (unsigned short __user *)s);
1060  FPU_get_user(partial_status, (unsigned short __user *)(s + 4));
1061  FPU_get_user(tag_word, (unsigned short __user *)(s + 8));
1063  (unsigned long __user *)(s + 0x0c));
1065  (unsigned short __user *)(s + 0x10));
1067  (unsigned short __user *)(s + 0x12));
1069  (unsigned long __user *)(s + 0x14));
1070  FPU_get_user(operand_address.selector,
1071  (unsigned long __user *)(s + 0x18));
1073  s += 0x1c;
1074  }
1075 
1076 #ifdef PECULIAR_486
1077  control_word &= ~0xe080;
1078 #endif /* PECULIAR_486 */
1079 
1080  top = (partial_status >> SW_Top_Shift) & 7;
1081 
1084  else
1086 
1087  for (i = 0; i < 8; i++) {
1088  tag = tag_word & 3;
1089  tag_word >>= 2;
1090 
1091  if (tag == TAG_Empty)
1092  /* New tag is empty. Accept it */
1093  FPU_settag(i, TAG_Empty);
1094  else if (FPU_gettag(i) == TAG_Empty) {
1095  /* Old tag is empty and new tag is not empty. New tag is determined
1096  by old reg contents */
1097  if (exponent(&fpu_register(i)) == -EXTENDED_Ebias) {
1098  if (!
1099  (fpu_register(i).sigl | fpu_register(i).
1100  sigh))
1101  FPU_settag(i, TAG_Zero);
1102  else
1103  FPU_settag(i, TAG_Special);
1104  } else if (exponent(&fpu_register(i)) ==
1105  0x7fff - EXTENDED_Ebias) {
1106  FPU_settag(i, TAG_Special);
1107  } else if (fpu_register(i).sigh & 0x80000000)
1108  FPU_settag(i, TAG_Valid);
1109  else
1110  FPU_settag(i, TAG_Special); /* An Un-normal */
1111  }
1112  /* Else old tag is not empty and new tag is not empty. Old tag
1113  remains correct */
1114  }
1115 
1116  return s;
1117 }
1118 
1119 void frstor(fpu_addr_modes addr_modes, u_char __user *data_address)
1120 {
1121  int i, regnr;
1122  u_char __user *s = fldenv(addr_modes, data_address);
1123  int offset = (top & 7) * 10, other = 80 - offset;
1124 
1125  /* Copy all registers in stack order. */
1127  FPU_access_ok(VERIFY_READ, s, 80);
1128  __copy_from_user(register_base + offset, s, other);
1129  if (offset)
1130  __copy_from_user(register_base, s + other, offset);
1132 
1133  for (i = 0; i < 8; i++) {
1134  regnr = (i + top) & 7;
1135  if (FPU_gettag(regnr) != TAG_Empty)
1136  /* The loaded data over-rides all other cases. */
1137  FPU_settag(regnr, FPU_tagof(&st(i)));
1138  }
1139 
1140 }
1141 
1143 {
1144  if ((addr_modes.default_mode == VM86) ||
1145  ((addr_modes.default_mode == PM16)
1146  ^ (addr_modes.override.operand_size == OP_SIZE_PREFIX))) {
1148  FPU_access_ok(VERIFY_WRITE, d, 14);
1149 #ifdef PECULIAR_486
1150  FPU_put_user(control_word & ~0xe080, (unsigned long __user *)d);
1151 #else
1152  FPU_put_user(control_word, (unsigned short __user *)d);
1153 #endif /* PECULIAR_486 */
1154  FPU_put_user(status_word(), (unsigned short __user *)(d + 2));
1155  FPU_put_user(fpu_tag_word, (unsigned short __user *)(d + 4));
1157  (unsigned short __user *)(d + 6));
1159  (unsigned short __user *)(d + 0x0a));
1160  if (addr_modes.default_mode == VM86) {
1162  offset & 0xf0000) >> 4,
1163  (unsigned short __user *)(d + 8));
1164  FPU_put_user((operand_address.offset & 0xf0000) >> 4,
1165  (unsigned short __user *)(d + 0x0c));
1166  } else {
1168  (unsigned short __user *)(d + 8));
1169  FPU_put_user(operand_address.selector,
1170  (unsigned short __user *)(d + 0x0c));
1171  }
1173  d += 0x0e;
1174  } else {
1176  FPU_access_ok(VERIFY_WRITE, d, 7 * 4);
1177 #ifdef PECULIAR_486
1178  control_word &= ~0xe080;
1179  /* An 80486 sets nearly all of the reserved bits to 1. */
1180  control_word |= 0xffff0040;
1181  partial_status = status_word() | 0xffff0000;
1182  fpu_tag_word |= 0xffff0000;
1183  I387->soft.fcs &= ~0xf8000000;
1184  I387->soft.fos |= 0xffff0000;
1185 #endif /* PECULIAR_486 */
1186  if (__copy_to_user(d, &control_word, 7 * 4))
1187  FPU_abort;
1189  d += 0x1c;
1190  }
1191 
1194 
1195  return d;
1196 }
1197 
1198 void fsave(fpu_addr_modes addr_modes, u_char __user *data_address)
1199 {
1200  u_char __user *d;
1201  int offset = (top & 7) * 10, other = 80 - offset;
1202 
1203  d = fstenv(addr_modes, data_address);
1204 
1206  FPU_access_ok(VERIFY_WRITE, d, 80);
1207 
1208  /* Copy all registers in stack order. */
1209  if (__copy_to_user(d, register_base + offset, other))
1210  FPU_abort;
1211  if (offset)
1212  if (__copy_to_user(d + other, register_base, offset))
1213  FPU_abort;
1215 
1216  finit();
1217 }
1218 
1219 /*===========================================================================*/