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;