This source file includes following definitions.
- FPU_load_store
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <linux/uaccess.h>
23
24 #include "fpu_system.h"
25 #include "exception.h"
26 #include "fpu_emu.h"
27 #include "status_w.h"
28 #include "control_w.h"
29
30 #define _NONE_ 0
31 #define _REG0_ 1
32 #define _PUSH_ 3
33 #define _null_ 4
34
35 #define pop_0() { FPU_settag0(TAG_Empty); top++; }
36
37
38 static u_char const type_table[32] = {
39 _PUSH_, _PUSH_, _PUSH_, _PUSH_,
40 _null_, _REG0_, _REG0_, _REG0_,
41 _REG0_, _REG0_, _REG0_, _REG0_,
42 _REG0_, _REG0_, _REG0_, _REG0_,
43 _NONE_, _null_, _NONE_, _PUSH_,
44 _NONE_, _PUSH_, _null_, _PUSH_,
45 _NONE_, _null_, _NONE_, _REG0_,
46 _NONE_, _REG0_, _NONE_, _REG0_
47 };
48
49 u_char const data_sizes_16[32] = {
50 4, 4, 8, 2,
51 0, 4, 8, 2,
52 4, 4, 8, 2,
53 4, 4, 8, 2,
54 14, 0, 94, 10, 2, 10, 0, 8,
55 14, 0, 94, 10, 2, 10, 2, 8
56 };
57
58 static u_char const data_sizes_32[32] = {
59 4, 4, 8, 2,
60 0, 4, 8, 2,
61 4, 4, 8, 2,
62 4, 4, 8, 2,
63 28, 0, 108, 10, 2, 10, 0, 8,
64 28, 0, 108, 10, 2, 10, 2, 8
65 };
66
67 int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
68 void __user * data_address)
69 {
70 FPU_REG loaded_data;
71 FPU_REG *st0_ptr;
72 u_char st0_tag = TAG_Empty;
73 u_char loaded_tag;
74 int sv_cw;
75
76 st0_ptr = NULL;
77
78 if (addr_modes.default_mode & PROTECTED) {
79 if (addr_modes.default_mode == SEG32) {
80 if (access_limit < data_sizes_32[type])
81 math_abort(FPU_info, SIGSEGV);
82 } else if (addr_modes.default_mode == PM16) {
83 if (access_limit < data_sizes_16[type])
84 math_abort(FPU_info, SIGSEGV);
85 }
86 #ifdef PARANOID
87 else
88 EXCEPTION(EX_INTERNAL | 0x140);
89 #endif
90 }
91
92 switch (type_table[type]) {
93 case _NONE_:
94 break;
95 case _REG0_:
96 st0_ptr = &st(0);
97
98 st0_tag = FPU_gettag0();
99 break;
100 case _PUSH_:
101 {
102 if (FPU_gettagi(-1) != TAG_Empty) {
103 FPU_stack_overflow();
104 return 0;
105 }
106 top--;
107 st0_ptr = &st(0);
108 }
109 break;
110 case _null_:
111 FPU_illegal();
112 return 0;
113 #ifdef PARANOID
114 default:
115 EXCEPTION(EX_INTERNAL | 0x141);
116 return 0;
117 #endif
118 }
119
120 switch (type) {
121
122 case 000:
123 clear_C1();
124 loaded_tag =
125 FPU_load_single((float __user *)data_address, &loaded_data);
126 if ((loaded_tag == TAG_Special)
127 && isNaN(&loaded_data)
128 && (real_1op_NaN(&loaded_data) < 0)) {
129 top++;
130 break;
131 }
132 FPU_copy_to_reg0(&loaded_data, loaded_tag);
133 break;
134 case 001:
135 clear_C1();
136 loaded_tag =
137 FPU_load_int32((long __user *)data_address, &loaded_data);
138 FPU_copy_to_reg0(&loaded_data, loaded_tag);
139 break;
140 case 002:
141 clear_C1();
142 loaded_tag =
143 FPU_load_double((double __user *)data_address,
144 &loaded_data);
145 if ((loaded_tag == TAG_Special)
146 && isNaN(&loaded_data)
147 && (real_1op_NaN(&loaded_data) < 0)) {
148 top++;
149 break;
150 }
151 FPU_copy_to_reg0(&loaded_data, loaded_tag);
152 break;
153 case 003:
154 clear_C1();
155 loaded_tag =
156 FPU_load_int16((short __user *)data_address, &loaded_data);
157 FPU_copy_to_reg0(&loaded_data, loaded_tag);
158 break;
159
160
161 case 005:
162 clear_C1();
163 sv_cw = control_word;
164 control_word |= RC_CHOP;
165 if (FPU_store_int32
166 (st0_ptr, st0_tag, (long __user *)data_address))
167 pop_0();
168
169 control_word = sv_cw;
170 break;
171 case 006:
172 clear_C1();
173 sv_cw = control_word;
174 control_word |= RC_CHOP;
175 if (FPU_store_int64
176 (st0_ptr, st0_tag, (long long __user *)data_address))
177 pop_0();
178
179 control_word = sv_cw;
180 break;
181 case 007:
182 clear_C1();
183 sv_cw = control_word;
184 control_word |= RC_CHOP;
185 if (FPU_store_int16
186 (st0_ptr, st0_tag, (short __user *)data_address))
187 pop_0();
188
189 control_word = sv_cw;
190 break;
191 case 010:
192 clear_C1();
193 FPU_store_single(st0_ptr, st0_tag,
194 (float __user *)data_address);
195 break;
196 case 011:
197 clear_C1();
198 FPU_store_int32(st0_ptr, st0_tag, (long __user *)data_address);
199 break;
200 case 012:
201 clear_C1();
202 FPU_store_double(st0_ptr, st0_tag,
203 (double __user *)data_address);
204 break;
205 case 013:
206 clear_C1();
207 FPU_store_int16(st0_ptr, st0_tag, (short __user *)data_address);
208 break;
209 case 014:
210 clear_C1();
211 if (FPU_store_single
212 (st0_ptr, st0_tag, (float __user *)data_address))
213 pop_0();
214
215 break;
216 case 015:
217 clear_C1();
218 if (FPU_store_int32
219 (st0_ptr, st0_tag, (long __user *)data_address))
220 pop_0();
221
222 break;
223 case 016:
224 clear_C1();
225 if (FPU_store_double
226 (st0_ptr, st0_tag, (double __user *)data_address))
227 pop_0();
228
229 break;
230 case 017:
231 clear_C1();
232 if (FPU_store_int16
233 (st0_ptr, st0_tag, (short __user *)data_address))
234 pop_0();
235
236 break;
237 case 020:
238 fldenv(addr_modes, (u_char __user *) data_address);
239
240
241 return 1;
242 case 022:
243 frstor(addr_modes, (u_char __user *) data_address);
244
245
246 return 1;
247 case 023:
248 clear_C1();
249 loaded_tag = FPU_load_bcd((u_char __user *) data_address);
250 FPU_settag0(loaded_tag);
251 break;
252 case 024:
253 RE_ENTRANT_CHECK_OFF;
254 FPU_access_ok(data_address, 2);
255 FPU_get_user(control_word,
256 (unsigned short __user *)data_address);
257 RE_ENTRANT_CHECK_ON;
258 if (partial_status & ~control_word & CW_Exceptions)
259 partial_status |= (SW_Summary | SW_Backward);
260 else
261 partial_status &= ~(SW_Summary | SW_Backward);
262 #ifdef PECULIAR_486
263 control_word |= 0x40;
264 #endif
265 return 1;
266 case 025:
267 clear_C1();
268 loaded_tag =
269 FPU_load_extended((long double __user *)data_address, 0);
270 FPU_settag0(loaded_tag);
271 break;
272 case 027:
273 clear_C1();
274 loaded_tag = FPU_load_int64((long long __user *)data_address);
275 if (loaded_tag == TAG_Error)
276 return 0;
277 FPU_settag0(loaded_tag);
278 break;
279 case 030:
280 fstenv(addr_modes, (u_char __user *) data_address);
281 return 1;
282 case 032:
283 fsave(addr_modes, (u_char __user *) data_address);
284 return 1;
285 case 033:
286 clear_C1();
287 if (FPU_store_bcd
288 (st0_ptr, st0_tag, (u_char __user *) data_address))
289 pop_0();
290
291 break;
292 case 034:
293 RE_ENTRANT_CHECK_OFF;
294 FPU_access_ok(data_address, 2);
295 FPU_put_user(control_word,
296 (unsigned short __user *)data_address);
297 RE_ENTRANT_CHECK_ON;
298 return 1;
299 case 035:
300 clear_C1();
301 if (FPU_store_extended
302 (st0_ptr, st0_tag, (long double __user *)data_address))
303 pop_0();
304
305 break;
306 case 036:
307 RE_ENTRANT_CHECK_OFF;
308 FPU_access_ok(data_address, 2);
309 FPU_put_user(status_word(),
310 (unsigned short __user *)data_address);
311 RE_ENTRANT_CHECK_ON;
312 return 1;
313 case 037:
314 clear_C1();
315 if (FPU_store_int64
316 (st0_ptr, st0_tag, (long long __user *)data_address))
317 pop_0();
318
319 break;
320 }
321 return 0;
322 }