Import 2.3.12pre2
[davej-history.git] / arch / i386 / math-emu / fpu_entry.c
blob9e1484836f3aa3ddf9858cba11db797faa758ac7
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 +---------------------------------------------------------------------------*/
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 +---------------------------------------------------------------------------*/
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>
29 #include <asm/uaccess.h>
30 #include <asm/desc.h>
32 #include "fpu_system.h"
33 #include "fpu_emu.h"
34 #include "exception.h"
35 #include "control_w.h"
36 #include "status_w.h"
38 #define __BAD__ FPU_illegal /* Illegal on an 80486, causes SIGILL */
40 #ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by default. */
42 /* WARNING: These codes are not documented by Intel in their 80486 manual
43 and may not work on FPU clones or later Intel FPUs. */
45 /* Changes to support the un-doc codes provided by Linus Torvalds. */
47 #define _d9_d8_ fstp_i /* unofficial code (19) */
48 #define _dc_d0_ fcom_st /* unofficial code (14) */
49 #define _dc_d8_ fcompst /* unofficial code (1c) */
50 #define _dd_c8_ fxch_i /* unofficial code (0d) */
51 #define _de_d0_ fcompst /* unofficial code (16) */
52 #define _df_c0_ ffreep /* unofficial code (07) ffree + pop */
53 #define _df_c8_ fxch_i /* unofficial code (0f) */
54 #define _df_d0_ fstp_i /* unofficial code (17) */
55 #define _df_d8_ fstp_i /* unofficial code (1f) */
57 static FUNC const st_instr_table[64] = {
58 fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, _df_c0_,
59 fmul__, fxch_i, __BAD__, __BAD__, fmul_i, _dd_c8_, fmulp_, _df_c8_,
60 fcom_st, fp_nop, __BAD__, __BAD__, _dc_d0_, fst_i_, _de_d0_, _df_d0_,
61 fcompst, _d9_d8_, __BAD__, __BAD__, _dc_d8_, fstp_i, fcompp, _df_d8_,
62 fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
63 fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
64 fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
65 fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
68 #else /* Support only documented FPU op-codes */
70 static FUNC const st_instr_table[64] = {
71 fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, __BAD__,
72 fmul__, fxch_i, __BAD__, __BAD__, fmul_i, __BAD__, fmulp_, __BAD__,
73 fcom_st, fp_nop, __BAD__, __BAD__, __BAD__, fst_i_, __BAD__, __BAD__,
74 fcompst, __BAD__, __BAD__, __BAD__, __BAD__, fstp_i, fcompp, __BAD__,
75 fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
76 fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
77 fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
78 fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
81 #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 */
95 #ifndef NO_UNDOC_CODE
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
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 **fpu_eip,
131 overrides *override);
133 asmlinkage void math_emulate(long arg)
135 u_char FPU_modrm, byte1;
136 unsigned short code;
137 fpu_addr_modes addr_modes;
138 int unmasked;
139 FPU_REG loaded_data;
140 FPU_REG *st0_ptr;
141 u_char loaded_tag, st0_tag;
142 void *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
150 if ( emulating )
152 printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
154 RE_ENTRANT_CHECK_ON;
155 #endif RE_ENTRANT_CHECKING
157 if (!current->used_math)
159 finit();
160 current->used_math = 1;
163 SETUP_DATA_AREA(arg);
165 FPU_ORIG_EIP = FPU_EIP;
167 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 */
174 else if ( FPU_CS == __USER_CS && FPU_DS == __USER_DS )
176 addr_modes.default_mode = 0;
178 else if ( FPU_CS == __KERNEL_CS )
180 printk("math_emulate: %04x:%08lx\n",FPU_CS,FPU_EIP);
181 panic("Math emulation needed in kernel");
183 else
186 if ( (FPU_CS & 4) != 4 ) /* Must be in the LDT */
188 /* Can only handle segmented addressing via the LDT
189 for now, and it must be 16 bit */
190 printk("FPU emulator: Unsupported addressing mode\n");
191 math_abort(FPU_info, SIGILL);
194 if ( SEG_D_SIZE(code_descriptor = LDT_DESCRIPTOR(FPU_CS)) )
196 /* The above test may be wrong, the book is not clear */
197 /* Segmented 32 bit protected mode */
198 addr_modes.default_mode = SEG32;
200 else
202 /* 16 bit protected mode */
203 addr_modes.default_mode = PM16;
205 FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor);
206 code_limit = code_base
207 + (SEG_LIMIT(code_descriptor)+1) * SEG_GRANULARITY(code_descriptor)
208 - 1;
209 if ( code_limit < code_base ) code_limit = 0xffffffff;
212 FPU_lookahead = 1;
213 if (current->flags & PF_PTRACED)
214 FPU_lookahead = 0;
216 if ( !valid_prefix(&byte1, (u_char **)&FPU_EIP,
217 &addr_modes.override) )
219 RE_ENTRANT_CHECK_OFF;
220 printk("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
221 "FPU emulator: self-modifying code! (emulation impossible)\n",
222 byte1);
223 RE_ENTRANT_CHECK_ON;
224 EXCEPTION(EX_INTERNAL|0x126);
225 math_abort(FPU_info,SIGILL);
228 do_another_FPU_instruction:
230 no_ip_update = 0;
232 FPU_EIP++; /* We have fetched the prefix and first code bytes. */
234 if ( addr_modes.default_mode )
236 /* This checks for the minimum instruction bytes.
237 We also need to check any extra (address mode) code access. */
238 if ( FPU_EIP > code_limit )
239 math_abort(FPU_info,SIGSEGV);
242 if ( (byte1 & 0xf8) != 0xd8 )
244 if ( byte1 == FWAIT_OPCODE )
246 if (partial_status & SW_Summary)
247 goto do_the_FPU_interrupt;
248 else
249 goto FPU_fwait_done;
251 #ifdef PARANOID
252 EXCEPTION(EX_INTERNAL|0x128);
253 math_abort(FPU_info,SIGILL);
254 #endif PARANOID
257 RE_ENTRANT_CHECK_OFF;
258 FPU_code_verify_area(1);
259 FPU_get_user(FPU_modrm, (u_char *) FPU_EIP);
260 RE_ENTRANT_CHECK_ON;
261 FPU_EIP++;
263 if (partial_status & SW_Summary)
265 /* Ignore the error for now if the current instruction is a no-wait
266 control instruction */
267 /* The 80486 manual contradicts itself on this topic,
268 but a real 80486 uses the following instructions:
269 fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
271 code = (FPU_modrm << 8) | byte1;
272 if ( ! ( (((code & 0xf803) == 0xe003) || /* fnclex, fninit, fnstsw */
273 (((code & 0x3003) == 0x3001) && /* fnsave, fnstcw, fnstenv,
274 fnstsw */
275 ((code & 0xc000) != 0xc000))) ) )
278 * We need to simulate the action of the kernel to FPU
279 * interrupts here.
281 do_the_FPU_interrupt:
283 FPU_EIP = FPU_ORIG_EIP; /* Point to current FPU instruction. */
285 RE_ENTRANT_CHECK_OFF;
286 current->thread.trap_no = 16;
287 current->thread.error_code = 0;
288 send_sig(SIGFPE, current, 1);
289 return;
293 entry_sel_off.offset = FPU_ORIG_EIP;
294 entry_sel_off.selector = FPU_CS;
295 entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
297 FPU_rm = FPU_modrm & 7;
299 if ( FPU_modrm < 0300 )
301 /* All of these instructions use the mod/rm byte to get a data address */
303 if ( (addr_modes.default_mode & SIXTEEN)
304 ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX) )
305 data_address = FPU_get_address_16(FPU_modrm, &FPU_EIP, &data_sel_off,
306 addr_modes);
307 else
308 data_address = FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
309 addr_modes);
311 if ( addr_modes.default_mode )
313 if ( FPU_EIP-1 > code_limit )
314 math_abort(FPU_info,SIGSEGV);
317 if ( !(byte1 & 1) )
319 unsigned short status1 = partial_status;
321 st0_ptr = &st(0);
322 st0_tag = FPU_gettag0();
324 /* Stack underflow has priority */
325 if ( NOT_EMPTY_ST0 )
327 if ( addr_modes.default_mode & PROTECTED )
329 /* This table works for 16 and 32 bit protected mode */
330 if ( access_limit < data_sizes_16[(byte1 >> 1) & 3] )
331 math_abort(FPU_info,SIGSEGV);
334 unmasked = 0; /* Do this here to stop compiler warnings. */
335 switch ( (byte1 >> 1) & 3 )
337 case 0:
338 unmasked = FPU_load_single((float *)data_address,
339 &loaded_data);
340 loaded_tag = unmasked & 0xff;
341 unmasked &= ~0xff;
342 break;
343 case 1:
344 loaded_tag = FPU_load_int32((long *)data_address, &loaded_data);
345 break;
346 case 2:
347 unmasked = FPU_load_double((double *)data_address,
348 &loaded_data);
349 loaded_tag = unmasked & 0xff;
350 unmasked &= ~0xff;
351 break;
352 case 3:
353 default: /* Used here to suppress gcc warnings. */
354 loaded_tag = FPU_load_int16((short *)data_address, &loaded_data);
355 break;
358 /* No more access to user memory, it is safe
359 to use static data now */
361 /* NaN operands have the next priority. */
362 /* We have to delay looking at st(0) until after
363 loading the data, because that data might contain an SNaN */
364 if ( ((st0_tag == TAG_Special) && isNaN(st0_ptr)) ||
365 ((loaded_tag == TAG_Special) && isNaN(&loaded_data)) )
367 /* Restore the status word; we might have loaded a
368 denormal. */
369 partial_status = status1;
370 if ( (FPU_modrm & 0x30) == 0x10 )
372 /* fcom or fcomp */
373 EXCEPTION(EX_Invalid);
374 setcc(SW_C3 | SW_C2 | SW_C0);
375 if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
376 FPU_pop(); /* fcomp, masked, so we pop. */
378 else
380 if ( loaded_tag == TAG_Special )
381 loaded_tag = FPU_Special(&loaded_data);
382 #ifdef PECULIAR_486
383 /* This is not really needed, but gives behaviour
384 identical to an 80486 */
385 if ( (FPU_modrm & 0x28) == 0x20 )
386 /* fdiv or fsub */
387 real_2op_NaN(&loaded_data, loaded_tag, 0, &loaded_data);
388 else
389 #endif PECULIAR_486
390 /* fadd, fdivr, fmul, or fsubr */
391 real_2op_NaN(&loaded_data, loaded_tag, 0, st0_ptr);
393 goto reg_mem_instr_done;
396 if ( unmasked && !((FPU_modrm & 0x30) == 0x10) )
398 /* Is not a comparison instruction. */
399 if ( (FPU_modrm & 0x38) == 0x38 )
401 /* fdivr */
402 if ( (st0_tag == TAG_Zero) &&
403 ((loaded_tag == TAG_Valid)
404 || (loaded_tag == TAG_Special
405 && isdenormal(&loaded_data))) )
407 if ( FPU_divide_by_zero(0, getsign(&loaded_data))
408 < 0 )
410 /* We use the fact here that the unmasked
411 exception in the loaded data was for a
412 denormal operand */
413 /* Restore the state of the denormal op bit */
414 partial_status &= ~SW_Denorm_Op;
415 partial_status |= status1 & SW_Denorm_Op;
417 else
418 setsign(st0_ptr, getsign(&loaded_data));
421 goto reg_mem_instr_done;
424 switch ( (FPU_modrm >> 3) & 7 )
426 case 0: /* fadd */
427 clear_C1();
428 FPU_add(&loaded_data, loaded_tag, 0, control_word);
429 break;
430 case 1: /* fmul */
431 clear_C1();
432 FPU_mul(&loaded_data, loaded_tag, 0, control_word);
433 break;
434 case 2: /* fcom */
435 FPU_compare_st_data(&loaded_data, loaded_tag);
436 break;
437 case 3: /* fcomp */
438 if ( !FPU_compare_st_data(&loaded_data, loaded_tag)
439 && !unmasked )
440 FPU_pop();
441 break;
442 case 4: /* fsub */
443 clear_C1();
444 FPU_sub(LOADED|loaded_tag, (int)&loaded_data, control_word);
445 break;
446 case 5: /* fsubr */
447 clear_C1();
448 FPU_sub(REV|LOADED|loaded_tag, (int)&loaded_data, control_word);
449 break;
450 case 6: /* fdiv */
451 clear_C1();
452 FPU_div(LOADED|loaded_tag, (int)&loaded_data, control_word);
453 break;
454 case 7: /* fdivr */
455 clear_C1();
456 if ( st0_tag == TAG_Zero )
457 partial_status = status1; /* Undo any denorm tag,
458 zero-divide has priority. */
459 FPU_div(REV|LOADED|loaded_tag, (int)&loaded_data, control_word);
460 break;
463 else
465 if ( (FPU_modrm & 0x30) == 0x10 )
467 /* The instruction is fcom or fcomp */
468 EXCEPTION(EX_StackUnder);
469 setcc(SW_C3 | SW_C2 | SW_C0);
470 if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
471 FPU_pop(); /* fcomp */
473 else
474 FPU_stack_underflow();
476 reg_mem_instr_done:
477 operand_address = data_sel_off;
479 else
481 if ( !(no_ip_update =
482 FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6)) >> 1,
483 addr_modes, data_address)) )
485 operand_address = data_sel_off;
490 else
492 /* None of these instructions access user memory */
493 u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
495 #ifdef PECULIAR_486
496 /* This is supposed to be undefined, but a real 80486 seems
497 to do this: */
498 operand_address.offset = 0;
499 operand_address.selector = FPU_DS;
500 #endif PECULIAR_486
502 st0_ptr = &st(0);
503 st0_tag = FPU_gettag0();
504 switch ( type_table[(int) instr_index] )
506 case _NONE_: /* also _REGIc: _REGIn */
507 break;
508 case _REG0_:
509 if ( !NOT_EMPTY_ST0 )
511 FPU_stack_underflow();
512 goto FPU_instruction_done;
514 break;
515 case _REGIi:
516 if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
518 FPU_stack_underflow_i(FPU_rm);
519 goto FPU_instruction_done;
521 break;
522 case _REGIp:
523 if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
525 FPU_stack_underflow_pop(FPU_rm);
526 goto FPU_instruction_done;
528 break;
529 case _REGI_:
530 if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
532 FPU_stack_underflow();
533 goto FPU_instruction_done;
535 break;
536 case _PUSH_: /* Only used by the fld st(i) instruction */
537 break;
538 case _null_:
539 FPU_illegal();
540 goto FPU_instruction_done;
541 default:
542 EXCEPTION(EX_INTERNAL|0x111);
543 goto FPU_instruction_done;
545 (*st_instr_table[(int) instr_index])();
547 FPU_instruction_done:
551 if ( ! no_ip_update )
552 instruction_address = entry_sel_off;
554 FPU_fwait_done:
556 #ifdef DEBUG
557 RE_ENTRANT_CHECK_OFF;
558 FPU_printall();
559 RE_ENTRANT_CHECK_ON;
560 #endif DEBUG
562 if (FPU_lookahead && !current->need_resched)
564 FPU_ORIG_EIP = FPU_EIP - code_base;
565 if ( valid_prefix(&byte1, (u_char **)&FPU_EIP,
566 &addr_modes.override) )
567 goto do_another_FPU_instruction;
570 if ( addr_modes.default_mode )
571 FPU_EIP -= code_base;
573 RE_ENTRANT_CHECK_OFF;
577 /* Support for prefix bytes is not yet complete. To properly handle
578 all prefix bytes, further changes are needed in the emulator code
579 which accesses user address space. Access to separate segments is
580 important for msdos emulation. */
581 static int valid_prefix(u_char *Byte, u_char **fpu_eip,
582 overrides *override)
584 u_char byte;
585 u_char *ip = *fpu_eip;
587 *override = (overrides) { 0, 0, PREFIX_DEFAULT }; /* defaults */
589 RE_ENTRANT_CHECK_OFF;
590 FPU_code_verify_area(1);
591 FPU_get_user(byte, ip);
592 RE_ENTRANT_CHECK_ON;
594 while ( 1 )
596 switch ( byte )
598 case ADDR_SIZE_PREFIX:
599 override->address_size = ADDR_SIZE_PREFIX;
600 goto do_next_byte;
602 case OP_SIZE_PREFIX:
603 override->operand_size = OP_SIZE_PREFIX;
604 goto do_next_byte;
606 case PREFIX_CS:
607 override->segment = PREFIX_CS_;
608 goto do_next_byte;
609 case PREFIX_ES:
610 override->segment = PREFIX_ES_;
611 goto do_next_byte;
612 case PREFIX_SS:
613 override->segment = PREFIX_SS_;
614 goto do_next_byte;
615 case PREFIX_FS:
616 override->segment = PREFIX_FS_;
617 goto do_next_byte;
618 case PREFIX_GS:
619 override->segment = PREFIX_GS_;
620 goto do_next_byte;
621 case PREFIX_DS:
622 override->segment = PREFIX_DS_;
623 goto do_next_byte;
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 */
630 case PREFIX_REPE:
631 case PREFIX_REPNE:
633 do_next_byte:
634 ip++;
635 RE_ENTRANT_CHECK_OFF;
636 FPU_code_verify_area(1);
637 FPU_get_user(byte, ip);
638 RE_ENTRANT_CHECK_ON;
639 break;
640 case FWAIT_OPCODE:
641 *Byte = byte;
642 return 1;
643 default:
644 if ( (byte & 0xf8) == 0xd8 )
646 *Byte = byte;
647 *fpu_eip = ip;
648 return 1;
650 else
652 /* Not a valid sequence of prefix bytes followed by
653 an FPU instruction. */
654 *Byte = byte; /* Needed for error message. */
655 return 0;
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));
670 #ifdef PARANOID
671 printk("ERROR: wm-FPU-emu math_abort failed!\n");
672 #endif PARANOID
677 #define S387 ((struct i387_soft_struct *)s387)
678 #define sstatus_word() \
679 ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
681 int restore_i387_soft(void *s387, struct _fpstate *buf)
683 u_char *d = (u_char *)buf;
684 int offset, other, i, tags, regnr, tag, newtop;
686 RE_ENTRANT_CHECK_OFF;
687 FPU_verify_area(VERIFY_READ, d, 7*4 + 8*10);
688 if (__copy_from_user(&S387->cwd, d, 7*4))
689 return -1;
690 RE_ENTRANT_CHECK_ON;
692 d += 7*4;
694 S387->ftop = (S387->swd >> SW_Top_Shift) & 7;
695 offset = (S387->ftop & 7) * 10;
696 other = 80 - offset;
698 RE_ENTRANT_CHECK_OFF;
699 /* Copy all registers in stack order. */
700 if (__copy_from_user(((u_char *)&S387->st_space)+offset, d, other))
701 return -1;
702 if ( offset )
703 if (__copy_from_user((u_char *)&S387->st_space, d+other, offset))
704 return -1;
705 RE_ENTRANT_CHECK_ON;
707 /* The tags may need to be corrected now. */
708 tags = S387->twd;
709 newtop = S387->ftop;
710 for ( i = 0; i < 8; i++ )
712 regnr = (i+newtop) & 7;
713 if ( ((tags >> ((regnr & 7)*2)) & 3) != TAG_Empty )
715 /* The loaded data over-rides all other cases. */
716 tag = FPU_tagof((FPU_REG *)((u_char *)S387->st_space + 10*regnr));
717 tags &= ~(3 << (regnr*2));
718 tags |= (tag & 3) << (regnr*2);
721 S387->twd = tags;
723 return 0;
727 int save_i387_soft(void *s387, struct _fpstate * buf)
729 u_char *d = (u_char *)buf;
730 int offset = (S387->ftop & 7) * 10, other = 80 - offset;
732 RE_ENTRANT_CHECK_OFF;
733 FPU_verify_area(VERIFY_WRITE, d, 7*4 + 8*10);
734 #ifdef PECULIAR_486
735 S387->cwd &= ~0xe080;
736 /* An 80486 sets nearly all of the reserved bits to 1. */
737 S387->cwd |= 0xffff0040;
738 S387->swd = sstatus_word() | 0xffff0000;
739 S387->twd |= 0xffff0000;
740 S387->fcs &= ~0xf8000000;
741 S387->fos |= 0xffff0000;
742 #endif PECULIAR_486
743 __copy_to_user(d, &S387->cwd, 7*4);
744 RE_ENTRANT_CHECK_ON;
746 d += 7*4;
748 RE_ENTRANT_CHECK_OFF;
749 /* Copy all registers in stack order. */
750 if (__copy_to_user(d, ((u_char *)&S387->st_space)+offset, other))
751 return -1;
752 if ( offset )
753 if (__copy_to_user(d+other, (u_char *)&S387->st_space, offset))
754 return -1
755 RE_ENTRANT_CHECK_ON;
757 return 1;