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