x86/fpu: Rename i387.h to fpu/api.h
[deliverable/linux.git] / arch / x86 / math-emu / fpu_entry.c
1 /*---------------------------------------------------------------------------+
2 | fpu_entry.c |
3 | |
4 | The entry functions for wm-FPU-emu |
5 | |
6 | Copyright (C) 1992,1993,1994,1996,1997 |
7 | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
8 | E-mail billm@suburbia.net |
9 | |
10 | See the files "README" and "COPYING" for further copyright and warranty |
11 | information. |
12 | |
13 +---------------------------------------------------------------------------*/
14
15 /*---------------------------------------------------------------------------+
16 | Note: |
17 | The file contains code which accesses user memory. |
18 | Emulator static data may change when user memory is accessed, due to |
19 | other processes using the emulator while swapping is in progress. |
20 +---------------------------------------------------------------------------*/
21
22 /*---------------------------------------------------------------------------+
23 | math_emulate(), restore_i387_soft() and save_i387_soft() are the only |
24 | entry points for wm-FPU-emu. |
25 +---------------------------------------------------------------------------*/
26
27 #include <linux/signal.h>
28 #include <linux/regset.h>
29
30 #include <asm/uaccess.h>
31 #include <asm/traps.h>
32 #include <asm/desc.h>
33 #include <asm/user.h>
34 #include <asm/fpu/api.h>
35
36 #include "fpu_system.h"
37 #include "fpu_emu.h"
38 #include "exception.h"
39 #include "control_w.h"
40 #include "status_w.h"
41
42 #define __BAD__ FPU_illegal /* Illegal on an 80486, causes SIGILL */
43
44 #ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by default. */
45
46 /* WARNING: These codes are not documented by Intel in their 80486 manual
47 and may not work on FPU clones or later Intel FPUs. */
48
49 /* Changes to support the un-doc codes provided by Linus Torvalds. */
50
51 #define _d9_d8_ fstp_i /* unofficial code (19) */
52 #define _dc_d0_ fcom_st /* unofficial code (14) */
53 #define _dc_d8_ fcompst /* unofficial code (1c) */
54 #define _dd_c8_ fxch_i /* unofficial code (0d) */
55 #define _de_d0_ fcompst /* unofficial code (16) */
56 #define _df_c0_ ffreep /* unofficial code (07) ffree + pop */
57 #define _df_c8_ fxch_i /* unofficial code (0f) */
58 #define _df_d0_ fstp_i /* unofficial code (17) */
59 #define _df_d8_ fstp_i /* unofficial code (1f) */
60
61 static FUNC const st_instr_table[64] = {
62 fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, _df_c0_,
63 fmul__, fxch_i, __BAD__, __BAD__, fmul_i, _dd_c8_, fmulp_, _df_c8_,
64 fcom_st, fp_nop, __BAD__, __BAD__, _dc_d0_, fst_i_, _de_d0_, _df_d0_,
65 fcompst, _d9_d8_, __BAD__, __BAD__, _dc_d8_, fstp_i, fcompp, _df_d8_,
66 fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
67 fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
68 fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
69 fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
70 };
71
72 #else /* Support only documented FPU op-codes */
73
74 static FUNC const st_instr_table[64] = {
75 fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, __BAD__,
76 fmul__, fxch_i, __BAD__, __BAD__, fmul_i, __BAD__, fmulp_, __BAD__,
77 fcom_st, fp_nop, __BAD__, __BAD__, __BAD__, fst_i_, __BAD__, __BAD__,
78 fcompst, __BAD__, __BAD__, __BAD__, __BAD__, fstp_i, fcompp, __BAD__,
79 fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
80 fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
81 fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
82 fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
83 };
84
85 #endif /* NO_UNDOC_CODE */
86
87 #define _NONE_ 0 /* Take no special action */
88 #define _REG0_ 1 /* Need to check for not empty st(0) */
89 #define _REGI_ 2 /* Need to check for not empty st(0) and st(rm) */
90 #define _REGi_ 0 /* Uses st(rm) */
91 #define _PUSH_ 3 /* Need to check for space to push onto stack */
92 #define _null_ 4 /* Function illegal or not implemented */
93 #define _REGIi 5 /* Uses st(0) and st(rm), result to st(rm) */
94 #define _REGIp 6 /* Uses st(0) and st(rm), result to st(rm) then pop */
95 #define _REGIc 0 /* Compare st(0) and st(rm) */
96 #define _REGIn 0 /* Uses st(0) and st(rm), but handle checks later */
97
98 #ifndef NO_UNDOC_CODE
99
100 /* Un-documented FPU op-codes supported by default. (see above) */
101
102 static u_char const type_table[64] = {
103 _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _REGi_,
104 _REGI_, _REGIn, _null_, _null_, _REGIi, _REGI_, _REGIp, _REGI_,
105 _REGIc, _NONE_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
106 _REGIc, _REG0_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
107 _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
108 _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
109 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
110 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
111 };
112
113 #else /* Support only documented FPU op-codes */
114
115 static u_char const type_table[64] = {
116 _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _null_,
117 _REGI_, _REGIn, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
118 _REGIc, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_,
119 _REGIc, _null_, _null_, _null_, _null_, _REG0_, _REGIc, _null_,
120 _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
121 _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
122 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
123 _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
124 };
125
126 #endif /* NO_UNDOC_CODE */
127
128 #ifdef RE_ENTRANT_CHECKING
129 u_char emulating = 0;
130 #endif /* RE_ENTRANT_CHECKING */
131
132 static int valid_prefix(u_char *Byte, u_char __user ** fpu_eip,
133 overrides * override);
134
135 void math_emulate(struct math_emu_info *info)
136 {
137 u_char FPU_modrm, byte1;
138 unsigned short code;
139 fpu_addr_modes addr_modes;
140 int unmasked;
141 FPU_REG loaded_data;
142 FPU_REG *st0_ptr;
143 u_char loaded_tag, st0_tag;
144 void __user *data_address;
145 struct address data_sel_off;
146 struct address entry_sel_off;
147 unsigned long code_base = 0;
148 unsigned long code_limit = 0; /* Initialized to stop compiler warnings */
149 struct desc_struct code_descriptor;
150 struct fpu *fpu = &current->thread.fpu;
151
152 if (!fpu->fpstate_active) {
153 if (fpstate_alloc_init(fpu)) {
154 do_group_exit(SIGKILL);
155 return;
156 }
157 }
158
159 #ifdef RE_ENTRANT_CHECKING
160 if (emulating) {
161 printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
162 }
163 RE_ENTRANT_CHECK_ON;
164 #endif /* RE_ENTRANT_CHECKING */
165
166 FPU_info = info;
167
168 FPU_ORIG_EIP = FPU_EIP;
169
170 if ((FPU_EFLAGS & 0x00020000) != 0) {
171 /* Virtual 8086 mode */
172 addr_modes.default_mode = VM86;
173 FPU_EIP += code_base = FPU_CS << 4;
174 code_limit = code_base + 0xffff; /* Assumes code_base <= 0xffff0000 */
175 } else if (FPU_CS == __USER_CS && FPU_DS == __USER_DS) {
176 addr_modes.default_mode = 0;
177 } else if (FPU_CS == __KERNEL_CS) {
178 printk("math_emulate: %04x:%08lx\n", FPU_CS, FPU_EIP);
179 panic("Math emulation needed in kernel");
180 } else {
181
182 if ((FPU_CS & 4) != 4) { /* Must be in the LDT */
183 /* Can only handle segmented addressing via the LDT
184 for now, and it must be 16 bit */
185 printk("FPU emulator: Unsupported addressing mode\n");
186 math_abort(FPU_info, SIGILL);
187 }
188
189 code_descriptor = LDT_DESCRIPTOR(FPU_CS);
190 if (SEG_D_SIZE(code_descriptor)) {
191 /* The above test may be wrong, the book is not clear */
192 /* Segmented 32 bit protected mode */
193 addr_modes.default_mode = SEG32;
194 } else {
195 /* 16 bit protected mode */
196 addr_modes.default_mode = PM16;
197 }
198 FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor);
199 code_limit = code_base
200 + (SEG_LIMIT(code_descriptor) +
201 1) * SEG_GRANULARITY(code_descriptor)
202 - 1;
203 if (code_limit < code_base)
204 code_limit = 0xffffffff;
205 }
206
207 FPU_lookahead = !(FPU_EFLAGS & X86_EFLAGS_TF);
208
209 if (!valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
210 &addr_modes.override)) {
211 RE_ENTRANT_CHECK_OFF;
212 printk
213 ("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
214 "FPU emulator: self-modifying code! (emulation impossible)\n",
215 byte1);
216 RE_ENTRANT_CHECK_ON;
217 EXCEPTION(EX_INTERNAL | 0x126);
218 math_abort(FPU_info, SIGILL);
219 }
220
221 do_another_FPU_instruction:
222
223 no_ip_update = 0;
224
225 FPU_EIP++; /* We have fetched the prefix and first code bytes. */
226
227 if (addr_modes.default_mode) {
228 /* This checks for the minimum instruction bytes.
229 We also need to check any extra (address mode) code access. */
230 if (FPU_EIP > code_limit)
231 math_abort(FPU_info, SIGSEGV);
232 }
233
234 if ((byte1 & 0xf8) != 0xd8) {
235 if (byte1 == FWAIT_OPCODE) {
236 if (partial_status & SW_Summary)
237 goto do_the_FPU_interrupt;
238 else
239 goto FPU_fwait_done;
240 }
241 #ifdef PARANOID
242 EXCEPTION(EX_INTERNAL | 0x128);
243 math_abort(FPU_info, SIGILL);
244 #endif /* PARANOID */
245 }
246
247 RE_ENTRANT_CHECK_OFF;
248 FPU_code_access_ok(1);
249 FPU_get_user(FPU_modrm, (u_char __user *) FPU_EIP);
250 RE_ENTRANT_CHECK_ON;
251 FPU_EIP++;
252
253 if (partial_status & SW_Summary) {
254 /* Ignore the error for now if the current instruction is a no-wait
255 control instruction */
256 /* The 80486 manual contradicts itself on this topic,
257 but a real 80486 uses the following instructions:
258 fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
259 */
260 code = (FPU_modrm << 8) | byte1;
261 if (!((((code & 0xf803) == 0xe003) || /* fnclex, fninit, fnstsw */
262 (((code & 0x3003) == 0x3001) && /* fnsave, fnstcw, fnstenv,
263 fnstsw */
264 ((code & 0xc000) != 0xc000))))) {
265 /*
266 * We need to simulate the action of the kernel to FPU
267 * interrupts here.
268 */
269 do_the_FPU_interrupt:
270
271 FPU_EIP = FPU_ORIG_EIP; /* Point to current FPU instruction. */
272
273 RE_ENTRANT_CHECK_OFF;
274 current->thread.trap_nr = X86_TRAP_MF;
275 current->thread.error_code = 0;
276 send_sig(SIGFPE, current, 1);
277 return;
278 }
279 }
280
281 entry_sel_off.offset = FPU_ORIG_EIP;
282 entry_sel_off.selector = FPU_CS;
283 entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
284 entry_sel_off.empty = 0;
285
286 FPU_rm = FPU_modrm & 7;
287
288 if (FPU_modrm < 0300) {
289 /* All of these instructions use the mod/rm byte to get a data address */
290
291 if ((addr_modes.default_mode & SIXTEEN)
292 ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX))
293 data_address =
294 FPU_get_address_16(FPU_modrm, &FPU_EIP,
295 &data_sel_off, addr_modes);
296 else
297 data_address =
298 FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
299 addr_modes);
300
301 if (addr_modes.default_mode) {
302 if (FPU_EIP - 1 > code_limit)
303 math_abort(FPU_info, SIGSEGV);
304 }
305
306 if (!(byte1 & 1)) {
307 unsigned short status1 = partial_status;
308
309 st0_ptr = &st(0);
310 st0_tag = FPU_gettag0();
311
312 /* Stack underflow has priority */
313 if (NOT_EMPTY_ST0) {
314 if (addr_modes.default_mode & PROTECTED) {
315 /* This table works for 16 and 32 bit protected mode */
316 if (access_limit <
317 data_sizes_16[(byte1 >> 1) & 3])
318 math_abort(FPU_info, SIGSEGV);
319 }
320
321 unmasked = 0; /* Do this here to stop compiler warnings. */
322 switch ((byte1 >> 1) & 3) {
323 case 0:
324 unmasked =
325 FPU_load_single((float __user *)
326 data_address,
327 &loaded_data);
328 loaded_tag = unmasked & 0xff;
329 unmasked &= ~0xff;
330 break;
331 case 1:
332 loaded_tag =
333 FPU_load_int32((long __user *)
334 data_address,
335 &loaded_data);
336 break;
337 case 2:
338 unmasked =
339 FPU_load_double((double __user *)
340 data_address,
341 &loaded_data);
342 loaded_tag = unmasked & 0xff;
343 unmasked &= ~0xff;
344 break;
345 case 3:
346 default: /* Used here to suppress gcc warnings. */
347 loaded_tag =
348 FPU_load_int16((short __user *)
349 data_address,
350 &loaded_data);
351 break;
352 }
353
354 /* No more access to user memory, it is safe
355 to use static data now */
356
357 /* NaN operands have the next priority. */
358 /* We have to delay looking at st(0) until after
359 loading the data, because that data might contain an SNaN */
360 if (((st0_tag == TAG_Special) && isNaN(st0_ptr))
361 || ((loaded_tag == TAG_Special)
362 && isNaN(&loaded_data))) {
363 /* Restore the status word; we might have loaded a
364 denormal. */
365 partial_status = status1;
366 if ((FPU_modrm & 0x30) == 0x10) {
367 /* fcom or fcomp */
368 EXCEPTION(EX_Invalid);
369 setcc(SW_C3 | SW_C2 | SW_C0);
370 if ((FPU_modrm & 0x08)
371 && (control_word &
372 CW_Invalid))
373 FPU_pop(); /* fcomp, masked, so we pop. */
374 } else {
375 if (loaded_tag == TAG_Special)
376 loaded_tag =
377 FPU_Special
378 (&loaded_data);
379 #ifdef PECULIAR_486
380 /* This is not really needed, but gives behaviour
381 identical to an 80486 */
382 if ((FPU_modrm & 0x28) == 0x20)
383 /* fdiv or fsub */
384 real_2op_NaN
385 (&loaded_data,
386 loaded_tag, 0,
387 &loaded_data);
388 else
389 #endif /* PECULIAR_486 */
390 /* fadd, fdivr, fmul, or fsubr */
391 real_2op_NaN
392 (&loaded_data,
393 loaded_tag, 0,
394 st0_ptr);
395 }
396 goto reg_mem_instr_done;
397 }
398
399 if (unmasked && !((FPU_modrm & 0x30) == 0x10)) {
400 /* Is not a comparison instruction. */
401 if ((FPU_modrm & 0x38) == 0x38) {
402 /* fdivr */
403 if ((st0_tag == TAG_Zero) &&
404 ((loaded_tag == TAG_Valid)
405 || (loaded_tag ==
406 TAG_Special
407 &&
408 isdenormal
409 (&loaded_data)))) {
410 if (FPU_divide_by_zero
411 (0,
412 getsign
413 (&loaded_data))
414 < 0) {
415 /* We use the fact here that the unmasked
416 exception in the loaded data was for a
417 denormal operand */
418 /* Restore the state of the denormal op bit */
419 partial_status
420 &=
421 ~SW_Denorm_Op;
422 partial_status
423 |=
424 status1 &
425 SW_Denorm_Op;
426 } else
427 setsign(st0_ptr,
428 getsign
429 (&loaded_data));
430 }
431 }
432 goto reg_mem_instr_done;
433 }
434
435 switch ((FPU_modrm >> 3) & 7) {
436 case 0: /* fadd */
437 clear_C1();
438 FPU_add(&loaded_data, loaded_tag, 0,
439 control_word);
440 break;
441 case 1: /* fmul */
442 clear_C1();
443 FPU_mul(&loaded_data, loaded_tag, 0,
444 control_word);
445 break;
446 case 2: /* fcom */
447 FPU_compare_st_data(&loaded_data,
448 loaded_tag);
449 break;
450 case 3: /* fcomp */
451 if (!FPU_compare_st_data
452 (&loaded_data, loaded_tag)
453 && !unmasked)
454 FPU_pop();
455 break;
456 case 4: /* fsub */
457 clear_C1();
458 FPU_sub(LOADED | loaded_tag,
459 (int)&loaded_data,
460 control_word);
461 break;
462 case 5: /* fsubr */
463 clear_C1();
464 FPU_sub(REV | LOADED | loaded_tag,
465 (int)&loaded_data,
466 control_word);
467 break;
468 case 6: /* fdiv */
469 clear_C1();
470 FPU_div(LOADED | loaded_tag,
471 (int)&loaded_data,
472 control_word);
473 break;
474 case 7: /* fdivr */
475 clear_C1();
476 if (st0_tag == TAG_Zero)
477 partial_status = status1; /* Undo any denorm tag,
478 zero-divide has priority. */
479 FPU_div(REV | LOADED | loaded_tag,
480 (int)&loaded_data,
481 control_word);
482 break;
483 }
484 } else {
485 if ((FPU_modrm & 0x30) == 0x10) {
486 /* The instruction is fcom or fcomp */
487 EXCEPTION(EX_StackUnder);
488 setcc(SW_C3 | SW_C2 | SW_C0);
489 if ((FPU_modrm & 0x08)
490 && (control_word & CW_Invalid))
491 FPU_pop(); /* fcomp */
492 } else
493 FPU_stack_underflow();
494 }
495 reg_mem_instr_done:
496 operand_address = data_sel_off;
497 } else {
498 if (!(no_ip_update =
499 FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6))
500 >> 1, addr_modes, data_address))) {
501 operand_address = data_sel_off;
502 }
503 }
504
505 } else {
506 /* None of these instructions access user memory */
507 u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
508
509 #ifdef PECULIAR_486
510 /* This is supposed to be undefined, but a real 80486 seems
511 to do this: */
512 operand_address.offset = 0;
513 operand_address.selector = FPU_DS;
514 #endif /* PECULIAR_486 */
515
516 st0_ptr = &st(0);
517 st0_tag = FPU_gettag0();
518 switch (type_table[(int)instr_index]) {
519 case _NONE_: /* also _REGIc: _REGIn */
520 break;
521 case _REG0_:
522 if (!NOT_EMPTY_ST0) {
523 FPU_stack_underflow();
524 goto FPU_instruction_done;
525 }
526 break;
527 case _REGIi:
528 if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
529 FPU_stack_underflow_i(FPU_rm);
530 goto FPU_instruction_done;
531 }
532 break;
533 case _REGIp:
534 if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
535 FPU_stack_underflow_pop(FPU_rm);
536 goto FPU_instruction_done;
537 }
538 break;
539 case _REGI_:
540 if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
541 FPU_stack_underflow();
542 goto FPU_instruction_done;
543 }
544 break;
545 case _PUSH_: /* Only used by the fld st(i) instruction */
546 break;
547 case _null_:
548 FPU_illegal();
549 goto FPU_instruction_done;
550 default:
551 EXCEPTION(EX_INTERNAL | 0x111);
552 goto FPU_instruction_done;
553 }
554 (*st_instr_table[(int)instr_index]) ();
555
556 FPU_instruction_done:
557 ;
558 }
559
560 if (!no_ip_update)
561 instruction_address = entry_sel_off;
562
563 FPU_fwait_done:
564
565 #ifdef DEBUG
566 RE_ENTRANT_CHECK_OFF;
567 FPU_printall();
568 RE_ENTRANT_CHECK_ON;
569 #endif /* DEBUG */
570
571 if (FPU_lookahead && !need_resched()) {
572 FPU_ORIG_EIP = FPU_EIP - code_base;
573 if (valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
574 &addr_modes.override))
575 goto do_another_FPU_instruction;
576 }
577
578 if (addr_modes.default_mode)
579 FPU_EIP -= code_base;
580
581 RE_ENTRANT_CHECK_OFF;
582 }
583
584 /* Support for prefix bytes is not yet complete. To properly handle
585 all prefix bytes, further changes are needed in the emulator code
586 which accesses user address space. Access to separate segments is
587 important for msdos emulation. */
588 static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
589 overrides * override)
590 {
591 u_char byte;
592 u_char __user *ip = *fpu_eip;
593
594 *override = (overrides) {
595 0, 0, PREFIX_DEFAULT}; /* defaults */
596
597 RE_ENTRANT_CHECK_OFF;
598 FPU_code_access_ok(1);
599 FPU_get_user(byte, ip);
600 RE_ENTRANT_CHECK_ON;
601
602 while (1) {
603 switch (byte) {
604 case ADDR_SIZE_PREFIX:
605 override->address_size = ADDR_SIZE_PREFIX;
606 goto do_next_byte;
607
608 case OP_SIZE_PREFIX:
609 override->operand_size = OP_SIZE_PREFIX;
610 goto do_next_byte;
611
612 case PREFIX_CS:
613 override->segment = PREFIX_CS_;
614 goto do_next_byte;
615 case PREFIX_ES:
616 override->segment = PREFIX_ES_;
617 goto do_next_byte;
618 case PREFIX_SS:
619 override->segment = PREFIX_SS_;
620 goto do_next_byte;
621 case PREFIX_FS:
622 override->segment = PREFIX_FS_;
623 goto do_next_byte;
624 case PREFIX_GS:
625 override->segment = PREFIX_GS_;
626 goto do_next_byte;
627 case PREFIX_DS:
628 override->segment = PREFIX_DS_;
629 goto do_next_byte;
630
631 /* lock is not a valid prefix for FPU instructions,
632 let the cpu handle it to generate a SIGILL. */
633 /* case PREFIX_LOCK: */
634
635 /* rep.. prefixes have no meaning for FPU instructions */
636 case PREFIX_REPE:
637 case PREFIX_REPNE:
638
639 do_next_byte:
640 ip++;
641 RE_ENTRANT_CHECK_OFF;
642 FPU_code_access_ok(1);
643 FPU_get_user(byte, ip);
644 RE_ENTRANT_CHECK_ON;
645 break;
646 case FWAIT_OPCODE:
647 *Byte = byte;
648 return 1;
649 default:
650 if ((byte & 0xf8) == 0xd8) {
651 *Byte = byte;
652 *fpu_eip = ip;
653 return 1;
654 } else {
655 /* Not a valid sequence of prefix bytes followed by
656 an FPU instruction. */
657 *Byte = byte; /* Needed for error message. */
658 return 0;
659 }
660 }
661 }
662 }
663
664 void math_abort(struct math_emu_info *info, unsigned int signal)
665 {
666 FPU_EIP = FPU_ORIG_EIP;
667 current->thread.trap_nr = X86_TRAP_MF;
668 current->thread.error_code = 0;
669 send_sig(signal, current, 1);
670 RE_ENTRANT_CHECK_OFF;
671 __asm__("movl %0,%%esp ; ret": :"g"(((long)info) - 4));
672 #ifdef PARANOID
673 printk("ERROR: wm-FPU-emu math_abort failed!\n");
674 #endif /* PARANOID */
675 }
676
677 #define S387 ((struct i387_soft_struct *)s387)
678 #define sstatus_word() \
679 ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
680
681 int fpregs_soft_set(struct task_struct *target,
682 const struct user_regset *regset,
683 unsigned int pos, unsigned int count,
684 const void *kbuf, const void __user *ubuf)
685 {
686 struct i387_soft_struct *s387 = &target->thread.fpu.state->soft;
687 void *space = s387->st_space;
688 int ret;
689 int offset, other, i, tags, regnr, tag, newtop;
690
691 RE_ENTRANT_CHECK_OFF;
692 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, s387, 0,
693 offsetof(struct i387_soft_struct, st_space));
694 RE_ENTRANT_CHECK_ON;
695
696 if (ret)
697 return ret;
698
699 S387->ftop = (S387->swd >> SW_Top_Shift) & 7;
700 offset = (S387->ftop & 7) * 10;
701 other = 80 - offset;
702
703 RE_ENTRANT_CHECK_OFF;
704
705 /* Copy all registers in stack order. */
706 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
707 space + offset, 0, other);
708 if (!ret && offset)
709 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
710 space, 0, offset);
711
712 RE_ENTRANT_CHECK_ON;
713
714 /* The tags may need to be corrected now. */
715 tags = S387->twd;
716 newtop = S387->ftop;
717 for (i = 0; i < 8; i++) {
718 regnr = (i + newtop) & 7;
719 if (((tags >> ((regnr & 7) * 2)) & 3) != TAG_Empty) {
720 /* The loaded data over-rides all other cases. */
721 tag =
722 FPU_tagof((FPU_REG *) ((u_char *) S387->st_space +
723 10 * regnr));
724 tags &= ~(3 << (regnr * 2));
725 tags |= (tag & 3) << (regnr * 2);
726 }
727 }
728 S387->twd = tags;
729
730 return ret;
731 }
732
733 int fpregs_soft_get(struct task_struct *target,
734 const struct user_regset *regset,
735 unsigned int pos, unsigned int count,
736 void *kbuf, void __user *ubuf)
737 {
738 struct i387_soft_struct *s387 = &target->thread.fpu.state->soft;
739 const void *space = s387->st_space;
740 int ret;
741 int offset = (S387->ftop & 7) * 10, other = 80 - offset;
742
743 RE_ENTRANT_CHECK_OFF;
744
745 #ifdef PECULIAR_486
746 S387->cwd &= ~0xe080;
747 /* An 80486 sets nearly all of the reserved bits to 1. */
748 S387->cwd |= 0xffff0040;
749 S387->swd = sstatus_word() | 0xffff0000;
750 S387->twd |= 0xffff0000;
751 S387->fcs &= ~0xf8000000;
752 S387->fos |= 0xffff0000;
753 #endif /* PECULIAR_486 */
754
755 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, s387, 0,
756 offsetof(struct i387_soft_struct, st_space));
757
758 /* Copy all registers in stack order. */
759 if (!ret)
760 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
761 space + offset, 0, other);
762 if (!ret)
763 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
764 space, 0, offset);
765
766 RE_ENTRANT_CHECK_ON;
767
768 return ret;
769 }
This page took 0.062823 seconds and 5 git commands to generate.