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