Esempio n. 1
0
I286_F6 _call_far_ea16(UINT op) {

	UINT32	seg;
	UINT	ad;

	I286_WORKCLOCK(16);
	if (op < 0xc0) {
		ad = GET_EA(op, &seg);
		REGPUSH0(I286_CS)								// ToDo
		REGPUSH0(I286_IP)
		I286_IP = i286_memoryread_w(seg + ad);
		I286_CS = i286_memoryread_w(seg + LOW16(ad + 2));
		CS_BASE = SEGSELECT(I286_CS);
	}
	else {
		INT_NUM(6, I286_IP - 2);
	}
}
Esempio n. 2
0
I286_F6 _push_ea16(UINT op) {

	UINT16	src;

	if (op >= 0xc0) {
		I286_WORKCLOCK(3);
		src = *(REG16_B20(op));
	}
	else {
		I286_WORKCLOCK(5);
		src = i286_memoryread_w(CALC_EA(op));
	}
	REGPUSH0(src);
}
Esempio n. 3
0
I286_F6 _call_ea16(UINT op) {

	UINT16	src;

	if (op >= 0xc0) {
		I286_WORKCLOCK(7);
		src = *(REG16_B20(op));
	}
	else {
		I286_WORKCLOCK(11);
		src = i286_memoryread_w(CALC_EA(op));
	}
	REGPUSH0(I286_IP);
	I286_IP = src;
}
Esempio n. 4
0
/*
 * STACK
 */
