--- np2/i386c/ia32/instructions/ctrl_trans.c 2004/02/09 16:12:54 1.9 +++ 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.9 2004/02/09 16:12:54 monaka 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,82 +43,84 @@ void JMP_Jb(void) { - DWORD ip; - CPU_WORKCLOCK(7); - GET_PCBYTESD(ip); - ADD_EIP(ip); + JMPSHORT(7); } void JMP_Jw(void) { - DWORD ip; - CPU_WORKCLOCK(7); - GET_PCWORDS(ip); - ADD_EIP(ip); + JMPNEAR(7); } void JMP_Jd(void) { - DWORD ip; - CPU_WORKCLOCK(7); - GET_PCDWORD(ip); - ADD_EIP(ip); + JMPNEAR32(7); } void -JMP_Ew(DWORD op) +JMP_Ew(UINT32 op) { - DWORD madr; - DWORD new_ip; + UINT32 madr; + 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 -JMP_Ed(DWORD op) +JMP_Ed(UINT32 op) { - DWORD madr; - DWORD new_ip; + UINT32 madr; + UINT32 new_ip; 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) { - DWORD new_ip; - WORD new_cs; + 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); @@ -126,16 +130,23 @@ JMP16_Ap(void) void JMP32_Ap(void) { - DWORD new_ip; - WORD new_cs; + 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); @@ -143,11 +154,13 @@ JMP32_Ap(void) } void -JMP16_Ep(DWORD op) +JMP16_Ep(UINT32 op) { - DWORD madr; - DWORD new_ip; - WORD new_cs; + descriptor_t sd; + UINT32 madr; + UINT16 new_ip; + UINT16 new_cs; + UINT16 sreg; CPU_WORKCLOCK(11); if (op < 0xc0) { @@ -156,8 +169,13 @@ JMP16_Ep(DWORD 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); @@ -168,11 +186,13 @@ JMP16_Ep(DWORD op) } void -JMP32_Ep(DWORD op) +JMP32_Ep(UINT32 op) { - DWORD madr; - DWORD new_ip; - WORD new_cs; + descriptor_t sd; + UINT32 madr; + UINT32 new_ip; + UINT16 new_cs; + UINT16 sreg; CPU_WORKCLOCK(11); if (op < 0xc0) { @@ -181,8 +201,13 @@ JMP32_Ep(DWORD 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); @@ -197,7 +222,7 @@ void JO_Jb(void) { - if (!CPU_OV) { + if (CC_NO) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -208,7 +233,7 @@ void JO_Jw(void) { - if (!CPU_OV) { + if (CC_NO) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -219,10 +244,10 @@ void JO_Jd(void) { - if (!CPU_OV) { + if (CC_NO) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -231,7 +256,7 @@ void JNO_Jb(void) { - if (CPU_OV) { + if (CC_O) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -242,7 +267,7 @@ void JNO_Jw(void) { - if (CPU_OV) { + if (CC_O) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -253,10 +278,10 @@ void JNO_Jd(void) { - if (CPU_OV) { + if (CC_O) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -265,7 +290,7 @@ void JC_Jb(void) { - if (!(CPU_FLAGL & C_FLAG)) { + if (CC_NC) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -276,7 +301,7 @@ void JC_Jw(void) { - if (!(CPU_FLAGL & C_FLAG)) { + if (CC_NC) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -287,10 +312,10 @@ void JC_Jd(void) { - if (!(CPU_FLAGL & C_FLAG)) { + if (CC_NC) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -299,7 +324,7 @@ void JNC_Jb(void) { - if (CPU_FLAGL & C_FLAG) { + if (CC_C) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -309,7 +334,7 @@ void JNC_Jw(void) { - if (CPU_FLAGL & C_FLAG) { + if (CC_C) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -319,10 +344,10 @@ void JNC_Jd(void) { - if (CPU_FLAGL & C_FLAG) { + if (CC_C) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -331,7 +356,7 @@ void JZ_Jb(void) { - if (!(CPU_FLAGL & Z_FLAG)) { + if (CC_NZ) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -342,7 +367,7 @@ void JZ_Jw(void) { - if (!(CPU_FLAGL & Z_FLAG)) { + if (CC_NZ) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -353,10 +378,10 @@ void JZ_Jd(void) { - if (!(CPU_FLAGL & Z_FLAG)) { + if (CC_NZ) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -365,7 +390,7 @@ void JNZ_Jb(void) { - if (CPU_FLAGL & Z_FLAG) { + if (CC_Z) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -376,7 +401,7 @@ void JNZ_Jw(void) { - if (CPU_FLAGL & Z_FLAG) { + if (CC_Z) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -387,10 +412,10 @@ void JNZ_Jd(void) { - if (CPU_FLAGL & Z_FLAG) { + if (CC_Z) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -399,7 +424,7 @@ void JNA_Jb(void) { - if (!(CPU_FLAGL & (Z_FLAG | C_FLAG))) { + if (CC_A) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -410,7 +435,7 @@ void JNA_Jw(void) { - if (!(CPU_FLAGL & (Z_FLAG | C_FLAG))) { + if (CC_A) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -421,10 +446,10 @@ void JNA_Jd(void) { - if (!(CPU_FLAGL & (Z_FLAG | C_FLAG))) { + if (CC_A) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -433,7 +458,7 @@ void JA_Jb(void) { - if (CPU_FLAGL & (Z_FLAG | C_FLAG)) { + if (CC_NA) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -444,7 +469,7 @@ void JA_Jw(void) { - if (CPU_FLAGL & (Z_FLAG | C_FLAG)) { + if (CC_NA) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -455,10 +480,10 @@ void JA_Jd(void) { - if (CPU_FLAGL & (Z_FLAG | C_FLAG)) { + if (CC_NA) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -467,7 +492,7 @@ void JS_Jb(void) { - if (!(CPU_FLAGL & S_FLAG)) { + if (CC_NS) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -478,7 +503,7 @@ void JS_Jw(void) { - if (!(CPU_FLAGL & S_FLAG)) { + if (CC_NS) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -489,10 +514,10 @@ void JS_Jd(void) { - if (!(CPU_FLAGL & S_FLAG)) { + if (CC_NS) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -501,7 +526,7 @@ void JNS_Jb(void) { - if (CPU_FLAGL & S_FLAG) { + if (CC_S) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -512,7 +537,7 @@ void JNS_Jw(void) { - if (CPU_FLAGL & S_FLAG) { + if (CC_S) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -523,10 +548,10 @@ void JNS_Jd(void) { - if (CPU_FLAGL & S_FLAG) { + if (CC_S) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -535,7 +560,7 @@ void JP_Jb(void) { - if (!(CPU_FLAGL & P_FLAG)) { + if (CC_NP) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -546,7 +571,7 @@ void JP_Jw(void) { - if (!(CPU_FLAGL & P_FLAG)) { + if (CC_NP) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -557,10 +582,10 @@ void JP_Jd(void) { - if (!(CPU_FLAGL & P_FLAG)) { + if (CC_NP) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -569,7 +594,7 @@ void JNP_Jb(void) { - if (CPU_FLAGL & P_FLAG) { + if (CC_P) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -580,7 +605,7 @@ void JNP_Jw(void) { - if (CPU_FLAGL & P_FLAG) { + if (CC_P) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -591,10 +616,10 @@ void JNP_Jd(void) { - if (CPU_FLAGL & P_FLAG) { + if (CC_P) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -603,7 +628,7 @@ void JL_Jb(void) { - if ((!(CPU_FLAGL & S_FLAG)) == (!CPU_OV)) { + if (CC_NL) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -614,7 +639,7 @@ void JL_Jw(void) { - if ((!(CPU_FLAGL & S_FLAG)) == (!CPU_OV)) { + if (CC_NL) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -625,10 +650,10 @@ void JL_Jd(void) { - if ((!(CPU_FLAGL & S_FLAG)) == (!CPU_OV)) { + if (CC_NL) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -637,7 +662,7 @@ void JNL_Jb(void) { - if ((!(CPU_FLAGL & S_FLAG)) != (!CPU_OV)) { + if (CC_L) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -648,7 +673,7 @@ void JNL_Jw(void) { - if ((!(CPU_FLAGL & S_FLAG)) != (!CPU_OV)) { + if (CC_L) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -659,10 +684,10 @@ void JNL_Jd(void) { - if ((!(CPU_FLAGL & S_FLAG)) != (!CPU_OV)) { + if (CC_L) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -671,7 +696,7 @@ void JLE_Jb(void) { - if ((!(CPU_FLAGL & Z_FLAG)) && ((!(CPU_FLAGL & S_FLAG)) == (!CPU_OV))) { + if (CC_NLE) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -682,7 +707,7 @@ void JLE_Jw(void) { - if ((!(CPU_FLAGL & Z_FLAG)) && ((!(CPU_FLAGL & S_FLAG)) == (!CPU_OV))) { + if (CC_NLE) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -693,10 +718,10 @@ void JLE_Jd(void) { - if ((!(CPU_FLAGL & Z_FLAG)) && ((!(CPU_FLAGL & S_FLAG)) == (!CPU_OV))) { + if (CC_NLE) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -705,7 +730,7 @@ void JNLE_Jb(void) { - if ((CPU_FLAGL & Z_FLAG) || ((!(CPU_FLAGL & S_FLAG)) != (!CPU_OV))) { + if (CC_LE) { JMPNOP(2, 1); } else { JMPSHORT(7); @@ -716,7 +741,7 @@ void JNLE_Jw(void) { - if ((CPU_FLAGL & Z_FLAG) || ((!(CPU_FLAGL & S_FLAG)) != (!CPU_OV))) { + if (CC_LE) { JMPNOP(2, 2); } else { JMPNEAR(7); @@ -727,10 +752,10 @@ void JNLE_Jd(void) { - if ((CPU_FLAGL & Z_FLAG) || ((!(CPU_FLAGL & S_FLAG)) != (!CPU_OV))) { + if (CC_LE) { JMPNOP(2, 4); } else { - JMPNEAR_4(7); + JMPNEAR32(7); } } @@ -740,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); } } } @@ -761,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--; } } @@ -783,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--; } } @@ -805,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--; } } @@ -829,30 +863,40 @@ LOOP_Jb(void) void CALL_Aw(void) { - DWORD 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_EIP = new_ip; } void CALL_Ad(void) { - DWORD 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_EIP = new_ip; } void -CALL_Ew(DWORD op) +CALL_Ew(UINT32 op) { - DWORD madr; - DWORD new_ip; + UINT32 madr; + UINT16 new_ip; if (op >= 0xc0) { CPU_WORKCLOCK(7); @@ -862,15 +906,18 @@ CALL_Ew(DWORD 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 -CALL_Ed(DWORD op) +CALL_Ed(UINT32 op) { - DWORD madr; - DWORD new_ip; + UINT32 madr; + UINT32 new_ip; if (op >= 0xc0) { CPU_WORKCLOCK(7); @@ -880,26 +927,37 @@ CALL_Ed(DWORD 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) { - DWORD new_ip; - WORD new_cs; + 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); @@ -909,19 +967,27 @@ CALL16_Ap(void) void CALL32_Ap(void) { - DWORD new_ip; - WORD new_cs; + 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); @@ -929,24 +995,32 @@ CALL32_Ap(void) } void -CALL16_Ep(DWORD op) +CALL16_Ep(UINT32 op) { - DWORD ad; - DWORD new_ip; - WORD new_cs; + 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); @@ -957,24 +1031,32 @@ CALL16_Ep(DWORD op) } void -CALL32_Ep(DWORD op) +CALL32_Ep(UINT32 op) { - DWORD ad; - DWORD new_ip; - WORD new_cs; + 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); @@ -990,71 +1072,101 @@ CALL32_Ep(DWORD op) void RETnear16(void) { - DWORD 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 RETnear32(void) { - DWORD new_ip; + 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) { - DWORD new_ip; - WORD ad; + UINT16 new_ip; + UINT16 size; + CPU_SET_PREV_ESP(); CPU_WORKCLOCK(11); - GET_PCWORD(ad); + 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 += ad; + CPU_SP += size; } else { - CPU_ESP += ad; + CPU_ESP += size; } + CPU_CLEAR_PREV_ESP(); } void RETnear32_Iw(void) { - DWORD new_ip; - DWORD ad; + UINT32 new_ip; + UINT16 size; + CPU_SET_PREV_ESP(); CPU_WORKCLOCK(11); - GET_PCWORD(ad); + GET_PCWORD(size); POP0_32(new_ip); - SET_EIP(new_ip); - if (CPU_STAT_SS32) { - CPU_ESP += ad; + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; + if (!CPU_STAT_SS32) { + CPU_SP += size; } else { - CPU_SP += ad; + CPU_ESP += size; } + CPU_CLEAR_PREV_ESP(); } void RETfar16(void) { - DWORD new_ip; - WORD new_cs; + 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); @@ -1064,17 +1176,27 @@ RETfar16(void) void RETfar32(void) { - DWORD new_ip; - WORD new_cs; + 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, 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); @@ -1084,70 +1206,91 @@ RETfar32(void) void RETfar16_Iw(void) { - DWORD ad; - DWORD new_ip; - WORD new_cs; + descriptor_t sd; + UINT16 new_ip; + UINT16 new_cs; + UINT16 sreg; + UINT16 size; CPU_WORKCLOCK(15); - GET_PCWORD(ad); + 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 += ad; + CPU_SP += size; } else { - CPU_ESP += ad; + CPU_ESP += size; } + CPU_CLEAR_PREV_ESP(); } else { /* Protected mode */ - RETfar_pm(ad); + RETfar_pm(size); } } void RETfar32_Iw(void) { - DWORD ad; - DWORD new_ip; - WORD new_cs; + descriptor_t sd; + UINT32 new_ip; + UINT32 new_cs; + UINT16 sreg; + UINT16 size; CPU_WORKCLOCK(15); - GET_PCWORD(ad); + 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, 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); + } - if (CPU_STAT_SS32) { - CPU_ESP += ad; + LOAD_SEGREG(CPU_CS_INDEX, (UINT16)new_cs); + CPU_EIP = new_ip; + if (!CPU_STAT_SS32) { + CPU_SP += size; } else { - CPU_SP += ad; + CPU_ESP += size; } + CPU_CLEAR_PREV_ESP(); } else { /* Protected mode */ - RETfar_pm(ad); + RETfar_pm(size); } } void IRET(void) { - DWORD new_ip; - DWORD new_flags; - DWORD mask; - WORD new_cs; + descriptor_t sd; + UINT32 new_ip; + UINT32 new_flags; + UINT32 new_cs; + UINT32 mask; + UINT16 sreg; - CPU_WORKCLOCK(31); + CPU_WORKCLOCK(22); if (!CPU_STAT_PM) { /* Real mode */ + CPU_SET_PREV_ESP(); mask = I_FLAG|IOPL_FLAG; if (!CPU_INST_OP32) { POP0_16(new_ip); @@ -1159,14 +1302,27 @@ IRET(void) POP0_32(new_flags); mask |= RF_FLAG; } - set_eflags(new_flags, mask); - 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, (UINT16)new_cs); + CPU_EIP = new_ip; + + set_eflags(new_flags, mask); + CPU_CLEAR_PREV_ESP(); } else { /* Protected mode */ IRET_pm(); } +#if defined(IA32_SUPPORT_DEBUG_REGISTER) + if (CPU_EFLAG & RF_FLAG) { + CPU_STAT_BP_EVENT |= CPU_STAT_BP_EVENT_RF; + } +#endif IRQCHECKTERM(); } @@ -1177,16 +1333,16 @@ void INT1(void) { - CPU_WORKCLOCK(23); - INTERRUPT(1, 1, 0, 0); + CPU_WORKCLOCK(33); + INTERRUPT(1, INTR_TYPE_SOFTINTR); } void INT3(void) { - CPU_WORKCLOCK(23); - INTERRUPT(3, 2, 0, 0); + CPU_WORKCLOCK(33); + INTERRUPT(3, INTR_TYPE_SOFTINTR); } void @@ -1194,33 +1350,36 @@ INTO(void) { if (!CPU_OV) { - CPU_WORKCLOCK(4); + CPU_WORKCLOCK(3); return; } - CPU_WORKCLOCK(24); - INTERRUPT(4, 3, 0, 0); + CPU_WORKCLOCK(35); + INTERRUPT(4, INTR_TYPE_SOFTINTR); } void INT_Ib(void) { - BYTE vect; + UINT8 vect; - CPU_WORKCLOCK(23); + CPU_WORKCLOCK(37); if (!CPU_STAT_PM || !CPU_STAT_VM86 || (CPU_STAT_IOPL == CPU_IOPL3)) { GET_PCBYTE(vect); - 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); } void BOUND_GwMa(void) { - DWORD op, madr; - WORD reg; - int vect; + UINT32 op, madr; + UINT16 reg; CPU_WORKCLOCK(13); GET_PCBYTE(op); @@ -1231,19 +1390,17 @@ 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 BOUND_GdMa(void) { - DWORD op, madr; - DWORD reg; - int vect; + UINT32 op, madr; + UINT32 reg; CPU_WORKCLOCK(13); GET_PCBYTE(op); @@ -1254,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); } /* @@ -1267,26 +1423,24 @@ BOUND_GdMa(void) void ENTER16_IwIb(void) { - DWORD sp, bp; - DWORD size; - DWORD val; - WORD dimsize; - BYTE level; + UINT32 sp, bp; + UINT32 size; + UINT32 val; + UINT16 dimsize; + UINT8 level; GET_PCWORD(dimsize); GET_PCBYTE(level); 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; - } - CHECK_STACK_PUSH(&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 */ @@ -1303,7 +1457,7 @@ ENTER16_IwIb(void) CPU_WORKCLOCK(15); sp = CPU_SP; PUSH0_16(sp); - CPU_BP = sp; + CPU_BP = (UINT16)sp; if (!CPU_STAT_SS32) { CPU_SP -= dimsize; } else { @@ -1318,7 +1472,7 @@ ENTER16_IwIb(void) bp -= 2; CPU_SP -= 2; val = cpu_vmemoryread_w(CPU_SS_INDEX, bp); - cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_SP, val); + cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_SP, (UINT16)val); } REGPUSH0(CPU_BP); CPU_SP -= dimsize; @@ -1329,7 +1483,7 @@ ENTER16_IwIb(void) bp -= 2; CPU_ESP -= 2; val = cpu_vmemoryread_w(CPU_SS_INDEX, bp); - cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_ESP, val); + cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_ESP, (UINT16)val); } REGPUSH0_16_32(CPU_BP); CPU_ESP -= dimsize; @@ -1341,26 +1495,24 @@ ENTER16_IwIb(void) void ENTER32_IwIb(void) { - DWORD sp, bp; - DWORD size; - DWORD val; - WORD dimsize; - BYTE level; + UINT32 sp, bp; + UINT32 size; + UINT32 val; + UINT16 dimsize; + UINT8 level; GET_PCWORD(dimsize); GET_PCBYTE(level); 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; - } - CHECK_STACK_PUSH(&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 */ @@ -1392,7 +1544,7 @@ ENTER32_IwIb(void) bp -= 4; CPU_ESP -= 4; val = cpu_vmemoryread_d(CPU_SS_INDEX, bp); - cpu_vmemorywrite(CPU_SS_INDEX, CPU_ESP, val); + cpu_vmemorywrite_d(CPU_SS_INDEX, CPU_ESP, val); } REGPUSH0_32(CPU_EBP); CPU_ESP -= dimsize; @@ -1413,51 +1565,28 @@ ENTER32_IwIb(void) } void -LEAVE16(void) +LEAVE(void) { - DWORD sp, size; + UINT s; - CPU_WORKCLOCK(5); + CPU_WORKCLOCK(4); - if (CPU_STAT_PM) { - if (!CPU_STAT_SS32) { - sp = CPU_SP; - size = 2; - } else { - sp = CPU_ESP; - size = 4; - } - if (CPU_BP < CPU_SP) { - ia32_panic("LEAVE16: BP(%04x) < SP(%04x)", CPU_BP, CPU_SP); - } - CHECK_STACK_PUSH(&CPU_STAT_SREG(CPU_SS_INDEX), sp, (CPU_BP - CPU_SP) + size); + /* check stack room size */ + if (!CPU_INST_OP32) { + s = 2; + } else { + s = 4; } - - CPU_SP = CPU_BP; - REGPOP0(CPU_BP); -} - -void -LEAVE32(void) -{ - DWORD sp, size; - - CPU_WORKCLOCK(5); - - if (CPU_STAT_PM) { - if (CPU_STAT_SS32) { - sp = CPU_ESP; - size = 4; - } else { - sp = CPU_SP; - size = 2; - } - if (CPU_EBP < CPU_ESP) { - ia32_panic("LEAVE32: EBP(%08x) < ESP(%08x)", CPU_EBP, CPU_ESP); - } - CHECK_STACK_PUSH(&CPU_STAT_SREG(CPU_SS_INDEX), sp, (CPU_EBP - CPU_ESP) + size); + 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) { + REGPOP0(CPU_BP); + } else { + POP0_32(CPU_EBP); } - - CPU_ESP = CPU_EBP; - POP0_32(CPU_EBP); }