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