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