ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[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 #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 **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 *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 (!current->used_math)
159     {
160       finit();
161       current->used_math = 1;
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       if ( SEG_D_SIZE(code_descriptor = LDT_DESCRIPTOR(FPU_CS)) )
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   FPU_lookahead = 1;
214   if (current->ptrace & PT_PTRACED)
215     FPU_lookahead = 0;
216
217   if ( !valid_prefix(&byte1, (u_char **)&FPU_EIP,
218                      &addr_modes.override) )
219     {
220       RE_ENTRANT_CHECK_OFF;
221       printk("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
222              "FPU emulator: self-modifying code! (emulation impossible)\n",
223              byte1);
224       RE_ENTRANT_CHECK_ON;
225       EXCEPTION(EX_INTERNAL|0x126);
226       math_abort(FPU_info,SIGILL);
227     }
228
229 do_another_FPU_instruction:
230
231   no_ip_update = 0;
232
233   FPU_EIP++;  /* We have fetched the prefix and first code bytes. */
234
235   if ( addr_modes.default_mode )
236     {
237       /* This checks for the minimum instruction bytes.
238          We also need to check any extra (address mode) code access. */
239       if ( FPU_EIP > code_limit )
240         math_abort(FPU_info,SIGSEGV);
241     }
242
243   if ( (byte1 & 0xf8) != 0xd8 )
244     {
245       if ( byte1 == FWAIT_OPCODE )
246         {
247           if (partial_status & SW_Summary)
248             goto do_the_FPU_interrupt;
249           else
250             goto FPU_fwait_done;
251         }
252 #ifdef PARANOID
253       EXCEPTION(EX_INTERNAL|0x128);
254       math_abort(FPU_info,SIGILL);
255 #endif /* PARANOID */
256     }
257
258   RE_ENTRANT_CHECK_OFF;
259   FPU_code_verify_area(1);
260   FPU_get_user(FPU_modrm, (u_char *) FPU_EIP);
261   RE_ENTRANT_CHECK_ON;
262   FPU_EIP++;
263
264   if (partial_status & SW_Summary)
265     {
266       /* Ignore the error for now if the current instruction is a no-wait
267          control instruction */
268       /* The 80486 manual contradicts itself on this topic,
269          but a real 80486 uses the following instructions:
270          fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
271        */
272       code = (FPU_modrm << 8) | byte1;
273       if ( ! ( (((code & 0xf803) == 0xe003) ||    /* fnclex, fninit, fnstsw */
274                 (((code & 0x3003) == 0x3001) &&   /* fnsave, fnstcw, fnstenv,
275                                                      fnstsw */
276                  ((code & 0xc000) != 0xc000))) ) )
277         {
278           /*
279            *  We need to simulate the action of the kernel to FPU
280            *  interrupts here.
281            */
282         do_the_FPU_interrupt:
283
284           FPU_EIP = FPU_ORIG_EIP;       /* Point to current FPU instruction. */
285
286           RE_ENTRANT_CHECK_OFF;
287           current->thread.trap_no = 16;
288           current->thread.error_code = 0;
289           send_sig(SIGFPE, current, 1);
290           return;
291         }
292     }
293
294   entry_sel_off.offset = FPU_ORIG_EIP;
295   entry_sel_off.selector = FPU_CS;
296   entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
297
298   FPU_rm = FPU_modrm & 7;
299
300   if ( FPU_modrm < 0300 )
301     {
302       /* All of these instructions use the mod/rm byte to get a data address */
303
304       if ( (addr_modes.default_mode & SIXTEEN)
305           ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX) )
306         data_address = FPU_get_address_16(FPU_modrm, &FPU_EIP, &data_sel_off,
307                                           addr_modes);
308       else
309         data_address = FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
310                                        addr_modes);
311
312       if ( addr_modes.default_mode )
313         {
314           if ( FPU_EIP-1 > code_limit )
315             math_abort(FPU_info,SIGSEGV);
316         }
317
318       if ( !(byte1 & 1) )
319         {
320           unsigned short status1 = partial_status;
321
322           st0_ptr = &st(0);
323           st0_tag = FPU_gettag0();
324
325           /* Stack underflow has priority */
326           if ( NOT_EMPTY_ST0 )
327             {
328               if ( addr_modes.default_mode & PROTECTED )
329                 {
330                   /* This table works for 16 and 32 bit protected mode */
331                   if ( access_limit < data_sizes_16[(byte1 >> 1) & 3] )
332                     math_abort(FPU_info,SIGSEGV);
333                 }
334
335               unmasked = 0;  /* Do this here to stop compiler warnings. */
336               switch ( (byte1 >> 1) & 3 )
337                 {
338                 case 0:
339                   unmasked = FPU_load_single((float *)data_address,
340                                              &loaded_data);
341                   loaded_tag = unmasked & 0xff;
342                   unmasked &= ~0xff;
343                   break;
344                 case 1:
345                   loaded_tag = FPU_load_int32((long *)data_address, &loaded_data);
346                   break;
347                 case 2:
348                   unmasked = FPU_load_double((double *)data_address,
349                                              &loaded_data);
350                   loaded_tag = unmasked & 0xff;
351                   unmasked &= ~0xff;
352                   break;
353                 case 3:
354                 default:  /* Used here to suppress gcc warnings. */
355                   loaded_tag = FPU_load_int16((short *)data_address, &loaded_data);
356                   break;
357                 }
358
359               /* No more access to user memory, it is safe
360                  to use static data now */
361
362               /* NaN operands have the next priority. */
363               /* We have to delay looking at st(0) until after
364                  loading the data, because that data might contain an SNaN */
365               if ( ((st0_tag == TAG_Special) && isNaN(st0_ptr)) ||
366                   ((loaded_tag == TAG_Special) && isNaN(&loaded_data)) )
367                 {
368                   /* Restore the status word; we might have loaded a
369                      denormal. */
370                   partial_status = status1;
371                   if ( (FPU_modrm & 0x30) == 0x10 )
372                     {
373                       /* fcom or fcomp */
374                       EXCEPTION(EX_Invalid);
375                       setcc(SW_C3 | SW_C2 | SW_C0);
376                       if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
377                         FPU_pop();             /* fcomp, masked, so we pop. */
378                     }
379                   else
380                     {
381                       if ( loaded_tag == TAG_Special )
382                         loaded_tag = FPU_Special(&loaded_data);
383 #ifdef PECULIAR_486
384                       /* This is not really needed, but gives behaviour
385                          identical to an 80486 */
386                       if ( (FPU_modrm & 0x28) == 0x20 )
387                         /* fdiv or fsub */
388                         real_2op_NaN(&loaded_data, loaded_tag, 0, &loaded_data);
389                       else
390 #endif /* PECULIAR_486 */ 
391                         /* fadd, fdivr, fmul, or fsubr */
392                         real_2op_NaN(&loaded_data, loaded_tag, 0, st0_ptr);
393                     }
394                   goto reg_mem_instr_done;
395                 }
396
397               if ( unmasked && !((FPU_modrm & 0x30) == 0x10) )
398                 {
399                   /* Is not a comparison instruction. */
400                   if ( (FPU_modrm & 0x38) == 0x38 )
401                     {
402                       /* fdivr */
403                       if ( (st0_tag == TAG_Zero) &&
404                            ((loaded_tag == TAG_Valid)
405                             || (loaded_tag == TAG_Special
406                                 && isdenormal(&loaded_data))) )
407                         {
408                           if ( FPU_divide_by_zero(0, getsign(&loaded_data))
409                                < 0 )
410                             {
411                               /* We use the fact here that the unmasked
412                                  exception in the loaded data was for a
413                                  denormal operand */
414                               /* Restore the state of the denormal op bit */
415                               partial_status &= ~SW_Denorm_Op;
416                               partial_status |= status1 & SW_Denorm_Op;
417                             }
418                           else
419                             setsign(st0_ptr, getsign(&loaded_data));
420                         }
421                     }
422                   goto reg_mem_instr_done;
423                 }
424
425               switch ( (FPU_modrm >> 3) & 7 )
426                 {
427                 case 0:         /* fadd */
428                   clear_C1();
429                   FPU_add(&loaded_data, loaded_tag, 0, control_word);
430                   break;
431                 case 1:         /* fmul */
432                   clear_C1();
433                   FPU_mul(&loaded_data, loaded_tag, 0, control_word);
434                   break;
435                 case 2:         /* fcom */
436                   FPU_compare_st_data(&loaded_data, loaded_tag);
437                   break;
438                 case 3:         /* fcomp */
439                   if ( !FPU_compare_st_data(&loaded_data, loaded_tag)
440                        && !unmasked )
441                     FPU_pop();
442                   break;
443                 case 4:         /* fsub */
444                   clear_C1();
445                   FPU_sub(LOADED|loaded_tag, (int)&loaded_data, control_word);
446                   break;
447                 case 5:         /* fsubr */
448                   clear_C1();
449                   FPU_sub(REV|LOADED|loaded_tag, (int)&loaded_data, control_word);
450                   break;
451                 case 6:         /* fdiv */
452                   clear_C1();
453                   FPU_div(LOADED|loaded_tag, (int)&loaded_data, control_word);
454                   break;
455                 case 7:         /* fdivr */
456                   clear_C1();
457                   if ( st0_tag == TAG_Zero )
458                     partial_status = status1;  /* Undo any denorm tag,
459                                                   zero-divide has priority. */
460                   FPU_div(REV|LOADED|loaded_tag, (int)&loaded_data, control_word);
461                   break;
462                 }
463             }
464           else
465             {
466               if ( (FPU_modrm & 0x30) == 0x10 )
467                 {
468                   /* The instruction is fcom or fcomp */
469                   EXCEPTION(EX_StackUnder);
470                   setcc(SW_C3 | SW_C2 | SW_C0);
471                   if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
472                     FPU_pop();             /* fcomp */
473                 }
474               else
475                 FPU_stack_underflow();
476             }
477         reg_mem_instr_done:
478           operand_address = data_sel_off;
479         }
480       else
481         {
482           if ( !(no_ip_update =
483                  FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6)) >> 1,
484                                 addr_modes, data_address)) )
485             {
486               operand_address = data_sel_off;
487             }
488         }
489
490     }
491   else
492     {
493       /* None of these instructions access user memory */
494       u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
495
496 #ifdef PECULIAR_486
497       /* This is supposed to be undefined, but a real 80486 seems
498          to do this: */
499       operand_address.offset = 0;
500       operand_address.selector = FPU_DS;
501 #endif /* PECULIAR_486 */
502
503       st0_ptr = &st(0);
504       st0_tag = FPU_gettag0();
505       switch ( type_table[(int) instr_index] )
506         {
507         case _NONE_:   /* also _REGIc: _REGIn */
508           break;
509         case _REG0_:
510           if ( !NOT_EMPTY_ST0 )
511             {
512               FPU_stack_underflow();
513               goto FPU_instruction_done;
514             }
515           break;
516         case _REGIi:
517           if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
518             {
519               FPU_stack_underflow_i(FPU_rm);
520               goto FPU_instruction_done;
521             }
522           break;
523         case _REGIp:
524           if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
525             {
526               FPU_stack_underflow_pop(FPU_rm);
527               goto FPU_instruction_done;
528             }
529           break;
530         case _REGI_:
531           if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
532             {
533               FPU_stack_underflow();
534               goto FPU_instruction_done;
535             }
536           break;
537         case _PUSH_:     /* Only used by the fld st(i) instruction */
538           break;
539         case _null_:
540           FPU_illegal();
541           goto FPU_instruction_done;
542         default:
543           EXCEPTION(EX_INTERNAL|0x111);
544           goto FPU_instruction_done;
545         }
546       (*st_instr_table[(int) instr_index])();
547
548 FPU_instruction_done:
549       ;
550     }
551
552   if ( ! no_ip_update )
553     instruction_address = entry_sel_off;
554
555 FPU_fwait_done:
556
557 #ifdef DEBUG
558   RE_ENTRANT_CHECK_OFF;
559   FPU_printall();
560   RE_ENTRANT_CHECK_ON;
561 #endif /* DEBUG */
562
563   if (FPU_lookahead && !need_resched())
564     {
565       FPU_ORIG_EIP = FPU_EIP - code_base;
566       if ( valid_prefix(&byte1, (u_char **)&FPU_EIP,
567                         &addr_modes.override) )
568         goto do_another_FPU_instruction;
569     }
570
571   if ( addr_modes.default_mode )
572     FPU_EIP -= code_base;
573
574   RE_ENTRANT_CHECK_OFF;
575 }
576
577
578 /* Support for prefix bytes is not yet complete. To properly handle
579    all prefix bytes, further changes are needed in the emulator code
580    which accesses user address space. Access to separate segments is
581    important for msdos emulation. */
582 static int valid_prefix(u_char *Byte, u_char **fpu_eip,
583                         overrides *override)
584 {
585   u_char byte;
586   u_char *ip = *fpu_eip;
587
588   *override = (overrides) { 0, 0, PREFIX_DEFAULT };       /* defaults */
589
590   RE_ENTRANT_CHECK_OFF;
591   FPU_code_verify_area(1);
592   FPU_get_user(byte, ip);
593   RE_ENTRANT_CHECK_ON;
594
595   while ( 1 )
596     {
597       switch ( byte )
598         {
599         case ADDR_SIZE_PREFIX:
600           override->address_size = ADDR_SIZE_PREFIX;
601           goto do_next_byte;
602
603         case OP_SIZE_PREFIX:
604           override->operand_size = OP_SIZE_PREFIX;
605           goto do_next_byte;
606
607         case PREFIX_CS:
608           override->segment = PREFIX_CS_;
609           goto do_next_byte;
610         case PREFIX_ES:
611           override->segment = PREFIX_ES_;
612           goto do_next_byte;
613         case PREFIX_SS:
614           override->segment = PREFIX_SS_;
615           goto do_next_byte;
616         case PREFIX_FS:
617           override->segment = PREFIX_FS_;
618           goto do_next_byte;
619         case PREFIX_GS:
620           override->segment = PREFIX_GS_;
621           goto do_next_byte;
622         case PREFIX_DS:
623           override->segment = PREFIX_DS_;
624           goto do_next_byte;
625
626 /* lock is not a valid prefix for FPU instructions,
627    let the cpu handle it to generate a SIGILL. */
628 /*      case PREFIX_LOCK: */
629
630           /* rep.. prefixes have no meaning for FPU instructions */
631         case PREFIX_REPE:
632         case PREFIX_REPNE:
633
634         do_next_byte:
635           ip++;
636           RE_ENTRANT_CHECK_OFF;
637           FPU_code_verify_area(1);
638           FPU_get_user(byte, ip);
639           RE_ENTRANT_CHECK_ON;
640           break;
641         case FWAIT_OPCODE:
642           *Byte = byte;
643           return 1;
644         default:
645           if ( (byte & 0xf8) == 0xd8 )
646             {
647               *Byte = byte;
648               *fpu_eip = ip;
649               return 1;
650             }
651           else
652             {
653               /* Not a valid sequence of prefix bytes followed by
654                  an FPU instruction. */
655               *Byte = byte;  /* Needed for error message. */
656               return 0;
657             }
658         }
659     }
660 }
661
662
663 void math_abort(struct info * info, unsigned int signal)
664 {
665         FPU_EIP = FPU_ORIG_EIP;
666         current->thread.trap_no = 16;
667         current->thread.error_code = 0;
668         send_sig(signal,current,1);
669         RE_ENTRANT_CHECK_OFF;
670         __asm__("movl %0,%%esp ; ret": :"g" (((long) info)-4));
671 #ifdef PARANOID
672       printk("ERROR: wm-FPU-emu math_abort failed!\n");
673 #endif /* PARANOID */
674 }
675
676
677
678 #define S387 ((struct i387_soft_struct *)s387)
679 #define sstatus_word() \
680   ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
681
682 int restore_i387_soft(void *s387, struct _fpstate *buf)
683 {
684   u_char *d = (u_char *)buf;
685   int offset, other, i, tags, regnr, tag, newtop;
686
687   RE_ENTRANT_CHECK_OFF;
688   FPU_verify_area(VERIFY_READ, d, 7*4 + 8*10);
689   if (__copy_from_user(&S387->cwd, d, 7*4))
690     return -1;
691   RE_ENTRANT_CHECK_ON;
692
693   d += 7*4;
694
695   S387->ftop = (S387->swd >> SW_Top_Shift) & 7;
696   offset = (S387->ftop & 7) * 10;
697   other = 80 - offset;
698
699   RE_ENTRANT_CHECK_OFF;
700   /* Copy all registers in stack order. */
701   if (__copy_from_user(((u_char *)&S387->st_space)+offset, d, other))
702     return -1;
703   if ( offset )
704     if (__copy_from_user((u_char *)&S387->st_space, d+other, offset))
705       return -1;
706   RE_ENTRANT_CHECK_ON;
707
708   /* The tags may need to be corrected now. */
709   tags = S387->twd;
710   newtop = S387->ftop;
711   for ( i = 0; i < 8; i++ )
712     {
713       regnr = (i+newtop) & 7;
714       if ( ((tags >> ((regnr & 7)*2)) & 3) != TAG_Empty )
715         {
716           /* The loaded data over-rides all other cases. */
717           tag = FPU_tagof((FPU_REG *)((u_char *)S387->st_space + 10*regnr));
718           tags &= ~(3 << (regnr*2));
719           tags |= (tag & 3) << (regnr*2);
720         }
721     }
722   S387->twd = tags;
723
724   return 0;
725 }
726
727
728 int save_i387_soft(void *s387, struct _fpstate * buf)
729 {
730   u_char *d = (u_char *)buf;
731   int offset = (S387->ftop & 7) * 10, other = 80 - offset;
732
733   RE_ENTRANT_CHECK_OFF;
734   FPU_verify_area(VERIFY_WRITE, d, 7*4 + 8*10);
735 #ifdef PECULIAR_486
736   S387->cwd &= ~0xe080;
737   /* An 80486 sets nearly all of the reserved bits to 1. */
738   S387->cwd |= 0xffff0040;
739   S387->swd = sstatus_word() | 0xffff0000;
740   S387->twd |= 0xffff0000;
741   S387->fcs &= ~0xf8000000;
742   S387->fos |= 0xffff0000;
743 #endif /* PECULIAR_486 */
744   __copy_to_user(d, &S387->cwd, 7*4);
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 }