void RETfar16(void) { 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); /* 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); } }
void POPF_Fw(void) { UINT16 flags, mask; CPU_WORKCLOCK(3); if (!CPU_STAT_PM) { /* Real Mode */ POP0_16(flags); mask = I_FLAG|IOPL_FLAG; } else if (!CPU_STAT_VM86) { /* Protected Mode */ POP0_16(flags); if (CPU_STAT_CPL == 0) { mask = I_FLAG|IOPL_FLAG; } else if (CPU_STAT_CPL <= CPU_STAT_IOPL) { mask = I_FLAG; } else { mask = 0; } } else if (CPU_STAT_IOPL == CPU_IOPL3) { /* Virtual-8086 Mode, IOPL == 3 */ POP0_16(flags); mask = I_FLAG; } else { EXCEPTION(GP_EXCEPTION, 0); flags = 0; mask = 0; /* compiler happy */ } set_eflags(flags, mask); IRQCHECKTERM(); }
void IRET(void) { descriptor_t sd; UINT32 new_ip; UINT32 new_flags; UINT32 new_cs; UINT32 mask; UINT16 sreg; 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); POP0_16(new_cs); POP0_16(new_flags); } else { POP0_32(new_ip); POP0_32(new_cs); POP0_32(new_flags); mask |= RF_FLAG; } /* 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(); } IRQCHECKTERM(); }
/* * RET */ void RETnear16(void) { UINT16 new_ip; CPU_WORKCLOCK(11); CPU_SET_PREV_ESP(); POP0_16(new_ip); if (new_ip > CPU_STAT_CS_LIMIT) { EXCEPTION(GP_EXCEPTION, 0); } CPU_EIP = new_ip; CPU_CLEAR_PREV_ESP(); }
void LEAVE(void) { CPU_WORKCLOCK(4); CPU_SET_PREV_ESP(); if (!CPU_STAT_SS32) { CPU_SP = CPU_BP; } else { CPU_ESP = CPU_EBP; } if (!CPU_INST_OP32) { POP0_16(CPU_BP); } else { POP0_32(CPU_EBP); } CPU_CLEAR_PREV_ESP(); }
void RETnear16_Iw(void) { UINT16 new_ip; UINT16 size; CPU_WORKCLOCK(11); CPU_SET_PREV_ESP(); GET_PCWORD(size); POP0_16(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(); }