Skip to content

Commit 7a74028

Browse files
committed
simx86: eliminate exit_INHI for STI
Using TheCPU.eip for the block we can reliably check in DoExec if the last executed block needs to inhibit ints, and as STI checks signals immediately after it will trigger that check. Similarly we can detect forever loops for the last block. Flagging back refs in the node linker can then be limited to blocks with F_FPOP (the original purpose of that flagging).
1 parent becb4eb commit 7a74028

File tree

4 files changed

+36
-31
lines changed

4 files changed

+36
-31
lines changed

src/base/emu-i386/simx86/codegen-sim.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3305,7 +3305,7 @@ static unsigned int _Sim_helper(unsigned int mem_ref, unsigned int data, int mod
33053305
e_printf("Return for STI ASAP fl=%08x\n",
33063306
EFLAGS);
33073307
/* force exit after next compiled block execution */
3308-
exit_pending_or(exit_RPIC|exit_INHI);
3308+
exit_pending_or(exit_RPIC);
33093309
}
33103310
}
33113311
break;

src/base/emu-i386/simx86/codegen.c

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -589,16 +589,10 @@ static unsigned int Exec_pre(unsigned char *ecpu)
589589
return flg;
590590
}
591591

592-
static void Exec_post(unsigned long flg, unsigned int mem_ref,
593-
unsigned short seqflg)
592+
static void Exec_post(unsigned long flg, unsigned int mem_ref)
594593
{
595594
EFLAGS = (EFLAGS & ~EFLAGS_CC) | (flg & EFLAGS_CC);
596595
TheCPU.mem_ref = mem_ref;
597-
/* checking for infinite loops, flagged in JumpGen() */
598-
if ((seqflg & F_SLFJ) && !(EFLAGS & (VIF|IF|TF))) {
599-
error("!Forever loop!\n");
600-
leavedos_main(0xebfe);
601-
}
602596
}
603597

