27 #include <linux/signal.h>
30 #include <asm/uaccess.h>
31 #include <asm/traps.h>
42 #define __BAD__ FPU_illegal
51 #define _d9_d8_ fstp_i
52 #define _dc_d0_ fcom_st
53 #define _dc_d8_ fcompst
54 #define _dd_c8_ fxch_i
55 #define _de_d0_ fcompst
56 #define _df_c0_ ffreep
57 #define _df_c8_ fxch_i
58 #define _df_d0_ fstp_i
59 #define _df_d8_ fstp_i
61 static FUNC const st_instr_table[64] = {
74 static FUNC const st_instr_table[64] = {
102 static u_char const type_table[64] = {
115 static u_char const type_table[64] = {
128 #ifdef RE_ENTRANT_CHECKING
143 u_char loaded_tag, st0_tag;
147 unsigned long code_base = 0;
148 unsigned long code_limit = 0;
158 #ifdef RE_ENTRANT_CHECKING
160 printk(
"ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
173 code_limit = code_base + 0xffff;
178 panic(
"Math emulation needed in kernel");
184 printk(
"FPU emulator: Unsupported addressing mode\n");
198 code_limit = code_base
202 if (code_limit < code_base)
203 code_limit = 0xffffffff;
212 (
"FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
213 "FPU emulator: self-modifying code! (emulation impossible)\n",
220 do_another_FPU_instruction:
233 if ((byte1 & 0xf8) != 0xd8) {
236 goto do_the_FPU_interrupt;
259 code = (FPU_modrm << 8) | byte1;
260 if (!((((code & 0xf803) == 0xe003) ||
261 (((code & 0x3003) == 0x3001) &&
263 ((code & 0xc000) != 0xc000))))) {
268 do_the_FPU_interrupt:
274 current->thread.error_code = 0;
282 entry_sel_off.
opcode = (byte1 << 8) | FPU_modrm;
283 entry_sel_off.
empty = 0;
287 if (FPU_modrm < 0300) {
294 &data_sel_off, addr_modes);
321 switch ((byte1 >> 1) & 3) {
327 loaded_tag = unmasked & 0xff;
341 loaded_tag = unmasked & 0xff;
361 &&
isNaN(&loaded_data))) {
365 if ((FPU_modrm & 0x30) == 0x10) {
369 if ((FPU_modrm & 0x08)
381 if ((FPU_modrm & 0x28) == 0x20)
395 goto reg_mem_instr_done;
398 if (unmasked && !((FPU_modrm & 0x30) == 0x10)) {
400 if ((FPU_modrm & 0x38) == 0x38) {
431 goto reg_mem_instr_done;
434 switch ((FPU_modrm >> 3) & 7) {
437 FPU_add(&loaded_data, loaded_tag, 0,
442 FPU_mul(&loaded_data, loaded_tag, 0,
451 (&loaded_data, loaded_tag)
484 if ((FPU_modrm & 0x30) == 0x10) {
488 if ((FPU_modrm & 0x08)
499 >> 1, addr_modes, data_address))) {
506 u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
517 switch (type_table[(
int)instr_index]) {
523 goto FPU_instruction_done;
529 goto FPU_instruction_done;
535 goto FPU_instruction_done;
541 goto FPU_instruction_done;
548 goto FPU_instruction_done;
551 goto FPU_instruction_done;
553 (*st_instr_table[(
int)instr_index]) ();
555 FPU_instruction_done:
574 goto do_another_FPU_instruction;
649 if ((byte & 0xf8) == 0xd8) {
667 current->thread.error_code = 0;
670 __asm__(
"movl %0,%%esp ; ret": :
"g"(((
long)info) - 4));
672 printk(
"ERROR: wm-FPU-emu math_abort failed!\n");
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))
682 unsigned int pos,
unsigned int count,
683 const void *kbuf,
const void __user *ubuf)
691 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, s387, 0,
699 offset = (
S387->ftop & 7) * 10;
705 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
706 space + offset, 0, other);
708 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
716 for (i = 0; i < 8; i++) {
717 regnr = (i + newtop) & 7;
718 if (((tags >> ((regnr & 7) * 2)) & 3) !=
TAG_Empty) {
723 tags &= ~(3 << (regnr * 2));
724 tags |= (tag & 3) << (regnr * 2);
734 unsigned int pos,
unsigned int count,
735 void *kbuf,
void __user *ubuf)
745 S387->cwd &= ~0xe080;
747 S387->cwd |= 0xffff0040;
749 S387->twd |= 0xffff0000;
750 S387->fcs &= ~0xf8000000;
751 S387->fos |= 0xffff0000;
754 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, s387, 0,
759 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
760 space + offset, 0,
other);
762 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,