root/drivers/FPU-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

   1 /*---------------------------------------------------------------------------+
   2  |  fpu_entry.c                                                              |
   3  |                                                                           |
   4  | The entry function for wm-FPU-emu                                         |
   5  |                                                                           |
   6  | Copyright (C) 1992,1993,1994                                              |
   7  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
   8  |                       Australia.  E-mail   billm@vaxc.cc.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() is the sole entry point for wm-FPU-emu                     |
  24  +---------------------------------------------------------------------------*/
  25 
  26 #include <linux/signal.h>
  27 #include <linux/segment.h>
  28 
  29 #include "fpu_system.h"
  30 #include "fpu_emu.h"
  31 #include "exception.h"
  32 #include "control_w.h"
  33 #include "status_w.h"
  34 
  35 #include <asm/segment.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 /* Be careful when using any of these global variables...
 126    they might change if swapping is triggered */
 127 unsigned char  FPU_rm;
 128 char           FPU_st0_tag;
 129 FPU_REG       *FPU_st0_ptr;
 130 
 131 /* ######## To be shifted */
 132 unsigned long FPU_entry_op_cs;
 133 unsigned short FPU_data_selector;
 134 
 135 
 136 #ifdef PARANOID
 137 char emulating=0;
 138 #endif PARANOID
 139 
 140 static int valid_prefix(unsigned char *byte, overrides *override);
 141 
 142 
 143 asmlinkage void math_emulate(long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 144 {
 145   unsigned char  FPU_modrm, byte1;
 146   overrides override;
 147   int unmasked;
 148 
 149 #ifdef PARANOID
 150   if ( emulating )
 151     {
 152       printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
 153     }
 154   RE_ENTRANT_CHECK_ON;
 155 #endif PARANOID
 156 
 157   if (!current->used_math)
 158     {
 159       int i;
 160       for ( i = 0; i < 8; i++ )
 161         {
 162           /* Make sure that the registers are compatible
 163              with the assumptions of the emulator. */
 164           regs[i].exp = 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   /* We cannot handle emulation in v86-mode */
 176   if (FPU_EFLAGS & 0x00020000)
 177     {
 178       math_abort(FPU_info,SIGILL);
 179     }
 180 
 181   /* user code space? */
 182   if (FPU_CS == KERNEL_CS)
 183     {
 184       printk("math_emulate: %04x:%08lx\n",FPU_CS,FPU_EIP);
 185       panic("Math emulation needed in kernel");
 186     }
 187 
 188   /* We cannot handle multiple segments yet */
 189   if (FPU_CS != USER_CS || FPU_DS != USER_DS)
 190     {
 191       math_abort(FPU_info,SIGILL);
 192     }
 193 
 194   FPU_lookahead = 1;
 195   if (current->flags & PF_PTRACED)
 196         FPU_lookahead = 0;
 197 
 198   if ( !valid_prefix(&byte1, &override) )
 199     {
 200       RE_ENTRANT_CHECK_OFF;
 201       printk("FPU emulator: Unknown prefix byte 0x%02x\n", byte1);
 202       RE_ENTRANT_CHECK_ON;
 203       EXCEPTION(EX_INTERNAL|0x126);
 204       math_abort(FPU_info,SIGILL);
 205     }
 206 
 207 do_another_FPU_instruction:
 208 
 209   FPU_EIP++;  /* We have fetched the prefix and first code bytes. */
 210 
 211 #ifdef PECULIAR_486
 212   /* It would be more logical to do this only in get_address(),
 213      but although it is supposed to be undefined for many fpu
 214      instructions, an 80486 behaves as if this were done here: */
 215   FPU_data_selector = FPU_DS;
 216 #endif PECULIAR_486
 217 
 218   if ( (byte1 & 0xf8) != 0xd8 )
 219     {
 220       if ( byte1 == FWAIT_OPCODE )
 221         {
 222           if (partial_status & SW_Summary)
 223             goto do_the_FPU_interrupt;
 224           else
 225             goto FPU_fwait_done;
 226         }
 227 #ifdef PARANOID
 228       EXCEPTION(EX_INTERNAL|0x128);
 229       math_abort(FPU_info,SIGILL);
 230 #endif PARANOID
 231     }
 232 
 233   RE_ENTRANT_CHECK_OFF;
 234   FPU_code_verify_area(1);
 235   FPU_modrm = get_fs_byte((unsigned short *) FPU_EIP);
 236   RE_ENTRANT_CHECK_ON;
 237   FPU_EIP++;
 238 
 239   if (partial_status & SW_Summary)
 240     {
 241       /* Ignore the error for now if the current instruction is a no-wait
 242          control instruction */
 243       /* The 80486 manual contradicts itself on this topic,
 244          but a real 80486 uses the following instructions:
 245          fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
 246        */
 247       unsigned short code = (FPU_modrm << 8) | byte1;
 248       if ( ! ( (((code & 0xf803) == 0xe003) ||    /* fnclex, fninit, fnstsw */
 249                 (((code & 0x3003) == 0x3001) &&   /* fnsave, fnstcw, fnstenv,
 250                                                      fnstsw */
 251                  ((code & 0xc000) != 0xc000))) ) )
 252         {
 253           /*
 254            *  We need to simulate the action of the kernel to FPU
 255            *  interrupts here.
 256            *  Currently, the "real FPU" part of the kernel (0.99.10)
 257            *  clears the exception flags, sets the registers to empty,
 258            *  and passes information back to the interrupted process
 259            *  via the cs selector and operand selector, so we do the same.
 260            */
 261         do_the_FPU_interrupt:
 262           cs_selector &= 0xffff0000;
 263           cs_selector |= status_word();
 264           operand_selector = tag_word();
 265           partial_status = 0;
 266           top = 0;
 267           {
 268             int r;
 269             for (r = 0; r < 8; r++)
 270               {
 271                 regs[r].tag = TW_Empty;
 272               }
 273           }
 274 
 275           RE_ENTRANT_CHECK_OFF;
 276           current->tss.trap_no = 16;
 277           current->tss.error_code = 0;
 278           send_sig(SIGFPE, current, 1);
 279           return;
 280         }
 281     }
 282 
 283   FPU_entry_eip = FPU_ORIG_EIP;
 284 
 285   FPU_entry_op_cs = (byte1 << 24) | (FPU_modrm << 16) | (FPU_CS & 0xffff) ;
 286 
 287   FPU_rm = FPU_modrm & 7;
 288 
 289   if ( FPU_modrm < 0300 )
 290     {
 291       /* All of these instructions use the mod/rm byte to get a data address */
 292       get_address(FPU_modrm, override);
 293       if ( !(byte1 & 1) )
 294         {
 295           unsigned short status1 = partial_status;
 296           FPU_st0_ptr = &st(0);
 297           FPU_st0_tag = FPU_st0_ptr->tag;
 298 
 299           /* Stack underflow has priority */
 300           if ( NOT_EMPTY_0 )
 301             {
 302               unmasked = 0;  /* Do this here to stop compiler warnings. */
 303               switch ( (byte1 >> 1) & 3 )
 304                 {
 305                 case 0:
 306                   unmasked = reg_load_single(override);
 307                   break;
 308                 case 1:
 309                   reg_load_int32(override);
 310                   break;
 311                 case 2:
 312                   unmasked = reg_load_double(override);
 313                   break;
 314                 case 3:
 315                   reg_load_int16(override);
 316                   break;
 317                 }
 318               
 319               /* No more access to user memory, it is safe
 320                  to use static data now */
 321               FPU_st0_ptr = &st(0);
 322               FPU_st0_tag = FPU_st0_ptr->tag;
 323 
 324               /* NaN operands have the next priority. */
 325               /* We have to delay looking at st(0) until after
 326                  loading the data, because that data might contain an SNaN */
 327               if ( (FPU_st0_tag == TW_NaN) ||
 328                   (FPU_loaded_data.tag == TW_NaN) )
 329                 {
 330                   /* Restore the status word; we might have loaded a
 331                      denormal. */
 332                   partial_status = status1;
 333                   if ( (FPU_modrm & 0x30) == 0x10 )
 334                     {
 335                       /* fcom or fcomp */
 336                       EXCEPTION(EX_Invalid);
 337                       setcc(SW_C3 | SW_C2 | SW_C0);
 338                       if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
 339                         pop();             /* fcomp, masked, so we pop. */
 340                     }
 341                   else
 342                     {
 343 #ifdef PECULIAR_486
 344                       /* This is not really needed, but gives behaviour
 345                          identical to an 80486 */
 346                       if ( (FPU_modrm & 0x28) == 0x20 )
 347                         /* fdiv or fsub */
 348                         real_2op_NaN(&FPU_loaded_data, FPU_st0_ptr,
 349                                      FPU_st0_ptr);
 350                       else
 351 #endif PECULIAR_486
 352                         /* fadd, fdivr, fmul, or fsubr */
 353                         real_2op_NaN(FPU_st0_ptr, &FPU_loaded_data,
 354                                      FPU_st0_ptr);
 355                     }
 356                   goto reg_mem_instr_done;
 357                 }
 358 
 359               if ( unmasked && !((FPU_modrm & 0x30) == 0x10) )
 360                 {
 361                   /* Is not a comparison instruction. */
 362                   if ( (FPU_modrm & 0x38) == 0x38 )
 363                     {
 364                       /* fdivr */
 365                       if ( (FPU_st0_tag == TW_Zero) &&
 366                           (FPU_loaded_data.tag == TW_Valid) )
 367                         {
 368                           if ( divide_by_zero(FPU_loaded_data.sign,
 369                                               FPU_st0_ptr) )
 370                             {
 371                               /* We use the fact here that the unmasked
 372                                  exception in the loaded data was for a
 373                                  denormal operand */
 374                               /* Restore the state of the denormal op bit */
 375                               partial_status &= ~SW_Denorm_Op;
 376                               partial_status |= status1 & SW_Denorm_Op;
 377                             }
 378                         }
 379                     }
 380                   goto reg_mem_instr_done;
 381                 }
 382 
 383               switch ( (FPU_modrm >> 3) & 7 )
 384                 {
 385                 case 0:         /* fadd */
 386                   clear_C1();
 387                   reg_add(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr,
 388                           control_word);
 389                   break;
 390                 case 1:         /* fmul */
 391                   clear_C1();
 392                   reg_mul(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr,
 393                           control_word);
 394                   break;
 395                 case 2:         /* fcom */
 396                   compare_st_data();
 397                   break;
 398                 case 3:         /* fcomp */
 399                   if ( !compare_st_data() && !unmasked )
 400                     pop();
 401                   break;
 402                 case 4:         /* fsub */
 403                   clear_C1();
 404                   reg_sub(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr,
 405                           control_word);
 406                   break;
 407                 case 5:         /* fsubr */
 408                   clear_C1();
 409                   reg_sub(&FPU_loaded_data, FPU_st0_ptr, FPU_st0_ptr,
 410                           control_word);
 411                   break;
 412                 case 6:         /* fdiv */
 413                   clear_C1();
 414                   reg_div(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr,
 415                           control_word);
 416                   break;
 417                 case 7:         /* fdivr */
 418                   clear_C1();
 419                   if ( FPU_st0_tag == TW_Zero )
 420                     partial_status = status1;  /* Undo any denorm tag,
 421                                                zero-divide has priority. */
 422                   reg_div(&FPU_loaded_data, FPU_st0_ptr, FPU_st0_ptr,
 423                           control_word);
 424                   break;
 425                 }
 426             }
 427           else
 428             {
 429               if ( (FPU_modrm & 0x30) == 0x10 )
 430                 {
 431                   /* The instruction is fcom or fcomp */
 432                   EXCEPTION(EX_StackUnder);
 433                   setcc(SW_C3 | SW_C2 | SW_C0);
 434                   if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
 435                     pop();             /* fcomp */
 436                 }
 437               else
 438                 stack_underflow();
 439             }
 440         }
 441       else
 442         {
 443           load_store_instr(((FPU_modrm & 0x38) | (byte1 & 6)) >> 1, override);
 444         }
 445 
 446     reg_mem_instr_done:
 447 
 448 #ifndef PECULIAR_486
 449       *(unsigned short *)&operand_selector = FPU_data_selector;
 450 #endif PECULIAR_486
 451       ;
 452     }
 453   else
 454     {
 455       /* None of these instructions access user memory */
 456       unsigned char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
 457 
 458 #ifdef PECULIAR_486
 459       /* This is supposed to be undefined, but a real 80486 seems
 460          to do this: */
 461       FPU_data_address = 0;
 462 #endif PECULIAR_486
 463 
 464       FPU_st0_ptr = &st(0);
 465       FPU_st0_tag = FPU_st0_ptr->tag;
 466       switch ( type_table[(int) instr_index] )
 467         {
 468         case _NONE_:   /* also _REGIc: _REGIn */
 469           break;
 470         case _REG0_:
 471           if ( !NOT_EMPTY_0 )
 472             {
 473               stack_underflow();
 474               goto FPU_instruction_done;
 475             }
 476           break;
 477         case _REGIi:
 478           if ( !NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm) )
 479             {
 480               stack_underflow_i(FPU_rm);
 481               goto FPU_instruction_done;
 482             }
 483           break;
 484         case _REGIp:
 485           if ( !NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm) )
 486             {
 487               stack_underflow_pop(FPU_rm);
 488               goto FPU_instruction_done;
 489             }
 490           break;
 491         case _REGI_:
 492           if ( !NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm) )
 493             {
 494               stack_underflow();
 495               goto FPU_instruction_done;
 496             }
 497           break;
 498         case _PUSH_:     /* Only used by the fld st(i) instruction */
 499           break;
 500         case _null_:
 501           FPU_illegal();
 502           goto FPU_instruction_done;
 503         default:
 504           EXCEPTION(EX_INTERNAL|0x111);
 505           goto FPU_instruction_done;
 506         }
 507       (*st_instr_table[(int) instr_index])();
 508     }
 509 
 510 FPU_instruction_done:
 511 
 512   ip_offset = FPU_entry_eip;
 513   cs_selector = FPU_entry_op_cs;
 514   data_operand_offset = (unsigned long)FPU_data_address;
 515 #ifdef PECULIAR_486
 516   *(unsigned short *)&operand_selector = FPU_data_selector;
 517 #endif PECULIAR_486
 518   
 519 FPU_fwait_done:
 520 
 521 #ifdef DEBUG
 522   RE_ENTRANT_CHECK_OFF;
 523   emu_printall();
 524   RE_ENTRANT_CHECK_ON;
 525 #endif DEBUG
 526 
 527   if (FPU_lookahead && !need_resched)
 528     {
 529       FPU_ORIG_EIP = FPU_EIP;
 530       if ( valid_prefix(&byte1, &override) )
 531         goto do_another_FPU_instruction;
 532     }
 533 
 534   RE_ENTRANT_CHECK_OFF;
 535 }
 536 
 537 
 538 /* Support for prefix bytes is not yet complete. To properly handle
 539    all prefix bytes, further changes are needed in the emulator code
 540    which accesses user address space. Access to separate segments is
 541    important for msdos emulation. */
 542 static int valid_prefix(unsigned char *Byte, overrides *override)
     /* [previous][next][first][last][top][bottom][index][help] */
 543 {
 544   unsigned char byte;
 545   unsigned long ip = FPU_EIP;
 546 
 547   *override = (overrides) { 0, PREFIX_DS };       /* defaults */
 548 
 549   RE_ENTRANT_CHECK_OFF;
 550   FPU_code_verify_area(1);
 551   byte = get_fs_byte((unsigned char *) FPU_EIP);
 552   RE_ENTRANT_CHECK_ON;
 553 
 554   while ( 1 )
 555     {
 556       switch ( byte )
 557         {
 558         case ADDR_SIZE_PREFIX:
 559           override->address_size = ADDR_SIZE_PREFIX;
 560           goto do_next_byte;
 561         case PREFIX_CS:
 562           override->segment = PREFIX_CS;
 563           goto do_next_byte;
 564         case PREFIX_ES:
 565           override->segment = PREFIX_ES;
 566           goto do_next_byte;
 567         case PREFIX_SS:
 568           override->segment = PREFIX_SS;
 569           goto do_next_byte;
 570         case PREFIX_FS:
 571           override->segment = PREFIX_FS;
 572           goto do_next_byte;
 573         case PREFIX_GS:
 574           override->segment = PREFIX_GS;
 575           goto do_next_byte;
 576 
 577         case PREFIX_DS:   /* Redundant unless preceded by another override. */
 578           override->segment = PREFIX_DS;
 579 
 580           /* rep.. prefixes have no meaning for FPU instructions */
 581         case PREFIX_LOCK:
 582         case PREFIX_REPE:
 583         case PREFIX_REPNE:
 584         case OP_SIZE_PREFIX:  /* Used often by gcc, but has no effect. */
 585         do_next_byte:
 586           FPU_EIP++;
 587           RE_ENTRANT_CHECK_OFF;
 588           FPU_code_verify_area(1);
 589           byte = get_fs_byte((unsigned char *) (FPU_EIP));
 590           RE_ENTRANT_CHECK_ON;
 591           break;
 592         case FWAIT_OPCODE:
 593           *Byte = byte;
 594           return 1;
 595         default:
 596           if ( (byte & 0xf8) == 0xd8 )
 597             {
 598               *Byte = byte;
 599               return 1;
 600             }
 601           else
 602             {
 603               FPU_EIP = ip;
 604               return 0;
 605             }
 606         }
 607     }
 608 }
 609 
 610 
 611 void __math_abort(struct info * info, unsigned int signal)
     /* [previous][next][first][last][top][bottom][index][help] */
 612 {
 613         FPU_EIP = FPU_ORIG_EIP;
 614         current->tss.trap_no = 16;
 615         current->tss.error_code = 0;
 616         send_sig(signal,current,1);
 617         RE_ENTRANT_CHECK_OFF;
 618         __asm__("movl %0,%%esp ; ret": :"g" (((long) info)-4));
 619 #ifdef PARANOID
 620       printk("ERROR: wm-FPU-emu math_abort failed!\n");
 621 #endif PARANOID
 622 }

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