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