Ove Kaaven, > > On Mon, 10 Jun 2002, admiral coeyman wrote: > > > This patch adds the self-modifying code part of the FPU interrupts 34->3b and > > moves int 3d into the winedos section. > > Oh, I've been meaning to reply, but hadn't got around to it yet... it > makes no sense to use MapDosToLinear(MapRealToLinear()). It should be > obvious from its name that MapRealToLinear already converted to a linear > address, so that's all you need. And MapLinearToDos will probably *not* do > what you want, you should change the real-mode pointer directly instead, > as in general you just can't convert a linear address back to real mode. > Otherwise, the code is probably OK... > I was unsure of the memory handling functions. Both of these functions report that they return linear addresses, but I read one as a dos linear address and the other as a wine linear address. It was a mistake on my part. I read it as though I had to convert the seg:offset code to a dos linear address, then convert it to a wine linear address. It may have made more sense to me if I hadn't been worried about the addresses being in the wrong order. What I read says that the stack's lowest address contains IP and the word above that is the code segment for the return. IP:CS I'm not sure that I could just point a segment:offset converting function at an address in that format and get the linear address. I'm still worried about the MSB/LSB locations on the stack. That's probably just my difficulty in picturing the stack. I've done the reverse conversion be backing IP up 2 bytes. The easiest way to do this would actually be to put the inline code for each FPU instruction just before the returns. Then you could just return without any fancy manipulation. I just don't know how that is done right now. I'll retire the bug when some people have had a chance to look this patch over. God Bless, --Admiral Coeyman -- --- May you live as long as you wish and age but a single day. http://www.dotguy.net/ admiral@corner.net Webmaster/ Linux Administrator Computer Co-Op/CornerNet
Index: dlls/kernel/wprocs.spec =================================================================== RCS file: /home/wine/wine/dlls/kernel/wprocs.spec,v retrieving revision 1.7 diff -u -u -r1.7 wprocs.spec --- dlls/kernel/wprocs.spec 14 Dec 2001 23:14:23 -0000 1.7 +++ dlls/kernel/wprocs.spec 11 Jun 2002 06:10:42 -0000 @@ -17,7 +17,6 @@ 142 pascal -interrupt INT_Int2aHandler() INT_Int2aHandler 147 pascal -interrupt INT_Int2fHandler() INT_Int2fHandler 149 pascal -interrupt INT_Int31Handler() INT_Int31Handler -161 pascal -interrupt INT_Int3dHandler() INT_Int3dHandler 165 pascal -interrupt INT_Int41Handler() INT_Int41Handler 175 pascal -interrupt INT_Int4bHandler() INT_Int4bHandler 192 pascal -interrupt INT_Int5cHandler() NetBIOSCall16 Index: dlls/ntdll/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/ntdll/Makefile.in,v retrieving revision 1.27 diff -u -u -r1.27 Makefile.in --- dlls/ntdll/Makefile.in 14 May 2002 20:55:01 -0000 1.27 +++ dlls/ntdll/Makefile.in 11 Jun 2002 06:10:42 -0000 @@ -62,7 +62,6 @@ $(TOPOBJDIR)/msdos/int26.c \ $(TOPOBJDIR)/msdos/int2a.c \ $(TOPOBJDIR)/msdos/int2f.c \ - $(TOPOBJDIR)/msdos/int3d.c \ $(TOPOBJDIR)/msdos/int41.c \ $(TOPOBJDIR)/msdos/int4b.c \ $(TOPOBJDIR)/msdos/int5c.c \ @@ -115,6 +114,9 @@ sync.c \ time.c \ wcstring.c + +### $(TOPOBJDIR)/msdos/int3d.c \ + GEN_ASM_SRCS = \ relay16.s \ Index: dlls/winedos/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/winedos/Makefile.in,v retrieving revision 1.13 diff -u -u -r1.13 Makefile.in --- dlls/winedos/Makefile.in 23 May 2002 02:46:10 -0000 1.13 +++ dlls/winedos/Makefile.in 11 Jun 2002 06:10:43 -0000 @@ -22,6 +22,7 @@ int31.c \ int33.c \ int67.c \ + fpu.c \ ioports.c \ module.c \ soundblaster.c \ Index: dlls/winedos/dosexe.h =================================================================== RCS file: /home/wine/wine/dlls/winedos/dosexe.h,v retrieving revision 1.7 diff -u -u -r1.7 dosexe.h --- dlls/winedos/dosexe.h 16 May 2002 18:34:48 -0000 1.7 +++ dlls/winedos/dosexe.h 11 Jun 2002 06:10:43 -0000 @@ -114,6 +114,19 @@ extern void WINAPI DOSVM_Int33Message(UINT,WPARAM,LPARAM); extern void WINAPI DOSVM_Int33Console(MOUSE_EVENT_RECORD*); +/* fpu.c */ +extern void WINAPI INT_Int34Handler(CONTEXT86*); +extern void WINAPI INT_Int35Handler(CONTEXT86*); +extern void WINAPI INT_Int36Handler(CONTEXT86*); +extern void WINAPI INT_Int37Handler(CONTEXT86*); +extern void WINAPI INT_Int38Handler(CONTEXT86*); +extern void WINAPI INT_Int39Handler(CONTEXT86*); +extern void WINAPI INT_Int3aHandler(CONTEXT86*); +extern void WINAPI INT_Int3bHandler(CONTEXT86*); +extern void WINAPI INT_Int3cHandler(CONTEXT86*); +extern void WINAPI INT_Int3dHandler(CONTEXT86*); +extern void WINAPI INT_Int3eHandler(CONTEXT86*); + /* int67.c */ extern void WINAPI DOSVM_Int67Handler(CONTEXT86*); extern void WINAPI EMS_Ioctl_Handler(CONTEXT86*); Index: dlls/winedos/dosvm.c =================================================================== RCS file: /home/wine/wine/dlls/winedos/dosvm.c,v retrieving revision 1.19 diff -u -u -r1.19 dosvm.c --- dlls/winedos/dosvm.c 31 May 2002 23:40:54 -0000 1.19 +++ dlls/winedos/dosvm.c 11 Jun 2002 06:10:43 -0000 @@ -652,8 +652,8 @@ /* 18 */ 0, 0, INT_Int1aHandler, 0, 0, 0, 0, 0, /* 20 */ DOSVM_Int20Handler, DOSVM_Int21Handler, 0, 0, 0, INT_Int25Handler, 0, 0, /* 28 */ 0, DOSVM_Int29Handler, INT_Int2aHandler, 0, 0, 0, 0, INT_Int2fHandler, - /* 30 */ 0, DOSVM_Int31Handler, 0, DOSVM_Int33Handler, 0, 0, 0, 0, - /* 38 */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 30 */ 0, DOSVM_Int31Handler, 0, DOSVM_Int33Handler, INT_Int34Handler, INT_Int35Handler, INT_Int36Handler, INT_Int37Handler, + /* 38 */ INT_Int38Handler, INT_Int39Handler, INT_Int3aHandler, INT_Int3bHandler, INT_Int3cHandler, INT_Int3dHandler, INT_Int3eHandler, 0, /* 40 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 48 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, Index: msdos/int3d.c =================================================================== RCS file: /home/wine/wine/msdos/int3d.c,v retrieving revision 1.6 diff -u -u -r1.6 int3d.c --- msdos/int3d.c 10 Mar 2002 00:18:35 -0000 1.6 +++ msdos/int3d.c 11 Jun 2002 06:10:46 -0000 @@ -28,11 +28,37 @@ * INT_Int3dHandler (WPROCS.161) * * Handler for int 3d (FLOATING POINT EMULATION - STANDALONE FWAIT). + * + * We'll work with the assertion that all systems have FPUs and + * handle the exceptions as exceptions to the rule. This requires + * getting the address in ss:sp, writing 9b 00 to that address-2 + * changing ss:sp to point to the address ss:sp -2 and returning. + * --Robert 'Admiral' Coeyman */ void WINAPI INT_Int3dHandler(CONTEXT86 *context) { + BYTE *codepointer; + +/* Are the addresses on the stack stored the right way around? */ + +/* this section should only execute if you have an FPU */ + /* first I have to get the return address. */ + BYTE *retpointer=(BYTE *)CTX_SEG_OFF_TO_LIN(context,context->SegSs,context->Esp); +/* now I have to convert THAT to a linear address. */ + codepointer=(BYTE *)DOSMEM_MapDosToLinear(DOSMEM_MapRealToLinear((DWORD)*retpointer)); + /* so that I can change the code at that location to 0x9b, 0x90 */ + codepointer--; /* back up one byte */ + *codepointer=0x90; /* nop */ + codepointer--; /* back up two bytes */ + *codepointer=0x9b; /* fwait */ +/* Finally, we have to save the new IP in ss:sp */ + *retpointer=DOSMEM_MapLinearToDos((LPVOID *)codepointer); + return; /* just return here */ +/* End of the section */ + switch(AH_reg(context)) { + case 0x00: break; --- /dev/null Sun Jul 17 19:46:18 1994 +++ dlls/winedos/fpu.c Mon Jun 10 21:45:25 2002 @@ -0,0 +1,283 @@ +/* + * DOS interrupt 34->3e handlers. All FPU interrupt code should be + * moved into this file. + * int 3d is not activated yet... + * + * Copyright 2002 Robert 'Admiral' Coeyman + * + * X11 Friendly. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdlib.h> +#include "msdos.h" +#include "miscemu.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(int); + +/* + * The actual work is done by a single routine. + */ + +void FPU_ModifyCode(CONTEXT86 *context, BYTE Opcode); + + + +/********************************************************************** + * INT_Int34Handler (WPROCS.152) + * + * Handler for int 34 (FLOATING POINT EMULATION - Opcode 0xd8). + * + * The interrupt list isn't specific about what this interrupt + * actually does. [ interrup.m ] + */ +void WINAPI INT_Int34Handler(CONTEXT86 *context) +{ + + TRACE("Int 0x34 called-- FP opcode 0xd8"); + FPU_ModifyCode(context, 0xd8); + +} + +/********************************************************************** + * INT_Int35Handler (WPROCS.153) + * + * Handler for int 35 (FLOATING POINT EMULATION - Opcode 0xd9). + * + * The interrupt list isn't specific about what this interrupt + * actually does. [ interrup.m ] + */ +void WINAPI INT_Int35Handler(CONTEXT86 *context) +{ + TRACE("Int 0x35 called-- FP opcode 0xd9"); + FPU_ModifyCode(context, 0xd9); + +} + + +/********************************************************************** + * INT_Int36Handler (WPROCS.154) + * + * Handler for int 36 (FLOATING POINT EMULATION - Opcode 0xda). + * + * The interrupt list isn't specific about what this interrupt + * actually does. [ interrup.m ] + */ +void WINAPI INT_Int36Handler(CONTEXT86 *context) +{ + TRACE("Int 0x36 called-- FP opcode 0xda"); + FPU_ModifyCode(context, 0xda); + +} + +/********************************************************************** + * INT_Int37Handler (WPROCS.155) + * + * Handler for int 37 (FLOATING POINT EMULATION - Opcode 0xdb). + * + * The interrupt list isn't specific about what this interrupt + * actually does. [ interrup.m ] + */ +void WINAPI INT_Int37Handler(CONTEXT86 *context) +{ + TRACE("Int 0x37 called-- FP opcode 0xdb"); + FPU_ModifyCode(context, 0xdb); + +} + +/********************************************************************** + * INT_Int38Handler (WPROCS.156) + * + * Handler for int 38 (FLOATING POINT EMULATION - Opcode 0xdc). + * + * Between versions 3.0 and 5.01, the original PC-MOS API call that + * was here was moved to int 0xd4. + * + * The interrupt list isn't specific about what this interrupt + * actually does. [ interrup.m ] + */ +void WINAPI INT_Int38Handler(CONTEXT86 *context) +{ + TRACE("Int 0x38 called-- FP opcode 0xdc"); + FPU_ModifyCode(context, 0xdc); + +} + +/********************************************************************** + * INT_Int39Handler (WPROCS.157) + * + * Handler for int 39 (FLOATING POINT EMULATION - Opcode 0xdd). + * + * The interrupt list isn't specific about what this interrupt + * actually does. [ interrup.m ] + */ +void WINAPI INT_Int39Handler(CONTEXT86 *context) +{ + TRACE("Int 0x39 called-- FP opcode 0xdd"); + FPU_ModifyCode(context, 0xdd); + +} + +/********************************************************************** + * INT_Int3aHandler (WPROCS.158) + * + * Handler for int 3a (FLOATING POINT EMULATION - Opcode 0xde). + * + * The interrupt list isn't specific about what this interrupt + * actually does. [ interrup.m ] + */ +void WINAPI INT_Int3aHandler(CONTEXT86 *context) +{ + TRACE("Int 0x3a called-- FP opcode 0xde"); + FPU_ModifyCode(context, 0xde); + +} + +/********************************************************************** + * INT_Int3bHandler (WPROCS.159) + * + * Handler for int 3B (FLOATING POINT EMULATION - Opcode 0xdf). + * + * The interrupt list isn't specific about what this interrupt + * actually does. [ interrup.m ] + */ +void WINAPI INT_Int3bHandler(CONTEXT86 *context) +{ + TRACE("Int 0x3b called-- FP opcode 0xdf"); + FPU_ModifyCode(context, 0xdf); + +} + + + +/********************************************************************** + * INT_Int3cHandler (WPROCS.160) + * + * Handler for int 3C (FLOATING POINT EMULATION - INSTRUCTIONS WITH SEGMENT OVERRIDE). + * + * Generated code is CD 3C xy mm ... (CD = int | 3C = this interrupt) + * xy is a modified ESC code and mm is the modR/M byte. + * xy byte seems to be encoded as ss011xxx or ss000xxx + * ss= segment override. + * 00 -> DS + * 01 -> SS + * 10 -> CS + * 11 -> ES + * + * 11011xxx should be the opcode instruction. + */ +void WINAPI INT_Int3cHandler(CONTEXT86 *context) +{ + FIXME("Int 3C NOT Implemented"); + INT_BARF(context, 0x3c); +} + +/********************************************************************** + * INT_Int3dHandler (WPROCS.161) + * + * Handler for int 3D (FLOATING POINT EMULATION - Standalone FWAIT). + * + * Opcode 0x90 is a NOP. It just fills space where the 3D was. + */ +void WINAPI INT_Int3dHandler(CONTEXT86 *context) +{ + TRACE("Int 0x3d called-- Standalone FWAIT"); + FPU_ModifyCode(context, 0x90); + +} + + + +/********************************************************************** + * INT_Int3eHandler (WPROCS.162) + * + * FLOATING POINT EMULATION -- Borland "Shortcut" call. + * The two bytes following the int 3E instruction are + * the subcode and a NOP ( 0x90 ), except for subcodes DC and DE + * where the second byte is the register count. + * + * Direct access 4.0 modifies and does not restore this vector. + * + */ +void WINAPI INT_Int3eHandler(CONTEXT86 *context) +{ + FIXME("Int 3E NOT Implemented"); + INT_BARF(context, 0x3e); +} + +/********************************************************************** + * FPU_ModifyCode + * + * This is the function that inserts the 0x9b fwait instruction + * and the actual FPU opcode into the program. + * -A.C. + * + */ + +void FPU_ModifyCode(CONTEXT86 *context, BYTE Opcode) +{ + BYTE *codepointer, *work; + WORD ReturnIP; /* INTs are far calls right? */ + WORD OldIP,OldCS; /* The pointer I'm working with. */ + +/* + * All *NIX systems should have a real or kernel emulated FPU. + */ + + /* + * first I have to get the return address. + */ + + BYTE *retpointer=(BYTE *)CTX_SEG_OFF_TO_LIN(context,context->SegSs,context->Esp); + work=(BYTE *)CTX_SEG_OFF_TO_LIN(context,context->SegSs,context->Esp); + + /* + * now I have to convert THAT to a linear address. + * I believe that this is in IP:CS format and I need it the other way around. + */ + OldIP=(WORD)*work; /* get the Instruction Pointer */ + work+=2; /* Advance two bytes */ + OldCS=(WORD)*work; /* get the Code Segment */ + +/* My C isn't good enough to tell if CS,IP should be pointers or ints. */ + + codepointer=PTR_REAL_TO_LIN( OldCS, OldIP); + + TRACE("FPU: Modifying code at %x.",*codepointer); + + /* + * so that I can change the code at that location to + * fwait [ 0x9b ] followed by the Opcode byte. + */ + + codepointer--; /* back up one byte */ + *codepointer=Opcode; /* The FPU opcode */ + codepointer--; /* back up two bytes */ + *codepointer=0x9b; /* fwait prefix */ + /* + * Finally, we have to save the new IP in + * ss:sp + * This method will work as long as I do + * NOT back over a segment boundry. + */ + ReturnIP = (WORD)*retpointer; + if ( ReturnIP < 2 ) FIXME("Backed up over a segment boundry in FPU code."); + ReturnIP -= 2; /* back up two bytes */ + *retpointer = ReturnIP; + TRACE("Modified code in FPU int call to 0x9b 0x%x",Opcode); + +}