Skip to content

Commit abd5f00

Browse files
committed
simx86: lret etc: new eip value in protmode via Sim_helper return
We can avoid setting TheCPU.eip if Sim_helper returns the new eip in eax, and as vm86 iret already calls Sim_helper anyway, use it for the cs:eip handling as well. So now the only places left that set TheCPU.eip are RETl and RETlisp in vm86, which are fully compiled there. Modifying O_POP2 and A_SR_SH4 to avoid %eax is a little tricky.
1 parent 4ebec28 commit abd5f00

File tree

2 files changed

+13
-19
lines changed

2 files changed

+13
-19
lines changed

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

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3096,34 +3096,37 @@ static unsigned int _Sim_helper(unsigned int mem_ref, unsigned int data, int mod
30963096
/*ca*/ case RETlisp:
30973097
/*cb*/ case RETl:
30983098
/*cf*/ case IRET: { /* restartable */
3099-
if (!REALADDR()) {
3099+
temp = data;
3100+
if (!REALADDR() || opc == IRET) {
31003101
unsigned int cs, eip;
31013102
unsigned int sp = rESP & TheCPU.StackMask;
31023103
if (mode&DATA16) {
31033104
eip = POPw(sp);
31043105
cs = POPw(sp);
3105-
if (opc == IRET) data = POPw(sp);
3106+
if (opc == IRET) temp = POPw(sp);
31063107
}
31073108
else {
31083109
eip = POPl(sp);
31093110
cs = POPl(sp);
3110-
if (opc == IRET) data = POPl(sp);
3111+
if (opc == IRET) temp = POPl(sp);
31113112
}
31123113
if (opc == RETlisp) {
31133114
sp += arg;
31143115
sp &= TheCPU.StackMask;
31153116
}
31163117
rESP = sp | (rESP&~TheCPU.StackMask);
3117-
if (SetSegProt_helper(cs, Ofs_CS) < 0)
3118+
if (REALADDR()) {
3119+
TheCPU.cs = cs;
3120+
LONG_CS = cs << 4;
3121+
}
3122+
else if (SetSegProt_helper(cs, Ofs_CS) < 0)
31183123
break;
3119-
/* safe to do here after any potential
3120-
page fault: we return to the main loop after */
3121-
TheCPU.eip = eip;
3124+
/* eax used by JMP_INDIRECT */
3125+
data = eip;
31223126
}
31233127
if (opc != IRET) break;
31243128
/* non-segment GPF handled in interpreter */
31253129
assert(!(V86MODE() && IOPL!=3 && !(TheCPU.cr[4] & CR4_VME)));
3126-
temp = data;
31273130
/* IRET always returns with the new PC;
31283131
TF is set via a negative exception code that doesn't
31293132
interrupt the IRET */

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

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,6 @@ static unsigned int JumpGen(unsigned int P2, unsigned int Interp_LONG_CS,
323323
Gen(JMP_LINK, mode, j_t, InstrMeta[0].npc);
324324
break;
325325
case RETl: case RETlisp: case IRET: // far ret, indirect
326-
Gen(L_REG, mode, Ofs_EIP);
327-
/* fall through */
328326
case JMPli: case CALLli: case INT: // far jmp/call, indirect
329327
case RET: case RETisp: case JMPi: case CALLi: // ret, indirect
330328
Gen(JMP_INDIRECT, mode);
@@ -1695,6 +1693,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)];
16951693
Gen(O_POP2, _mode|MNOREG|MRETISP, dr);
16961694
AddrGen(A_SR_SH4, _mode, Ofs_CS, Ofs_XCS);
16971695
Gen(O_POP3, _mode);
1696+
Gen(L_REG, _mode, Ofs_EIP);
16981697
}
16991698
else {
17001699
Gen(O_SIM, _mode, opc, dr, P0);
@@ -1773,6 +1772,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)];
17731772
Gen(O_POP2, _mode|MNOREG);
17741773
AddrGen(A_SR_SH4, _mode, Ofs_CS, Ofs_XCS);
17751774
Gen(O_POP3, _mode);
1775+
Gen(L_REG, _mode, Ofs_EIP);
17761776
}
17771777
else {
17781778
Gen(O_SIM, _mode, opc, 0, P0);
@@ -1784,15 +1784,6 @@ intop3b: { int op = ArOpsFR[D_MO(opc)];
17841784
if (V86MODE() && IOPL!=3 && !(TheCPU.cr[4] & CR4_VME)) {
17851785
PC++; goto not_permitted; /* GPF */
17861786
}
1787-
if (REALADDR()) {
1788-
/* pop from stack without adjusting esp before A_SR_* */
1789-
Gen(O_POP1, _mode);
1790-
Gen(O_POP2, _mode, Ofs_EIP);
1791-
Gen(O_POP2, _mode|MNOREG);
1792-
AddrGen(A_SR_SH4, _mode, Ofs_CS, Ofs_XCS);
1793-
Gen(O_POP3, _mode);
1794-
Gen(O_POP, _mode);
1795-
}
17961787
Gen(O_SIM, _mode, opc, 0, P0);
17971788
PC = JumpGen(PC, Interp_LONG_CS, _mode, opc, 1);
17981789
break;

0 commit comments

Comments
 (0)