Linux Audio

Check our new training course

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