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   billm@suburbia.net                              |
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
38static 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
52int FPU_tagof(FPU_REG *ptr)
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 */
81int FPU_load_extended(long double __user *s, int stnr)
82{
83	FPU_REG *sti_ptr = &st(stnr);
84
85	RE_ENTRANT_CHECK_OFF;
86	FPU_access_ok(VERIFY_READ, s, 10);
87	__copy_from_user(sti_ptr, s, 10);
88	RE_ENTRANT_CHECK_ON;
89
90	return FPU_tagof(sti_ptr);
91}
92
93/* Get a double from user memory */
94int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data)
95{
96	int exp, tag, negative;
97	unsigned m64, l64;
98
99	RE_ENTRANT_CHECK_OFF;
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);
103	RE_ENTRANT_CHECK_ON;
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;
114			exp = EXP_Infinity + EXTENDED_Ebias;
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 */
155int FPU_load_single(float __user *single, FPU_REG *loaded_data)
156{
157	unsigned m32;
158	int exp, tag, negative;
159
160	RE_ENTRANT_CHECK_OFF;
161	FPU_access_ok(VERIFY_READ, single, 4);
162	FPU_get_user(m32, (unsigned long __user *)single);
163	RE_ENTRANT_CHECK_ON;
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;
188			exp = EXP_Infinity + EXTENDED_Ebias;
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 */
209int FPU_load_int64(long long __user *_s)
210{
211	long long s;
212	int sign;
213	FPU_REG *st0_ptr = &st(0);
214
215	RE_ENTRANT_CHECK_OFF;
216	FPU_access_ok(VERIFY_READ, _s, 8);
217	if (copy_from_user(&s, _s, 8))
218		FPU_abort;
219	RE_ENTRANT_CHECK_ON;
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 */
239int FPU_load_int32(long __user *_s, FPU_REG *loaded_data)
240{
241	long s;
242	int negative;
243
244	RE_ENTRANT_CHECK_OFF;
245	FPU_access_ok(VERIFY_READ, _s, 4);
246	FPU_get_user(s, _s);
247	RE_ENTRANT_CHECK_ON;
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 */
268int FPU_load_int16(short __user *_s, FPU_REG *loaded_data)
269{
270	int s, negative;
271
272	RE_ENTRANT_CHECK_OFF;
273	FPU_access_ok(VERIFY_READ, _s, 2);
274	/* Cast as short to get the sign extended. */
275	FPU_get_user(s, _s);
276	RE_ENTRANT_CHECK_ON;
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 */
297int 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
305	RE_ENTRANT_CHECK_OFF;
306	FPU_access_ok(VERIFY_READ, s, 10);
307	RE_ENTRANT_CHECK_ON;
308	for (pos = 8; pos >= 0; pos--) {
309		l *= 10;
310		RE_ENTRANT_CHECK_OFF;
311		FPU_get_user(bcd, s + pos);
312		RE_ENTRANT_CHECK_ON;
313		l += bcd >> 4;
314		l *= 10;
315		l += bcd & 0x0f;
316	}
317
318	RE_ENTRANT_CHECK_OFF;
319	FPU_get_user(sign, s + 9);
320	sign = sign & 0x80 ? SIGN_Negative : SIGN_Positive;
321	RE_ENTRANT_CHECK_ON;
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 */
336int 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) {
346		RE_ENTRANT_CHECK_OFF;
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));
355		RE_ENTRANT_CHECK_ON;
356
357		return 1;
358	}
359
360	/* Empty register (stack underflow) */
361	EXCEPTION(EX_StackUnder);
362	if (control_word & CW_Invalid) {
363		/* The masked response */
364		/* Put out the QNaN indefinite */
365		RE_ENTRANT_CHECK_OFF;
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);
370		RE_ENTRANT_CHECK_ON;
371		return 1;
372	} else
373		return 0;
374
375}
376
377/* Put a double into user memory */
378int 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 */
394denormal_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				{
406					EXCEPTION(EX_Underflow);
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:
471				EXCEPTION(EX_Overflow);
472				if (!(control_word & CW_Overflow))
473					return 0;
474				set_precision_flag_up();
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)
484						set_precision_flag_up();
485					else
486						set_precision_flag_down();
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. */
502			if (control_word & CW_Underflow)
503				denormal_operand();
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 */
520					EXCEPTION(EX_Invalid);
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 */
528				EXCEPTION(EX_Invalid);
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) */
536		EXCEPTION(EX_StackUnder);
537		if (control_word & CW_Invalid) {
538			/* The masked response */
539			/* Put out the QNaN indefinite */
540			RE_ENTRANT_CHECK_OFF;
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);
545			RE_ENTRANT_CHECK_ON;
546			return 1;
547		} else
548			return 0;
549	}
550	if (getsign(st0_ptr))
551		l[1] |= 0x80000000;
552
553	RE_ENTRANT_CHECK_OFF;
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);
557	RE_ENTRANT_CHECK_ON;
558
559	return 1;
560}
561
562/* Put a float into user memory */
563int 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				{
592					EXCEPTION(EX_Underflow);
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:
652				EXCEPTION(EX_Overflow);
653				if (!(control_word & CW_Overflow))
654					return 0;
655				set_precision_flag_up();
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)
665						set_precision_flag_up();
666					else
667						set_precision_flag_down();
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. */
685			if (control_word & CW_Underflow)
686				denormal_operand();
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 */
699					EXCEPTION(EX_Invalid);
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 */
707				EXCEPTION(EX_Invalid);
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) */
721		EXCEPTION(EX_StackUnder);
722		if (control_word & EX_Invalid) {
723			/* The masked response */
724			/* Put out the QNaN indefinite */
725			RE_ENTRANT_CHECK_OFF;
726			FPU_access_ok(VERIFY_WRITE, single, 4);
727			FPU_put_user(0xffc00000,
728				     (unsigned long __user *)single);
729			RE_ENTRANT_CHECK_ON;
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
743	RE_ENTRANT_CHECK_OFF;
744	FPU_access_ok(VERIFY_WRITE, single, 4);
745	FPU_put_user(templ, (unsigned long __user *)single);
746	RE_ENTRANT_CHECK_ON;
747
748	return 1;
749}
750
751/* Put a long long into user memory */
752int 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) */
760		EXCEPTION(EX_StackUnder);
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)) {
765			EXCEPTION(EX_Invalid);
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)))) {
777		EXCEPTION(EX_Invalid);
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
792	RE_ENTRANT_CHECK_OFF;
793	FPU_access_ok(VERIFY_WRITE, d, 8);
794	if (copy_to_user(d, &tll, 8))
795		FPU_abort;
796	RE_ENTRANT_CHECK_ON;
797
798	return 1;
799}
800
801/* Put a long into user memory */
802int 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) */
809		EXCEPTION(EX_StackUnder);
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)) {
814			EXCEPTION(EX_Invalid);
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)))) {
824		EXCEPTION(EX_Invalid);
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
839	RE_ENTRANT_CHECK_OFF;
840	FPU_access_ok(VERIFY_WRITE, d, 4);
841	FPU_put_user(t.sigl, (unsigned long __user *)d);
842	RE_ENTRANT_CHECK_ON;
843
844	return 1;
845}
846
847/* Put a short into user memory */
848int 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) */
855		EXCEPTION(EX_StackUnder);
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)) {
860			EXCEPTION(EX_Invalid);
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)))) {
870		EXCEPTION(EX_Invalid);
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
885	RE_ENTRANT_CHECK_OFF;
886	FPU_access_ok(VERIFY_WRITE, d, 2);
887	FPU_put_user((short)t.sigl, d);
888	RE_ENTRANT_CHECK_ON;
889
890	return 1;
891}
892
893/* Put a packed bcd array into user memory */
894int 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) */
904		EXCEPTION(EX_StackUnder);
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)) {
909			EXCEPTION(EX_Invalid);
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))) {
921		EXCEPTION(EX_Invalid);
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" */
926			RE_ENTRANT_CHECK_OFF;
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);
933			RE_ENTRANT_CHECK_ON;
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
942	RE_ENTRANT_CHECK_OFF;
943	FPU_access_ok(VERIFY_WRITE, d, 10);
944	RE_ENTRANT_CHECK_ON;
945	for (i = 0; i < 9; i++) {
946		b = FPU_div_small(&ll, 10);
947		b |= (FPU_div_small(&ll, 10)) << 4;
948		RE_ENTRANT_CHECK_OFF;
949		FPU_put_user(b, d + i);
950		RE_ENTRANT_CHECK_ON;
951	}
952	RE_ENTRANT_CHECK_OFF;
953	FPU_put_user(sign, d + 9);
954	RE_ENTRANT_CHECK_ON;
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 */
969int FPU_round_to_int(FPU_REG *r, u_char tag)
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
1026u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s)
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))) {
1035		RE_ENTRANT_CHECK_OFF;
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));
1040		FPU_get_user(instruction_address.offset,
1041			     (unsigned short __user *)(s + 6));
1042		FPU_get_user(instruction_address.selector,
1043			     (unsigned short __user *)(s + 8));
1044		FPU_get_user(operand_address.offset,
1045			     (unsigned short __user *)(s + 0x0a));
1046		FPU_get_user(operand_address.selector,
1047			     (unsigned short __user *)(s + 0x0c));
1048		RE_ENTRANT_CHECK_ON;
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 {
1057		RE_ENTRANT_CHECK_OFF;
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));
1062		FPU_get_user(instruction_address.offset,
1063			     (unsigned long __user *)(s + 0x0c));
1064		FPU_get_user(instruction_address.selector,
1065			     (unsigned short __user *)(s + 0x10));
1066		FPU_get_user(instruction_address.opcode,
1067			     (unsigned short __user *)(s + 0x12));
1068		FPU_get_user(operand_address.offset,
1069			     (unsigned long __user *)(s + 0x14));
1070		FPU_get_user(operand_address.selector,
1071			     (unsigned long __user *)(s + 0x18));
1072		RE_ENTRANT_CHECK_ON;
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
1082	if (partial_status & ~control_word & CW_Exceptions)
1083		partial_status |= (SW_Summary | SW_Backward);
1084	else
1085		partial_status &= ~(SW_Summary | SW_Backward);
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
1119void 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. */
1126	RE_ENTRANT_CHECK_OFF;
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);
1131	RE_ENTRANT_CHECK_ON;
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
1142u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d)
1143{
1144	if ((addr_modes.default_mode == VM86) ||
1145	    ((addr_modes.default_mode == PM16)
1146	     ^ (addr_modes.override.operand_size == OP_SIZE_PREFIX))) {
1147		RE_ENTRANT_CHECK_OFF;
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));
1156		FPU_put_user(instruction_address.offset,
1157			     (unsigned short __user *)(d + 6));
1158		FPU_put_user(operand_address.offset,
1159			     (unsigned short __user *)(d + 0x0a));
1160		if (addr_modes.default_mode == VM86) {
1161			FPU_put_user((instruction_address.
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 {
1167			FPU_put_user(instruction_address.selector,
1168				     (unsigned short __user *)(d + 8));
1169			FPU_put_user(operand_address.selector,
1170				     (unsigned short __user *)(d + 0x0c));
1171		}
1172		RE_ENTRANT_CHECK_ON;
1173		d += 0x0e;
1174	} else {
1175		RE_ENTRANT_CHECK_OFF;
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;
1188		RE_ENTRANT_CHECK_ON;
1189		d += 0x1c;
1190	}
1191
1192	control_word |= CW_Exceptions;
1193	partial_status &= ~(SW_Summary | SW_Backward);
1194
1195	return d;
1196}
1197
1198void 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
1205	RE_ENTRANT_CHECK_OFF;
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;
1214	RE_ENTRANT_CHECK_ON;
1215
1216	finit();
1217}
1218
1219/*===========================================================================*/
1220