604598
static void HandleEmuSignals(int tfset)
@@ -612,8 +606,7 @@ static void HandleEmuSignals(int tfset)
612606
#endif
613607
if (tfset) {
614608
/* force exit for single step trap */
615-
if (!TheCPU.err)
616-
TheCPU.err = EXCP01_SSTP;
609+
TheCPU.err = EXCP01_SSTP;
617610
}
618611
//else if (CEmuStat & CeS_DRTRAP) {
619612
// if (e_debug_check(PC)) {
@@ -695,8 +688,6 @@ unsigned int DoExec(TNode *G, unsigned *pLastXKey)
695688
hitimer_t TimeStartExec;
696689
if (debug_level('e')) TimeStartExec = GETTSC();
697690
#endif
698-
/* these flags need to be checked only once for the node */
699-
G->flags &= ~(F_SPEC|F_LEAV);
700691
/* if there is just one compiled instruction inhibition
701692
should be ignored unconditionally if signals and traps
702693
were already ignored, e.g. two "sti"s in a row */
@@ -706,22 +697,25 @@ unsigned int DoExec(TNode *G, unsigned *pLastXKey)
706697
flg = Exec_pre(ecpu);
707698
#if !defined(ASM_DUMP) && !defined(SINGLESTEP)
708699
/* try fast inner loop if nothing special is going on */
709-
if (!tfset && !block_inhibit && !debug_level('e')) {
700+
if (!tfset && !block_inhibit && !debug_level('e') &&
701+
!(seqflg & (F_SPEC|F_LEAV))) {
710702
while (1) {
711703
ePC = ExecOne(G, &mem_ref, &flg, ecpu, pLastXKey);
712-
if (TheCPU.err || exit_pending() ||
713-
(seqflg & (F_INHI|F_SLFJ|F_SPEC|F_LEAV)))
704+
if (TheCPU.err || exit_pending())
714705
break;
715706
G = FindTree(ePC);
716707
if (!G || !GoodNode(G))
717708
break;
718-
seqflg = G->flags;
719709
}
720710
} else
721711
#endif
712+
{
713+
/* these flags need to be checked only once for the node */
714+
G->flags &= ~(F_SPEC|F_LEAV);
722715
ePC = ExecOne(G, &mem_ref, &flg, ecpu, pLastXKey);
716+
}
723717
// G is unreliable (maybe deleted) past this point!
724-
Exec_post(flg, mem_ref, seqflg);
718+
Exec_post(flg, mem_ref);
725719

726720
if (debug_level('e')) {
727721
#if PROFILE >= 2
@@ -745,14 +739,27 @@ unsigned int DoExec(TNode *G, unsigned *pLastXKey)
745739
/* exit_pending at this point is non-zero if there was ANY signal,
746740
* not just a SIGALRM
747741
*/
748-
if (((seqflg & F_INHI) || (exit_pending() & exit_INHI)) && !block_inhibit) {
749-
/* ignore signals and traps for movss/popss */
750-
CEmuStat |= CeS_INHI;
751-
if (exit_pending() & exit_INHI)
752-
exit_pending_and(~exit_INHI);
753-
} else {
754-
CEmuStat &= ~CeS_INHI;
755-
HandleEmuSignals(tfset);
742+
CEmuStat &= ~CeS_INHI;
743+
if (TheCPU.err) {
744+
/* CPU exceptions override everything else */
745+
exit_pending_w(0);
746+
}
747+
else if (exit_pending() || tfset) {
748+
/* TheCPU.eip points to the first instruction of the last
749+
executed block, except for real-mode retf, which neither
750+
inhibits interrupts nor causes forever loops */
751+
TNode *LastG = FindTree(LONG_CS + TheCPU.eip);
752+
seqflg = LastG ? LastG->flags : 0;
753+
if ((seqflg & F_INHI) && !block_inhibit)
754+
/* ignore signals and traps for movss/popss */
755+
CEmuStat |= CeS_INHI;
756+
else
757+
HandleEmuSignals(tfset);
758+
/* checking for infinite loops, flagged in JumpGen() */
759+
if ((seqflg & F_SLFJ) && !(EFLAGS & (VIF|IF|TF))) {
760+
error("!Forever loop!\n");
761+
leavedos_main(0xebfe);
762+
}
756763
}
757764

758765
#if defined(SINGLESTEP)

src/base/emu-i386/simx86/emu86.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -683,9 +683,8 @@ extern int SpecPrejits;
683683

684684
#define exit_SIGPEND 0x01 /* signal pending mask */
685685
#define exit_RPIC 0x02 /* pic asks for interruption */
686-
#define exit_STI 0x04 /* STI shadow active */
687-
#define exit_INHI 0x08 /* inhibit interrupts(pop ss; pop sp et sim.) */
688-
#define exit_TRAP 0x10 /* INT01 Sstep set by POPF/IRET */
686+
#define exit_STI 0x04 /* exit from IF set with VIP active in vm86 */
687+
#define exit_TRAP 0x08 /* INT01 Sstep set by POPF/IRET */
689688

690689
/////////////////////////////////////////////////////////////////////////////
691690

src/base/emu-i386/simx86/trees.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -750,8 +750,7 @@ static void linknode(TNode *LG, TNode *G, linkdesc *L, unsigned target_type)
750750
backref *B;
751751

752752
// points to current node, which can't be a forever loop?
753-
if (L->target!=G->key || !(LG->unlinked_jmp_targets & target_type) ||
754-
(G->flags & F_SLFJ))
753+
if (L->target!=G->key || !(LG->unlinked_jmp_targets & target_type))
755754
return;
756755

757756
if (L->ref!=0) {
@@ -787,7 +786,7 @@ static void linknode(TNode *LG, TNode *G, linkdesc *L, unsigned target_type)
787786
G,G->key,G->addr,
788787
L->target, B->branch, G->nrefs, L->ref, *L->ref);
789788
}
790-
_nodeflagbackrefs(LG, G->flags);
789+
_nodeflagbackrefs(LG, G->flags&F_FPOP);
791790
if (debug_level('e')>8) {
792791
backref *bk = G->bkr.next;
793792
#ifdef DEBUG_LINKER

0 commit comments

Comments
 (0)