|
|
1.1 ! root 1: /*---------------------------------------------------------------------------+ ! 2: | load_store.c | ! 3: | | ! 4: | This file contains most of the code to interpret the FPU instructions | ! 5: | which load and store from user memory. | ! 6: | | ! 7: | Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | ! 8: | Australia. E-mail [email protected] | ! 9: | | ! 10: | | ! 11: +---------------------------------------------------------------------------*/ ! 12: ! 13: /*---------------------------------------------------------------------------+ ! 14: | Note: | ! 15: | The file contains code which accesses user memory. | ! 16: | Emulator static data may change when user memory is accessed, due to | ! 17: | other processes using the emulator while swapping is in progress. | ! 18: +---------------------------------------------------------------------------*/ ! 19: ! 20: #include <asm/segment.h> ! 21: ! 22: #include "fpu_system.h" ! 23: #include "exception.h" ! 24: #include "fpu_emu.h" ! 25: #include "status_w.h" ! 26: ! 27: ! 28: #define _NONE_ 0 /* FPU_st0_ptr etc not needed */ ! 29: #define _REG0_ 1 /* Will be storing st(0) */ ! 30: #define _PUSH_ 3 /* Need to check for space to push onto stack */ ! 31: #define _null_ 4 /* Function illegal or not implemented */ ! 32: ! 33: #define pop_0() { pop_ptr->tag = TW_Empty; top++; } ! 34: ! 35: ! 36: static unsigned char type_table[32] = { ! 37: _PUSH_, _PUSH_, _PUSH_, _PUSH_, ! 38: _null_, _null_, _null_, _null_, ! 39: _REG0_, _REG0_, _REG0_, _REG0_, ! 40: _REG0_, _REG0_, _REG0_, _REG0_, ! 41: _null_, _null_, _NONE_, _PUSH_, ! 42: _NONE_, _PUSH_, _null_, _PUSH_, ! 43: _null_, _null_, _NONE_, _REG0_, ! 44: _NONE_, _REG0_, _NONE_, _REG0_ ! 45: }; ! 46: ! 47: void load_store_instr(char type) ! 48: { ! 49: FPU_REG *pop_ptr; /* We need a version of FPU_st0_ptr which won't change. */ ! 50: ! 51: pop_ptr = NULL; ! 52: switch ( type_table[(int) (unsigned) type] ) ! 53: { ! 54: case _NONE_: ! 55: break; ! 56: case _REG0_: ! 57: pop_ptr = &st(0); /* Some of these instructions pop after ! 58: storing */ ! 59: ! 60: FPU_st0_ptr = pop_ptr; /* Set the global variables. */ ! 61: FPU_st0_tag = FPU_st0_ptr->tag; ! 62: break; ! 63: case _PUSH_: ! 64: { ! 65: pop_ptr = &st(-1); ! 66: if ( pop_ptr->tag != TW_Empty ) ! 67: { stack_overflow(); return; } ! 68: top--; ! 69: } ! 70: break; ! 71: case _null_: ! 72: return Un_impl(); ! 73: #ifdef PARANOID ! 74: default: ! 75: return EXCEPTION(EX_INTERNAL); ! 76: #endif PARANOID ! 77: } ! 78: ! 79: switch ( type ) ! 80: { ! 81: case 000: /* fld m32real */ ! 82: reg_load_single(); ! 83: reg_move(&FPU_loaded_data, pop_ptr); ! 84: break; ! 85: case 001: /* fild m32int */ ! 86: reg_load_int32(); ! 87: reg_move(&FPU_loaded_data, pop_ptr); ! 88: break; ! 89: case 002: /* fld m64real */ ! 90: reg_load_double(); ! 91: reg_move(&FPU_loaded_data, pop_ptr); ! 92: break; ! 93: case 003: /* fild m16int */ ! 94: reg_load_int16(); ! 95: reg_move(&FPU_loaded_data, pop_ptr); ! 96: break; ! 97: case 010: /* fst m32real */ ! 98: reg_store_single(); ! 99: break; ! 100: case 011: /* fist m32int */ ! 101: reg_store_int32(); ! 102: break; ! 103: case 012: /* fst m64real */ ! 104: reg_store_double(); ! 105: break; ! 106: case 013: /* fist m16int */ ! 107: reg_store_int16(); ! 108: break; ! 109: case 014: /* fstp m32real */ ! 110: if ( reg_store_single() ) ! 111: pop_0(); /* pop only if the number was actually stored ! 112: (see the 80486 manual p16-28) */ ! 113: break; ! 114: case 015: /* fistp m32int */ ! 115: if ( reg_store_int32() ) ! 116: pop_0(); /* pop only if the number was actually stored ! 117: (see the 80486 manual p16-28) */ ! 118: break; ! 119: case 016: /* fstp m64real */ ! 120: if ( reg_store_double() ) ! 121: pop_0(); /* pop only if the number was actually stored ! 122: (see the 80486 manual p16-28) */ ! 123: break; ! 124: case 017: /* fistp m16int */ ! 125: if ( reg_store_int16() ) ! 126: pop_0(); /* pop only if the number was actually stored ! 127: (see the 80486 manual p16-28) */ ! 128: break; ! 129: case 020: /* fldenv m14/28byte */ ! 130: fldenv(); ! 131: break; ! 132: case 022: /* frstor m94/108byte */ ! 133: frstor(); ! 134: break; ! 135: case 023: /* fbld m80dec */ ! 136: reg_load_bcd(); ! 137: reg_move(&FPU_loaded_data, pop_ptr); ! 138: break; ! 139: case 024: /* fldcw */ ! 140: RE_ENTRANT_CHECK_OFF ! 141: control_word = get_fs_word((unsigned short *) FPU_data_address); ! 142: RE_ENTRANT_CHECK_ON ! 143: #ifdef NO_UNDERFLOW_TRAP ! 144: if ( !(control_word & EX_Underflow) ) ! 145: { ! 146: control_word |= EX_Underflow; ! 147: } ! 148: #endif ! 149: FPU_data_address = (void *)data_operand_offset; /* We want no net effect */ ! 150: FPU_entry_eip = ip_offset; /* We want no net effect */ ! 151: break; ! 152: case 025: /* fld m80real */ ! 153: reg_load_extended(); ! 154: reg_move(&FPU_loaded_data, pop_ptr); ! 155: break; ! 156: case 027: /* fild m64int */ ! 157: reg_load_int64(); ! 158: reg_move(&FPU_loaded_data, pop_ptr); ! 159: break; ! 160: case 030: /* fstenv m14/28byte */ ! 161: fstenv(); ! 162: FPU_data_address = (void *)data_operand_offset; /* We want no net effect */ ! 163: FPU_entry_eip = ip_offset; /* We want no net effect */ ! 164: break; ! 165: case 032: /* fsave */ ! 166: fsave(); ! 167: finit_instr(); ! 168: FPU_data_address = (void *)data_operand_offset; /* We want no net effect */ ! 169: FPU_entry_eip = ip_offset; /* We want no net effect */ ! 170: break; ! 171: case 033: /* fbstp m80dec */ ! 172: if ( reg_store_bcd() ) ! 173: pop_0(); /* pop only if the number was actually stored ! 174: (see the 80486 manual p16-28) */ ! 175: break; ! 176: case 034: /* fstcw m16int */ ! 177: RE_ENTRANT_CHECK_OFF ! 178: #ifdef COHERENT ! 179: if (verify_area(FPU_data_address,2)) ! 180: put_fs_word(control_word, (short *) FPU_data_address); ! 181: #else ! 182: verify_area(FPU_data_address,2); ! 183: put_fs_word(control_word, (short *) FPU_data_address); ! 184: #endif ! 185: RE_ENTRANT_CHECK_ON ! 186: FPU_data_address = (void *)data_operand_offset; /* We want no net effect */ ! 187: FPU_entry_eip = ip_offset; /* We want no net effect */ ! 188: break; ! 189: case 035: /* fstp m80real */ ! 190: if ( reg_store_extended() ) ! 191: pop_0(); /* pop only if the number was actually stored ! 192: (see the 80486 manual p16-28) */ ! 193: break; ! 194: case 036: /* fstsw m2byte */ ! 195: status_word &= ~SW_TOP; ! 196: status_word |= (top&7) << SW_TOPS; ! 197: RE_ENTRANT_CHECK_OFF ! 198: #ifdef COHERENT ! 199: if (verify_area(FPU_data_address,2)) ! 200: put_fs_word(status_word,(short *) FPU_data_address); ! 201: #else ! 202: verify_area(FPU_data_address,2); ! 203: put_fs_word(status_word,(short *) FPU_data_address); ! 204: #endif ! 205: RE_ENTRANT_CHECK_ON ! 206: FPU_data_address = (void *)data_operand_offset; /* We want no net effect */ ! 207: FPU_entry_eip = ip_offset; /* We want no net effect */ ! 208: break; ! 209: case 037: /* fistp m64int */ ! 210: if ( reg_store_int64() ) ! 211: pop_0(); /* pop only if the number was actually stored ! 212: (see the 80486 manual p16-28) */ ! 213: break; ! 214: } ! 215: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.