diff --git a/memory/selector.c b/memory/selector.c index 16bddc6ff27..17577f39934 100644 --- a/memory/selector.c +++ b/memory/selector.c @@ -162,7 +162,6 @@ void SELECTOR_FreeBlock( WORD sel, WORD count ) { WORD i, nextsel; ldt_entry entry; - STACK16FRAME *frame; TRACE(selector, "(%04x,%d)\n", sel, count ); sel &= ~(__AHINCR - 1); /* clear bottom bits of selector */ @@ -190,16 +189,6 @@ void SELECTOR_FreeBlock( WORD sel, WORD count ) LDT_SetEntry( i, &entry ); ldt_flags_copy[i] &= ~LDT_FLAGS_ALLOCATED; } - - /* Clear the saved 16-bit selector */ - frame = CURRENT_STACK16; - while (frame && frame->frame32) - { - if ((frame->ds >= sel) && (frame->ds < nextsel)) frame->ds = 0; - if ((frame->es >= sel) && (frame->es < nextsel)) frame->es = 0; - if ((frame->fs >= sel) && (frame->fs < nextsel)) frame->fs = 0; - frame = PTR_SEG_TO_LIN( frame->frame32->frame16 ); - } } diff --git a/miscemu/instr.c b/miscemu/instr.c index 94bbe2b74ef..48e0b11dad1 100644 --- a/miscemu/instr.c +++ b/miscemu/instr.c @@ -11,6 +11,7 @@ #include "dosexe.h" #include "miscemu.h" #include "sig_context.h" +#include "selectors.h" #include "debug.h" @@ -33,6 +34,9 @@ (IS_SELECTOR_SYSTEM(SS_sig(context)) ? (void *)ESP_sig(context) : \ (PTR_SEG_OFF_TO_LIN(SS_sig(context),STACK_sig(context))))) +/* For invalid registers fixup */ +extern DWORD CallFrom16_Start,CallFrom16_End; + /*********************************************************************** * INSTR_ReplaceSelector @@ -386,9 +390,24 @@ BOOL32 INSTR_EmulateInstruction( SIGCONTEXT *context ) case 0x1f: /* pop ds */ { WORD seg = *(WORD *)STACK_PTR( context ); + + /* Sometimes invalid selectors are left on the stackframe + * pop them if needed. + */ + if ((EIP_sig(context)>=(DWORD)&CallFrom16_Start) && + (EIP_sig(context)<(DWORD)&CallFrom16_End) + ) { + switch(*instr) { + case 0x07: ES_sig(context) = 0; break; + case 0x17: SS_sig(context) = 0; break; + case 0x1f: DS_sig(context) = 0; break; + } + STACK_sig(context) += long_op ? 4 : 2; + EIP_sig(context) += prefixlen + 1; + return TRUE; + } if ((seg = INSTR_ReplaceSelector( context, seg )) != 0) - { - switch(*instr) + { switch(*instr) { case 0x07: ES_sig(context) = seg; break; case 0x17: SS_sig(context) = seg; break; @@ -426,6 +445,14 @@ BOOL32 INSTR_EmulateInstruction( SIGCONTEXT *context ) case 0xa1: /* pop fs */ { WORD seg = *(WORD *)STACK_PTR( context ); + if ((EIP_sig(context)>=(DWORD)&CallFrom16_Start) && + (EIP_sig(context)<(DWORD)&CallFrom16_End) + ) { + FS_sig(context) = 0; + STACK_sig(context) += long_op ? 4 : 2; + EIP_sig(context) += prefixlen + 1; + return TRUE; + } if ((seg = INSTR_ReplaceSelector( context, seg )) != 0) { FS_sig(context) = seg; @@ -441,6 +468,14 @@ BOOL32 INSTR_EmulateInstruction( SIGCONTEXT *context ) case 0xa9: /* pop gs */ { WORD seg = *(WORD *)STACK_PTR( context ); + if ((EIP_sig(context)>=(DWORD)&CallFrom16_Start) && + (EIP_sig(context)<(DWORD)&CallFrom16_End) + ) { + GS_sig(context) = 0; + STACK_sig(context) += long_op ? 4 : 2; + EIP_sig(context) += prefixlen + 1; + return TRUE; + } if ((seg = INSTR_ReplaceSelector( context, seg )) != 0) { GS_sig(context) = seg; diff --git a/tools/build.c b/tools/build.c index 24edf164774..f02c91dce9c 100644 --- a/tools/build.c +++ b/tools/build.c @@ -2506,6 +2506,8 @@ static int BuildCallFrom16( FILE *outfile, char * outname, int argc, char *argv[ fprintf( outfile, "\t.align 4\n" ); fprintf( outfile, "Code_Start:\n\n" ); #endif + fprintf( outfile, PREFIX"CallFrom16_Start:\n" ); + fprintf( outfile, "\t.globl "PREFIX"CallFrom16_Start\n" ); /* Build the callback functions */ @@ -2526,6 +2528,8 @@ static int BuildCallFrom16( FILE *outfile, char * outname, int argc, char *argv[ fprintf( outfile, STRING " \"%s\\0\"\n", argv[i] + 7 ); } } + fprintf( outfile, PREFIX"CallFrom16_End:\n" ); + fprintf( outfile, "\t.globl "PREFIX"CallFrom16_End\n" ); #ifdef USE_STABS fprintf( outfile, "\t.text\n");