Subject: i387 emulation & prefixes
To: None <port-i386@netbsd.org>
From: Fvdl van der Linden <fvdl@wins.uva.nl>
List: port-i386
Date: 04/22/1999 02:46:44
For the people who had problems with the i387 emulation, or to be more
precise: who had the problem that the emulator didn't handle instruction
prefixes: the following patch should work (it's simple and I've tested it).

It makes no sense for gas to actually emit prefixes for some of
these instructions, but tthat's another matter..

- Frank


Index: math_emu.h
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/math_emu.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -c -r1.5 -r1.6
*** math_emu.h	1995/05/03 00:17:16	1.5
--- math_emu.h	1999/04/22 00:23:33	1.6
***************
*** 1,4 ****
! /*	$NetBSD: math_emu.h,v 1.5 1995/05/03 00:17:16 mycroft Exp $	*/
  
  /*
   * linux/include/linux/math_emu.h
--- 1,4 ----
! /*	$NetBSD: math_emu.h,v 1.6 1999/04/22 00:23:33 fvdl Exp $	*/
  
  /*
   * linux/include/linux/math_emu.h
***************
*** 102,107 ****
--- 102,122 ----
  #define set_C1() (I387.swd |= 0x0200)
  #define set_C2() (I387.swd |= 0x0400)
  #define set_C3() (I387.swd |= 0x4000)
+ 
+ #define INSPREF_LOCK	0xf0
+ #define INSPREF_REPN	0xf2
+ #define INSPREF_REPE	0xf3
+ 
+ #define INSPREF_CS	0x2e
+ #define INSPREF_SS	0x36
+ #define INSPREF_DS	0x3e
+ #define INSPREF_ES	0x26
+ #define INSPREF_FS	0x64
+ #define INSPREF_GS	0x65
+ 
+ #define INSPREF_OSIZE	0x66
+ #define INSPREF_ASIZE	0x67
+ 
  
  /* ea.c */
  
Index: math_emulate.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/math_emulate.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -c -r1.20 -r1.21
*** math_emulate.c	1998/01/24 13:19:53	1.20
--- math_emulate.c	1999/04/22 00:23:33	1.21
***************
*** 1,4 ****
! /*	$NetBSD: math_emulate.c,v 1.20 1998/01/24 13:19:53 mycroft Exp $	*/
  
  /*
   * expediant "port" of linux 8087 emulator to 386BSD, with apologies -wfj
--- 1,4 ----
! /*	$NetBSD: math_emulate.c,v 1.21 1999/04/22 00:23:33 fvdl Exp $	*/
  
  /*
   * expediant "port" of linux 8087 emulator to 386BSD, with apologies -wfj
***************
*** 76,82 ****
--- 76,86 ----
  	temp_real tmp;
  	char * address;
  	u_long oldeip;
+ 	int override_seg, override_addrsize, override_datasize;
+ 	int prefix;
  
+ 	override_seg = override_addrsize = override_datasize = 0;
+ 
  	if (!USERMODE(info->tf_cs, info->tf_eflags))
  		panic("math emulator called from supervisor mode");
  
***************
*** 94,101 ****
  		I387.swd &= 0x7fff;
  
  	I387.fip = oldeip = info->tf_eip;
  	info->tf_eip += 2;
- 	code = htons(fusword((u_short *) oldeip)) & 0x7ff;
  	*((u_short *) &I387.fcs) = (u_short) info->tf_cs;
  	*((u_short *) &I387.fcs + 1) = code;
  
--- 98,144 ----
  		I387.swd &= 0x7fff;
  
  	I387.fip = oldeip = info->tf_eip;
+ 
+ 	/*
+ 	 * Scan for instruction prefixes. More to be politically correct
+ 	 * than anything else. Prefixes aren't useful for the instructions
+ 	 * we can emulate anyway.
+ 	 */
+ 	while (1) {
+ 		prefix = fubyte((const void *)info->tf_eip);
+ 		switch (prefix) {
+ 		case INSPREF_LOCK:
+ 			math_abort(info, SIGILL);
+ 			break;
+ 		case INSPREF_REPN:
+ 		case INSPREF_REPE:
+ 			break;
+ 		case INSPREF_CS:
+ 		case INSPREF_SS:
+ 		case INSPREF_DS:
+ 		case INSPREF_ES:
+ 		case INSPREF_FS:
+ 		case INSPREF_GS:
+ 			override_seg = prefix;
+ 			break;
+ 		case INSPREF_OSIZE:
+ 			override_datasize = prefix;	
+ 			break;
+ 		case INSPREF_ASIZE:
+ 			override_addrsize = prefix;
+ 			break;
+ 		case -1:
+ 			math_abort(info,SIGSEGV);
+ 			break;
+ 		default:
+ 			goto done;
+ 		}
+ 		info->tf_eip++;
+ 	}
+ 
+ done:
+ 	code = htons(fusword((u_short *) info->tf_eip)) & 0x7ff;
  	info->tf_eip += 2;
  	*((u_short *) &I387.fcs) = (u_short) info->tf_cs;
  	*((u_short *) &I387.fcs + 1) = code;