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