|
|
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.