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