fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / 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 __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     {
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 (!used_math())
158     {
159       finit();
160       set_used_math();
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       code_descriptor = LDT_DESCRIPTOR(FPU_CS);
195       if ( SEG_D_SIZE(code_descriptor) )
196         {
197           /* The above test may be wrong, the book is not clear */
198           /* Segmented 32 bit protected mode */
199           addr_modes.default_mode = SEG32;
200         }
201       else
202         {
203           /* 16 bit protected mode */
204           addr_modes.default_mode = PM16;
205         }
206       FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor);
207       code_limit = code_base
208         + (SEG_LIMIT(code_descriptor)+1) * SEG_GRANULARITY(code_descriptor)
209           - 1;
210       if ( code_limit < code_base ) code_limit = 0xffffffff;
211     }
212
213   /* Don't run ahead if single-stepping.  */
214   FPU_lookahead = (FPU_EFLAGS & X86_EFLAGS_TF) == 0;
215
216   if ( !valid_prefix(&byte1, (u_char __user **)&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_access_ok(1);
259   FPU_get_user(FPU_modrm, (u_char __user *) 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 __user *)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 __user *)data_address, &loaded_data);
345                   break;
346                 case 2:
347                   unmasked = FPU_load_double((double __user *)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 __user *)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 && !need_resched())
563     {
564       FPU_ORIG_EIP = FPU_EIP - code_base;
565       if ( valid_prefix(&byte1, (u_char __user **)&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 __user **fpu_eip,
582                         overrides *override)
583 {
584   u_char byte;
585   u_char __user *ip = *fpu_eip;
586
587   *override = (overrides) { 0, 0, PREFIX_DEFAULT };       /* defaults */
588
589   RE_ENTRANT_CHECK_OFF;
590   FPU_code_access_ok(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_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             {
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 __user *buf)
682 {
683   u_char __user *d = (u_char __user *)buf;
684   int offset, other, i, tags, regnr, tag, newtop;
685
686   RE_ENTRANT_CHECK_OFF;
687   FPU_access_ok(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 __user * buf)
728 {
729   u_char __user *d = (u_char __user *)buf;
730   int offset = (S387->ftop & 7) * 10, other = 80 - offset;
731
732   RE_ENTRANT_CHECK_OFF;
733   FPU_access_ok(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   if (__copy_to_user(d, &S387->cwd, 7*4))
744     return -1;
745   RE_ENTRANT_CHECK_ON;
746
747   d += 7*4;
748
749   RE_ENTRANT_CHECK_OFF;
750   /* Copy all registers in stack order. */
751   if (__copy_to_user(d, ((u_char *)&S387->st_space)+offset, other))
752     return -1;
753   if ( offset )
754     if (__copy_to_user(d+other, (u_char *)&S387->st_space, offset))
755       return -1
756   RE_ENTRANT_CHECK_ON;
757
758   return 1;
759 }