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>
35 #include "fpu_system.h"
37 #include "exception.h"
38 #include "control_w.h"
41 #define __BAD__ FPU_illegal /* Illegal on an 80486, causes SIGILL */
43 #ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by default. */
45 /* WARNING: These codes are not documented by Intel in their 80486 manual
46 and may not work on FPU clones or later Intel FPUs. */
48 /* Changes to support the un-doc codes provided by Linus Torvalds. */
50 #define _d9_d8_ fstp_i /* unofficial code (19) */
51 #define _dc_d0_ fcom_st /* unofficial code (14) */
52 #define _dc_d8_ fcompst /* unofficial code (1c) */
53 #define _dd_c8_ fxch_i /* unofficial code (0d) */
54 #define _de_d0_ fcompst /* unofficial code (16) */
55 #define _df_c0_ ffreep /* unofficial code (07) ffree + pop */
56 #define _df_c8_ fxch_i /* unofficial code (0f) */
57 #define _df_d0_ fstp_i /* unofficial code (17) */
58 #define _df_d8_ fstp_i /* unofficial code (1f) */
60 static FUNC const st_instr_table[64] = {
61 fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, _df_c0_,
62 fmul__, fxch_i, __BAD__, __BAD__, fmul_i, _dd_c8_, fmulp_, _df_c8_,
63 fcom_st, fp_nop, __BAD__, __BAD__, _dc_d0_, fst_i_, _de_d0_, _df_d0_,
64 fcompst, _d9_d8_, __BAD__, __BAD__, _dc_d8_, fstp_i, fcompp, _df_d8_,
65 fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
66 fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
67 fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
68 fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
71 #else /* Support only documented FPU op-codes */
73 static FUNC const st_instr_table[64] = {
74 fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, __BAD__,
75 fmul__, fxch_i, __BAD__, __BAD__, fmul_i, __BAD__, fmulp_, __BAD__,
76 fcom_st, fp_nop, __BAD__, __BAD__, __BAD__, fst_i_, __BAD__, __BAD__,
77 fcompst, __BAD__, __BAD__, __BAD__, __BAD__, fstp_i, fcompp, __BAD__,
78 fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
79 fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
80 fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
81 fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
84 #endif /* NO_UNDOC_CODE */
86 #define _NONE_ 0 /* Take no special action */
87 #define _REG0_ 1 /* Need to check for not empty st(0) */
88 #define _REGI_ 2 /* Need to check for not empty st(0) and st(rm) */
89 #define _REGi_ 0 /* Uses st(rm) */
90 #define _PUSH_ 3 /* Need to check for space to push onto stack */
91 #define _null_ 4 /* Function illegal or not implemented */
92 #define _REGIi 5 /* Uses st(0) and st(rm), result to st(rm) */
93 #define _REGIp 6 /* Uses st(0) and st(rm), result to st(rm) then pop */
94 #define _REGIc 0 /* Compare st(0) and st(rm) */
95 #define _REGIn 0 /* Uses st(0) and st(rm), but handle checks later */
99 /* Un-documented FPU op-codes supported by default. (see above) */
101 static u_char const type_table[64] = {
102 _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _REGi_,
103 _REGI_, _REGIn, _null_, _null_, _REGIi, _REGI_, _REGIp, _REGI_,
104 _REGIc, _NONE_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
105 _REGIc, _REG0_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
106 _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
107 _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
108 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
109 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
112 #else /* Support only documented FPU op-codes */
114 static u_char const type_table[64] = {
115 _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _null_,
116 _REGI_, _REGIn, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
117 _REGIc, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_,
118 _REGIc, _null_, _null_, _null_, _null_, _REG0_, _REGIc, _null_,
119 _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
120 _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
121 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
122 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
125 #endif /* NO_UNDOC_CODE */
127 #ifdef RE_ENTRANT_CHECKING
128 u_char emulating = 0;
129 #endif /* RE_ENTRANT_CHECKING */
131 static int valid_prefix(u_char *Byte, u_char __user ** fpu_eip,
132 overrides * override);
134 asmlinkage void math_emulate(long arg)
136 u_char FPU_modrm, byte1;
138 fpu_addr_modes addr_modes;
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;
151 if (init_fpu(current)) {
152 do_group_exit(SIGKILL);
157 #ifdef RE_ENTRANT_CHECKING
159 printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
162 #endif /* RE_ENTRANT_CHECKING */
164 SETUP_DATA_AREA(arg);
166 FPU_ORIG_EIP = FPU_EIP;
168 if ((FPU_EFLAGS & 0x00020000) != 0) {
169 /* Virtual 8086 mode */
170 addr_modes.default_mode = VM86;
171 FPU_EIP += code_base = FPU_CS << 4;
172 code_limit = code_base + 0xffff; /* Assumes code_base <= 0xffff0000 */
173 } else if (FPU_CS == __USER_CS && FPU_DS == __USER_DS) {
174 addr_modes.default_mode = 0;
175 } else if (FPU_CS == __KERNEL_CS) {
176 printk("math_emulate: %04x:%08lx\n", FPU_CS, FPU_EIP);
177 panic("Math emulation needed in kernel");
180 if ((FPU_CS & 4) != 4) { /* Must be in the LDT */
181 /* Can only handle segmented addressing via the LDT
182 for now, and it must be 16 bit */
183 printk("FPU emulator: Unsupported addressing mode\n");
184 math_abort(FPU_info, SIGILL);
187 code_descriptor = LDT_DESCRIPTOR(FPU_CS);
188 if (SEG_D_SIZE(code_descriptor)) {
189 /* The above test may be wrong, the book is not clear */
190 /* Segmented 32 bit protected mode */
191 addr_modes.default_mode = SEG32;
193 /* 16 bit protected mode */
194 addr_modes.default_mode = PM16;
196 FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor);
197 code_limit = code_base
198 + (SEG_LIMIT(code_descriptor) +
199 1) * SEG_GRANULARITY(code_descriptor)
201 if (code_limit < code_base)
202 code_limit = 0xffffffff;
205 FPU_lookahead = !(FPU_EFLAGS & X86_EFLAGS_TF);
207 if (!valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
208 &addr_modes.override)) {
209 RE_ENTRANT_CHECK_OFF;
211 ("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
212 "FPU emulator: self-modifying code! (emulation impossible)\n",
215 EXCEPTION(EX_INTERNAL | 0x126);
216 math_abort(FPU_info, SIGILL);
219 do_another_FPU_instruction:
223 FPU_EIP++; /* We have fetched the prefix and first code bytes. */
225 if (addr_modes.default_mode) {
226 /* This checks for the minimum instruction bytes.
227 We also need to check any extra (address mode) code access. */
228 if (FPU_EIP > code_limit)
229 math_abort(FPU_info, SIGSEGV);
232 if ((byte1 & 0xf8) != 0xd8) {
233 if (byte1 == FWAIT_OPCODE) {
234 if (partial_status & SW_Summary)
235 goto do_the_FPU_interrupt;
240 EXCEPTION(EX_INTERNAL | 0x128);
241 math_abort(FPU_info, SIGILL);
242 #endif /* PARANOID */
245 RE_ENTRANT_CHECK_OFF;
246 FPU_code_access_ok(1);
247 FPU_get_user(FPU_modrm, (u_char __user *) FPU_EIP);
251 if (partial_status & SW_Summary) {
252 /* Ignore the error for now if the current instruction is a no-wait
253 control instruction */
254 /* The 80486 manual contradicts itself on this topic,
255 but a real 80486 uses the following instructions:
256 fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
258 code = (FPU_modrm << 8) | byte1;
259 if (!((((code & 0xf803) == 0xe003) || /* fnclex, fninit, fnstsw */
260 (((code & 0x3003) == 0x3001) && /* fnsave, fnstcw, fnstenv,
262 ((code & 0xc000) != 0xc000))))) {
264 * We need to simulate the action of the kernel to FPU
267 do_the_FPU_interrupt:
269 FPU_EIP = FPU_ORIG_EIP; /* Point to current FPU instruction. */
271 RE_ENTRANT_CHECK_OFF;
272 current->thread.trap_no = 16;
273 current->thread.error_code = 0;
274 send_sig(SIGFPE, current, 1);
279 entry_sel_off.offset = FPU_ORIG_EIP;
280 entry_sel_off.selector = FPU_CS;
281 entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
282 entry_sel_off.empty = 0;
284 FPU_rm = FPU_modrm & 7;
286 if (FPU_modrm < 0300) {
287 /* All of these instructions use the mod/rm byte to get a data address */
289 if ((addr_modes.default_mode & SIXTEEN)
290 ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX))
292 FPU_get_address_16(FPU_modrm, &FPU_EIP,
293 &data_sel_off, addr_modes);
296 FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
299 if (addr_modes.default_mode) {
300 if (FPU_EIP - 1 > code_limit)
301 math_abort(FPU_info, SIGSEGV);
305 unsigned short status1 = partial_status;
308 st0_tag = FPU_gettag0();
310 /* Stack underflow has priority */
312 if (addr_modes.default_mode & PROTECTED) {
313 /* This table works for 16 and 32 bit protected mode */
315 data_sizes_16[(byte1 >> 1) & 3])
316 math_abort(FPU_info, SIGSEGV);
319 unmasked = 0; /* Do this here to stop compiler warnings. */
320 switch ((byte1 >> 1) & 3) {
323 FPU_load_single((float __user *)
326 loaded_tag = unmasked & 0xff;
331 FPU_load_int32((long __user *)
337 FPU_load_double((double __user *)
340 loaded_tag = unmasked & 0xff;
344 default: /* Used here to suppress gcc warnings. */
346 FPU_load_int16((short __user *)
352 /* No more access to user memory, it is safe
353 to use static data now */
355 /* NaN operands have the next priority. */
356 /* We have to delay looking at st(0) until after
357 loading the data, because that data might contain an SNaN */
358 if (((st0_tag == TAG_Special) && isNaN(st0_ptr))
359 || ((loaded_tag == TAG_Special)
360 && isNaN(&loaded_data))) {
361 /* Restore the status word; we might have loaded a
363 partial_status = status1;
364 if ((FPU_modrm & 0x30) == 0x10) {
366 EXCEPTION(EX_Invalid);
367 setcc(SW_C3 | SW_C2 | SW_C0);
368 if ((FPU_modrm & 0x08)
371 FPU_pop(); /* fcomp, masked, so we pop. */
373 if (loaded_tag == TAG_Special)
378 /* This is not really needed, but gives behaviour
379 identical to an 80486 */
380 if ((FPU_modrm & 0x28) == 0x20)
387 #endif /* PECULIAR_486 */
388 /* fadd, fdivr, fmul, or fsubr */
394 goto reg_mem_instr_done;
397 if (unmasked && !((FPU_modrm & 0x30) == 0x10)) {
398 /* Is not a comparison instruction. */
399 if ((FPU_modrm & 0x38) == 0x38) {
401 if ((st0_tag == TAG_Zero) &&
402 ((loaded_tag == TAG_Valid)
408 if (FPU_divide_by_zero
413 /* We use the fact here that the unmasked
414 exception in the loaded data was for a
416 /* Restore the state of the denormal op bit */
430 goto reg_mem_instr_done;
433 switch ((FPU_modrm >> 3) & 7) {
436 FPU_add(&loaded_data, loaded_tag, 0,
441 FPU_mul(&loaded_data, loaded_tag, 0,
445 FPU_compare_st_data(&loaded_data,
449 if (!FPU_compare_st_data
450 (&loaded_data, loaded_tag)
456 FPU_sub(LOADED | loaded_tag,
462 FPU_sub(REV | LOADED | loaded_tag,
468 FPU_div(LOADED | loaded_tag,
474 if (st0_tag == TAG_Zero)
475 partial_status = status1; /* Undo any denorm tag,
476 zero-divide has priority. */
477 FPU_div(REV | LOADED | loaded_tag,
483 if ((FPU_modrm & 0x30) == 0x10) {
484 /* The instruction is fcom or fcomp */
485 EXCEPTION(EX_StackUnder);
486 setcc(SW_C3 | SW_C2 | SW_C0);
487 if ((FPU_modrm & 0x08)
488 && (control_word & CW_Invalid))
489 FPU_pop(); /* fcomp */
491 FPU_stack_underflow();
494 operand_address = data_sel_off;
497 FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6))
498 >> 1, addr_modes, data_address))) {
499 operand_address = data_sel_off;
504 /* None of these instructions access user memory */
505 u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
508 /* This is supposed to be undefined, but a real 80486 seems
510 operand_address.offset = 0;
511 operand_address.selector = FPU_DS;
512 #endif /* PECULIAR_486 */
515 st0_tag = FPU_gettag0();
516 switch (type_table[(int)instr_index]) {
517 case _NONE_: /* also _REGIc: _REGIn */
520 if (!NOT_EMPTY_ST0) {
521 FPU_stack_underflow();
522 goto FPU_instruction_done;
526 if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
527 FPU_stack_underflow_i(FPU_rm);
528 goto FPU_instruction_done;
532 if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
533 FPU_stack_underflow_pop(FPU_rm);
534 goto FPU_instruction_done;
538 if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
539 FPU_stack_underflow();
540 goto FPU_instruction_done;
543 case _PUSH_: /* Only used by the fld st(i) instruction */
547 goto FPU_instruction_done;
549 EXCEPTION(EX_INTERNAL | 0x111);
550 goto FPU_instruction_done;
552 (*st_instr_table[(int)instr_index]) ();
554 FPU_instruction_done:
559 instruction_address = entry_sel_off;
564 RE_ENTRANT_CHECK_OFF;
569 if (FPU_lookahead && !need_resched()) {
570 FPU_ORIG_EIP = FPU_EIP - code_base;
571 if (valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
572 &addr_modes.override))
573 goto do_another_FPU_instruction;
576 if (addr_modes.default_mode)
577 FPU_EIP -= code_base;
579 RE_ENTRANT_CHECK_OFF;
582 /* Support for prefix bytes is not yet complete. To properly handle
583 all prefix bytes, further changes are needed in the emulator code
584 which accesses user address space. Access to separate segments is
585 important for msdos emulation. */
586 static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
587 overrides * override)
590 u_char __user *ip = *fpu_eip;
592 *override = (overrides) {
593 0, 0, PREFIX_DEFAULT}; /* defaults */
595 RE_ENTRANT_CHECK_OFF;
596 FPU_code_access_ok(1);
597 FPU_get_user(byte, ip);
602 case ADDR_SIZE_PREFIX:
603 override->address_size = ADDR_SIZE_PREFIX;
607 override->operand_size = OP_SIZE_PREFIX;
611 override->segment = PREFIX_CS_;
614 override->segment = PREFIX_ES_;
617 override->segment = PREFIX_SS_;
620 override->segment = PREFIX_FS_;
623 override->segment = PREFIX_GS_;
626 override->segment = PREFIX_DS_;
629 /* lock is not a valid prefix for FPU instructions,
630 let the cpu handle it to generate a SIGILL. */
631 /* case PREFIX_LOCK: */
633 /* rep.. prefixes have no meaning for FPU instructions */
639 RE_ENTRANT_CHECK_OFF;
640 FPU_code_access_ok(1);
641 FPU_get_user(byte, ip);
648 if ((byte & 0xf8) == 0xd8) {
653 /* Not a valid sequence of prefix bytes followed by
654 an FPU instruction. */
655 *Byte = byte; /* Needed for error message. */
662 void math_abort(struct info *info, unsigned int signal)
664 FPU_EIP = FPU_ORIG_EIP;
665 current->thread.trap_no = 16;
666 current->thread.error_code = 0;
667 send_sig(signal, current, 1);
668 RE_ENTRANT_CHECK_OFF;
669 __asm__("movl %0,%%esp ; ret": :"g"(((long)info) - 4));
671 printk("ERROR: wm-FPU-emu math_abort failed!\n");
672 #endif /* PARANOID */
675 #define S387 ((struct i387_soft_struct *)s387)
676 #define sstatus_word() \
677 ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
679 int fpregs_soft_set(struct task_struct *target,
680 const struct user_regset *regset,
681 unsigned int pos, unsigned int count,
682 const void *kbuf, const void __user *ubuf)
684 struct i387_soft_struct *s387 = &target->thread.xstate->soft;
685 void *space = s387->st_space;
687 int offset, other, i, tags, regnr, tag, newtop;
689 RE_ENTRANT_CHECK_OFF;
690 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, s387, 0,
691 offsetof(struct i387_soft_struct, st_space));
697 S387->ftop = (S387->swd >> SW_Top_Shift) & 7;
698 offset = (S387->ftop & 7) * 10;
701 RE_ENTRANT_CHECK_OFF;
703 /* Copy all registers in stack order. */
704 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
705 space + offset, 0, other);
707 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
712 /* The tags may need to be corrected now. */
715 for (i = 0; i < 8; i++) {
716 regnr = (i + newtop) & 7;
717 if (((tags >> ((regnr & 7) * 2)) & 3) != TAG_Empty) {
718 /* The loaded data over-rides all other cases. */
720 FPU_tagof((FPU_REG *) ((u_char *) S387->st_space +
722 tags &= ~(3 << (regnr * 2));
723 tags |= (tag & 3) << (regnr * 2);
731 int fpregs_soft_get(struct task_struct *target,
732 const struct user_regset *regset,
733 unsigned int pos, unsigned int count,
734 void *kbuf, void __user *ubuf)
736 struct i387_soft_struct *s387 = &target->thread.xstate->soft;
737 const void *space = s387->st_space;
739 int offset = (S387->ftop & 7) * 10, other = 80 - offset;
741 RE_ENTRANT_CHECK_OFF;
744 S387->cwd &= ~0xe080;
745 /* An 80486 sets nearly all of the reserved bits to 1. */
746 S387->cwd |= 0xffff0040;
747 S387->swd = sstatus_word() | 0xffff0000;
748 S387->twd |= 0xffff0000;
749 S387->fcs &= ~0xf8000000;
750 S387->fos |= 0xffff0000;
751 #endif /* PECULIAR_486 */
753 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, s387, 0,
754 offsetof(struct i387_soft_struct, st_space));
756 /* Copy all registers in stack order. */
758 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
759 space + offset, 0, other);
761 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,