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