Linux Audio

Check our new training course

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