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