Pull video into release branch
[linux-2.6] / 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 #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 }