Skip to content

Commit 377d90e

Browse files
committed
simx86: merge DoExec_fast into DoExec
Common inner loop functionality went into a new static ExecOne function, so the fast loop could be compactly written. This reduces duplicate code and makes it easier to follow the control flow.
1 parent cce5717 commit 377d90e

File tree

3 files changed

+77
-102
lines changed

3 files changed

+77
-102
lines changed

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

Lines changed: 66 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -608,30 +608,10 @@ static void Exec_post(unsigned long flg, unsigned int mem_ref,
608608
}
609609
}
610610

611-
unsigned int DoExec(TNode *G, unsigned *pLastXKey)
611+
static unsigned ExecOne(TNode *G, unsigned *mem_ref, unsigned long *flg,
612+
unsigned char *ecpu, unsigned int *pLastXKey)
612613
{
613-
unsigned long flg;
614-
unsigned char *ecpu;
615-
unsigned int mem_ref;
616614
unsigned int ePC;
617-
unsigned short seqflg = G->flags;
618-
unsigned char *SeqStart = G->addr;
619-
620-
ecpu = CPUOFFS(0);
621-
if (debug_level('e')>1) {
622-
unsigned e = exit_pending();
623-
if (e & CeS_SIGPEND) e_printf("** SIGALRM is pending\n");
624-
if (e & CeS_RPIC) e_printf("** PIC is pending\n");
625-
e_printf("==== Executing code at %p flg=%04x\n",
626-
SeqStart,seqflg);
627-
}
628-
#ifdef ASM_DUMP
629-
fprintf(aLog,"%p: exec\n",G->key);
630-
#endif
631-
#if PROFILE >= 2
632-
hitimer_t TimeStartExec;
633-
if (debug_level('e')) TimeStartExec = GETTSC();
634-
#endif
635615
/*
636616
* Just before execution comes the linker stage.
637617
* So the order is:
@@ -653,25 +633,75 @@ unsigned int DoExec(TNode *G, unsigned *pLastXKey)
653633
/* check links FROM LastXNode TO current node */
654634
if (*pLastXKey != G->key)
655635
NodeLinker(FindTree(*pLastXKey), G);
636+
ePC = Exec(mem_ref, flg, ecpu, G->addr, G->flags, pLastXKey);
637+
#ifdef SKIP_EMU_VBIOS
638+
if ((TheCPU.cs&0xf000)==config.vbios_seg && !TheCPU.err)
639+
TheCPU.err = EXCP_GOBACK;
640+
#endif
641+
return ePC;
642+
}
643+
644+
unsigned int DoExec(TNode *G, unsigned *pLastXKey)
645+
{
646+
unsigned long flg;
647+
unsigned char *ecpu;
648+
unsigned int mem_ref;
649+
unsigned int ePC;
650+
unsigned short seqflg = G->flags;
651+
int block_inhibit;
652+
#if defined(SINGLESTEP)
653+
unsigned int key = G->key;
654+
#endif
656655

656+
ecpu = CPUOFFS(0);
657+
if (debug_level('e')>1) {
658+
unsigned e = exit_pending();
659+
if (e & CeS_SIGPEND) e_printf("** SIGALRM is pending\n");
660+
if (e & CeS_RPIC) e_printf("** PIC is pending\n");
661+
e_printf("==== Executing code at %p flg=%04x\n",
662+
G->addr,seqflg);
663+
}
664+
#ifdef ASM_DUMP
665+
fprintf(aLog,"%p: exec\n",G->key);
666+
#endif
667+
#if PROFILE >= 2
668+
hitimer_t TimeStartExec;
669+
if (debug_level('e')) TimeStartExec = GETTSC();
670+
#endif
671+
/* these flags need to be checked only once for the node */
672+
G->flags &= ~(F_SPEC|F_LEAV);
673+
/* if there is just one compiled instruction inhibition
674+
should be ignored unconditionally if signals and traps
675+
were already ignored, e.g. two "sti"s in a row */
676+
block_inhibit = (seqflg & F_INHI) && G->seqnum == 1 &&
677+
(CEmuStat & CeS_INHI);
657678
flg = Exec_pre(ecpu);
658-
ePC = Exec(&mem_ref, &flg, ecpu, SeqStart, seqflg, pLastXKey);
679+
#if !defined(ASM_DUMP) && !defined(SINGLESTEP)
680+
/* try fast inner loop if nothing special is going on */
681+
if (!(EFLAGS & TF) && !block_inhibit && !debug_level('e')) {
682+
while (1) {
683+
ePC = ExecOne(G, &mem_ref, &flg, ecpu, pLastXKey);
684+
if (TheCPU.err || exit_pending() ||
685+
(seqflg & (F_INHI|F_SLFJ|F_SPEC|F_LEAV)))
686+
break;
687+
G = FindTree(ePC);
688+
if (!G || !GoodNode(G))
689+
break;
690+
seqflg = G->flags;
691+
}
692+
} else
693+
#endif
694+
ePC = ExecOne(G, &mem_ref, &flg, ecpu, pLastXKey);
659695
// G is unreliable (maybe deleted) past this point!
660696
Exec_post(flg, mem_ref, seqflg);
661697

662-
if (debug_level('e')>2 && *pLastXKey != ePC)
663-
e_printf("New LastXKey=%08x\n",*pLastXKey);
664-
665-
#ifdef SKIP_EMU_VBIOS
666-
if ((jcs&0xf000)==config.vbios_seg && !TheCPU.err)
667-
TheCPU.err = EXCP_GOBACK;
668-
#endif
669-
670698
if (debug_level('e')) {
671699
#if PROFILE >= 2
672700
ExecTime += GETTSC() - TimeStartExec;
673701
#endif
674702
if (debug_level('e')>1) {
703+
if (debug_level('e')>2 && *pLastXKey != ePC)
704+
e_printf("New LastXKey=%08x\n",*pLastXKey);
675705
e_printf("** End code, PC=%08x sig=%x\n",ePC,
676706
exit_pending());
677707
if ((debug_level('e')>3) && (seqflg & F_FPOP)) {
@@ -684,14 +714,11 @@ unsigned int DoExec(TNode *G, unsigned *pLastXKey)
684714
}
685715
}
686716
}
687-
/* signal_pending at this point is 1 if there was ANY signal,
717+
/* exit_pending at this point is non-zero if there was ANY signal,
688718
* not just a SIGALRM
689719
*/
690-
if (((seqflg & F_INHI) || (CEmuStat & CeS_STI)) &&
691-
!(G->seqnum == 1 && (CEmuStat & CeS_INHI))) {
692-
/* ignore signals and traps for movss/popss; if there is just
693-
one compiled instruction it should be ignored unconditionally
694-
if signals and traps were already ignored */
720+
if (((seqflg & F_INHI) || (CEmuStat & CeS_STI)) && !block_inhibit) {
721+
/* ignore signals and traps for movss/popss */
695722
CEmuStat |= CeS_INHI;
696723
CEmuStat &= ~CeS_TRAP;
697724
} else {
@@ -700,47 +727,10 @@ unsigned int DoExec(TNode *G, unsigned *pLastXKey)
700727
}
701728

702729
#if defined(SINGLESTEP)
703-
InvalidateNodeRange(G->key, 1, NULL);
704-
avltr_delete(G->key);
705-
#endif
706-
707-
return ePC;
708-
}
709-
710-
/* fast loop, only used if nothing special is going on; if anything
711-
out of the ordinary happens, the above DoExec() is called */
712-
unsigned int DoExec_fast(TNode *G, unsigned *pLastXKey)
713-
{
714-
unsigned char *ecpu = CPUOFFS(0);
715-
unsigned LastXKey = *pLastXKey;
716-
unsigned long flg = Exec_pre(ecpu);
717-
unsigned int ePC, mem_ref;
718-
unsigned short seqflg = G->flags;
719-
720-
do {
721-
if (LastXKey != G->key)
722-
NodeLinker(FindTree(LastXKey), G);
723-
ePC = Exec(&mem_ref, &flg, ecpu, G->addr, 0, &LastXKey);
724-
// G is unreliable (maybe deleted) past this point!
725-
if (TheCPU.err == EXCP_STISHADOW) {
726-
/* as STI can exit here as well from the middle
727-
of a block we must mirror DoExec here */
728-
CEmuStat |= CeS_INHI;
729-
CEmuStat &= ~CeS_TRAP;
730-
break;
731-
}
732-
if (exit_pending())
733-
break;
734-
#ifdef SKIP_EMU_VBIOS
735-
if ((jcs&0xf000)==config.vbios_seg && !TheCPU.err)
736-
TheCPU.err = EXCP_GOBACK;
730+
InvalidateNodeRange(key, 1, NULL);
731+
avltr_delete(key);
737732
#endif
738-
} while (!TheCPU.err && (G=FindTree(ePC)) &&
739-
!((seqflg=G->flags) & (F_FPOP|F_INHI|F_SLFJ)) && GoodNode(G));
740733

741-
CEmuStat |= exit_pending_xchg(0);
742-
Exec_post(flg, mem_ref, G ? seqflg : 0);
743-
*pLastXKey = LastXKey;
744734
return ePC;
745735
}
746736

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,6 @@ extern unsigned (*Exec)(unsigned *mem_ref, unsigned long *flg,
229229
unsigned char *ecpu, void *SeqStart,
230230
unsigned short seqflg, unsigned *seqbase);
231231
unsigned int DoExec(TNode *G, unsigned *LastXKey);
232-
unsigned int DoExec_fast(TNode *G, unsigned *LastXKey);
233232
void EndGen(void);
234233
extern void fp87_mask_except(void);
235234
extern void fp87_save_except(void);

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

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -444,41 +444,27 @@ static unsigned int FindExecCode(unsigned int PC)
444444
error("@corrupted at %x\n", G->key + j);
445445
}
446446
/* ---- this is the MAIN EXECUTE point ---- */
447+
unsigned short seqflg = G->flags;
447448
NodesExecd++;
448449
#if PROFILE
449450
TotalNodesExecd++;
450-
if (G->flags & F_PREJ)
451+
if (seqflg & F_PREJ)
451452
PrejitNodesExecd++;
452453
#endif
453454
assert(G->seqlen);
454-
#if !defined(ASM_DUMP) && !defined(SINGLESTEP)
455-
/* try fast inner loop if nothing special is going on */
456-
if (!(EFLAGS & TF) && !(CEmuStat & (CeS_INHI)) &&
457-
!debug_level('e') &&
458-
GoodNode(G) && !(G->flags & (F_FPOP|F_INHI|F_SPEC|F_LEAV)))
459-
PC = DoExec_fast(G, &LastXKey);
460-
else
461-
#endif
462-
{
463-
unsigned short seqflg = G->flags;
464-
G->flags &= ~(F_SPEC|F_LEAV);
465455
#if SPEC_PREJIT
466-
if (seqflg & F_SPEC)
467-
prejit_run(G);
456+
if (seqflg & F_SPEC)
457+
prejit_run(G);
468458
#endif
469-
PC = DoExec(G, &LastXKey);
470-
// G is unreliable (maybe deleted) past this point!
459+
PC = DoExec(G, &LastXKey);
460+
// G is unreliable (maybe deleted) past this point!
471461
#if SPEC_PREJIT
472-
if (seqflg & F_SPEC) {
473-
prejit_sync();
474-
}
475-
#endif
476-
if (seqflg & F_LEAV) {
477-
TheCPU.err = EXCP_EMULEAVE;
478-
}
479-
}
480-
#if PROFILE
462+
if (seqflg & F_SPEC)
463+
prejit_sync();
481464
#endif
465+
if (seqflg & F_LEAV)
466+
TheCPU.err = EXCP_EMULEAVE;
467+
482468
if (TheCPU.err) return PC;
483469
if (CEmuStat & (CeS_TRAP|CeS_DRTRAP|CeS_SIGPEND|CeS_RPIC))
484470
HandleEmuSignals();

0 commit comments

Comments
 (0)