Clean invalid selectors on the pop %xs from the STACKFRAME itself
instead of using linked list hack.
diff --git a/memory/selector.c b/memory/selector.c
index 16bddc6..17577f3 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -162,7 +162,6 @@
{
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 @@
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 94bbe2b..48e0b11 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 @@
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 @@
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 @@
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 24edf16..f02c91d 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -2506,6 +2506,8 @@
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 @@
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");