Annotation of coherent/b/kernel/emulator/fpu_entry.c, revision 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.