Date: Mon, 30 Aug 1999 09:59:49 +0300 (IDT) From: Eli Zaretskii X-Sender: eliz AT is To: DJ Delorie , Charles Sandmann cc: djgpp-workers AT delorie DOT com, Morten Welinder Subject: FWAIT emulation in emu387.cc Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Reply-To: djgpp-workers AT delorie DOT com The main function of the emu387 emulator is attached below (I removed the ifdef'ed away debug code, for clarity). Why is the line marked with "<<<<<<<<<<" commented out? It doesn't seem right to me. I actually traced a bug (reported on c.o.m.d. some 2 years ago ;-) to this line: on Windows, any program that uses FWAIT gets stuck in an endless loop (when emulation is used), because EIP isn't being incremented. The test program posted with the bug report just called `floor', and that was enough to get it wedged. How come it works on DOS, you ask? Well, it seems that on DOS, FWAIT never gets into the emulator! Charles, is this expected behavior? Intel manuals say that FWAIT generates the coprocessor not present exception when the MP and TS flags in CR0 are set. I guess Windows sets these flags (although Intel recommends to leave it cleared) while on plain DOS they remain unset, right? Anyway, I tested this on DOS, with and without a memory manager, with CWSDPMI and QDPMI, and never saw FWAIT inside the emulator. But on Windows, both 95 and 3.1, FWAIT gets into the emulator. The Intel manual says the EIP points to FWAIT when it generates the exception. So it seems like we need to resurrect that line. Does anyone remember why it was commented out? int _emu_entry(jmp_buf _exception_state) { int jmpval; eip = (unsigned char *) _exception_state->__eip; eax = _exception_state->__eax; ebx = _exception_state->__ebx; ecx = _exception_state->__ecx; edx = _exception_state->__edx; esi = _exception_state->__esi; edi = _exception_state->__edi; ebp = _exception_state->__ebp; esp = _exception_state->__esp; if (*eip == 0x66) // operand size - we know what size we need eip++; if (*eip == 0x9b) // fwait { // _exception_state->__eip++; <<<<<<<<<<<<<<<< return 0; } jmpval = setjmp(jumpbuf); if(jmpval) return 1; /* Emulator failed for some reason */ int esc_value = *eip++ & 7; modrm = *eip++; esc_value |= (modrm & 070); (esc_table[esc_value])(); // emu_printall(); _exception_state->__eip = (unsigned long) eip; _exception_state->__eax = eax; return 0; }