void
ENTER16_IwIb(void)
{
	UINT32 sp, bp;
	UINT32 val;
	UINT16 dimsize;
	UINT16 new_bp;
	UINT8 level;

	GET_PCWORD(dimsize);
	GET_PCBYTE(level);
	level &= 0x1f;

	CPU_SET_PREV_ESP();
	PUSH0_16(CPU_BP);
	if (level == 0) {			/* enter level=0 */
		CPU_WORKCLOCK(11);
		CPU_BP = CPU_SP;
		if (!CPU_STAT_SS32) {
			CPU_SP -= dimsize;
		} else {
			CPU_ESP -= dimsize;
		}
	} else {
		--level;
		if (level == 0) {		/* enter level=1 */
			CPU_WORKCLOCK(15);
			sp = CPU_SP;
			PUSH0_16(sp);
			CPU_BP = (UINT16)sp;
			if (!CPU_STAT_SS32) {
				CPU_SP -= dimsize;
			} else {
				CPU_ESP -= dimsize;
			}
		} else {			/* enter level=2-31 */
			CPU_WORKCLOCK(12 + level * 4);
			if (!CPU_STAT_SS32) {
				bp = CPU_BP;
				new_bp = CPU_SP;
				while (level--) {
					bp -= 2;
					CPU_SP -= 2;
					val = cpu_vmemoryread_w(CPU_SS_INDEX, bp);
					cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_SP, (UINT16)val);
				}
				REGPUSH0(new_bp);
				CPU_BP = new_bp;
				CPU_SP -= dimsize;
			} else {
				bp = CPU_EBP;
				new_bp = CPU_SP;
				while (level--) {
					bp -= 2;
					CPU_ESP -= 2;
					val = cpu_vmemoryread_w(CPU_SS_INDEX, bp);
					cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_ESP, (UINT16)val);
				}
				REGPUSH0_16_32(new_bp);
				CPU_BP = new_bp;
				CPU_ESP -= dimsize;
			}
		}
	}
	CPU_CLEAR_PREV_ESP();
}
Esempio n. 5
0
void CPUCALL
interrupt(int num, int intrtype, int errorp, int error_code)
{
    descriptor_t gsd;
    UINT idt_idx;
    UINT32 new_ip;
    UINT16 new_cs;
    int exc_errcode;

    VERBOSE(("interrupt: num = 0x%02x, intrtype = %s, errorp = %s, error_code = %08x", num, (intrtype == INTR_TYPE_EXTINTR) ? "external" : (intrtype == INTR_TYPE_EXCEPTION ? "exception" : "softint"), errorp ? "on" : "off", error_code));

    if(num == 0x21 && md_int21())	{
        return;
    }

    CPU_SET_PREV_ESP();

    if (!CPU_STAT_PM) {
        /* real mode */
        CPU_WORKCLOCK(20);

        idt_idx = num * 4;
        if (idt_idx + 3 > CPU_IDTR_LIMIT) {
            VERBOSE(("interrupt: real-mode IDTR limit check failure (idx = 0x%04x, limit = 0x%08x", idt_idx, CPU_IDTR_LIMIT));
            EXCEPTION(GP_EXCEPTION, idt_idx + 2);
        }

        if ((intrtype == INTR_TYPE_EXTINTR) && CPU_STAT_HLT) {
            VERBOSE(("interrupt: reset HTL in real mode"));
            CPU_EIP++;
            CPU_STAT_HLT = 0;
        }

        REGPUSH0(REAL_FLAGREG);
        REGPUSH0(CPU_CS);
        REGPUSH0(CPU_IP);

        CPU_EFLAG &= ~(T_FLAG | I_FLAG | AC_FLAG | RF_FLAG);
        CPU_TRAP = 0;

        new_ip = cpu_memoryread_w(CPU_IDTR_BASE + idt_idx);
        new_cs = cpu_memoryread_w(CPU_IDTR_BASE + idt_idx + 2);
        LOAD_SEGREG(CPU_CS_INDEX, new_cs);
        CPU_EIP = new_ip;
    } else {
        /* protected mode */
        CPU_WORKCLOCK(200);

        VERBOSE(("interrupt: -------------------------------------------------------------- start"));
        VERBOSE(("interrupt: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP));

#if defined(DEBUG)
        if (num == 0x80) {
            /* Linux, FreeBSD, NetBSD, OpenBSD system call */
            VERBOSE(("interrupt: syscall# = %d\n%s", CPU_EAX, cpu_reg2str()));
        }
#endif

        idt_idx = num * 8;
        exc_errcode = idt_idx + 2;
        if (intrtype == INTR_TYPE_EXTINTR)
            exc_errcode++;

        if (idt_idx + 7 > CPU_IDTR_LIMIT) {
            VERBOSE(("interrupt: IDTR limit check failure (idx = 0x%04x, limit = 0x%08x", idt_idx, CPU_IDTR_LIMIT));
            EXCEPTION(GP_EXCEPTION, exc_errcode);
        }

        /* load a gate descriptor from interrupt descriptor table */
        memset(&gsd, 0, sizeof(gsd));
        load_descriptor(&gsd, CPU_IDTR_BASE + idt_idx);
        if (!SEG_IS_VALID(&gsd)) {
            VERBOSE(("interrupt: gate descripter is invalid."));
            EXCEPTION(GP_EXCEPTION, exc_errcode);
        }
        if (!SEG_IS_SYSTEM(&gsd)) {
            VERBOSE(("interrupt: gate descriptor is not system segment."));
            EXCEPTION(GP_EXCEPTION, exc_errcode);
        }

        switch (gsd.type) {
        case CPU_SYSDESC_TYPE_TASK:
        case CPU_SYSDESC_TYPE_INTR_16:
        case CPU_SYSDESC_TYPE_INTR_32:
        case CPU_SYSDESC_TYPE_TRAP_16:
        case CPU_SYSDESC_TYPE_TRAP_32:
            break;

        default:
            VERBOSE(("interrupt: invalid gate type (%d)", gsd.type));
            EXCEPTION(GP_EXCEPTION, exc_errcode);
            break;
        }

        /* 5.10.1.1. 例外/割り込みハンドラ・プロシージャの保護 */
        if ((intrtype == INTR_TYPE_SOFTINTR) && (gsd.dpl < CPU_STAT_CPL)) {
            VERBOSE(("interrupt: intrtype(softint) && DPL(%d) < CPL(%d)", gsd.dpl, CPU_STAT_CPL));
            EXCEPTION(GP_EXCEPTION, exc_errcode);
        }

        if (!SEG_IS_PRESENT(&gsd)) {
            VERBOSE(("interrupt: gate descriptor is not present."));
            EXCEPTION(NP_EXCEPTION, exc_errcode);
        }

        if ((intrtype == INTR_TYPE_EXTINTR) && CPU_STAT_HLT) {
            VERBOSE(("interrupt: reset HTL in protected mode"));
            CPU_EIP++;
            CPU_STAT_HLT = 0;
        }

        switch (gsd.type) {
        case CPU_SYSDESC_TYPE_TASK:
            interrupt_task_gate(&gsd, intrtype, errorp, error_code);
            break;

        case CPU_SYSDESC_TYPE_INTR_16:
        case CPU_SYSDESC_TYPE_INTR_32:
        case CPU_SYSDESC_TYPE_TRAP_16:
        case CPU_SYSDESC_TYPE_TRAP_32:
            interrupt_intr_or_trap(&gsd, intrtype, errorp, error_code);
            break;

        default:
            EXCEPTION(GP_EXCEPTION, exc_errcode);
            break;
        }

        VERBOSE(("interrupt: ---------------------------------------------------------------- end"));
    }

    CPU_CLEAR_PREV_ESP();
}