Modified CallTo16Register routines to update register context after

call returns. Callers adapted.
This commit is contained in:
Ulrich Weigand 2000-09-13 20:29:44 +00:00 committed by Alexandre Julliard
parent 52b2d2cff6
commit a761e3dad0
5 changed files with 73 additions and 25 deletions

View file

@ -67,10 +67,10 @@ WORD CALLBACK CallTo16Word( FARPROC16 target, INT nArgs )
LONG CALLBACK CallTo16Long( FARPROC16 target, INT nArgs ) LONG CALLBACK CallTo16Long( FARPROC16 target, INT nArgs )
{ assert( FALSE ); } { assert( FALSE ); }
LONG CALLBACK CallTo16RegisterShort( const CONTEXT86 *context, INT nArgs ) void CALLBACK CallTo16RegisterShort( CONTEXT86 *context, INT nArgs )
{ assert( FALSE ); } { assert( FALSE ); }
LONG CALLBACK CallTo16RegisterLong ( const CONTEXT86 *context, INT nArgs ) void CALLBACK CallTo16RegisterLong ( CONTEXT86 *context, INT nArgs )
{ assert( FALSE ); } { assert( FALSE ); }
WORD CallFrom16Word( void ) WORD CallFrom16Word( void )
@ -327,12 +327,27 @@ void RELAY_DebugCallTo16( LPVOID target, int nb_args, BOOL reg_func )
/*********************************************************************** /***********************************************************************
* RELAY_DebugCallTo16Ret * RELAY_DebugCallTo16Ret
*/ */
void RELAY_DebugCallTo16Ret( int ret_val ) void RELAY_DebugCallTo16Ret( BOOL reg_func, int ret_val )
{ {
if (!TRACE_ON(relay)) return; if (!TRACE_ON(relay)) return;
DPRINTF("CallTo16() ss:sp=%04x:%04x retval=0x%08x\n", if (!reg_func)
SELECTOROF(NtCurrentTeb()->cur_stack), {
OFFSETOF(NtCurrentTeb()->cur_stack), ret_val); DPRINTF("CallTo16() ss:sp=%04x:%04x retval=0x%08x\n",
SELECTOROF(NtCurrentTeb()->cur_stack),
OFFSETOF(NtCurrentTeb()->cur_stack), ret_val);
}
else
{
CONTEXT86 *context = (CONTEXT86 *)ret_val;
DPRINTF("CallTo16() ss:sp=%04x:%04x\n",
SELECTOROF(NtCurrentTeb()->cur_stack),
OFFSETOF(NtCurrentTeb()->cur_stack));
DPRINTF(" AX=%04x BX=%04x CX=%04x DX=%04x BP=%04x SP=%04x\n",
AX_reg(context), BX_reg(context), CX_reg(context),
DX_reg(context), BP_reg(context), LOWORD(ESP_reg(context)));
}
SYSLEVEL_CheckNotLevel( 2 ); SYSLEVEL_CheckNotLevel( 2 );
} }

View file

@ -20,8 +20,8 @@ extern void CallFrom16Thunk();
extern WORD CALLBACK CallTo16Word( FARPROC16 target, INT nArgs ); extern WORD CALLBACK CallTo16Word( FARPROC16 target, INT nArgs );
extern LONG CALLBACK CallTo16Long( FARPROC16 target, INT nArgs ); extern LONG CALLBACK CallTo16Long( FARPROC16 target, INT nArgs );
extern LONG CALLBACK CallTo16RegisterShort( const struct _CONTEXT86 *context, INT nArgs ); extern void CALLBACK CallTo16RegisterShort( struct _CONTEXT86 *context, INT nArgs );
extern LONG CALLBACK CallTo16RegisterLong ( const struct _CONTEXT86 *context, INT nArgs ); extern void CALLBACK CallTo16RegisterLong ( struct _CONTEXT86 *context, INT nArgs );
#include "pshpack1.h" #include "pshpack1.h"

View file

@ -1193,7 +1193,8 @@ static void NE_InitProcess(void)
SELECTOROF(pTask->teb->cur_stack), SELECTOROF(pTask->teb->cur_stack),
OFFSETOF(pTask->teb->cur_stack) ); OFFSETOF(pTask->teb->cur_stack) );
ExitThread( CallTo16RegisterShort( &context, 0 ) ); CallTo16RegisterShort( &context, 0 );
ExitThread( AX_reg( &context ) );
} }
SYSLEVEL_LeaveWin16Lock(); SYSLEVEL_LeaveWin16Lock();

View file

