root/arch/i386/math-emu/fpu_entry.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. math_emulate
  2. valid_prefix
  3. math_abort
  4. restore_i387_soft
  5. save_i387_soft

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

/* [previous][next][first][last][top][bottom][index][help] */