Annotation of coherent/b/kernel/emulator/fpu_entry.c, revision 1.1.1.1

1.1       root        1: /*---------------------------------------------------------------------------+
                      2:  |  fpu_entry.c                                                              |
                      3:  |                                                                           |
                      4:  | The entry function for wm-FPU-emu                                         |
                      5:  |                                                                           |
                      6:  | Copyright (C) 1992    W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
                      7:  |                       Australia.  E-mail [email protected]    |
                      8:  |                                                                           |
                      9:  | See the files "README" and "COPYING" for further copyright and warranty   |
                     10:  | information.                                                              |
                     11:  |                                                                           |
                     12:  +---------------------------------------------------------------------------*/
                     13: 
                     14: /*---------------------------------------------------------------------------+
                     15:  | Note:                                                                     |
                     16:  |    The file contains code which accesses user memory.                     |
                     17:  |    Emulator static data may change when user memory is accessed, due to   |
                     18:  |    other processes using the emulator while swapping is in progress.      |
                     19:  +---------------------------------------------------------------------------*/
                     20: 
                     21: /*---------------------------------------------------------------------------+
                     22:  | math_emulate() is the sole entry point for wm-FPU-emu                     |
                     23:  +---------------------------------------------------------------------------*/
                     24: 
                     25: #ifdef KERNEL_MATH_EMULATION
                     26: 
                     27: #include <linux/signal.h>
                     28: 
                     29: #include "fpu_system.h"
                     30: #include "fpu_emu.h"
                     31: #include "exception.h"
                     32: 
                     33: #include <asm/segment.h>
                     34: 
                     35: #ifdef COHERENT
                     36: struct _fpstackframe *emCurrent;
                     37: struct _fpemstate *FPU_info;
                     38: #endif
                     39: 
                     40: #define __BAD__ Un_impl   /* Not implemented */
                     41: 
                     42: static FUNC st_instr_table[64] = {
                     43:   fadd__,   fld_i_,  __BAD__, __BAD__, fadd_i,  ffree_,  faddp_,  __BAD__,
                     44:   fmul__,   fxch_i,  __BAD__, __BAD__, fmul_i,  __BAD__, fmulp_,  __BAD__,
                     45:   fcom_st,  fp_nop,  __BAD__, __BAD__, __BAD__, fst_i_,  __BAD__, __BAD__,
                     46:   fcompst,  __BAD__, __BAD__, __BAD__, __BAD__, fstp_i,  fcompp,  __BAD__,
                     47:   fsub__,   fp_etc,  __BAD__, finit_,  fsubri,  fucom_,  fsubrp,  fstsw_,
                     48:   fsubr_,   fconst,  fucompp, __BAD__, fsub_i,  fucomp,  fsubp_,  __BAD__,
                     49:   fdiv__,   trig_a,  __BAD__, __BAD__, fdivri,  __BAD__, fdivrp,  __BAD__,
                     50:   fdivr_,   trig_b,  __BAD__, __BAD__, fdiv_i,  __BAD__, fdivp_,  __BAD__,
                     51: };
                     52: 
                     53: #define _NONE_ 0   /* Take no special action */
                     54: #define _REG0_ 1   /* Need to check for not empty st(0) */
                     55: #define _REGI_ 2   /* Need to check for not empty st(0) and st(rm) */
                     56: #define _REGi_ 0   /* Uses st(rm) */
                     57: #define _PUSH_ 3   /* Need to check for space to push onto stack */
                     58: #define _null_ 4   /* Function illegal or not implemented */
                     59: 
                     60: static unsigned char type_table[64] = {
                     61:   _REGI_, _NONE_, _null_, _null_, _REGI_, _REGi_, _REGI_, _null_,
                     62:   _REGI_, _REGI_, _null_, _null_, _REGI_, _null_, _REGI_, _null_,
                     63:   _REGI_, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_,
                     64:   _REGI_, _null_, _null_, _null_, _null_, _REG0_, _REGI_, _null_,
                     65:   _REGI_, _NONE_, _null_, _NONE_, _REGI_, _REGI_, _REGI_, _NONE_,
                     66:   _REGI_, _NONE_, _REGI_, _null_, _REGI_, _REGI_, _REGI_, _null_,
                     67:   _REGI_, _NONE_, _null_, _null_, _REGI_, _null_, _REGI_, _null_,
                     68:   _REGI_, _NONE_, _null_, _null_, _REGI_, _null_, _REGI_, _null_
                     69: };
                     70: 
                     71: 
                     72: /* Be careful when using any of these global variables...
                     73:    they might change if swapping is triggered */
                     74: unsigned char  FPU_rm;
                     75: char          FPU_st0_tag;
                     76: FPU_REG       *FPU_st0_ptr;
                     77: 
                     78: #ifdef PARANOID
                     79: char emulating=0;
                     80: #endif PARANOID
                     81: 
                     82: #define bswapw(x) __asm__("xchgb %%al,%%ah":"=a" (x):"0" ((short)x))
                     83: 
                     84: #if COHERENT
                     85: /* Special kernel routines to pack and unpack emulator to normal */
                     86: void kfsave(struct _fpemstate *fpem, struct _fpstate *fp)
                     87: {
                     88:        FPU_info = fpem;
                     89:        FPU_data_address = (void *)fp;
                     90:        fsave();
                     91: }
                     92: 
                     93: void kfrstor(struct _fpstate *fp, struct _fpemstate *fpem)
                     94: {
                     95:        FPU_info = fpem;
                     96:        FPU_data_address = (void *)fp;
                     97:        frstor();
                     98: }
                     99: 
                    100: void math_emulate(long *saveRegs, struct _fpemstate *fpem, int looker)
                    101: {
                    102:   unsigned char  FPU_modrm;
                    103:   unsigned short code;
                    104: 
                    105:   emCurrent = (struct _fpstackframe *)(saveRegs - 1);
                    106:   FPU_info  = fpem;
                    107: 
                    108:   FPU_lookahead = looker;
                    109: #else
                    110: void math_emulate(long arg)
                    111: {
                    112:   unsigned char  FPU_modrm;
                    113:   unsigned short code;
                    114: 
                    115: #ifdef PARANOID
                    116:   if ( emulating )
                    117:     {
                    118:       printf("ERROR: wm-FPU-emu is not RE-ENTRANT!\r\n");
                    119:     }
                    120:   RE_ENTRANT_CHECK_ON
                    121: #endif PARANOID
                    122: 
                    123:   if (!emCurrent->used_math)
                    124:     {
                    125:       finit();
                    126:       emCurrent->used_math = 1;
                    127:       control_word = 0x037f;
                    128:       status_word = 0x0000;
                    129:     }
                    130: 
                    131:   FPU_info = (struct info *) &arg;
                    132: 
                    133:   /* We cannot handle emulation in v86-mode */
                    134:   if (FPU_EFLAGS & 0x00020000)
                    135:     math_abort(FPU_info,SIGILL);
                    136: 
                    137:   /* 0x000f means user code space */
                    138:   if (FPU_CS != 0x000f)
                    139:     {
                    140:       printf("math_emulate: %04x:%08x\n\r",FPU_CS,FPU_EIP);
                    141:       emPanic("Math emulation needed in kernel");
                    142:     }
                    143: 
                    144:   FPU_lookahead = 1;
                    145:   if (emCurrent->flags & PF_PTRACED)
                    146:        FPU_lookahead = 0;
                    147: #endif
                    148: do_another:
                    149: 
                    150:   FPU_entry_eip = FPU_ORIG_EIP = FPU_EIP;
                    151: 
                    152:   RE_ENTRANT_CHECK_OFF
                    153:   code = get_fs_word((unsigned short *) FPU_EIP);
                    154:   RE_ENTRANT_CHECK_ON
                    155: 
                    156:   if ( (code & 0xff) == 0x66 )
                    157:     {
                    158:       FPU_EIP++;
                    159:       RE_ENTRANT_CHECK_OFF
                    160:       code = get_fs_word((unsigned short *) FPU_EIP);
                    161:       RE_ENTRANT_CHECK_ON
                    162:     }
                    163:   FPU_EIP += 2;
                    164: 
                    165:   FPU_modrm = code >> 8;
                    166:   FPU_rm = FPU_modrm & 7;
                    167: 
                    168:   if ( FPU_modrm < 0300 )
                    169:     {
                    170:       /* All of these instructions use the mod/rm byte to get a data address */
                    171:       get_address(FPU_modrm);
                    172: 
                    173:       if ( !(code & 1) )
                    174:        {
                    175:          switch ( (code >> 1) & 3 )
                    176:            {
                    177:            case 0:
                    178:              reg_load_single();
                    179:              break;
                    180:            case 1:
                    181:              reg_load_int32();
                    182:              break;
                    183:            case 2:
                    184:              reg_load_double();
                    185:              break;
                    186:            case 3:
                    187:              reg_load_int16();
                    188:              break;
                    189:            }
                    190: 
                    191:          /* No more access to user memory, it is safe
                    192:             to use static data now */
                    193:          FPU_st0_ptr = &st(0);
                    194:          FPU_st0_tag = FPU_st0_ptr->tag;
                    195:          if ( NOT_EMPTY_0 )
                    196:            {
                    197:              switch ( (FPU_modrm >> 3) & 7 )
                    198:                {
                    199:                case 0:         /* fadd */
                    200:                  reg_add(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr);
                    201:                  break;
                    202:                case 1:         /* fmul */
                    203:                  reg_mul(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr);
                    204:                  break;
                    205:                case 2:         /* fcom */
                    206:                  compare_st_data();
                    207:                  break;
                    208:                case 3:         /* fcomp */
                    209:                  compare_st_data();
                    210:                  pop();
                    211:                  break;
                    212:                case 4:         /* fsub */
                    213:                  reg_sub(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr);
                    214:                  break;
                    215:                case 5:         /* fsubr */
                    216:                  reg_sub(&FPU_loaded_data, FPU_st0_ptr, FPU_st0_ptr);
                    217:                  break;
                    218:                case 6:         /* fdiv */
                    219:                  reg_div(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr);
                    220:                  break;
                    221:                case 7:         /* fdivr */
                    222:                  reg_div(&FPU_loaded_data, FPU_st0_ptr, FPU_st0_ptr);
                    223:                  break;
                    224:                }
                    225:            }
                    226:          else
                    227:            stack_underflow();
                    228:        }
                    229:       else
                    230:        {
                    231:          load_store_instr(((FPU_modrm & 0x38) | (code & 6)) >> 1);
                    232:        }
                    233: 
                    234: #ifdef COHERENT
                    235:       if (data_operand_offset != (unsigned long)FPU_data_address) {
                    236:         data_operand_offset = (unsigned long)FPU_data_address;
                    237:         operand_selector = FPU_DS;
                    238:       }
                    239: #else
                    240:       data_operand_offset = (unsigned long)FPU_data_address;
                    241: #endif
                    242:     }
                    243:   else
                    244:     {
                    245:       /* None of these instructions access user memory */
                    246:       unsigned char instr_index = (FPU_modrm & 0x38) | (code & 7);
                    247:       FPU_st0_ptr = &st(0);
                    248:       FPU_st0_tag = FPU_st0_ptr->tag;
                    249:       switch ( type_table[(int) instr_index] )
                    250:        {
                    251:        case _NONE_:
                    252:          break;
                    253:        case _REG0_:
                    254:          if ( !NOT_EMPTY_0 )
                    255:            {
                    256:              stack_underflow();
                    257:              goto instruction_done;
                    258:            }
                    259:          break;
                    260:        case _REGI_:
                    261:          if ( !NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm) )
                    262:            {
                    263:              stack_underflow();
                    264:              goto instruction_done;
                    265:            }
                    266:          break;
                    267:        case _PUSH_:     /* Only used by the fld st(i) instruction */
                    268:          break;
                    269:        case _null_:
                    270:          Un_impl();
                    271:          goto instruction_done;
                    272:        default:
                    273:          EXCEPTION(EX_INTERNAL|0x111);
                    274:          goto instruction_done;
                    275:        }
                    276:       (*st_instr_table[(int) instr_index])();
                    277:     }
                    278: 
                    279: instruction_done:
                    280: 
                    281: #ifdef COHERENT
                    282:   if (ip_offset != FPU_entry_eip) {
                    283:     ip_offset = FPU_entry_eip;
                    284:     bswapw(code);
                    285:     cs_selector = ((code & 0x7ff) << 16) | FPU_CS;
                    286:   }
                    287: #else
                    288:   ip_offset = FPU_entry_eip;
                    289:   bswapw(code);
                    290:   *(1 + (unsigned short *)&cs_selector) = code & 0x7ff;
                    291: #endif
                    292: 
                    293: #ifdef COHERENT
                    294:   if (FPU_lookahead)
                    295: #else
                    296:   if (FPU_lookahead && !need_resched)
                    297: #endif
                    298:     {
                    299:       unsigned char next;
                    300: skip_fwait:
                    301:       RE_ENTRANT_CHECK_OFF
                    302:       next = get_fs_byte((unsigned char *) FPU_EIP);
                    303:       RE_ENTRANT_CHECK_ON
                    304: test_for_fp:
                    305:       if ( (next & 0xf8) == 0xd8 )
                    306:        {
                    307:          goto do_another;
                    308:        }
                    309:       if ( next == 0x9b )  /* fwait */
                    310:        { FPU_EIP++; goto skip_fwait; }
                    311:       if ( next == 0x66 )  /* size prefix */
                    312:        {
                    313:          RE_ENTRANT_CHECK_OFF
                    314:          next = get_fs_byte((unsigned char *) (FPU_EIP+1));
                    315:          RE_ENTRANT_CHECK_ON
                    316:          if ( (next & 0xf8) == 0xd8 )
                    317:            goto test_for_fp;
                    318:        }
                    319:     }
                    320: 
                    321:   RE_ENTRANT_CHECK_OFF
                    322: }
                    323: 
                    324: #ifndef COHERENT
                    325: void __math_abort(struct info * info, unsigned int signal)
                    326: {
                    327:        FPU_EIP = FPU_ORIG_EIP;
                    328:        emSendsig(signal,emCurrent,1);
                    329:        __asm__("movl %0,%%esp ; ret"::"g" (((long) info)-4));
                    330: }
                    331: #endif
                    332: #else /* no math emulation */
                    333: 
                    334: #include <linux/signal.h>
                    335: #include <linux/sched.h>
                    336: 
                    337: void math_emulate(long arg)
                    338: {
                    339:   emSendsig(SIGFPE,emCurrent,1);
                    340:   schedule();
                    341: }
                    342: 
                    343: #endif /* KERNEL_MATH_EMULATION */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.