@ -504,20 +504,44 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func )
fprintf( outfile, "\tpushl %%cs\n" ); fprintf( outfile, "\tpushl %%cs\n" );
fprintf( outfile, "\tcall .LCallTo16%s\n", name ); fprintf( outfile, "\tcall .LCallTo16%s\n", name );
/* Convert and push return value */ if ( !reg_func )
if ( short_ret )
{ {
fprintf( outfile, "\tmovzwl %%ax, %%eax\n" ); /* Convert and push return value */
fprintf( outfile, "\tpushl %%eax\n" ); if ( short_ret )
} {
else if ( reg_func != 2 ) fprintf( outfile, "\tmovzwl %%ax, %%eax\n" );
{ fprintf( outfile, "\tpushl %%eax\n" );
fprintf( outfile, "\tshll $16,%%edx\n" ); }
fprintf( outfile, "\tmovw %%ax,%%dx\n" ); else
fprintf( outfile, "\tpushl %%edx\n" ); {
fprintf( outfile, "\tshll $16,%%edx\n" );
fprintf( outfile, "\tmovw %%ax,%%dx\n" );
fprintf( outfile, "\tpushl %%edx\n" );
}
} }
else else
fprintf( outfile, "\tpushl %%eax\n" ); {
/*
* Modify CONTEXT86 structure to contain new values
*
* NOTE: We restore only EAX, EBX, EDX, EDX, EBP, and ESP.
* The segment registers as well as ESI and EDI should
* not be modified by a well-behaved 16-bit routine in
* any case. [If necessary, we could restore them as well,
* at the cost of a somewhat less efficient return path.]
*/
fprintf( outfile, "\tmovl %d(%%esp), %%edi\n", STACK32OFFSET(target)-12 );
fprintf( outfile, "\tmovl %%eax, %d(%%edi)\n", CONTEXTOFFSET(Eax) );
fprintf( outfile, "\tmovl %%ebx, %d(%%edi)\n", CONTEXTOFFSET(Ebx) );
fprintf( outfile, "\tmovl %%ecx, %d(%%edi)\n", CONTEXTOFFSET(Ecx) );
fprintf( outfile, "\tmovl %%edx, %d(%%edi)\n", CONTEXTOFFSET(Edx) );
fprintf( outfile, "\tmovl %%ebp, %d(%%edi)\n", CONTEXTOFFSET(Ebp) );
fprintf( outfile, "\tmovl %%esi, %d(%%edi)\n", CONTEXTOFFSET(Esp) );
/* The return glue code saved %esp into %esi */
fprintf( outfile, "\tpushl %%edi\n" );
}
if ( UsePIC ) if ( UsePIC )
{ {
@ -531,10 +555,14 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func )
/* Print debugging info */ /* Print debugging info */
if (debugging) if (debugging)
{ {
fprintf( outfile, "\tpushl $%d\n", reg_func );
if ( UsePIC ) if ( UsePIC )
fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallTo16Ret@PLT\n" ); fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallTo16Ret@PLT\n" );
else else
fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallTo16Ret\n" ); fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallTo16Ret\n" );
fprintf( outfile, "\taddl $4, %%esp\n" );
} }
/* Leave Win16 Mutex */ /* Leave Win16 Mutex */
@ -657,17 +685,20 @@ static void BuildRet16Func( FILE *outfile )
fprintf( outfile, "\t.globl " PREFIX "CallTo16_Ret\n" ); fprintf( outfile, "\t.globl " PREFIX "CallTo16_Ret\n" );
fprintf( outfile, PREFIX "CallTo16_Ret:\n" ); fprintf( outfile, PREFIX "CallTo16_Ret:\n" );
/* Save %esp into %esi */
fprintf( outfile, "\tmovl %%esp,%%esi\n" );
/* Restore 32-bit segment registers */ /* Restore 32-bit segment registers */
fprintf( outfile, "\tmovw $0x%04x,%%bx\n", data_selector ); fprintf( outfile, "\tmovw $0x%04x,%%di\n", data_selector );
#ifdef __svr4__ #ifdef __svr4__
fprintf( outfile, "\tdata16\n"); fprintf( outfile, "\tdata16\n");
#endif #endif
fprintf( outfile, "\tmovw %%bx,%%ds\n" ); fprintf( outfile, "\tmovw %%di,%%ds\n" );
#ifdef __svr4__ #ifdef __svr4__
fprintf( outfile, "\tdata16\n"); fprintf( outfile, "\tdata16\n");
#endif #endif
fprintf( outfile, "\tmovw %%bx,%%es\n" ); fprintf( outfile, "\tmovw %%di,%%es\n" );
fprintf( outfile, "\tmovw " PREFIX "SYSLEVEL_Win16CurrentTeb,%%fs\n" ); fprintf( outfile, "\tmovw " PREFIX "SYSLEVEL_Win16CurrentTeb,%%fs\n" );
@ -676,7 +707,7 @@ static void BuildRet16Func( FILE *outfile )
#ifdef __svr4__ #ifdef __svr4__
fprintf( outfile, "\tdata16\n"); fprintf( outfile, "\tdata16\n");
#endif #endif
fprintf( outfile, "\tmovw %%bx,%%ss\n" ); fprintf( outfile, "\tmovw %%di,%%ss\n" );
fprintf( outfile, "\t.byte 0x64\n\tmovl (%d),%%esp\n", STACKOFFSET ); fprintf( outfile, "\t.byte 0x64\n\tmovl (%d),%%esp\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET ); fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );

View file

@ -238,7 +238,8 @@ static LRESULT WINAPI WINPROC_CallWndProc16( WNDPROC16 proc, HWND16 hwnd,
args[3] = msg; args[3] = msg;
args[4] = hwnd; args[4] = hwnd;
ret = CallTo16RegisterShort( &context, 5 * sizeof(WORD) ); CallTo16RegisterShort( &context, 5 * sizeof(WORD) );
ret = MAKELONG( AX_reg(&context), DX_reg(&context) );
if (offset) stack16_pop( offset ); if (offset) stack16_pop( offset );
WIN_RestoreWndsLock(iWndsLocks); WIN_RestoreWndsLock(iWndsLocks);