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/ptrace.h>
30 #include <asm/uaccess.h>
33 #include "fpu_system.h"
35 #include "exception.h"
36 #include "control_w.h"
39 #define __BAD__ FPU_illegal /* Illegal on an 80486, causes SIGILL */
41 #ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by default. */
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. */
46 /* Changes to support the un-doc codes provided by Linus Torvalds. */
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) */
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__,
69 #else /* Support only documented FPU op-codes */
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__,
82 #endif /* NO_UNDOC_CODE */
84 #define _NONE_ 0 /* Take no special action */
85 #define _REG0_ 1 /* Need to check for not empty st(0) */
86 #define _REGI_ 2 /* Need to check for not empty st(0) and st(rm) */
87 #define _REGi_ 0 /* Uses st(rm) */
88 #define _PUSH_ 3 /* Need to check for space to push onto stack */
89 #define _null_ 4 /* Function illegal or not implemented */
90 #define _REGIi 5 /* Uses st(0) and st(rm), result to st(rm) */
91 #define _REGIp 6 /* Uses st(0) and st(rm), result to st(rm) then pop */
92 #define _REGIc 0 /* Compare st(0) and st(rm) */
93 #define _REGIn 0 /* Uses st(0) and st(rm), but handle checks later */
97 /* Un-documented FPU op-codes supported by default. (see above) */
99 static u_char const type_table[64] = {
100 _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _REGi_,
101 _REGI_, _REGIn, _null_, _null_, _REGIi, _REGI_, _REGIp, _REGI_,
102 _REGIc, _NONE_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
103 _REGIc, _REG0_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
104 _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
105 _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
106 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
107 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
110 #else /* Support only documented FPU op-codes */
112 static u_char const type_table[64] = {
113 _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _null_,
114 _REGI_, _REGIn, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
115 _REGIc, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_,
116 _REGIc, _null_, _null_, _null_, _null_, _REG0_, _REGIc, _null_,
117 _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
118 _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
119 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
120 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
123 #endif /* NO_UNDOC_CODE */
125 #ifdef RE_ENTRANT_CHECKING
126 u_char emulating = 0;
127 #endif /* RE_ENTRANT_CHECKING */
129 static int valid_prefix(u_char * Byte, u_char __user ** fpu_eip,
130 overrides * override);
132 asmlinkage void math_emulate(long arg)
134 u_char FPU_modrm, byte1;
136 fpu_addr_modes addr_modes;
140 u_char loaded_tag, st0_tag;
141 void __user *data_address;
142 struct address data_sel_off;
143 struct address entry_sel_off;
144 unsigned long code_base = 0;
145 unsigned long code_limit = 0; /* Initialized to stop compiler warnings */
146 struct desc_struct code_descriptor;
148 #ifdef RE_ENTRANT_CHECKING
150 printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
153 #endif /* RE_ENTRANT_CHECKING */
160 SETUP_DATA_AREA(arg);
162 FPU_ORIG_EIP = FPU_EIP;
164 if ((FPU_EFLAGS & 0x00020000) != 0) {
165 /* Virtual 8086 mode */
166 addr_modes.default_mode = VM86;
167 FPU_EIP += code_base = FPU_CS << 4;
168 code_limit = code_base + 0xffff; /* Assumes code_base <= 0xffff0000 */
169 } else if (FPU_CS == __USER_CS && FPU_DS == __USER_DS) {
170 addr_modes.default_mode = 0;
171 } else if (FPU_CS == __KERNEL_CS) {
172 printk("math_emulate: %04x:%08lx\n", FPU_CS, FPU_EIP);
173 panic("Math emulation needed in kernel");
176 if ((FPU_CS & 4) != 4) { /* Must be in the LDT */
177 /* Can only handle segmented addressing via the LDT
178 for now, and it must be 16 bit */
179 printk("FPU emulator: Unsupported addressing mode\n");
180 math_abort(FPU_info, SIGILL);
183 code_descriptor = LDT_DESCRIPTOR(FPU_CS);
184 if (SEG_D_SIZE(code_descriptor)) {
185 /* The above test may be wrong, the book is not clear */
186 /* Segmented 32 bit protected mode */
187 addr_modes.default_mode = SEG32;
189 /* 16 bit protected mode */
190 addr_modes.default_mode = PM16;
192 FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor);
193 code_limit = code_base
194 + (SEG_LIMIT(code_descriptor) +
195 1) * SEG_GRANULARITY(code_descriptor)
197 if (code_limit < code_base)
198 code_limit = 0xffffffff;
202 if (current->ptrace & PT_PTRACED)
205 if (!valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
206 &addr_modes.override)) {
207 RE_ENTRANT_CHECK_OFF;
209 ("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
210 "FPU emulator: self-modifying code! (emulation impossible)\n",
213 EXCEPTION(EX_INTERNAL | 0x126);
214 math_abort(FPU_info, SIGILL);
217 do_another_FPU_instruction:
221 FPU_EIP++; /* We have fetched the prefix and first code bytes. */
223 if (addr_modes.default_mode) {
224 /* This checks for the minimum instruction bytes.
225 We also need to check any extra (address mode) code access. */
226 if (FPU_EIP > code_limit)
227 math_abort(FPU_info, SIGSEGV);
230 if ((byte1 & 0xf8) != 0xd8) {
231 if (byte1 == FWAIT_OPCODE) {
232 if (partial_status & SW_Summary)
233 goto do_the_FPU_interrupt;
238 EXCEPTION(EX_INTERNAL | 0x128);
239 math_abort(FPU_info, SIGILL);
240 #endif /* PARANOID */
243 RE_ENTRANT_CHECK_OFF;
244 FPU_code_access_ok(1);
245 FPU_get_user(FPU_modrm, (u_char __user *) FPU_EIP);
249 if (partial_status & SW_Summary) {
250 /* Ignore the error for now if the current instruction is a no-wait
251 control instruction */
252 /* The 80486 manual contradicts itself on this topic,
253 but a real 80486 uses the following instructions:
254 fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
256 code = (FPU_modrm << 8) | byte1;
257 if (!((((code & 0xf803) == 0xe003) || /* fnclex, fninit, fnstsw */
258 (((code & 0x3003) == 0x3001) && /* fnsave, fnstcw, fnstenv,
260 ((code & 0xc000) != 0xc000))))) {
262 * We need to simulate the action of the kernel to FPU
265 do_the_FPU_interrupt:
267 FPU_EIP = FPU_ORIG_EIP; /* Point to current FPU instruction. */
269 RE_ENTRANT_CHECK_OFF;
270 current->thread.trap_no = 16;
271 current->thread.error_code = 0;
272 send_sig(SIGFPE, current, 1);
277 entry_sel_off.offset = FPU_ORIG_EIP;
278 entry_sel_off.selector = FPU_CS;
279 entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
281 FPU_rm = FPU_modrm & 7;
283 if (FPU_modrm < 0300) {
284 /* All of these instructions use the mod/rm byte to get a data address */
286 if ((addr_modes.default_mode & SIXTEEN)
287 ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX))
289 FPU_get_address_16(FPU_modrm, &FPU_EIP,
290 &data_sel_off, addr_modes);
293 FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
296 if (addr_modes.default_mode) {
297 if (FPU_EIP - 1 > code_limit)
298 math_abort(FPU_info, SIGSEGV);
302 unsigned short status1 = partial_status;
305 st0_tag = FPU_gettag0();
307 /* Stack underflow has priority */
309 if (addr_modes.default_mode & PROTECTED) {
310 /* This table works for 16 and 32 bit protected mode */
312 data_sizes_16[(byte1 >> 1) & 3])
313 math_abort(FPU_info, SIGSEGV);
316 unmasked = 0; /* Do this here to stop compiler warnings. */
317 switch ((byte1 >> 1) & 3) {
320 FPU_load_single((float __user *)
323 loaded_tag = unmasked & 0xff;
328 FPU_load_int32((long __user *)
334 FPU_load_double((double __user *)
337 loaded_tag = unmasked & 0xff;
341 default: /* Used here to suppress gcc warnings. */
343 FPU_load_int16((short __user *)
349 /* No more access to user memory, it is safe
350 to use static data now */
352 /* NaN operands have the next priority. */
353 /* We have to delay looking at st(0) until after
354 loading the data, because that data might contain an SNaN */
355 if (((st0_tag == TAG_Special) && isNaN(st0_ptr))
356 || ((loaded_tag == TAG_Special)
357 && isNaN(&loaded_data))) {
358 /* Restore the status word; we might have loaded a
360 partial_status = status1;
361 if ((FPU_modrm & 0x30) == 0x10) {
363 EXCEPTION(EX_Invalid);
364 setcc(SW_C3 | SW_C2 | SW_C0);
365 if ((FPU_modrm & 0x08)
368 FPU_pop(); /* fcomp, masked, so we pop. */
370 if (loaded_tag == TAG_Special)
375 /* This is not really needed, but gives behaviour
376 identical to an 80486 */
377 if ((FPU_modrm & 0x28) == 0x20)
384 #endif /* PECULIAR_486 */
385 /* fadd, fdivr, fmul, or fsubr */
391 goto reg_mem_instr_done;
394 if (unmasked && !((FPU_modrm & 0x30) == 0x10)) {
395 /* Is not a comparison instruction. */
396 if ((FPU_modrm & 0x38) == 0x38) {
398 if ((st0_tag == TAG_Zero) &&
399 ((loaded_tag == TAG_Valid)
405 if (FPU_divide_by_zero
410 /* We use the fact here that the unmasked
411 exception in the loaded data was for a
413 /* Restore the state of the denormal op bit */
427 goto reg_mem_instr_done;
430 switch ((FPU_modrm >> 3) & 7) {
433 FPU_add(&loaded_data, loaded_tag, 0,
438 FPU_mul(&loaded_data, loaded_tag, 0,
442 FPU_compare_st_data(&loaded_data,
446 if (!FPU_compare_st_data
447 (&loaded_data, loaded_tag)
453 FPU_sub(LOADED | loaded_tag,
459 FPU_sub(REV | LOADED | loaded_tag,
465 FPU_div(LOADED | loaded_tag,
471 if (st0_tag == TAG_Zero)
472 partial_status = status1; /* Undo any denorm tag,
473 zero-divide has priority. */
474 FPU_div(REV | LOADED | loaded_tag,
480 if ((FPU_modrm & 0x30) == 0x10) {
481 /* The instruction is fcom or fcomp */
482 EXCEPTION(EX_StackUnder);
483 setcc(SW_C3 | SW_C2 | SW_C0);
484 if ((FPU_modrm & 0x08)
485 && (control_word & CW_Invalid))
486 FPU_pop(); /* fcomp */
488 FPU_stack_underflow();
491 operand_address = data_sel_off;
494 FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6))
495 >> 1, addr_modes, data_address))) {
496 operand_address = data_sel_off;
501 /* None of these instructions access user memory */
502 u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
505 /* This is supposed to be undefined, but a real 80486 seems
507 operand_address.offset = 0;
508 operand_address.selector = FPU_DS;
509 #endif /* PECULIAR_486 */
512 st0_tag = FPU_gettag0();
513 switch (type_table[(int)instr_index]) {
514 case _NONE_: /* also _REGIc: _REGIn */
517 if (!NOT_EMPTY_ST0) {
518 FPU_stack_underflow();
519 goto FPU_instruction_done;
523 if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
524 FPU_stack_underflow_i(FPU_rm);
525 goto FPU_instruction_done;
529 if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
530 FPU_stack_underflow_pop(FPU_rm);
531 goto FPU_instruction_done;
535 if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
536 FPU_stack_underflow();
537 goto FPU_instruction_done;
540 case _PUSH_: /* Only used by the fld st(i) instruction */
544 goto FPU_instruction_done;
546 EXCEPTION(EX_INTERNAL | 0x111);
547 goto FPU_instruction_done;
549 (*st_instr_table[(int)instr_index]) ();
551 FPU_instruction_done:
556 instruction_address = entry_sel_off;
561 RE_ENTRANT_CHECK_OFF;
566 if (FPU_lookahead && !need_resched()) {
567 FPU_ORIG_EIP = FPU_EIP - code_base;
568 if (valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
569 &addr_modes.override))
570 goto do_another_FPU_instruction;
573 if (addr_modes.default_mode)
574 FPU_EIP -= code_base;
576 RE_ENTRANT_CHECK_OFF;
579 /* Support for prefix bytes is not yet complete. To properly handle
580 all prefix bytes, further changes are needed in the emulator code
581 which accesses user address space. Access to separate segments is
582 important for msdos emulation. */
583 static int valid_prefix(u_char * Byte, u_char __user ** fpu_eip,
584 overrides * override)
587 u_char __user *ip = *fpu_eip;
589 *override = (overrides) {
590 0, 0, PREFIX_DEFAULT}; /* defaults */
592 RE_ENTRANT_CHECK_OFF;
593 FPU_code_access_ok(1);
594 FPU_get_user(byte, ip);
599 case ADDR_SIZE_PREFIX:
600 override->address_size = ADDR_SIZE_PREFIX;
604 override->operand_size = OP_SIZE_PREFIX;
608 override->segment = PREFIX_CS_;
611 override->segment = PREFIX_ES_;
614 override->segment = PREFIX_SS_;
617 override->segment = PREFIX_FS_;
620 override->segment = PREFIX_GS_;
623 override->segment = PREFIX_DS_;
626 /* lock is not a valid prefix for FPU instructions,
627 let the cpu handle it to generate a SIGILL. */
628 /* case PREFIX_LOCK: */
630 /* rep.. prefixes have no meaning for FPU instructions */
636 RE_ENTRANT_CHECK_OFF;
637 FPU_code_access_ok(1);
638 FPU_get_user(byte, ip);
645 if ((byte & 0xf8) == 0xd8) {
650 /* Not a valid sequence of prefix bytes followed by
651 an FPU instruction. */
652 *Byte = byte; /* Needed for error message. */
659 void math_abort(struct info *info, unsigned int signal)
661 FPU_EIP = FPU_ORIG_EIP;
662 current->thread.trap_no = 16;
663 current->thread.error_code = 0;
664 send_sig(signal, current, 1);
665 RE_ENTRANT_CHECK_OFF;
666 __asm__("movl %0,%%esp ; ret": :"g"(((long)info) - 4));
668 printk("ERROR: wm-FPU-emu math_abort failed!\n");
669 #endif /* PARANOID */
672 #define S387 ((struct i387_soft_struct *)s387)
673 #define sstatus_word() \
674 ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
676 int restore_i387_soft(void *s387, struct _fpstate __user * buf)
678 u_char __user *d = (u_char __user *) buf;
679 int offset, other, i, tags, regnr, tag, newtop;
681 RE_ENTRANT_CHECK_OFF;
682 FPU_access_ok(VERIFY_READ, d, 7 * 4 + 8 * 10);
683 if (__copy_from_user(&S387->cwd, d, 7 * 4))
689 S387->ftop = (S387->swd >> SW_Top_Shift) & 7;
690 offset = (S387->ftop & 7) * 10;
693 RE_ENTRANT_CHECK_OFF;
694 /* Copy all registers in stack order. */
695 if (__copy_from_user(((u_char *) & S387->st_space) + offset, d, other))
699 ((u_char *) & S387->st_space, d + other, offset))
703 /* The tags may need to be corrected now. */
706 for (i = 0; i < 8; i++) {
707 regnr = (i + newtop) & 7;
708 if (((tags >> ((regnr & 7) * 2)) & 3) != TAG_Empty) {
709 /* The loaded data over-rides all other cases. */
711 FPU_tagof((FPU_REG *) ((u_char *) S387->st_space +
713 tags &= ~(3 << (regnr * 2));
714 tags |= (tag & 3) << (regnr * 2);
722 int save_i387_soft(void *s387, struct _fpstate __user * buf)
724 u_char __user *d = (u_char __user *) buf;
725 int offset = (S387->ftop & 7) * 10, other = 80 - offset;
727 RE_ENTRANT_CHECK_OFF;
728 FPU_access_ok(VERIFY_WRITE, d, 7 * 4 + 8 * 10);
730 S387->cwd &= ~0xe080;
731 /* An 80486 sets nearly all of the reserved bits to 1. */
732 S387->cwd |= 0xffff0040;
733 S387->swd = sstatus_word() | 0xffff0000;
734 S387->twd |= 0xffff0000;
735 S387->fcs &= ~0xf8000000;
736 S387->fos |= 0xffff0000;
737 #endif /* PECULIAR_486 */
738 if (__copy_to_user(d, &S387->cwd, 7 * 4))
744 RE_ENTRANT_CHECK_OFF;
745 /* Copy all registers in stack order. */
746 if (__copy_to_user(d, ((u_char *) & S387->st_space) + offset, other))
750 (d + other, (u_char *) & S387->st_space, offset))