xref: /openbmc/linux/arch/x86/math-emu/fpu_entry.c (revision 612a462a)
1 /*---------------------------------------------------------------------------+
2  |  fpu_entry.c                                                              |
3  |                                                                           |
4  | The entry functions for wm-FPU-emu                                        |
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  | See the files "README" and "COPYING" for further copyright and warranty   |
11  | information.                                                              |
12  |                                                                           |
13  +---------------------------------------------------------------------------*/
14 
15 /*---------------------------------------------------------------------------+
16  | Note:                                                                     |
17  |    The file contains code which accesses user memory.                     |
18  |    Emulator static data may change when user memory is accessed, due to   |
19  |    other processes using the emulator while swapping is in progress.      |
20  +---------------------------------------------------------------------------*/
21 
22 /*---------------------------------------------------------------------------+
23  | math_emulate(), restore_i387_soft() and save_i387_soft() are the only     |
24  | entry points for wm-FPU-emu.                                              |
25  +---------------------------------------------------------------------------*/
26 
27 #include <linux/signal.h>
28 #include <linux/regset.h>
29 
30 #include <linux/uaccess.h>
31 #include <asm/traps.h>
32 #include <asm/user.h>
33 #include <asm/fpu/internal.h>
34 
35 #include "fpu_system.h"
36 #include "fpu_emu.h"
37 #include "exception.h"
38 #include "control_w.h"
39 #include "status_w.h"
40 
41 #define __BAD__ FPU_illegal	/* Illegal on an 80486, causes SIGILL */
42 
43 /* fcmovCC and f(u)comi(p) are enabled if CPUID(1).EDX(15) "cmov" is set */
44 
45 /* WARNING: "u" entries are not documented by Intel in their 80486 manual
46    and may not work on FPU clones or later Intel FPUs.
47    Changes to support them provided by Linus Torvalds. */
48 
49 static FUNC const st_instr_table[64] = {
50 /* Opcode:	d8		d9		da		db */
51 /*		dc		dd		de		df */
52 /* c0..7 */	fadd__,		fld_i_,		fcmovb,		fcmovnb,
53 /* c0..7 */	fadd_i,		ffree_,		faddp_,		ffreep,/*u*/
54 /* c8..f */	fmul__,		fxch_i,		fcmove,		fcmovne,
55 /* c8..f */	fmul_i,		fxch_i,/*u*/	fmulp_,		fxch_i,/*u*/
56 /* d0..7 */	fcom_st,	fp_nop,		fcmovbe,	fcmovnbe,
57 /* d0..7 */	fcom_st,/*u*/	fst_i_,		fcompst,/*u*/	fstp_i,/*u*/
58 /* d8..f */	fcompst,	fstp_i,/*u*/	fcmovu,		fcmovnu,
59 /* d8..f */	fcompst,/*u*/	fstp_i,		fcompp,		fstp_i,/*u*/
60 /* e0..7 */	fsub__,		FPU_etc,	__BAD__,	finit_,
61 /* e0..7 */	fsubri,		fucom_,		fsubrp,		fstsw_,
62 /* e8..f */	fsubr_,		fconst,		fucompp,	fucomi_,
63 /* e8..f */	fsub_i,		fucomp,		fsubp_,		fucomip,
64 /* f0..7 */	fdiv__,		FPU_triga,	__BAD__,	fcomi_,
65 /* f0..7 */	fdivri,		__BAD__,	fdivrp,		fcomip,
66 /* f8..f */	fdivr_,		FPU_trigb,	__BAD__,	__BAD__,
67 /* f8..f */	fdiv_i,		__BAD__,	fdivp_,		__BAD__,
68 };
69 
70 #define _NONE_ 0		/* Take no special action */
71 #define _REG0_ 1		/* Need to check for not empty st(0) */
72 #define _REGI_ 2		/* Need to check for not empty st(0) and st(rm) */
73 #define _REGi_ 0		/* Uses st(rm) */
74 #define _PUSH_ 3		/* Need to check for space to push onto stack */
75 #define _null_ 4		/* Function illegal or not implemented */
76 #define _REGIi 5		/* Uses st(0) and st(rm), result to st(rm) */
77 #define _REGIp 6		/* Uses st(0) and st(rm), result to st(rm) then pop */
78 #define _REGIc 0		/* Compare st(0) and st(rm) */
79 #define _REGIn 0		/* Uses st(0) and st(rm), but handle checks later */
80 
81 static u_char const type_table[64] = {
82 /* Opcode:	d8	d9	da	db	dc	dd	de	df */
83 /* c0..7 */	_REGI_, _NONE_, _REGIn, _REGIn, _REGIi, _REGi_, _REGIp, _REGi_,
84 /* c8..f */	_REGI_, _REGIn, _REGIn, _REGIn, _REGIi, _REGI_, _REGIp, _REGI_,
85 /* d0..7 */	_REGIc, _NONE_, _REGIn, _REGIn, _REGIc, _REG0_, _REGIc, _REG0_,
86 /* d8..f */	_REGIc, _REG0_, _REGIn, _REGIn, _REGIc, _REG0_, _REGIc, _REG0_,
87 /* e0..7 */	_REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
88 /* e8..f */	_REGI_, _NONE_, _REGIc, _REGIc, _REGIi, _REGIc, _REGIp, _REGIc,
89 /* f0..7 */	_REGI_, _NONE_, _null_, _REGIc, _REGIi, _null_, _REGIp, _REGIc,
90 /* f8..f */	_REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
91 };
92 
93 #ifdef RE_ENTRANT_CHECKING
94 u_char emulating = 0;
95 #endif /* RE_ENTRANT_CHECKING */
96 
97 static int valid_prefix(u_char *Byte, u_char __user ** fpu_eip,
98 			overrides * override);
99 
100 void math_emulate(struct math_emu_info *info)
101 {
102 	u_char FPU_modrm, byte1;
103 	unsigned short code;
104 	fpu_addr_modes addr_modes;
105 	int unmasked;
106 	FPU_REG loaded_data;
107 	FPU_REG *st0_ptr;
108 	u_char loaded_tag, st0_tag;
109 	void __user *data_address;
110 	struct address data_sel_off;
111 	struct address entry_sel_off;
112 	unsigned long code_base = 0;
113 	unsigned long code_limit = 0;	/* Initialized to stop compiler warnings */
114 	struct desc_struct code_descriptor;
115 	struct fpu *fpu = &current->thread.fpu;
116 
117 	fpu__initialize(fpu);
118 
119 #ifdef RE_ENTRANT_CHECKING
120 	if (emulating) {
121 		printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
122 	}
123 	RE_ENTRANT_CHECK_ON;
124 #endif /* RE_ENTRANT_CHECKING */
125 
126 	FPU_info = info;
127 
128 	FPU_ORIG_EIP = FPU_EIP;
129 
130 	if ((FPU_EFLAGS & 0x00020000) != 0) {
131 		/* Virtual 8086 mode */
132 		addr_modes.default_mode = VM86;
133 		FPU_EIP += code_base = FPU_CS << 4;
134 		code_limit = code_base + 0xffff;	/* Assumes code_base <= 0xffff0000 */
135 	} else if (FPU_CS == __USER_CS && FPU_DS == __USER_DS) {
136 		addr_modes.default_mode = 0;
137 	} else if (FPU_CS == __KERNEL_CS) {
138 		printk("math_emulate: %04x:%08lx\n", FPU_CS, FPU_EIP);
139 		panic("Math emulation needed in kernel");
140 	} else {
141 
142 		if ((FPU_CS & 4) != 4) {	/* Must be in the LDT */
143 			/* Can only handle segmented addressing via the LDT
144 			   for now, and it must be 16 bit */
145 			printk("FPU emulator: Unsupported addressing mode\n");
146 			math_abort(FPU_info, SIGILL);
147 		}
148 
149 		code_descriptor = FPU_get_ldt_descriptor(FPU_CS);
150 		if (code_descriptor.d) {
151 			/* The above test may be wrong, the book is not clear */
152 			/* Segmented 32 bit protected mode */
153 			addr_modes.default_mode = SEG32;
154 		} else {
155 			/* 16 bit protected mode */
156 			addr_modes.default_mode = PM16;
157 		}
158 		FPU_EIP += code_base = seg_get_base(&code_descriptor);
159 		code_limit = seg_get_limit(&code_descriptor) + 1;
160 		code_limit *= seg_get_granularity(&code_descriptor);
161 		code_limit += code_base - 1;
162 		if (code_limit < code_base)
163 			code_limit = 0xffffffff;
164 	}
165 
166 	FPU_lookahead = !(FPU_EFLAGS & X86_EFLAGS_TF);
167 
168 	if (!valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
169 			  &addr_modes.override)) {
170 		RE_ENTRANT_CHECK_OFF;
171 		printk
172 		    ("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
173 		     "FPU emulator: self-modifying code! (emulation impossible)\n",
174 		     byte1);
175 		RE_ENTRANT_CHECK_ON;
176 		EXCEPTION(EX_INTERNAL | 0x126);
177 		math_abort(FPU_info, SIGILL);
178 	}
179 
180       do_another_FPU_instruction:
181 
182 	no_ip_update = 0;
183 
184 	FPU_EIP++;		/* We have fetched the prefix and first code bytes. */
185 
186 	if (addr_modes.default_mode) {
187 		/* This checks for the minimum instruction bytes.
188 		   We also need to check any extra (address mode) code access. */
189 		if (FPU_EIP > code_limit)
190 			math_abort(FPU_info, SIGSEGV);
191 	}
192 
193 	if ((byte1 & 0xf8) != 0xd8) {
194 		if (byte1 == FWAIT_OPCODE) {
195 			if (partial_status & SW_Summary)
196 				goto do_the_FPU_interrupt;
197 			else
198 				goto FPU_fwait_done;
199 		}
200 #ifdef PARANOID
201 		EXCEPTION(EX_INTERNAL | 0x128);
202 		math_abort(FPU_info, SIGILL);
203 #endif /* PARANOID */
204 	}
205 
206 	RE_ENTRANT_CHECK_OFF;
207 	FPU_code_access_ok(1);
208 	FPU_get_user(FPU_modrm, (u_char __user *) FPU_EIP);
209 	RE_ENTRANT_CHECK_ON;
210 	FPU_EIP++;
211 
212 	if (partial_status & SW_Summary) {
213 		/* Ignore the error for now if the current instruction is a no-wait
214 		   control instruction */
215 		/* The 80486 manual contradicts itself on this topic,
216 		   but a real 80486 uses the following instructions:
217 		   fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
218 		 */
219 		code = (FPU_modrm << 8) | byte1;
220 		if (!((((code & 0xf803) == 0xe003) ||	/* fnclex, fninit, fnstsw */
221 		       (((code & 0x3003) == 0x3001) &&	/* fnsave, fnstcw, fnstenv,
222 							   fnstsw */
223 			((code & 0xc000) != 0xc000))))) {
224 			/*
225 			 *  We need to simulate the action of the kernel to FPU
226 			 *  interrupts here.
227 			 */
228 		      do_the_FPU_interrupt:
229 
230 			FPU_EIP = FPU_ORIG_EIP;	/* Point to current FPU instruction. */
231 
232 			RE_ENTRANT_CHECK_OFF;
233 			current->thread.trap_nr = X86_TRAP_MF;
234 			current->thread.error_code = 0;
235 			send_sig(SIGFPE, current, 1);
236 			return;
237 		}
238 	}
239 
240 	entry_sel_off.offset = FPU_ORIG_EIP;
241 	entry_sel_off.selector = FPU_CS;
242 	entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
243 	entry_sel_off.empty = 0;
244 
245 	FPU_rm = FPU_modrm & 7;
246 
247 	if (FPU_modrm < 0300) {
248 		/* All of these instructions use the mod/rm byte to get a data address */
249 
250 		if ((addr_modes.default_mode & SIXTEEN)
251 		    ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX))
252 			data_address =
253 			    FPU_get_address_16(FPU_modrm, &FPU_EIP,
254 					       &data_sel_off, addr_modes);
255 		else
256 			data_address =
257 			    FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
258 					    addr_modes);
259 
260 		if (addr_modes.default_mode) {
261 			if (FPU_EIP - 1 > code_limit)
262 				math_abort(FPU_info, SIGSEGV);
263 		}
264 
265 		if (!(byte1 & 1)) {
266 			unsigned short status1 = partial_status;
267 
268 			st0_ptr = &st(0);
269 			st0_tag = FPU_gettag0();
270 
271 			/* Stack underflow has priority */
272 			if (NOT_EMPTY_ST0) {
273 				if (addr_modes.default_mode & PROTECTED) {
274 					/* This table works for 16 and 32 bit protected mode */
275 					if (access_limit <
276 					    data_sizes_16[(byte1 >> 1) & 3])
277 						math_abort(FPU_info, SIGSEGV);
278 				}
279 
280 				unmasked = 0;	/* Do this here to stop compiler warnings. */
281 				switch ((byte1 >> 1) & 3) {
282 				case 0:
283 					unmasked =
284 					    FPU_load_single((float __user *)
285 							    data_address,
286 							    &loaded_data);
287 					loaded_tag = unmasked & 0xff;
288 					unmasked &= ~0xff;
289 					break;
290 				case 1:
291 					loaded_tag =
292 					    FPU_load_int32((long __user *)
293 							   data_address,
294 							   &loaded_data);
295 					break;
296 				case 2:
297 					unmasked =
298 					    FPU_load_double((double __user *)
299 							    data_address,
300 							    &loaded_data);
301 					loaded_tag = unmasked & 0xff;
302 					unmasked &= ~0xff;
303 					break;
304 				case 3:
305 				default:	/* Used here to suppress gcc warnings. */
306 					loaded_tag =
307 					    FPU_load_int16((short __user *)
308 							   data_address,
309 							   &loaded_data);
310 					break;
311 				}
312 
313 				/* No more access to user memory, it is safe
314 				   to use static data now */
315 
316 				/* NaN operands have the next priority. */
317 				/* We have to delay looking at st(0) until after
318 				   loading the data, because that data might contain an SNaN */
319 				if (((st0_tag == TAG_Special) && isNaN(st0_ptr))
320 				    || ((loaded_tag == TAG_Special)
321 					&& isNaN(&loaded_data))) {
322 					/* Restore the status word; we might have loaded a
323 					   denormal. */
324 					partial_status = status1;
325 					if ((FPU_modrm & 0x30) == 0x10) {
326 						/* fcom or fcomp */
327 						EXCEPTION(EX_Invalid);
328 						setcc(SW_C3 | SW_C2 | SW_C0);
329 						if ((FPU_modrm & 0x08)
330 						    && (control_word &
331 							CW_Invalid))
332 							FPU_pop();	/* fcomp, masked, so we pop. */
333 					} else {
334 						if (loaded_tag == TAG_Special)
335 							loaded_tag =
336 							    FPU_Special
337 							    (&loaded_data);
338 #ifdef PECULIAR_486
339 						/* This is not really needed, but gives behaviour
340 						   identical to an 80486 */
341 						if ((FPU_modrm & 0x28) == 0x20)
342 							/* fdiv or fsub */
343 							real_2op_NaN
344 							    (&loaded_data,
345 							     loaded_tag, 0,
346 							     &loaded_data);
347 						else
348 #endif /* PECULIAR_486 */
349 							/* fadd, fdivr, fmul, or fsubr */
350 							real_2op_NaN
351 							    (&loaded_data,
352 							     loaded_tag, 0,
353 							     st0_ptr);
354 					}
355 					goto reg_mem_instr_done;
356 				}
357 
358 				if (unmasked && !((FPU_modrm & 0x30) == 0x10)) {
359 					/* Is not a comparison instruction. */
360 					if ((FPU_modrm & 0x38) == 0x38) {
361 						/* fdivr */
362 						if ((st0_tag == TAG_Zero) &&
363 						    ((loaded_tag == TAG_Valid)
364 						     || (loaded_tag ==
365 							 TAG_Special
366 							 &&
367 							 isdenormal
368 							 (&loaded_data)))) {
369 							if (FPU_divide_by_zero
370 							    (0,
371 							     getsign
372 							     (&loaded_data))
373 							    < 0) {
374 								/* We use the fact here that the unmasked
375 								   exception in the loaded data was for a
376 								   denormal operand */
377 								/* Restore the state of the denormal op bit */
378 								partial_status
379 								    &=
380 								    ~SW_Denorm_Op;
381 								partial_status
382 								    |=
383 								    status1 &
384 								    SW_Denorm_Op;
385 							} else
386 								setsign(st0_ptr,
387 									getsign
388 									(&loaded_data));
389 						}
390 					}
391 					goto reg_mem_instr_done;
392 				}
393 
394 				switch ((FPU_modrm >> 3) & 7) {
395 				case 0:	/* fadd */
396 					clear_C1();
397 					FPU_add(&loaded_data, loaded_tag, 0,
398 						control_word);
399 					break;
400 				case 1:	/* fmul */
401 					clear_C1();
402 					FPU_mul(&loaded_data, loaded_tag, 0,
403 						control_word);
404 					break;
405 				case 2:	/* fcom */
406 					FPU_compare_st_data(&loaded_data,
407 							    loaded_tag);
408 					break;
409 				case 3:	/* fcomp */
410 					if (!FPU_compare_st_data
411 					    (&loaded_data, loaded_tag)
412 					    && !unmasked)
413 						FPU_pop();
414 					break;
415 				case 4:	/* fsub */
416 					clear_C1();
417 					FPU_sub(LOADED | loaded_tag,
418 						(int)&loaded_data,
419 						control_word);
420 					break;
421 				case 5:	/* fsubr */
422 					clear_C1();
423 					FPU_sub(REV | LOADED | loaded_tag,
424 						(int)&loaded_data,
425 						control_word);
426 					break;
427 				case 6:	/* fdiv */
428 					clear_C1();
429 					FPU_div(LOADED | loaded_tag,
430 						(int)&loaded_data,
431 						control_word);
432 					break;
433 				case 7:	/* fdivr */
434 					clear_C1();
435 					if (st0_tag == TAG_Zero)
436 						partial_status = status1;	/* Undo any denorm tag,
437 										   zero-divide has priority. */
438 					FPU_div(REV | LOADED | loaded_tag,
439 						(int)&loaded_data,
440 						control_word);
441 					break;
442 				}
443 			} else {
444 				if ((FPU_modrm & 0x30) == 0x10) {
445 					/* The instruction is fcom or fcomp */
446 					EXCEPTION(EX_StackUnder);
447 					setcc(SW_C3 | SW_C2 | SW_C0);
448 					if ((FPU_modrm & 0x08)
449 					    && (control_word & CW_Invalid))
450 						FPU_pop();	/* fcomp */
451 				} else
452 					FPU_stack_underflow();
453 			}
454 		      reg_mem_instr_done:
455 			operand_address = data_sel_off;
456 		} else {
457 			if (!(no_ip_update =
458 			      FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6))
459 					     >> 1, addr_modes, data_address))) {
460 				operand_address = data_sel_off;
461 			}
462 		}
463 
464 	} else {
465 		/* None of these instructions access user memory */
466 		u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
467 
468 #ifdef PECULIAR_486
469 		/* This is supposed to be undefined, but a real 80486 seems
470 		   to do this: */
471 		operand_address.offset = 0;
472 		operand_address.selector = FPU_DS;
473 #endif /* PECULIAR_486 */
474 
475 		st0_ptr = &st(0);
476 		st0_tag = FPU_gettag0();
477 		switch (type_table[(int)instr_index]) {
478 		case _NONE_:	/* also _REGIc: _REGIn */
479 			break;
480 		case _REG0_:
481 			if (!NOT_EMPTY_ST0) {
482 				FPU_stack_underflow();
483 				goto FPU_instruction_done;
484 			}
485 			break;
486 		case _REGIi:
487 			if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
488 				FPU_stack_underflow_i(FPU_rm);
489 				goto FPU_instruction_done;
490 			}
491 			break;
492 		case _REGIp:
493 			if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
494 				FPU_stack_underflow_pop(FPU_rm);
495 				goto FPU_instruction_done;
496 			}
497 			break;
498 		case _REGI_:
499 			if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
500 				FPU_stack_underflow();
501 				goto FPU_instruction_done;
502 			}
503 			break;
504 		case _PUSH_:	/* Only used by the fld st(i) instruction */
505 			break;
506 		case _null_:
507 			FPU_illegal();
508 			goto FPU_instruction_done;
509 		default:
510 			EXCEPTION(EX_INTERNAL | 0x111);
511 			goto FPU_instruction_done;
512 		}
513 		(*st_instr_table[(int)instr_index]) ();
514 
515 	      FPU_instruction_done:
516 		;
517 	}
518 
519 	if (!no_ip_update)
520 		instruction_address = entry_sel_off;
521 
522       FPU_fwait_done:
523 
524 #ifdef DEBUG
525 	RE_ENTRANT_CHECK_OFF;
526 	FPU_printall();
527 	RE_ENTRANT_CHECK_ON;
528 #endif /* DEBUG */
529 
530 	if (FPU_lookahead && !need_resched()) {
531 		FPU_ORIG_EIP = FPU_EIP - code_base;
532 		if (valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
533 				 &addr_modes.override))
534 			goto do_another_FPU_instruction;
535 	}
536 
537 	if (addr_modes.default_mode)
538 		FPU_EIP -= code_base;
539 
540 	RE_ENTRANT_CHECK_OFF;
541 }
542 
543 /* Support for prefix bytes is not yet complete. To properly handle
544    all prefix bytes, further changes are needed in the emulator code
545    which accesses user address space. Access to separate segments is
546    important for msdos emulation. */
547 static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
548 			overrides * override)
549 {
550 	u_char byte;
551 	u_char __user *ip = *fpu_eip;
552 
553 	*override = (overrides) {
554 	0, 0, PREFIX_DEFAULT};	/* defaults */
555 
556 	RE_ENTRANT_CHECK_OFF;
557 	FPU_code_access_ok(1);
558 	FPU_get_user(byte, ip);
559 	RE_ENTRANT_CHECK_ON;
560 
561 	while (1) {
562 		switch (byte) {
563 		case ADDR_SIZE_PREFIX:
564 			override->address_size = ADDR_SIZE_PREFIX;
565 			goto do_next_byte;
566 
567 		case OP_SIZE_PREFIX:
568 			override->operand_size = OP_SIZE_PREFIX;
569 			goto do_next_byte;
570 
571 		case PREFIX_CS:
572 			override->segment = PREFIX_CS_;
573 			goto do_next_byte;
574 		case PREFIX_ES:
575 			override->segment = PREFIX_ES_;
576 			goto do_next_byte;
577 		case PREFIX_SS:
578 			override->segment = PREFIX_SS_;
579 			goto do_next_byte;
580 		case PREFIX_FS:
581 			override->segment = PREFIX_FS_;
582 			goto do_next_byte;
583 		case PREFIX_GS:
584 			override->segment = PREFIX_GS_;
585 			goto do_next_byte;
586 		case PREFIX_DS:
587 			override->segment = PREFIX_DS_;
588 			goto do_next_byte;
589 
590 /* lock is not a valid prefix for FPU instructions,
591    let the cpu handle it to generate a SIGILL. */
592 /*	case PREFIX_LOCK: */
593 
594 			/* rep.. prefixes have no meaning for FPU instructions */
595 		case PREFIX_REPE:
596 		case PREFIX_REPNE:
597 
598 		      do_next_byte:
599 			ip++;
600 			RE_ENTRANT_CHECK_OFF;
601 			FPU_code_access_ok(1);
602 			FPU_get_user(byte, ip);
603 			RE_ENTRANT_CHECK_ON;
604 			break;
605 		case FWAIT_OPCODE:
606 			*Byte = byte;
607 			return 1;
608 		default:
609 			if ((byte & 0xf8) == 0xd8) {
610 				*Byte = byte;
611 				*fpu_eip = ip;
612 				return 1;
613 			} else {
614 				/* Not a valid sequence of prefix bytes followed by
615 				   an FPU instruction. */
616 				*Byte = byte;	/* Needed for error message. */
617 				return 0;
618 			}
619 		}
620 	}
621 }
622 
623 void math_abort(struct math_emu_info *info, unsigned int signal)
624 {
625 	FPU_EIP = FPU_ORIG_EIP;
626 	current->thread.trap_nr = X86_TRAP_MF;
627 	current->thread.error_code = 0;
628 	send_sig(signal, current, 1);
629 	RE_ENTRANT_CHECK_OFF;
630       __asm__("movl %0,%%esp ; ret": :"g"(((long)info) - 4));
631 #ifdef PARANOID
632 	printk("ERROR: wm-FPU-emu math_abort failed!\n");
633 #endif /* PARANOID */
634 }
635 
636 #define S387 ((struct swregs_state *)s387)
637 #define sstatus_word() \
638   ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
639 
640 int fpregs_soft_set(struct task_struct *target,
641 		    const struct user_regset *regset,
642 		    unsigned int pos, unsigned int count,
643 		    const void *kbuf, const void __user *ubuf)
644 {
645 	struct swregs_state *s387 = &target->thread.fpu.state.soft;
646 	void *space = s387->st_space;
647 	int ret;
648 	int offset, other, i, tags, regnr, tag, newtop;
649 
650 	RE_ENTRANT_CHECK_OFF;
651 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, s387, 0,
652 				 offsetof(struct swregs_state, st_space));
653 	RE_ENTRANT_CHECK_ON;
654 
655 	if (ret)
656 		return ret;
657 
658 	S387->ftop = (S387->swd >> SW_Top_Shift) & 7;
659 	offset = (S387->ftop & 7) * 10;
660 	other = 80 - offset;
661 
662 	RE_ENTRANT_CHECK_OFF;
663 
664 	/* Copy all registers in stack order. */
665 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
666 				 space + offset, 0, other);
667 	if (!ret && offset)
668 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
669 					 space, 0, offset);
670 
671 	RE_ENTRANT_CHECK_ON;
672 
673 	/* The tags may need to be corrected now. */
674 	tags = S387->twd;
675 	newtop = S387->ftop;
676 	for (i = 0; i < 8; i++) {
677 		regnr = (i + newtop) & 7;
678 		if (((tags >> ((regnr & 7) * 2)) & 3) != TAG_Empty) {
679 			/* The loaded data over-rides all other cases. */
680 			tag =
681 			    FPU_tagof((FPU_REG *) ((u_char *) S387->st_space +
682 						   10 * regnr));
683 			tags &= ~(3 << (regnr * 2));
684 			tags |= (tag & 3) << (regnr * 2);
685 		}
686 	}
687 	S387->twd = tags;
688 
689 	return ret;
690 }
691 
692 int fpregs_soft_get(struct task_struct *target,
693 		    const struct user_regset *regset,
694 		    unsigned int pos, unsigned int count,
695 		    void *kbuf, void __user *ubuf)
696 {
697 	struct swregs_state *s387 = &target->thread.fpu.state.soft;
698 	const void *space = s387->st_space;
699 	int ret;
700 	int offset = (S387->ftop & 7) * 10, other = 80 - offset;
701 
702 	RE_ENTRANT_CHECK_OFF;
703 
704 #ifdef PECULIAR_486
705 	S387->cwd &= ~0xe080;
706 	/* An 80486 sets nearly all of the reserved bits to 1. */
707 	S387->cwd |= 0xffff0040;
708 	S387->swd = sstatus_word() | 0xffff0000;
709 	S387->twd |= 0xffff0000;
710 	S387->fcs &= ~0xf8000000;
711 	S387->fos |= 0xffff0000;
712 #endif /* PECULIAR_486 */
713 
714 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, s387, 0,
715 				  offsetof(struct swregs_state, st_space));
716 
717 	/* Copy all registers in stack order. */
718 	if (!ret)
719 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
720 					  space + offset, 0, other);
721 	if (!ret)
722 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
723 					  space, 0, offset);
724 
725 	RE_ENTRANT_CHECK_ON;
726 
727 	return ret;
728 }
729