--- np2/i386c/ia32/instructions/ctrl_trans.c 2005/02/04 05:32:24 1.17 +++ np2/i386c/ia32/instructions/ctrl_trans.c 2008/03/22 04:03:08 1.24 @@ -1,4 +1,4 @@ -/* $Id: ctrl_trans.c,v 1.17 2005/02/04 05:32:24 yui Exp $ */ +/* $Id: ctrl_trans.c,v 1.24 2008/03/22 04:03:08 monaka Exp $ */ /* * Copyright (c) 2002-2003 NONAKA Kimihiro @@ -12,8 +12,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -34,6 +32,10 @@ #include "ctrl_trans.h" +#if defined(ENABLE_TRAP) +#include "inttrap.h" +#endif + /* * JMP @@ -41,52 +43,42 @@ void JMP_Jb(void) { - UINT32 ip; - CPU_WORKCLOCK(7); - GET_PCBYTESD(ip); - ADD_EIP(ip); - CPU_PREFETCH_CLEAR(); + JMPSHORT(7); } void JMP_Jw(void) { - UINT32 ip; - CPU_WORKCLOCK(7); - GET_PCWORDS(ip); - ADD_EIP(ip); - CPU_PREFETCH_CLEAR(); + JMPNEAR(7); } void JMP_Jd(void) { - UINT32 ip; - CPU_WORKCLOCK(7); - GET_PCDWORD(ip); - ADD_EIP(ip); - CPU_PREFETCH_CLEAR(); + JMPNEAR32(7); } void JMP_Ew(UINT32 op) { UINT32 madr; - UINT32 new_ip; + UINT16 new_ip; if (op >= 0xc0) { CPU_WORKCLOCK(7); new_ip = *(reg16_b20[op]); - SET_EIP(new_ip); } else { CPU_WORKCLOCK(11); madr = calc_ea_dst(op); new_ip = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - SET_EIP(new_ip); } + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; } void @@ -98,28 +90,37 @@ JMP_Ed(UINT32 op) if (op >= 0xc0) { CPU_WORKCLOCK(7); new_ip = *(reg32_b20[op]); - SET_EIP(new_ip); } else { CPU_WORKCLOCK(11); madr = calc_ea_dst(op); new_ip = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - SET_EIP(new_ip); } + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; } void JMP16_Ap(void) { - UINT32 new_ip; + descriptor_t sd; + UINT16 new_ip; UINT16 new_cs; + UINT16 sreg; CPU_WORKCLOCK(11); GET_PCWORD(new_ip); GET_PCWORD(new_cs); if (!CPU_STAT_PM || CPU_STAT_VM86) { /* Real mode or VM86 mode */ - CPU_SET_SEGREG(CPU_CS_INDEX, new_cs); - SET_EIP(new_ip); + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; } else { /* Protected mode */ JMPfar_pm(new_cs, new_ip); @@ -129,16 +130,23 @@ JMP16_Ap(void) void JMP32_Ap(void) { + descriptor_t sd; UINT32 new_ip; UINT16 new_cs; + UINT16 sreg; CPU_WORKCLOCK(11); GET_PCDWORD(new_ip); GET_PCWORD(new_cs); if (!CPU_STAT_PM || CPU_STAT_VM86) { /* Real mode or VM86 mode */ - CPU_SET_SEGREG(CPU_CS_INDEX, new_cs); - SET_EIP(new_ip); + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; } else { /* Protected mode */ JMPfar_pm(new_cs, new_ip); @@ -148,9 +156,11 @@ JMP32_Ap(void) void JMP16_Ep(UINT32 op) { + descriptor_t sd; UINT32 madr; - UINT32 new_ip; + UINT16 new_ip; UINT16 new_cs; + UINT16 sreg; CPU_WORKCLOCK(11); if (op < 0xc0) { @@ -159,8 +169,13 @@ JMP16_Ep(UINT32 op) new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); if (!CPU_STAT_PM || CPU_STAT_VM86) { /* Real mode or VM86 mode */ - CPU_SET_SEGREG(CPU_CS_INDEX, new_cs); - SET_EIP(new_ip); + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; } else { /* Protected mode */ JMPfar_pm(new_cs, new_ip); @@ -173,9 +188,11 @@ JMP16_Ep(UINT32 op) void JMP32_Ep(UINT32 op) { + descriptor_t sd; UINT32 madr; UINT32 new_ip; UINT16 new_cs; + UINT16 sreg; CPU_WORKCLOCK(11); if (op < 0xc0) { @@ -184,8 +201,13 @@ JMP32_Ep(UINT32 op) new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); if (!CPU_STAT_PM || CPU_STAT_VM86) { /* Real mode or VM86 mode */ - CPU_SET_SEGREG(CPU_CS_INDEX, new_cs); - SET_EIP(new_ip); + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; } else { /* Protected mode */ JMPfar_pm(new_cs, new_ip); @@ -225,7 +247,7 @@ JO_Jd(void) if (CC_NO) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -259,7 +281,7 @@ JNO_Jd(void) if (CC_O) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -293,7 +315,7 @@ JC_Jd(void) if (CC_NC) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -325,7 +347,7 @@ JNC_Jd(void) if (CC_C) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -359,7 +381,7 @@ JZ_Jd(void) if (CC_NZ) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -393,7 +415,7 @@ JNZ_Jd(void) if (CC_Z) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -427,7 +449,7 @@ JNA_Jd(void) if (CC_A) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -461,7 +483,7 @@ JA_Jd(void) if (CC_NA) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -495,7 +517,7 @@ JS_Jd(void) if (CC_NS) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -529,7 +551,7 @@ JNS_Jd(void) if (CC_S) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -563,7 +585,7 @@ JP_Jd(void) if (CC_NP) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -597,7 +619,7 @@ JNP_Jd(void) if (CC_P) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -631,7 +653,7 @@ JL_Jd(void) if (CC_NL) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -665,7 +687,7 @@ JNL_Jd(void) if (CC_L) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -699,7 +721,7 @@ JLE_Jd(void) if (CC_NLE) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -733,7 +755,7 @@ JNLE_Jd(void) if (CC_LE) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -743,16 +765,16 @@ JeCXZ_Jb(void) { if (!CPU_INST_AS32) { - if (CPU_CX) { - JMPNOP(4, 1); - } else { + if (CPU_CX == 0) { JMPSHORT(8); + } else { + JMPNOP(4, 1); } } else { - if (CPU_ECX) { - JMPNOP(4, 1); - } else { + if (CPU_ECX == 0) { JMPSHORT(8); + } else { + JMPNOP(4, 1); } } } @@ -764,21 +786,24 @@ JeCXZ_Jb(void) void LOOPNE_Jb(void) { + UINT32 cx; if (!CPU_INST_AS32) { - CPU_CX--; - if (CPU_CX == 0 || (CPU_FLAGL & Z_FLAG)) { - JMPNOP(4, 1); - } else { + cx = CPU_CX; + if (--cx != 0 && CC_NZ) { JMPSHORT(8); + } else { + JMPNOP(4, 1); } + CPU_CX--; } else { - CPU_ECX--; - if (CPU_ECX == 0 || (CPU_FLAGL & Z_FLAG)) { - JMPNOP(4, 1); - } else { + cx = CPU_ECX; + if (--cx != 0 && CC_NZ) { JMPSHORT(8); + } else { + JMPNOP(4, 1); } + CPU_ECX--; } } @@ -786,21 +811,24 @@ LOOPNE_Jb(void) void LOOPE_Jb(void) { + UINT32 cx; if (!CPU_INST_AS32) { - CPU_CX--; - if (CPU_CX == 0 || !(CPU_FLAGL & Z_FLAG)) { - JMPNOP(4, 1); - } else { + cx = CPU_CX; + if (--cx != 0 && CC_Z) { JMPSHORT(8); + } else { + JMPNOP(4, 1); } + CPU_CX--; } else { - CPU_ECX--; - if (CPU_ECX == 0 || !(CPU_FLAGL & Z_FLAG)) { - JMPNOP(4, 1); - } else { + cx = CPU_ECX; + if (--cx != 0 && CC_Z) { JMPSHORT(8); + } else { + JMPNOP(4, 1); } + CPU_ECX--; } } @@ -808,21 +836,24 @@ LOOPE_Jb(void) void LOOP_Jb(void) { + UINT32 cx; if (!CPU_INST_AS32) { - CPU_CX--; - if (CPU_CX == 0) { - JMPNOP(4, 1); - } else { + cx = CPU_CX; + if (--cx != 0) { JMPSHORT(8); + } else { + JMPNOP(4, 1); } + CPU_CX--; } else { - CPU_ECX--; - if (CPU_ECX == 0) { - JMPNOP(4, 1); - } else { + cx = CPU_ECX; + if (--cx != 0) { JMPSHORT(8); + } else { + JMPNOP(4, 1); } + CPU_ECX--; } } @@ -832,32 +863,40 @@ LOOP_Jb(void) void CALL_Aw(void) { - SINT32 ip; + UINT16 new_ip; + SINT16 dest; CPU_WORKCLOCK(7); - GET_PCWORDS(ip); + GET_PCWORDS(dest); + new_ip = CPU_EIP + dest; + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } PUSH0_16(CPU_IP); - ADD_EIP(ip); - CPU_PREFETCH_CLEAR(); + CPU_EIP = new_ip; } void CALL_Ad(void) { - UINT32 ip; + UINT32 new_ip; + UINT32 dest; CPU_WORKCLOCK(7); - GET_PCDWORD(ip); + GET_PCDWORD(dest); + new_ip = CPU_EIP + dest; + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } PUSH0_32(CPU_EIP); - ADD_EIP(ip); - CPU_PREFETCH_CLEAR(); + CPU_EIP = new_ip; } void CALL_Ew(UINT32 op) { UINT32 madr; - UINT32 new_ip; + UINT16 new_ip; if (op >= 0xc0) { CPU_WORKCLOCK(7); @@ -867,8 +906,11 @@ CALL_Ew(UINT32 op) madr = calc_ea_dst(op); new_ip = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); } + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } PUSH0_16(CPU_IP); - SET_EIP(new_ip); + CPU_EIP = new_ip; } void @@ -885,26 +927,37 @@ CALL_Ed(UINT32 op) madr = calc_ea_dst(op); new_ip = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); } + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } PUSH0_32(CPU_EIP); - SET_EIP(new_ip); + CPU_EIP = new_ip; } void CALL16_Ap(void) { - UINT32 new_ip; + descriptor_t sd; + UINT16 new_ip; UINT16 new_cs; + UINT16 sreg; CPU_WORKCLOCK(13); GET_PCWORD(new_ip); GET_PCWORD(new_cs); if (!CPU_STAT_PM || CPU_STAT_VM86) { /* Real mode or VM86 mode */ + SS_PUSH_CHECK(CPU_STAT_SS32 ? CPU_ESP : CPU_SP, 4); + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + PUSH0_16(CPU_CS); PUSH0_16(CPU_IP); - CPU_SET_SEGREG(CPU_CS_INDEX, new_cs); - SET_EIP(new_ip); + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; } else { /* Protected mode */ CALLfar_pm(new_cs, new_ip); @@ -914,19 +967,27 @@ CALL16_Ap(void) void CALL32_Ap(void) { + descriptor_t sd; UINT32 new_ip; UINT16 new_cs; + UINT16 sreg; CPU_WORKCLOCK(13); GET_PCDWORD(new_ip); GET_PCWORD(new_cs); if (!CPU_STAT_PM || CPU_STAT_VM86) { /* Real mode or VM86 mode */ + SS_PUSH_CHECK(CPU_STAT_SS32 ? CPU_ESP : CPU_SP, 8); + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + PUSH0_32(CPU_CS); PUSH0_32(CPU_EIP); - CPU_SET_SEGREG(CPU_CS_INDEX, new_cs); - SET_EIP(new_ip); + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; } else { /* Protected mode */ CALLfar_pm(new_cs, new_ip); @@ -936,22 +997,30 @@ CALL32_Ap(void) void CALL16_Ep(UINT32 op) { - UINT32 ad; - UINT32 new_ip; + descriptor_t sd; + UINT32 madr; + UINT16 new_ip; UINT16 new_cs; + UINT16 sreg; CPU_WORKCLOCK(16); if (op < 0xc0) { - ad = calc_ea_dst(op); - new_ip = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, ad); - new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, ad + 2); + madr = calc_ea_dst(op); + new_ip = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); if (!CPU_STAT_PM || CPU_STAT_VM86) { /* Real mode or VM86 mode */ + SS_PUSH_CHECK(CPU_STAT_SS32 ? CPU_ESP : CPU_SP, 4); + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + PUSH0_16(CPU_CS); PUSH0_16(CPU_IP); - CPU_SET_SEGREG(CPU_CS_INDEX, new_cs); - SET_EIP(new_ip); + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; } else { /* Protected mode */ CALLfar_pm(new_cs, new_ip); @@ -964,22 +1033,30 @@ CALL16_Ep(UINT32 op) void CALL32_Ep(UINT32 op) { - UINT32 ad; + descriptor_t sd; + UINT32 madr; UINT32 new_ip; UINT16 new_cs; + UINT16 sreg; CPU_WORKCLOCK(16); if (op < 0xc0) { - ad = calc_ea_dst(op); - new_ip = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, ad); - new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, ad + 4); + madr = calc_ea_dst(op); + new_ip = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); if (!CPU_STAT_PM || CPU_STAT_VM86) { /* Real mode or VM86 mode */ + SS_PUSH_CHECK(CPU_STAT_SS32 ? CPU_ESP : CPU_SP, 8); + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + PUSH0_32(CPU_CS); PUSH0_32(CPU_EIP); - CPU_SET_SEGREG(CPU_CS_INDEX, new_cs); - SET_EIP(new_ip); + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; } else { /* Protected mode */ CALLfar_pm(new_cs, new_ip); @@ -995,11 +1072,16 @@ CALL32_Ep(UINT32 op) void RETnear16(void) { - UINT32 new_ip; + UINT16 new_ip; + CPU_SET_PREV_ESP(); CPU_WORKCLOCK(11); POP0_16(new_ip); - SET_EIP(new_ip); + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); } void @@ -1007,26 +1089,36 @@ RETnear32(void) { UINT32 new_ip; + CPU_SET_PREV_ESP(); CPU_WORKCLOCK(11); POP0_32(new_ip); - SET_EIP(new_ip); + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); } void RETnear16_Iw(void) { - UINT32 new_ip; + UINT16 new_ip; UINT16 size; + CPU_SET_PREV_ESP(); CPU_WORKCLOCK(11); GET_PCWORD(size); POP0_16(new_ip); - SET_EIP(new_ip); + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; if (!CPU_STAT_SS32) { CPU_SP += size; } else { CPU_ESP += size; } + CPU_CLEAR_PREV_ESP(); } void @@ -1035,31 +1127,46 @@ RETnear32_Iw(void) UINT32 new_ip; UINT16 size; + CPU_SET_PREV_ESP(); CPU_WORKCLOCK(11); GET_PCWORD(size); POP0_32(new_ip); - SET_EIP(new_ip); + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; if (!CPU_STAT_SS32) { CPU_SP += size; } else { CPU_ESP += size; } + CPU_CLEAR_PREV_ESP(); } void RETfar16(void) { - UINT32 new_ip; + descriptor_t sd; + UINT16 new_ip; UINT16 new_cs; + UINT16 sreg; CPU_WORKCLOCK(15); if (!CPU_STAT_PM || CPU_STAT_VM86) { /* Real mode or VM86 mode */ + CPU_SET_PREV_ESP(); POP0_16(new_ip); POP0_16(new_cs); - CPU_SET_SEGREG(CPU_CS_INDEX, new_cs); - SET_EIP(new_ip); + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); } else { /* Protected mode */ RETfar_pm(0); @@ -1069,17 +1176,27 @@ RETfar16(void) void RETfar32(void) { + descriptor_t sd; UINT32 new_ip; UINT32 new_cs; + UINT16 sreg; CPU_WORKCLOCK(15); if (!CPU_STAT_PM || CPU_STAT_VM86) { /* Real mode or VM86 mode */ + CPU_SET_PREV_ESP(); POP0_32(new_ip); POP0_32(new_cs); - CPU_SET_SEGREG(CPU_CS_INDEX, (UINT16)new_cs); - SET_EIP(new_ip); + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + + LOAD_SEGREG(CPU_CS_INDEX, (UINT16)new_cs); + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); } else { /* Protected mode */ RETfar_pm(0); @@ -1089,25 +1206,34 @@ RETfar32(void) void RETfar16_Iw(void) { - UINT32 new_ip; + descriptor_t sd; + UINT16 new_ip; UINT16 new_cs; + UINT16 sreg; UINT16 size; CPU_WORKCLOCK(15); GET_PCWORD(size); if (!CPU_STAT_PM || CPU_STAT_VM86) { /* Real mode or VM86 mode */ + CPU_SET_PREV_ESP(); POP0_16(new_ip); POP0_16(new_cs); - CPU_SET_SEGREG(CPU_CS_INDEX, new_cs); - SET_EIP(new_ip); + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; if (!CPU_STAT_SS32) { CPU_SP += size; } else { CPU_ESP += size; } + CPU_CLEAR_PREV_ESP(); } else { /* Protected mode */ RETfar_pm(size); @@ -1117,25 +1243,34 @@ RETfar16_Iw(void) void RETfar32_Iw(void) { + descriptor_t sd; UINT32 new_ip; UINT32 new_cs; + UINT16 sreg; UINT16 size; CPU_WORKCLOCK(15); GET_PCWORD(size); if (!CPU_STAT_PM || CPU_STAT_VM86) { /* Real mode or VM86 mode */ + CPU_SET_PREV_ESP(); POP0_32(new_ip); POP0_32(new_cs); - CPU_SET_SEGREG(CPU_CS_INDEX, (UINT16)new_cs); - SET_EIP(new_ip); + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + LOAD_SEGREG(CPU_CS_INDEX, (UINT16)new_cs); + CPU_EIP = new_ip; if (!CPU_STAT_SS32) { CPU_SP += size; } else { CPU_ESP += size; } + CPU_CLEAR_PREV_ESP(); } else { /* Protected mode */ RETfar_pm(size); @@ -1145,31 +1280,17 @@ RETfar32_Iw(void) void IRET(void) { + descriptor_t sd; UINT32 new_ip; UINT32 new_flags; UINT32 new_cs; -#if !defined(IA32_DONT_USE_SET_EFLAGS_FUNCTION) UINT32 mask; -#endif + UINT16 sreg; + CPU_WORKCLOCK(22); if (!CPU_STAT_PM) { /* Real mode */ - CPU_WORKCLOCK(22); -#if defined(IA32_DONT_USE_SET_EFLAGS_FUNCTION) - if (!CPU_INST_OP32) { - POP0_16(new_ip); - POP0_16(new_cs); - POP0_16(new_flags); - CPU_FLAG = new_flags & ALL_FLAG; - } else { - POP0_32(new_ip); - POP0_32(new_cs); - POP0_32(new_flags); - CPU_EFLAG = (new_flags & (ALL_FLAG|RF_FLAG|AC_FLAG|ID_FLAG)) | (CPU_EFLAG & (VM_FLAG|VIF_FLAG|VIP_FLAG)); - } - CPU_OV = CPU_FLAG & O_FLAG; - CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG); -#else + CPU_SET_PREV_ESP(); mask = I_FLAG|IOPL_FLAG; if (!CPU_INST_OP32) { POP0_16(new_ip); @@ -1182,11 +1303,17 @@ IRET(void) mask |= RF_FLAG; } - set_eflags(new_flags, mask); -#endif + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } - CPU_SET_SEGREG(CPU_CS_INDEX, (UINT16)new_cs); - SET_EIP(new_ip); + LOAD_SEGREG(CPU_CS_INDEX, (UINT16)new_cs); + CPU_EIP = new_ip; + + set_eflags(new_flags, mask); + CPU_CLEAR_PREV_ESP(); } else { /* Protected mode */ IRET_pm(); @@ -1207,7 +1334,7 @@ INT1(void) { CPU_WORKCLOCK(33); - INTERRUPT(1, 1, 0, 0); + INTERRUPT(1, INTR_TYPE_SOFTINTR); } void @@ -1215,7 +1342,7 @@ INT3(void) { CPU_WORKCLOCK(33); - INTERRUPT(3, 2, 0, 0); + INTERRUPT(3, INTR_TYPE_SOFTINTR); } void @@ -1227,7 +1354,7 @@ INTO(void) return; } CPU_WORKCLOCK(35); - INTERRUPT(4, 3, 0, 0); + INTERRUPT(4, INTR_TYPE_SOFTINTR); } void @@ -1238,17 +1365,13 @@ INT_Ib(void) CPU_WORKCLOCK(37); if (!CPU_STAT_PM || !CPU_STAT_VM86 || (CPU_STAT_IOPL == CPU_IOPL3)) { GET_PCBYTE(vect); -if (vect == 0x50) { - if (CPU_AH == 0) { - TRACEOUT(("INT50 AX=%.4x %.4x:%.4x", CPU_AX, CPU_ES, CPU_DI)); - } - else if ((CPU_AH != 0x09) && (CPU_AH != 0x0b) && (CPU_AH != 0x11) && (CPU_AH != 0x14)) { - TRACEOUT(("INT50 AX=%.4x", CPU_AX)); - } -} - INTERRUPT(vect, -1, 0, 0); +#if defined(ENABLE_TRAP) + softinttrap(CPU_CS, CPU_EIP - 2, vect); +#endif + INTERRUPT(vect, INTR_TYPE_SOFTINTR); return; } + VERBOSE(("INT_Ib: VM86 && IOPL < 3 && INTn")); EXCEPTION(GP_EXCEPTION, 0); } @@ -1257,7 +1380,6 @@ BOUND_GwMa(void) { UINT32 op, madr; UINT16 reg; - int vect; CPU_WORKCLOCK(13); GET_PCBYTE(op); @@ -1268,11 +1390,10 @@ BOUND_GwMa(void) reg <= cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2)) { return; } - vect = BR_EXCEPTION; - } else { - vect = UD_EXCEPTION; + EXCEPTION(BR_EXCEPTION, 0); + return; } - EXCEPTION(vect, 0); + EXCEPTION(UD_EXCEPTION, 0); } void @@ -1280,7 +1401,6 @@ BOUND_GdMa(void) { UINT32 op, madr; UINT32 reg; - int vect; CPU_WORKCLOCK(13); GET_PCBYTE(op); @@ -1291,11 +1411,10 @@ BOUND_GdMa(void) reg <= cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 4)) { return; } - vect = BR_EXCEPTION; - } else { - vect = UD_EXCEPTION; + EXCEPTION(BR_EXCEPTION, 0); + return; } - EXCEPTION(vect, 0); + EXCEPTION(UD_EXCEPTION, 0); } /* @@ -1315,15 +1434,13 @@ ENTER16_IwIb(void) level &= 0x1f; /* check stack room size */ - if (CPU_STAT_PM) { - size = dimsize + (level + 1) * 2; - if (!CPU_STAT_SS32) { - sp = CPU_SP; - } else { - sp = CPU_ESP; - } - STACK_PUSH_CHECK(CPU_REGS_SREG(CPU_SS_INDEX), &CPU_STAT_SREG(CPU_SS_INDEX), sp, size); + size = dimsize + (level + 1) * 2; + if (!CPU_STAT_SS32) { + sp = CPU_SP; + } else { + sp = CPU_ESP; } + SS_PUSH_CHECK(sp, size); PUSH0_16(CPU_BP); if (level == 0) { /* enter level=0 */ @@ -1389,15 +1506,13 @@ ENTER32_IwIb(void) level &= 0x1f; /* check stack room size */ - if (CPU_STAT_PM) { - size = dimsize + (level + 1) * 4; - if (CPU_STAT_SS32) { - sp = CPU_ESP; - } else { - sp = CPU_SP; - } - STACK_PUSH_CHECK(CPU_REGS_SREG(CPU_SS_INDEX), &CPU_STAT_SREG(CPU_SS_INDEX), sp, size); + size = dimsize + (level + 1) * 4; + if (CPU_STAT_SS32) { + sp = CPU_ESP; + } else { + sp = CPU_SP; } + SS_PUSH_CHECK(sp, size); PUSH0_32(CPU_EBP); if (level == 0) { /* enter level=0 */ @@ -1452,30 +1567,21 @@ ENTER32_IwIb(void) void LEAVE(void) { - UINT32 sp, bp; UINT s; CPU_WORKCLOCK(4); - if (CPU_STAT_PM) { - if (!CPU_INST_OP32) { - s = 2; - } else { - s = 4; - } - if (!CPU_STAT_SS32) { - sp = CPU_SP; - bp = CPU_BP; - } else { - sp = CPU_ESP; - bp = CPU_EBP; - } - STACK_POP_CHECK(CPU_REGS_SREG(CPU_SS_INDEX), &CPU_STAT_SREG(CPU_SS_INDEX), sp, (bp - sp) + s); + /* check stack room size */ + if (!CPU_INST_OP32) { + s = 2; + } else { + s = 4; } - if (!CPU_STAT_SS32) { + SS_POP_CHECK(CPU_SP, (CPU_BP - CPU_SP) + s); CPU_SP = CPU_BP; } else { + SS_POP_CHECK(CPU_ESP, (CPU_EBP - CPU_ESP) + s); CPU_ESP = CPU_EBP; } if (!CPU_INST_OP32) {