@@ -383,7 +383,7 @@ static unsigned int FindExecCode(unsigned int PC)
383383 while (1 ) {
384384 if (EFLAGS & TF )
385385 CEmuStat |= CeS_TRAP ;
386- if (CEmuStat & ( CeS_TRAP | CeS_STI ) )
386+ if (CEmuStat & CeS_TRAP )
387387 TheCPU .mode |= MSSTP ;
388388 else
389389 TheCPU .mode &= ~MSSTP ;
@@ -512,7 +512,7 @@ void Interp86(void)
512512 return ;
513513 }
514514
515- CEmuStat &= ~( CeS_TRAP | CeS_STI ) ;
515+ CEmuStat &= ~CeS_TRAP ;
516516
517517 PC = LONG_CS + TheCPU .eip ;
518518 assert (CurrIMeta < 0 );
@@ -607,7 +607,14 @@ static unsigned int InterpOne(unsigned int PC, unsigned int Interp_LONG_CS,
607607 signed char OVERR_DS = Ofs_XDS ;
608608 signed char OVERR_SS = Ofs_XSS ;
609609
610- if (!NewIMeta (P0 )) {
610+ /* sti, pop ss, or mov ss recursively call InterpOne to make
611+ sure the next instruction is in the same block so it
612+ it cannot be interrupted. This only applies strictly to the
613+ next instruction, the inhibition doesn't last past two "sti"s
614+ for example. We must signal to NewIMeta that we want one more
615+ item.
616+ */
617+ if (!NewIMeta (P0 , (basemode & MINHI ) ? 1 : 0 )) {
611618 if (debug_level ('e' )> 2 )
612619 e_printf ("============ Tab full:cannot close sequence\n" );
613620
@@ -878,8 +885,10 @@ intop3b: { int op = ArOpsFR[D_MO(opc)];
878885 AddrGen (A_SR_PROT , _mode , Ofs_SS , P0 );
879886 Gen (O_POP3 , _mode );
880887 }
881- InstrMeta [CurrIMeta ].flags |= F_INHI ;
882888 PC ++ ;
889+ if (!(_mode & MINHI ))
890+ PC = InterpOne (PC , Interp_LONG_CS , ocs ,
891+ basemode |MINHI );
883892 break ;
884893/*1f*/ case POPds : _mode |= SEGREG ;
885894 if (REALADDR ()) {
@@ -1324,8 +1333,9 @@ intop3b: { int op = ArOpsFR[D_MO(opc)];
13241333 else {
13251334 AddrGen (A_SR_PROT , _mode , REG1 , P0 );
13261335 }
1327- if (REG1 == Ofs_SS )
1328- InstrMeta [CurrIMeta ].flags |= F_INHI ;
1336+ if (REG1 == Ofs_SS && !(_mode & MINHI ))
1337+ PC = InterpOne (PC , Interp_LONG_CS , ocs ,
1338+ basemode |MINHI );
13291339 break ;
13301340
13311341/*9b*/ case oWAIT :
@@ -2088,8 +2098,16 @@ intop3b: { int op = ArOpsFR[D_MO(opc)];
20882098 Gen (O_SIM , _mode , opc , 0 , PC );
20892099 /* real mode inhibits after STI as well but
20902100 we've always relied on trapping behaviour with vm86 */
2091- if (!V86MODE ())
2092- InstrMeta [CurrIMeta ].flags |= F_INHI ;
2101+ if (!V86MODE () && !(_mode & MINHI )) {
2102+ PC = InterpOne (PC , Interp_LONG_CS , ocs ,
2103+ basemode |MINHI |MSSTP );
2104+ /* check signals immediately after the
2105+ instruction following STI, if it's not
2106+ already a jump */
2107+ IMeta * GL = & InstrMeta [CurrIMeta ];
2108+ if (GL -> gen [GL -> ngen - 1 ].op < JMP_TAILCODE )
2109+ Gen (JMP_LINK , _mode |CKSIGN , PC , InstrMeta [0 ].npc );
2110+ }
20932111 break ;
20942112/*fc*/ case CLD : PC ++ ;
20952113 Gen (O_SETFL , _mode , CLD );
0 commit comments