File: /usr/src/linux/arch/i386/math-emu/fpu_entry.c

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