Skip to content

Commit b41c85f

Browse files
committed
simx86: handle popss/movss/sti inhibition at compile time
We force the generation of one more instruction within the same block using a recursive call to InterpOne, so no interruption is possible there. Then, for STI only, a signal check is generated for the instuction past STI. This cleans up the DoExec checks considerably.
1 parent 4cc0530 commit b41c85f

File tree

7 files changed

+36
-47
lines changed

7 files changed

+36
-47
lines changed

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3310,7 +3310,6 @@ static unsigned int _Sim_helper(unsigned int mem_ref, unsigned int data, int mod
33103310
EFLAGS);
33113311
/* force exit after next compiled block execution */
33123312
exit_pending_or(CeS_RPIC);
3313-
TheCPU.err = EXCP_STISHADOW;
33143313
}
33153314
}
33163315
break;

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

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -458,16 +458,7 @@ static CodeBuf *ProduceCode(unsigned int PC, IMeta *I0)
458458
cp1 = CodePtr;
459459
}
460460
I->len = CodePtr - cp;
461-
if (i > 0) {
462-
/* F_INHI (pop ss/mov ss) only applies to the last
463-
instruction in the sequence and not twice in
464-
a row */
465-
if ((I->flags & F_INHI) && !(I0->flags & F_INHI))
466-
I0->flags |= F_INHI;
467-
else
468-
I0->flags &= ~F_INHI;
469-
I0->flags |= I->flags & ~F_INHI;
470-
}
461+
I0->flags |= I->flags;
471462
if (debug_level('e')>3) {
472463
if (debug_level('e')>4) {
473464
e_printf("Metadata %03d PC=%08x flags=%x(%x) ng=%d\n",
@@ -593,12 +584,7 @@ static void Exec_post(unsigned long flg, unsigned int mem_ref,
593584
{
594585
EFLAGS = (EFLAGS & ~EFLAGS_CC) | (flg & EFLAGS_CC);
595586
TheCPU.mem_ref = mem_ref;
596-
CEmuStat &= ~CeS_STI;
597587
TheCPU.err = abs(TheCPU.err);
598-
if (TheCPU.err == EXCP_STISHADOW) {
599-
CEmuStat |= CeS_STI;
600-
TheCPU.err = 0;
601-
}
602588
if (TheCPU.err == EXCP_TFSET)
603589
TheCPU.err = 0;
604590
/* checking for infinite loops, flagged in JumpGen() */
@@ -648,7 +634,6 @@ unsigned int DoExec(TNode *G, unsigned *pLastXKey)
648634
unsigned int mem_ref;
649635
unsigned int ePC;
650636
unsigned short seqflg = G->flags;
651-
int block_inhibit;
652637
#if defined(SINGLESTEP)
653638
unsigned int key = G->key;
654639
#endif
@@ -670,19 +655,14 @@ unsigned int DoExec(TNode *G, unsigned *pLastXKey)
670655
#endif
671656
/* these flags need to be checked only once for the node */
672657
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);
678658
flg = Exec_pre(ecpu);
679659
#if !defined(ASM_DUMP) && !defined(SINGLESTEP)
680660
/* try fast inner loop if nothing special is going on */
681-
if (!(EFLAGS & TF) && !block_inhibit && !debug_level('e')) {
661+
if (!(EFLAGS & TF) && !debug_level('e')) {
682662
while (1) {
683663
ePC = ExecOne(G, &mem_ref, &flg, ecpu, pLastXKey);
684664
if (TheCPU.err || exit_pending() ||
685-
(seqflg & (F_INHI|F_SLFJ|F_SPEC|F_LEAV)))
665+
(seqflg & (F_SLFJ|F_SPEC|F_LEAV)))
686666
break;
687667
G = FindTree(ePC);
688668
if (!G || !GoodNode(G))
@@ -717,14 +697,7 @@ unsigned int DoExec(TNode *G, unsigned *pLastXKey)
717697
/* exit_pending at this point is non-zero if there was ANY signal,
718698
* not just a SIGALRM
719699
*/
720-
if (((seqflg & F_INHI) || (CEmuStat & CeS_STI)) && !block_inhibit) {
721-
/* ignore signals and traps for movss/popss */
722-
CEmuStat |= CeS_INHI;
723-
CEmuStat &= ~CeS_TRAP;
724-
} else {
725-
CEmuStat &= ~(CeS_INHI|CeS_STI);
726-
CEmuStat |= exit_pending_xchg(0);
727-
}
700+
CEmuStat |= exit_pending_xchg(0);
728701

729702
#if defined(SINGLESTEP)
730703
InvalidateNodeRange(key, 1, NULL);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,12 @@
188188
#define MREPCOND 0x01000000 // this is SCASx or CMPSx, REP can be terminated
189189
// by flags
190190
#define MSSTP 0x02000000 // generate only one instruction
191+
#define MINHI 0x04000000 // inhibits IRQs (MOVss/POPss/STI)
191192

192193
// values for TNode.flags and IMeta.flags
193194
#define F_FPOP 0x0001 // has at least one FP instruction
194195
#define F_SPEC 0x0002 // start speculative prejit when executing this node
195196
#define F_SLFL 0x0004 // links to itself
196-
#define F_INHI 0x0008 // inhibits IRQs (MOVss/POPss/STI)
197197
#define F_PREJ 0x0010 // generated by any prejit thread
198198
#define F_SPRJ 0x0020 // generated by speculative prejit thread
199199
#define F_LEAV 0x0040 // leave instremu after executing this node
@@ -216,7 +216,7 @@ static __inline__ int FastLog2(int v)
216216
/////////////////////////////////////////////////////////////////////////////
217217

218218
void InitGen(void);
219-
int NewIMeta(int npc);
219+
int NewIMeta(int npc, int override);
220220
extern int CurrIMeta;
221221
extern void Gen(int op, int mode, ...);
222222
extern void AddrGen(int op, int mode, ...);

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,6 @@ extern int SpecPrejits;
681681
#define EXCP_MODESWITCH 68
682682
#define EXCP_EMULEAVE 69
683683
#define EXCP_TFSET 71
684-
#define EXCP_STISHADOW 72
685684

686685
/////////////////////////////////////////////////////////////////////////////
687686

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

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,15 +1622,17 @@ int e_invalidate_page_full(unsigned data)
16221622

16231623
/////////////////////////////////////////////////////////////////////////////
16241624

1625-
int NewIMeta(int npc)
1625+
int NewIMeta(int npc, int override)
16261626
{
16271627
int ret = 0;
16281628
#if PROFILE >= 2
16291629
hitimer_t t0 = 0;
16301630

16311631
if (debug_level('e')) t0 = GETTSC();
16321632
#endif
1633-
if (CurrIMeta < MAXINODES-1) {
1633+
/* normally we have max MAXINODES-1 instructions in the buffer, but
1634+
we allow one more for the instruction following STI/POPss/MOVss */
1635+
if (CurrIMeta < MAXINODES-2+override) {
16341636
// add new opcode metadata
16351637
IMeta *I,*I0;
16361638

src/include/cpu-emu.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ extern void e_priv_iopl(int);
5050
#define CeS_SIGPEND 0x01 /* signal pending mask */
5151
#define CeS_SIGACT 0x02 /* signal active mask */
5252
#define CeS_RPIC 0x04 /* pic asks for interruption */
53-
#define CeS_STI 0x08 /* STI shadow active */
54-
#define CeS_INHI 0x800 /* inhibit interrupts(pop ss; pop sp et sim.) */
5553
#define CeS_TRAP 0x1000 /* INT01 Sstep active */
5654
#define CeS_DRTRAP 0x2000 /* Debug Registers active */
5755
#define CeS_INSTREMU_RM 0x4000

0 commit comments

Comments
 (0)