linux/arch/x86/math-emu/fpu_entry.c
<<
>>
Prefs
   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 +---------------------------------------------------------------------------*/
  14
  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 +---------------------------------------------------------------------------*/
  21
  22/*---------------------------------------------------------------------------+
  23 | math_emulate(), restore_i387_soft() and save_i387_soft() are the only     |
  24 | entry points for wm-FPU-emu.                                              |
  25 +---------------------------------------------------------------------------*/
  26
  27#include <linux/signal.h>
  28#include <linux/regset.h>
  29
  30#include <asm/uaccess.h>
  31#include <asm/traps.h>
  32#include <asm/desc.h>
  33#include <asm/user.h>
  34#include <asm/i387.h>
  35
  36#include "fpu_system.h"
  37#include "fpu_emu.h"
  38#include "exception.h"
  39#include "control_w.h"
  40#include "status_w.h"
  41
  42#define __BAD__ FPU_illegal     /* Illegal on an 80486, causes SIGILL */
  43
  44#ifndef NO_UNDOC_CODE           /* Un-documented FPU op-codes supported by default. */
  45
  46/* WARNING: These codes are not documented by Intel in their 80486 manual
  47   and may not work on FPU clones or later Intel FPUs. */
  48
  49/* Changes to support the un-doc codes provided by Linus Torvalds. */
  50
  51#define _d9_d8_ fstp_i          /* unofficial code (19) */
  52#define _dc_d0_ fcom_st         /* unofficial code (14) */
  53#define _dc_d8_ fcompst         /* unofficial code (1c) */
  54#define _dd_c8_ fxch_i          /* unofficial code (0d) */
  55#define _de_d0_ fcompst         /* unofficial code (16) */
  56#define _df_c0_ ffreep          /* unofficial code (07) ffree + pop */
  57#define _df_c8_ fxch_i          /* unofficial code (0f) */
  58#define _df_d0_ fstp_i          /* unofficial code (17) */
  59#define _df_d8_ fstp_i          /* unofficial code (1f) */
  60
  61static FUNC const st_instr_table[64] = {
  62        fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, _df_c0_,
  63        fmul__, fxch_i, __BAD__, __BAD__, fmul_i, _dd_c8_, fmulp_, _df_c8_,
  64        fcom_st, fp_nop, __BAD__, __BAD__, _dc_d0_, fst_i_, _de_d0_, _df_d0_,
  65        fcompst, _d9_d8_, __BAD__, __BAD__, _dc_d8_, fstp_i, fcompp, _df_d8_,
  66        fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
  67        fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
  68        fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
  69        fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
  70};
  71
  72#else /* Support only documented FPU op-codes */
  73
  74static FUNC const st_instr_table[64] = {
  75        fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, __BAD__,
  76        fmul__, fxch_i, __BAD__, __BAD__, fmul_i, __BAD__, fmulp_, __BAD__,
  77        fcom_st, fp_nop, __BAD__, __BAD__, __BAD__, fst_i_, __BAD__, __BAD__,
  78        fcompst, __BAD__, __BAD__, __BAD__, __BAD__, fstp_i, fcompp, __BAD__,
  79        fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
  80        fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
  81        fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
  82        fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
  83};
  84
  85#endif /* NO_UNDOC_CODE */
  86
  87#define _NONE_ 0                /* Take no special action */
  88#define _REG0_ 1                /* Need to check for not empty st(0) */
  89#define _REGI_ 2                /* Need to check for not empty st(0) and st(rm) */
  90#define _REGi_ 0                /* Uses st(rm) */
  91#define _PUSH_ 3                /* Need to check for space to push onto stack */
  92#define _null_ 4                /* Function illegal or not implemented */
  93#define _REGIi 5                /* Uses st(0) and st(rm), result to st(rm) */
  94#define _REGIp 6                /* Uses st(0) and st(rm), result to st(rm) then pop */
  95#define _REGIc 0                /* Compare st(0) and st(rm) */
  96#define _REGIn 0                /* Uses st(0) and st(rm), but handle checks later */
  97
  98#ifndef NO_UNDOC_CODE
  99
 100/* Un-documented FPU op-codes supported by default. (see above) */
 101
 102static u_char const type_table[64] = {
 103        _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _REGi_,
 104        _REGI_, _REGIn, _null_, _null_, _REGIi, _REGI_, _REGIp, _REGI_,
 105        _REGIc, _NONE_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
 106        _REGIc, _REG0_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
 107        _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
 108        _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
 109        _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
 110        _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
 111};
 112
 113#else /* Support only documented FPU op-codes */
 114
 115static u_char const type_table[64] = {
 116        _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _null_,
 117        _REGI_, _REGIn, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
 118        _REGIc, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_,
 119        _REGIc, _null_, _null_, _null_, _null_, _REG0_, _REGIc, _null_,
 120        _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
 121        _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
 122        _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
 123        _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
 124};
 125
 126#endif /* NO_UNDOC_CODE */
 127
 128#ifdef RE_ENTRANT_CHECKING
 129u_char emulating = 0;
 130#endif /* RE_ENTRANT_CHECKING */
 131
 132static int valid_prefix(u_char *Byte, u_char __user ** fpu_eip,
 133                        overrides * override);
 134
 135void math_emulate(struct math_emu_info *info)
 136{
 137        u_char FPU_modrm, byte1;
 138        unsigned short code;
 139        fpu_addr_modes addr_modes;
 140        int unmasked;
 141        FPU_REG loaded_data;
 142        FPU_REG *st0_ptr;
 143        u_char loaded_tag, st0_tag;
 144        void __user *data_address;
 145        struct address data_sel_off;
 146        struct address entry_sel_off;
 147        unsigned long code_base = 0;
 148        unsigned long code_limit = 0;   /* Initialized to stop compiler warnings */
 149        struct desc_struct code_descriptor;
 150
 151        if (!used_math()) {
 152                if (init_fpu(current)) {
 153                        do_group_exit(SIGKILL);
 154                        return;
 155                }
 156        }
 157
 158#ifdef RE_ENTRANT_CHECKING
 159        if (emulating) {
 160                printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
 161        }
 162        RE_ENTRANT_CHECK_ON;
 163#endif /* RE_ENTRANT_CHECKING */
 164
 165        FPU_info = info;
 166
 167        FPU_ORIG_EIP = FPU_EIP;
 168
 169        if ((FPU_EFLAGS & 0x00020000) != 0) {
 170                /* Virtual 8086 mode */
 171                addr_modes.default_mode = VM86;
 172                FPU_EIP += code_base = FPU_CS << 4;
 173                code_limit = code_base + 0xffff;        /* Assumes code_base <= 0xffff0000 */
 174        } else if (FPU_CS == __USER_CS && FPU_DS == __USER_DS) {
 175                addr_modes.default_mode = 0;
 176        } else if (FPU_CS == __KERNEL_CS) {
 177                printk("math_emulate: %04x:%08lx\n", FPU_CS, FPU_EIP);
 178                panic("Math emulation needed in kernel");
 179        } else {
 180
 181                if ((FPU_CS & 4) != 4) {        /* Must be in the LDT */
 182                        /* Can only handle segmented addressing via the LDT
 183                           for now, and it must be 16 bit */
 184                        printk("FPU emulator: Unsupported addressing mode\n");
 185                        math_abort(FPU_info, SIGILL);
 186                }
 187
 188                code_descriptor = LDT_DESCRIPTOR(FPU_CS);
 189                if (SEG_D_SIZE(code_descriptor)) {
 190                        /* The above test may be wrong, the book is not clear */
 191                        /* Segmented 32 bit protected mode */
 192                        addr_modes.default_mode = SEG32;
 193                } else {
 194                        /* 16 bit protected mode */
 195                        addr_modes.default_mode = PM16;
 196                }
 197                FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor);
 198                code_limit = code_base
 199                    + (SEG_LIMIT(code_descriptor) +
 200                       1) * SEG_GRANULARITY(code_descriptor)
 201                    - 1;
 202                if (code_limit < code_base)
 203                        code_limit = 0xffffffff;
 204        }
 205
 206        FPU_lookahead = !(FPU_EFLAGS & X86_EFLAGS_TF);
 207
 208        if (!valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
 209                          &addr_modes.override)) {
 210                RE_ENTRANT_CHECK_OFF;
 211                printk
 212                    ("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
 213                     "FPU emulator: self-modifying code! (emulation impossible)\n",
 214                     byte1);
 215                RE_ENTRANT_CHECK_ON;
 216                EXCEPTION(EX_INTERNAL | 0x126);
 217                math_abort(FPU_info, SIGILL);
 218        }
 219
 220      do_another_FPU_instruction:
 221
 222        no_ip_update = 0;
 223
 224        FPU_EIP++;              /* We have fetched the prefix and first code bytes. */
 225
 226        if (addr_modes.default_mode) {
 227                /* This checks for the minimum instruction bytes.
 228                   We also need to check any extra (address mode) code access. */
 229                if (FPU_EIP > code_limit)
 230                        math_abort(FPU_info, SIGSEGV);
 231        }
 232
 233        if ((byte1 & 0xf8) != 0xd8) {
 234                if (byte1 == FWAIT_OPCODE) {
 235                        if (partial_status & SW_Summary)
 236                                goto do_the_FPU_interrupt;
 237                        else
 238                                goto FPU_fwait_done;
 239                }
 240#ifdef PARANOID
 241                EXCEPTION(EX_INTERNAL | 0x128);
 242                math_abort(FPU_info, SIGILL);
 243#endif /* PARANOID */
 244        }
 245
 246        RE_ENTRANT_CHECK_OFF;
 247        FPU_code_access_ok(1);
 248        FPU_get_user(FPU_modrm, (u_char __user *) FPU_EIP);
 249        RE_ENTRANT_CHECK_ON;
 250        FPU_EIP++;
 251
 252        if (partial_status & SW_Summary) {
 253                /* Ignore the error for now if the current instruction is a no-wait
 254                   control instruction */
 255                /* The 80486 manual contradicts itself on this topic,
 256                   but a real 80486 uses the following instructions:
 257                   fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
 258                 */
 259                code = (FPU_modrm << 8) | byte1;
 260                if (!((((code & 0xf803) == 0xe003) ||   /* fnclex, fninit, fnstsw */
 261                       (((code & 0x3003) == 0x3001) &&  /* fnsave, fnstcw, fnstenv,
 262                                                           fnstsw */
 263                        ((code & 0xc000) != 0xc000))))) {
 264                        /*
 265                         *  We need to simulate the action of the kernel to FPU
 266                         *  interrupts here.
 267                         */
 268                      do_the_FPU_interrupt:
 269
 270                        FPU_EIP = FPU_ORIG_EIP; /* Point to current FPU instruction. */
 271
 272                        RE_ENTRANT_CHECK_OFF;
 273                        current->thread.trap_nr = X86_TRAP_MF;
 274                        current->thread.error_code = 0;
 275                        send_sig(SIGFPE, current, 1);
 276                        return;
 277                }
 278        }
 279
 280        entry_sel_off.offset = FPU_ORIG_EIP;
 281        entry_sel_off.selector = FPU_CS;
 282        entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
 283        entry_sel_off.empty = 0;
 284
 285        FPU_rm = FPU_modrm & 7;
 286
 287        if (FPU_modrm < 0300) {
 288                /* All of these instructions use the mod/rm byte to get a data address */
 289
 290                if ((addr_modes.default_mode & SIXTEEN)
 291                    ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX))
 292                        data_address =
 293                            FPU_get_address_16(FPU_modrm, &FPU_EIP,
 294                                               &data_sel_off, addr_modes);
 295                else
 296                        data_address =
 297                            FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
 298                                            addr_modes);
 299
 300                if (addr_modes.default_mode) {
 301                        if (FPU_EIP - 1 > code_limit)
 302                                math_abort(FPU_info, SIGSEGV);
 303                }
 304
 305                if (!(byte1 & 1)) {
 306                        unsigned short status1 = partial_status;
 307
 308                        st0_ptr = &st(0);
 309                        st0_tag = FPU_gettag0();
 310
 311                        /* Stack underflow has priority */
 312                        if (NOT_EMPTY_ST0) {
 313                                if (addr_modes.default_mode & PROTECTED) {
 314                                        /* This table works for 16 and 32 bit protected mode */
 315                                        if (access_limit <
 316                                            data_sizes_16[(byte1 >> 1) & 3])
 317                                                math_abort(FPU_info, SIGSEGV);
 318                                }
 319
 320                                unmasked = 0;   /* Do this here to stop compiler warnings. */
 321                                switch ((byte1 >> 1) & 3) {
 322                                case 0:
 323                                        unmasked =
 324                                            FPU_load_single((float __user *)
 325                                                            data_address,
 326                                                            &loaded_data);
 327                                        loaded_tag = unmasked & 0xff;
 328                                        unmasked &= ~0xff;
 329                                        break;
 330                                case 1:
 331                                        loaded_tag =
 332                                            FPU_load_int32((long __user *)
 333                                                           data_address,
 334                                                           &loaded_data);
 335                                        break;
 336                                case 2:
 337                                        unmasked =
 338                                            FPU_load_double((double __user *)
 339                                                            data_address,
 340                                                            &loaded_data);
 341                                        loaded_tag = unmasked & 0xff;
 342                                        unmasked &= ~0xff;
 343                                        break;
 344                                case 3:
 345                                default:        /* Used here to suppress gcc warnings. */
 346                                        loaded_tag =
 347                                            FPU_load_int16((short __user *)
 348                                                           data_address,
 349                                                           &loaded_data);
 350                                        break;
 351                                }
 352
 353                                /* No more access to user memory, it is safe
 354                                   to use static data now */
 355
 356                                /* NaN operands have the next priority. */
 357                                /* We have to delay looking at st(0) until after
 358                                   loading the data, because that data might contain an SNaN */
 359                                if (((st0_tag == TAG_Special) && isNaN(st0_ptr))
 360                                    || ((loaded_tag == TAG_Special)
 361                                        && isNaN(&loaded_data))) {
 362                                        /* Restore the status word; we might have loaded a
 363                                           denormal. */
 364                                        partial_status = status1;
 365                                        if ((FPU_modrm & 0x30) == 0x10) {
 366                                                /* fcom or fcomp */
 367                                                EXCEPTION(EX_Invalid);
 368                                                setcc(SW_C3 | SW_C2 | SW_C0);
 369                                                if ((FPU_modrm & 0x08)
 370                                                    && (control_word &
 371                                                        CW_Invalid))
 372                                                        FPU_pop();      /* fcomp, masked, so we pop. */
 373                                        } else {
 374                                                if (loaded_tag == TAG_Special)
 375                                                        loaded_tag =
 376                                                            FPU_Special
 377                                                            (&loaded_data);
 378#ifdef PECULIAR_486
 379                                                /* This is not really needed, but gives behaviour
 380                                                   identical to an 80486 */
 381                                                if ((FPU_modrm & 0x28) == 0x20)
 382                                                        /* fdiv or fsub */
 383                                                        real_2op_NaN
 384                                                            (&loaded_data,
 385                                                             loaded_tag, 0,
 386                                                             &loaded_data);
 387                                                else
 388#endif /* PECULIAR_486 */
 389                                                        /* fadd, fdivr, fmul, or fsubr */
 390                                                        real_2op_NaN
 391                                                            (&loaded_data,
 392                                                             loaded_tag, 0,
 393                                                             st0_ptr);
 394                                        }
 395                                        goto reg_mem_instr_done;
 396                                }
 397
 398                                if (unmasked && !((FPU_modrm & 0x30) == 0x10)) {
 399                                        /* Is not a comparison instruction. */
 400                                        if ((FPU_modrm & 0x38) == 0x38) {
 401                                                /* fdivr */
 402                                                if ((st0_tag == TAG_Zero) &&
 403                                                    ((loaded_tag == TAG_Valid)
 404                                                     || (loaded_tag ==
 405                                                         TAG_Special
 406                                                         &&
 407                                                         isdenormal
 408                                                         (&loaded_data)))) {
 409                                                        if (FPU_divide_by_zero
 410                                                            (0,
 411                                                             getsign
 412                                                             (&loaded_data))
 413                                                            < 0) {
 414                                                                /* We use the fact here that the unmasked
 415                                                                   exception in the loaded data was for a
 416                                                                   denormal operand */
 417                                                                /* Restore the state of the denormal op bit */
 418                                                                partial_status
 419                                                                    &=
 420                                                                    ~SW_Denorm_Op;
 421                                                                partial_status
 422                                                                    |=
 423                                                                    status1 &
 424                                                                    SW_Denorm_Op;
 425                                                        } else
 426                                                                setsign(st0_ptr,
 427                                                                        getsign
 428                                                                        (&loaded_data));
 429                                                }
 430                                        }
 431                                        goto reg_mem_instr_done;
 432                                }
 433
 434                                switch ((FPU_modrm >> 3) & 7) {
 435                                case 0: /* fadd */
 436                                        clear_C1();
 437                                        FPU_add(&loaded_data, loaded_tag, 0,
 438                                                control_word);
 439                                        break;
 440                                case 1: /* fmul */
 441                                        clear_C1();
 442                                        FPU_mul(&loaded_data, loaded_tag, 0,
 443                                                control_word);
 444                                        break;
 445                                case 2: /* fcom */
 446                                        FPU_compare_st_data(&loaded_data,
 447                                                            loaded_tag);
 448                                        break;
 449                                case 3: /* fcomp */
 450                                        if (!FPU_compare_st_data
 451                                            (&loaded_data, loaded_tag)
 452                                            && !unmasked)
 453                                                FPU_pop();
 454                                        break;
 455                                case 4: /* fsub */
 456                                        clear_C1();
 457                                        FPU_sub(LOADED | loaded_tag,
 458                                                (int)&loaded_data,
 459                                                control_word);
 460                                        break;
 461                                case 5: /* fsubr */
 462                                        clear_C1();
 463                                        FPU_sub(REV | LOADED | loaded_tag,
 464                                                (int)&loaded_data,
 465                                                control_word);
 466                                        break;
 467                                case 6: /* fdiv */
 468                                        clear_C1();
 469                                        FPU_div(LOADED | loaded_tag,
 470                                                (int)&loaded_data,
 471                                                control_word);
 472                                        break;
 473                                case 7: /* fdivr */
 474                                        clear_C1();
 475                                        if (st0_tag == TAG_Zero)
 476                                                partial_status = status1;       /* Undo any denorm tag,
 477                                                                                   zero-divide has priority. */
 478                                        FPU_div(REV | LOADED | loaded_tag,
 479                                                (int)&loaded_data,
 480                                                control_word);
 481                                        break;
 482                                }
 483                        } else {
 484                                if ((FPU_modrm & 0x30) == 0x10) {
 485                                        /* The instruction is fcom or fcomp */
 486                                        EXCEPTION(EX_StackUnder);
 487                                        setcc(SW_C3 | SW_C2 | SW_C0);
 488                                        if ((FPU_modrm & 0x08)
 489                                            && (control_word & CW_Invalid))
 490                                                FPU_pop();      /* fcomp */
 491                                } else
 492                                        FPU_stack_underflow();
 493                        }
 494                      reg_mem_instr_done:
 495                        operand_address = data_sel_off;
 496                } else {
 497                        if (!(no_ip_update =
 498                              FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6))
 499                                             >> 1, addr_modes, data_address))) {
 500                                operand_address = data_sel_off;
 501                        }
 502                }
 503
 504        } else {
 505                /* None of these instructions access user memory */
 506                u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
 507
 508#ifdef PECULIAR_486
 509                /* This is supposed to be undefined, but a real 80486 seems
 510                   to do this: */
 511                operand_address.offset = 0;
 512                operand_address.selector = FPU_DS;
 513#endif /* PECULIAR_486 */
 514
 515                st0_ptr = &st(0);
 516                st0_tag = FPU_gettag0();
 517                switch (type_table[(int)instr_index]) {
 518                case _NONE_:    /* also _REGIc: _REGIn */
 519                        break;
 520                case _REG0_:
 521                        if (!NOT_EMPTY_ST0) {
 522                                FPU_stack_underflow();
 523                                goto FPU_instruction_done;
 524                        }
 525                        break;
 526                case _REGIi:
 527                        if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
 528                                FPU_stack_underflow_i(FPU_rm);
 529                                goto FPU_instruction_done;
 530                        }
 531                        break;
 532                case _REGIp:
 533                        if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
 534                                FPU_stack_underflow_pop(FPU_rm);
 535                                goto FPU_instruction_done;
 536                        }
 537                        break;
 538                case _REGI_:
 539                        if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
 540                                FPU_stack_underflow();
 541                                goto FPU_instruction_done;
 542                        }
 543                        break;
 544                case _PUSH_:    /* Only used by the fld st(i) instruction */
 545                        break;
 546                case _null_:
 547                        FPU_illegal();
 548                        goto FPU_instruction_done;
 549                default:
 550                        EXCEPTION(EX_INTERNAL | 0x111);
 551                        goto FPU_instruction_done;
 552                }
 553                (*st_instr_table[(int)instr_index]) ();
 554
 555              FPU_instruction_done:
 556                ;
 557        }
 558
 559        if (!no_ip_update)
 560                instruction_address = entry_sel_off;
 561
 562      FPU_fwait_done:
 563
 564#ifdef DEBUG
 565        RE_ENTRANT_CHECK_OFF;
 566        FPU_printall();
 567        RE_ENTRANT_CHECK_ON;
 568#endif /* DEBUG */
 569
 570        if (FPU_lookahead && !need_resched()) {
 571                FPU_ORIG_EIP = FPU_EIP - code_base;
 572                if (valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
 573                                 &addr_modes.override))
 574                        goto do_another_FPU_instruction;
 575        }
 576
 577        if (addr_modes.default_mode)
 578                FPU_EIP -= code_base;
 579
 580        RE_ENTRANT_CHECK_OFF;
 581}
 582
 583/* Support for prefix bytes is not yet complete. To properly handle
 584   all prefix bytes, further changes are needed in the emulator code
 585   which accesses user address space. Access to separate segments is
 586   important for msdos emulation. */
 587static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
 588                        overrides * override)
 589{
 590        u_char byte;
 591        u_char __user *ip = *fpu_eip;
 592
 593        *override = (overrides) {
 594        0, 0, PREFIX_DEFAULT};  /* defaults */
 595
 596        RE_ENTRANT_CHECK_OFF;
 597        FPU_code_access_ok(1);
 598        FPU_get_user(byte, ip);
 599        RE_ENTRANT_CHECK_ON;
 600
 601        while (1) {
 602                switch (byte) {
 603                case ADDR_SIZE_PREFIX:
 604                        override->address_size = ADDR_SIZE_PREFIX;
 605                        goto do_next_byte;
 606
 607                case OP_SIZE_PREFIX:
 608                        override->operand_size = OP_SIZE_PREFIX;
 609                        goto do_next_byte;
 610
 611                case PREFIX_CS:
 612                        override->segment = PREFIX_CS_;
 613                        goto do_next_byte;
 614                case PREFIX_ES:
 615                        override->segment = PREFIX_ES_;
 616                        goto do_next_byte;
 617                case PREFIX_SS:
 618                        override->segment = PREFIX_SS_;
 619                        goto do_next_byte;
 620                case PREFIX_FS:
 621                        override->segment = PREFIX_FS_;
 622                        goto do_next_byte;
 623                case PREFIX_GS:
 624                        override->segment = PREFIX_GS_;
 625                        goto do_next_byte;
 626                case PREFIX_DS:
 627                        override->segment = PREFIX_DS_;
 628                        goto do_next_byte;
 629
 630/* lock is not a valid prefix for FPU instructions,
 631   let the cpu handle it to generate a SIGILL. */
 632/*      case PREFIX_LOCK: */
 633
 634                        /* rep.. prefixes have no meaning for FPU instructions */
 635                case PREFIX_REPE:
 636                case PREFIX_REPNE:
 637
 638                      do_next_byte:
 639                        ip++;
 640                        RE_ENTRANT_CHECK_OFF;
 641                        FPU_code_access_ok(1);
 642                        FPU_get_user(byte, ip);
 643                        RE_ENTRANT_CHECK_ON;
 644                        break;
 645                case FWAIT_OPCODE:
 646                        *Byte = byte;
 647                        return 1;
 648                default:
 649                        if ((byte & 0xf8) == 0xd8) {
 650                                *Byte = byte;
 651                                *fpu_eip = ip;
 652                                return 1;
 653                        } else {
 654                                /* Not a valid sequence of prefix bytes followed by
 655                                   an FPU instruction. */
 656                                *Byte = byte;   /* Needed for error message. */
 657                                return 0;
 658                        }
 659                }
 660        }
 661}
 662
 663void math_abort(struct math_emu_info *info, unsigned int signal)
 664{
 665        FPU_EIP = FPU_ORIG_EIP;
 666        current->thread.trap_nr = X86_TRAP_MF;
 667        current->thread.error_code = 0;
 668        send_sig(signal, current, 1);
 669        RE_ENTRANT_CHECK_OFF;
 670      __asm__("movl %0,%%esp ; ret": :"g"(((long)info) - 4));
 671#ifdef PARANOID
 672        printk("ERROR: wm-FPU-emu math_abort failed!\n");
 673#endif /* PARANOID */
 674}
 675
 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))
 679
 680int fpregs_soft_set(struct task_struct *target,
 681                    const struct user_regset *regset,
 682                    unsigned int pos, unsigned int count,
 683                    const void *kbuf, const void __user *ubuf)
 684{
 685        struct i387_soft_struct *s387 = &target->thread.fpu.state->soft;
 686        void *space = s387->st_space;
 687        int ret;
 688        int offset, other, i, tags, regnr, tag, newtop;
 689
 690        RE_ENTRANT_CHECK_OFF;
 691        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, s387, 0,
 692                                 offsetof(struct i387_soft_struct, st_space));
 693        RE_ENTRANT_CHECK_ON;
 694
 695        if (ret)
 696                return ret;
 697
 698        S387->ftop = (S387->swd >> SW_Top_Shift) & 7;
 699        offset = (S387->ftop & 7) * 10;
 700        other = 80 - offset;
 701
 702        RE_ENTRANT_CHECK_OFF;
 703
 704        /* Copy all registers in stack order. */
 705        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 706                                 space + offset, 0, other);
 707        if (!ret && offset)
 708                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 709                                         space, 0, offset);
 710
 711        RE_ENTRANT_CHECK_ON;
 712
 713        /* The tags may need to be corrected now. */
 714        tags = S387->twd;
 715        newtop = S387->ftop;
 716        for (i = 0; i < 8; i++) {
 717                regnr = (i + newtop) & 7;
 718                if (((tags >> ((regnr & 7) * 2)) & 3) != TAG_Empty) {
 719                        /* The loaded data over-rides all other cases. */
 720                        tag =
 721                            FPU_tagof((FPU_REG *) ((u_char *) S387->st_space +
 722                                                   10 * regnr));
 723                        tags &= ~(3 << (regnr * 2));
 724                        tags |= (tag & 3) << (regnr * 2);
 725                }
 726        }
 727        S387->twd = tags;
 728
 729        return ret;
 730}
 731
 732int fpregs_soft_get(struct task_struct *target,
 733                    const struct user_regset *regset,
 734                    unsigned int pos, unsigned int count,
 735                    void *kbuf, void __user *ubuf)
 736{
 737        struct i387_soft_struct *s387 = &target->thread.fpu.state->soft;
 738        const void *space = s387->st_space;
 739        int ret;
 740        int offset = (S387->ftop & 7) * 10, other = 80 - offset;
 741
 742        RE_ENTRANT_CHECK_OFF;
 743
 744#ifdef PECULIAR_486
 745        S387->cwd &= ~0xe080;
 746        /* An 80486 sets nearly all of the reserved bits to 1. */
 747        S387->cwd |= 0xffff0040;
 748        S387->swd = sstatus_word() | 0xffff0000;
 749        S387->twd |= 0xffff0000;
 750        S387->fcs &= ~0xf8000000;
 751        S387->fos |= 0xffff0000;
 752#endif /* PECULIAR_486 */
 753
 754        ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, s387, 0,
 755                                  offsetof(struct i387_soft_struct, st_space));
 756
 757        /* Copy all registers in stack order. */
 758        if (!ret)
 759                ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 760                                          space + offset, 0, other);
 761        if (!ret)
 762                ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 763                                          space, 0, offset);
 764
 765        RE_ENTRANT_CHECK_ON;
 766
 767        return ret;
 768}
 769