1 /*---------------------------------------------------------------------------+
4 | The entry functions for wm-FPU-emu |
6 | Copyright (C) 1992,1993,1994,1996,1997 |
7 | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
8 | E-mail billm@suburbia.net |
10 | See the files "README" and "COPYING" for further copyright and warranty |
13 +---------------------------------------------------------------------------*/
15 /*---------------------------------------------------------------------------+
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 +---------------------------------------------------------------------------*/
22 /*---------------------------------------------------------------------------+
23 | math_emulate(), restore_i387_soft() and save_i387_soft() are the only |
24 | entry points for wm-FPU-emu. |
25 +---------------------------------------------------------------------------*/
27 #include <linux/signal.h>
28 #include <linux/regset.h>
30 #include <asm/uaccess.h>
34 #include "fpu_system.h"
36 #include "exception.h"
37 #include "control_w.h"
40 #define __BAD__ FPU_illegal /* Illegal on an 80486, causes SIGILL */
42 #ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by default. */
44 /* WARNING: These codes are not documented by Intel in their 80486 manual
45 and may not work on FPU clones or later Intel FPUs. */
47 /* Changes to support the un-doc codes provided by Linus Torvalds. */
49 #define _d9_d8_ fstp_i /* unofficial code (19) */
50 #define _dc_d0_ fcom_st /* unofficial code (14) */
51 #define _dc_d8_ fcompst /* unofficial code (1c) */
52 #define _dd_c8_ fxch_i /* unofficial code (0d) */
53 #define _de_d0_ fcompst /* unofficial code (16) */
54 #define _df_c0_ ffreep /* unofficial code (07) ffree + pop */
55 #define _df_c8_ fxch_i /* unofficial code (0f) */
56 #define _df_d0_ fstp_i /* unofficial code (17) */
57 #define _df_d8_ fstp_i /* unofficial code (1f) */
59 static FUNC const st_instr_table[64] = {
60 fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, _df_c0_,
61 fmul__, fxch_i, __BAD__, __BAD__, fmul_i, _dd_c8_, fmulp_, _df_c8_,
62 fcom_st, fp_nop, __BAD__, __BAD__, _dc_d0_, fst_i_, _de_d0_, _df_d0_,
63 fcompst, _d9_d8_, __BAD__, __BAD__, _dc_d8_, fstp_i, fcompp, _df_d8_,
64 fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
65 fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
66 fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
67 fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
70 #else /* Support only documented FPU op-codes */
72 static FUNC const st_instr_table[64] = {
73 fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, __BAD__,
74 fmul__, fxch_i, __BAD__, __BAD__, fmul_i, __BAD__, fmulp_, __BAD__,
75 fcom_st, fp_nop, __BAD__, __BAD__, __BAD__, fst_i_, __BAD__, __BAD__,
76 fcompst, __BAD__, __BAD__, __BAD__, __BAD__, fstp_i, fcompp, __BAD__,
77 fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
78 fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
79 fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
80 fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
83 #endif /* NO_UNDOC_CODE */
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 */
98 /* Un-documented FPU op-codes supported by default. (see above) */
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_
111 #else /* Support only documented FPU op-codes */
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_
124 #endif /* NO_UNDOC_CODE */
126 #ifdef RE_ENTRANT_CHECKING
127 u_char emulating = 0;
128 #endif /* RE_ENTRANT_CHECKING */
130 static int valid_prefix(u_char *Byte, u_char __user ** fpu_eip,
131 overrides * override);
133 asmlinkage void math_emulate(long arg)
135 u_char FPU_modrm, byte1;
137 fpu_addr_modes addr_modes;
141 u_char loaded_tag, st0_tag;
142 void __user *data_address;
143 struct address data_sel_off;
144 struct address entry_sel_off;
145 unsigned long code_base = 0;
146 unsigned long code_limit = 0; /* Initialized to stop compiler warnings */
147 struct desc_struct code_descriptor;
149 #ifdef RE_ENTRANT_CHECKING
151 printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
154 #endif /* RE_ENTRANT_CHECKING */
161 SETUP_DATA_AREA(arg);
163 FPU_ORIG_EIP = FPU_EIP;
165 if ((FPU_EFLAGS & 0x00020000) != 0) {
166 /* Virtual 8086 mode */
167 addr_modes.default_mode = VM86;
168 FPU_EIP += code_base = FPU_CS << 4;
169 code_limit = code_base + 0xffff; /* Assumes code_base <= 0xffff0000 */
170 } else if (FPU_CS == __USER_CS && FPU_DS == __USER_DS) {
171 addr_modes.default_mode = 0;
172 } else if (FPU_CS == __KERNEL_CS) {
173 printk("math_emulate: %04x:%08lx\n", FPU_CS, FPU_EIP);
174 panic("Math emulation needed in kernel");
177 if ((FPU_CS & 4) != 4) { /* Must be in the LDT */
178 /* Can only handle segmented addressing via the LDT
179 for now, and it must be 16 bit */
180 printk("FPU emulator: Unsupported addressing mode\n");
181 math_abort(FPU_info, SIGILL);
184 code_descriptor = LDT_DESCRIPTOR(FPU_CS);
185 if (SEG_D_SIZE(code_descriptor)) {
186 /* The above test may be wrong, the book is not clear */
187 /* Segmented 32 bit protected mode */
188 addr_modes.default_mode = SEG32;
190 /* 16 bit protected mode */
191 addr_modes.default_mode = PM16;
193 FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor);
194 code_limit = code_base
195 + (SEG_LIMIT(code_descriptor) +
196 1) * SEG_GRANULARITY(code_descriptor)
198 if (code_limit < code_base)
199 code_limit = 0xffffffff;
202 FPU_lookahead = !(FPU_EFLAGS & X86_EFLAGS_TF);
204 if (!valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
205 &addr_modes.override)) {
206 RE_ENTRANT_CHECK_OFF;
208 ("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
209 "FPU emulator: self-modifying code! (emulation impossible)\n",
212 EXCEPTION(EX_INTERNAL | 0x126);
213 math_abort(FPU_info, SIGILL);
216 do_another_FPU_instruction:
220 FPU_EIP++; /* We have fetched the prefix and first code bytes. */
222 if (addr_modes.default_mode) {
223 /* This checks for the minimum instruction bytes.
224 We also need to check any extra (address mode) code access. */
225 if (FPU_EIP > code_limit)
226 math_abort(FPU_info, SIGSEGV);
229 if ((byte1 & 0xf8) != 0xd8) {
230 if (byte1 == FWAIT_OPCODE) {
231 if (partial_status & SW_Summary)
232 goto do_the_FPU_interrupt;
237 EXCEPTION(EX_INTERNAL | 0x128);
238 math_abort(FPU_info, SIGILL);
239 #endif /* PARANOID */
242 RE_ENTRANT_CHECK_OFF;
243 FPU_code_access_ok(1);
244 FPU_get_user(FPU_modrm, (u_char __user *) FPU_EIP);
248 if (partial_status & SW_Summary) {
249 /* Ignore the error for now if the current instruction is a no-wait
250 control instruction */
251 /* The 80486 manual contradicts itself on this topic,
252 but a real 80486 uses the following instructions:
253 fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
255 code = (FPU_modrm << 8) | byte1;
256 if (!((((code & 0xf803) == 0xe003) || /* fnclex, fninit, fnstsw */
257 (((code & 0x3003) == 0x3001) && /* fnsave, fnstcw, fnstenv,
259 ((code & 0xc000) != 0xc000))))) {
261 * We need to simulate the action of the kernel to FPU
264 do_the_FPU_interrupt:
266 FPU_EIP = FPU_ORIG_EIP; /* Point to current FPU instruction. */
268 RE_ENTRANT_CHECK_OFF;
269 current->thread.trap_no = 16;
270 current->thread.error_code = 0;
271 send_sig(SIGFPE, current, 1);
276 entry_sel_off.offset = FPU_ORIG_EIP;
277 entry_sel_off.selector = FPU_CS;
278 entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
280 FPU_rm = FPU_modrm & 7;
282 if (FPU_modrm < 0300) {
283 /* All of these instructions use the mod/rm byte to get a data address */
285 if ((addr_modes.default_mode & SIXTEEN)
286 ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX))
288 FPU_get_address_16(FPU_modrm, &FPU_EIP,
289 &data_sel_off, addr_modes);
292 FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
295 if (addr_modes.default_mode) {
296 if (FPU_EIP - 1 > code_limit)
297 math_abort(FPU_info, SIGSEGV);
301 unsigned short status1 = partial_status;
304 st0_tag = FPU_gettag0();
306 /* Stack underflow has priority */
308 if (addr_modes.default_mode & PROTECTED) {
309 /* This table works for 16 and 32 bit protected mode */
311 data_sizes_16[(byte1 >> 1) & 3])
312 math_abort(FPU_info, SIGSEGV);
315 unmasked = 0; /* Do this here to stop compiler warnings. */
316 switch ((byte1 >> 1) & 3) {
319 FPU_load_single((float __user *)
322 loaded_tag = unmasked & 0xff;
327 FPU_load_int32((long __user *)
333 FPU_load_double((double __user *)
336 loaded_tag = unmasked & 0xff;
340 default: /* Used here to suppress gcc warnings. */
342 FPU_load_int16((short __user *)
348 /* No more access to user memory, it is safe
349 to use static data now */
351 /* NaN operands have the next priority. */
352 /* We have to delay looking at st(0) until after
353 loading the data, because that data might contain an SNaN */
354 if (((st0_tag == TAG_Special) && isNaN(st0_ptr))
355 || ((loaded_tag == TAG_Special)
356 && isNaN(&loaded_data))) {
357 /* Restore the status word; we might have loaded a
359 partial_status = status1;
360 if ((FPU_modrm & 0x30) == 0x10) {
362 EXCEPTION(EX_Invalid);
363 setcc(SW_C3 | SW_C2 | SW_C0);
364 if ((FPU_modrm & 0x08)
367 FPU_pop(); /* fcomp, masked, so we pop. */
369 if (loaded_tag == TAG_Special)
374 /* This is not really needed, but gives behaviour
375 identical to an 80486 */
376 if ((FPU_modrm & 0x28) == 0x20)
383 #endif /* PECULIAR_486 */
384 /* fadd, fdivr, fmul, or fsubr */
390 goto reg_mem_instr_done;
393 if (unmasked && !((FPU_modrm & 0x30) == 0x10)) {
394 /* Is not a comparison instruction. */
395 if ((FPU_modrm & 0x38) == 0x38) {
397 if ((st0_tag == TAG_Zero) &&
398 ((loaded_tag == TAG_Valid)
404 if (FPU_divide_by_zero
409 /* We use the fact here that the unmasked
410 exception in the loaded data was for a
412 /* Restore the state of the denormal op bit */
426 goto reg_mem_instr_done;
429 switch ((FPU_modrm >> 3) & 7) {
432 FPU_add(&loaded_data, loaded_tag, 0,
437 FPU_mul(&loaded_data, loaded_tag, 0,
441 FPU_compare_st_data(&loaded_data,
445 if (!FPU_compare_st_data
446 (&loaded_data, loaded_tag)
452 FPU_sub(LOADED | loaded_tag,
458 FPU_sub(REV | LOADED | loaded_tag,
464 FPU_div(LOADED | loaded_tag,
470 if (st0_tag == TAG_Zero)
471 partial_status = status1; /* Undo any denorm tag,
472 zero-divide has priority. */
473 FPU_div(REV | LOADED | loaded_tag,
479 if ((FPU_modrm & 0x30) == 0x10) {
480 /* The instruction is fcom or fcomp */
481 EXCEPTION(EX_StackUnder);
482 setcc(SW_C3 | SW_C2 | SW_C0);
483 if ((FPU_modrm & 0x08)
484 && (control_word & CW_Invalid))
485 FPU_pop(); /* fcomp */
487 FPU_stack_underflow();
490 operand_address = data_sel_off;
493 FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6))
494 >> 1, addr_modes, data_address))) {
495 operand_address = data_sel_off;
500 /* None of these instructions access user memory */
501 u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
504 /* This is supposed to be undefined, but a real 80486 seems
506 operand_address.offset = 0;
507 operand_address.selector = FPU_DS;
508 #endif /* PECULIAR_486 */
511 st0_tag = FPU_gettag0();
512 switch (type_table[(int)instr_index]) {
513 case _NONE_: /* also _REGIc: _REGIn */
516 if (!NOT_EMPTY_ST0) {
517 FPU_stack_underflow();
518 goto FPU_instruction_done;
522 if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
523 FPU_stack_underflow_i(FPU_rm);
524 goto FPU_instruction_done;
528 if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
529 FPU_stack_underflow_pop(FPU_rm);
530 goto FPU_instruction_done;
534 if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
535 FPU_stack_underflow();
536 goto FPU_instruction_done;
539 case _PUSH_: /* Only used by the fld st(i) instruction */
543 goto FPU_instruction_done;
545 EXCEPTION(EX_INTERNAL | 0x111);
546 goto FPU_instruction_done;
548 (*st_instr_table[(int)instr_index]) ();
550 FPU_instruction_done:
555 instruction_address = entry_sel_off;
560 RE_ENTRANT_CHECK_OFF;
565 if (FPU_lookahead && !need_resched()) {
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;
572 if (addr_modes.default_mode)
573 FPU_EIP -= code_base;
575 RE_ENTRANT_CHECK_OFF;
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 __user **fpu_eip,
583 overrides * override)
586 u_char __user *ip = *fpu_eip;
588 *override = (overrides) {
589 0, 0, PREFIX_DEFAULT}; /* defaults */
591 RE_ENTRANT_CHECK_OFF;
592 FPU_code_access_ok(1);
593 FPU_get_user(byte, ip);
598 case ADDR_SIZE_PREFIX:
599 override->address_size = ADDR_SIZE_PREFIX;
603 override->operand_size = OP_SIZE_PREFIX;
607 override->segment = PREFIX_CS_;
610 override->segment = PREFIX_ES_;
613 override->segment = PREFIX_SS_;
616 override->segment = PREFIX_FS_;
619 override->segment = PREFIX_GS_;
622 override->segment = PREFIX_DS_;
625 /* lock is not a valid prefix for FPU instructions,
626 let the cpu handle it to generate a SIGILL. */
627 /* case PREFIX_LOCK: */
629 /* rep.. prefixes have no meaning for FPU instructions */
635 RE_ENTRANT_CHECK_OFF;
636 FPU_code_access_ok(1);
637 FPU_get_user(byte, ip);
644 if ((byte & 0xf8) == 0xd8) {
649 /* Not a valid sequence of prefix bytes followed by
650 an FPU instruction. */
651 *Byte = byte; /* Needed for error message. */
658 void math_abort(struct info *info, unsigned int signal)
660 FPU_EIP = FPU_ORIG_EIP;
661 current->thread.trap_no = 16;
662 current->thread.error_code = 0;
663 send_sig(signal, current, 1);
664 RE_ENTRANT_CHECK_OFF;
665 __asm__("movl %0,%%esp ; ret": :"g"(((long)info) - 4));
667 printk("ERROR: wm-FPU-emu math_abort failed!\n");
668 #endif /* PARANOID */
671 #define S387 ((struct i387_soft_struct *)s387)
672 #define sstatus_word() \
673 ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
675 int fpregs_soft_set(struct task_struct *target,
676 const struct user_regset *regset,
677 unsigned int pos, unsigned int count,
678 const void *kbuf, const void __user *ubuf)
680 struct i387_soft_struct *s387 = &target->thread.i387.soft;
681 void *space = s387->st_space;
683 int offset, other, i, tags, regnr, tag, newtop;
685 RE_ENTRANT_CHECK_OFF;
686 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, s387, 0,
687 offsetof(struct i387_soft_struct, st_space));
693 S387->ftop = (S387->swd >> SW_Top_Shift) & 7;
694 offset = (S387->ftop & 7) * 10;
697 RE_ENTRANT_CHECK_OFF;
699 /* Copy all registers in stack order. */
700 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
701 space + offset, 0, other);
703 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
708 /* The tags may need to be corrected now. */
711 for (i = 0; i < 8; i++) {
712 regnr = (i + newtop) & 7;
713 if (((tags >> ((regnr & 7) * 2)) & 3) != TAG_Empty) {
714 /* The loaded data over-rides all other cases. */
716 FPU_tagof((FPU_REG *) ((u_char *) S387->st_space +
718 tags &= ~(3 << (regnr * 2));
719 tags |= (tag & 3) << (regnr * 2);
727 int fpregs_soft_get(struct task_struct *target,
728 const struct user_regset *regset,
729 unsigned int pos, unsigned int count,
730 void *kbuf, void __user *ubuf)
732 struct i387_soft_struct *s387 = &target->thread.i387.soft;
733 const void *space = s387->st_space;
735 int offset = (S387->ftop & 7) * 10, other = 80 - offset;
737 RE_ENTRANT_CHECK_OFF;
740 S387->cwd &= ~0xe080;
741 /* An 80486 sets nearly all of the reserved bits to 1. */
742 S387->cwd |= 0xffff0040;
743 S387->swd = sstatus_word() | 0xffff0000;
744 S387->twd |= 0xffff0000;
745 S387->fcs &= ~0xf8000000;
746 S387->fos |= 0xffff0000;
747 #endif /* PECULIAR_486 */
749 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, s387, 0,
750 offsetof(struct i387_soft_struct, st_space));
752 /* Copy all registers in stack order. */
754 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
755 space + offset, 0, other);
757 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,