Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
load_store.c
Go to the documentation of this file.
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,1993,1994,1997 |
8  | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
9  | Australia. E-mail [email protected] |
10  | |
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 #include <asm/uaccess.h>
22 
23 #include "fpu_system.h"
24 #include "exception.h"
25 #include "fpu_emu.h"
26 #include "status_w.h"
27 #include "control_w.h"
28 
29 #define _NONE_ 0 /* st0_ptr etc not needed */
30 #define _REG0_ 1 /* Will be storing st(0) */
31 #define _PUSH_ 3 /* Need to check for space to push onto stack */
32 #define _null_ 4 /* Function illegal or not implemented */
33 
34 #define pop_0() { FPU_settag0(TAG_Empty); top++; }
35 
36 static u_char const type_table[32] = {
44  _NONE_, _REG0_, _NONE_, _REG0_
45 };
46 
47 u_char const data_sizes_16[32] = {
48  4, 4, 8, 2, 0, 0, 0, 0,
49  4, 4, 8, 2, 4, 4, 8, 2,
50  14, 0, 94, 10, 2, 10, 0, 8,
51  14, 0, 94, 10, 2, 10, 2, 8
52 };
53 
54 static u_char const data_sizes_32[32] = {
55  4, 4, 8, 2, 0, 0, 0, 0,
56  4, 4, 8, 2, 4, 4, 8, 2,
57  28, 0, 108, 10, 2, 10, 0, 8,
58  28, 0, 108, 10, 2, 10, 2, 8
59 };
60 
62  void __user * data_address)
63 {
64  FPU_REG loaded_data;
65  FPU_REG *st0_ptr;
66  u_char st0_tag = TAG_Empty; /* This is just to stop a gcc warning. */
67  u_char loaded_tag;
68 
69  st0_ptr = NULL; /* Initialized just to stop compiler warnings. */
70 
71  if (addr_modes.default_mode & PROTECTED) {
72  if (addr_modes.default_mode == SEG32) {
73  if (access_limit < data_sizes_32[type])
75  } else if (addr_modes.default_mode == PM16) {
76  if (access_limit < data_sizes_16[type])
78  }
79 #ifdef PARANOID
80  else
81  EXCEPTION(EX_INTERNAL | 0x140);
82 #endif /* PARANOID */
83  }
84 
85  switch (type_table[type]) {
86  case _NONE_:
87  break;
88  case _REG0_:
89  st0_ptr = &st(0); /* Some of these instructions pop after
90  storing */
91  st0_tag = FPU_gettag0();
92  break;
93  case _PUSH_:
94  {
95  if (FPU_gettagi(-1) != TAG_Empty) {
97  return 0;
98  }
99  top--;
100  st0_ptr = &st(0);
101  }
102  break;
103  case _null_:
104  FPU_illegal();
105  return 0;
106 #ifdef PARANOID
107  default:
108  EXCEPTION(EX_INTERNAL | 0x141);
109  return 0;
110 #endif /* PARANOID */
111  }
112 
113  switch (type) {
114  case 000: /* fld m32real */
115  clear_C1();
116  loaded_tag =
117  FPU_load_single((float __user *)data_address, &loaded_data);
118  if ((loaded_tag == TAG_Special)
119  && isNaN(&loaded_data)
120  && (real_1op_NaN(&loaded_data) < 0)) {
121  top++;
122  break;
123  }
124  FPU_copy_to_reg0(&loaded_data, loaded_tag);
125  break;
126  case 001: /* fild m32int */
127  clear_C1();
128  loaded_tag =
129  FPU_load_int32((long __user *)data_address, &loaded_data);
130  FPU_copy_to_reg0(&loaded_data, loaded_tag);
131  break;
132  case 002: /* fld m64real */
133  clear_C1();
134  loaded_tag =
135  FPU_load_double((double __user *)data_address,
136  &loaded_data);
137  if ((loaded_tag == TAG_Special)
138  && isNaN(&loaded_data)
139  && (real_1op_NaN(&loaded_data) < 0)) {
140  top++;
141  break;
142  }
143  FPU_copy_to_reg0(&loaded_data, loaded_tag);
144  break;
145  case 003: /* fild m16int */
146  clear_C1();
147  loaded_tag =
148  FPU_load_int16((short __user *)data_address, &loaded_data);
149  FPU_copy_to_reg0(&loaded_data, loaded_tag);
150  break;
151  case 010: /* fst m32real */
152  clear_C1();
153  FPU_store_single(st0_ptr, st0_tag,
154  (float __user *)data_address);
155  break;
156  case 011: /* fist m32int */
157  clear_C1();
158  FPU_store_int32(st0_ptr, st0_tag, (long __user *)data_address);
159  break;
160  case 012: /* fst m64real */
161  clear_C1();
162  FPU_store_double(st0_ptr, st0_tag,
163  (double __user *)data_address);
164  break;
165  case 013: /* fist m16int */
166  clear_C1();
167  FPU_store_int16(st0_ptr, st0_tag, (short __user *)data_address);
168  break;
169  case 014: /* fstp m32real */
170  clear_C1();
171  if (FPU_store_single
172  (st0_ptr, st0_tag, (float __user *)data_address))
173  pop_0(); /* pop only if the number was actually stored
174  (see the 80486 manual p16-28) */
175  break;
176  case 015: /* fistp m32int */
177  clear_C1();
178  if (FPU_store_int32
179  (st0_ptr, st0_tag, (long __user *)data_address))
180  pop_0(); /* pop only if the number was actually stored
181  (see the 80486 manual p16-28) */
182  break;
183  case 016: /* fstp m64real */
184  clear_C1();
185  if (FPU_store_double
186  (st0_ptr, st0_tag, (double __user *)data_address))
187  pop_0(); /* pop only if the number was actually stored
188  (see the 80486 manual p16-28) */
189  break;
190  case 017: /* fistp m16int */
191  clear_C1();
192  if (FPU_store_int16
193  (st0_ptr, st0_tag, (short __user *)data_address))
194  pop_0(); /* pop only if the number was actually stored
195  (see the 80486 manual p16-28) */
196  break;
197  case 020: /* fldenv m14/28byte */
198  fldenv(addr_modes, (u_char __user *) data_address);
199  /* Ensure that the values just loaded are not changed by
200  fix-up operations. */
201  return 1;
202  case 022: /* frstor m94/108byte */
203  frstor(addr_modes, (u_char __user *) data_address);
204  /* Ensure that the values just loaded are not changed by
205  fix-up operations. */
206  return 1;
207  case 023: /* fbld m80dec */
208  clear_C1();
209  loaded_tag = FPU_load_bcd((u_char __user *) data_address);
210  FPU_settag0(loaded_tag);
211  break;
212  case 024: /* fldcw */
214  FPU_access_ok(VERIFY_READ, data_address, 2);
216  (unsigned short __user *)data_address);
220  else
222 #ifdef PECULIAR_486
223  control_word |= 0x40; /* An 80486 appears to always set this bit */
224 #endif /* PECULIAR_486 */
225  return 1;
226  case 025: /* fld m80real */
227  clear_C1();
228  loaded_tag =
229  FPU_load_extended((long double __user *)data_address, 0);
230  FPU_settag0(loaded_tag);
231  break;
232  case 027: /* fild m64int */
233  clear_C1();
234  loaded_tag = FPU_load_int64((long long __user *)data_address);
235  if (loaded_tag == TAG_Error)
236  return 0;
237  FPU_settag0(loaded_tag);
238  break;
239  case 030: /* fstenv m14/28byte */
240  fstenv(addr_modes, (u_char __user *) data_address);
241  return 1;
242  case 032: /* fsave */
243  fsave(addr_modes, (u_char __user *) data_address);
244  return 1;
245  case 033: /* fbstp m80dec */
246  clear_C1();
247  if (FPU_store_bcd
248  (st0_ptr, st0_tag, (u_char __user *) data_address))
249  pop_0(); /* pop only if the number was actually stored
250  (see the 80486 manual p16-28) */
251  break;
252  case 034: /* fstcw m16int */
254  FPU_access_ok(VERIFY_WRITE, data_address, 2);
256  (unsigned short __user *)data_address);
258  return 1;
259  case 035: /* fstp m80real */
260  clear_C1();
262  (st0_ptr, st0_tag, (long double __user *)data_address))
263  pop_0(); /* pop only if the number was actually stored
264  (see the 80486 manual p16-28) */
265  break;
266  case 036: /* fstsw m2byte */
268  FPU_access_ok(VERIFY_WRITE, data_address, 2);
270  (unsigned short __user *)data_address);
272  return 1;
273  case 037: /* fistp m64int */
274  clear_C1();
275  if (FPU_store_int64
276  (st0_ptr, st0_tag, (long long __user *)data_address))
277  pop_0(); /* pop only if the number was actually stored
278  (see the 80486 manual p16-28) */
279  break;
280  }
281  return 0;
282 }