Exemplo n.º 1
0
Arquivo: cpu.c Projeto: saper/em400
// -----------------------------------------------------------------------
int cpu_ctx_switch(uint16_t arg, uint16_t ic, uint16_t sr_mask)
{
    uint16_t sp;

    if (!mem_cpu_get(0, 97, &sp)) return 0;

    LOG(L_CPU, 3, "H/W stack push @ 0x%04x (IC = 0x%04x, R0 = 0x%04x, SR = 0x%04x, arg = 0x%04x), new IC = 0x%04x",
        sp,
        regs[R_IC],
        regs[0],
        regs[R_SR],
        arg,
        ic
       );

    if (!mem_cpu_put(0, sp, regs[R_IC])) return 0;
    if (!mem_cpu_put(0, sp+1, regs[0])) return 0;
    if (!mem_cpu_put(0, sp+2, regs[R_SR])) return 0;
    if (!mem_cpu_put(0, sp+3, arg)) return 0;
    if (!mem_cpu_put(0, 97, sp+4)) return 0;

    regs[0] = 0;
    regs[R_IC] = ic;
    regs[R_SR] &= sr_mask;

    int_update_mask(regs[R_SR]);

    return 1;
}
Exemplo n.º 2
0
Arquivo: cpu.c Projeto: saper/em400
// -----------------------------------------------------------------------
int cpu_ctx_restore()
{
    uint16_t data;
    uint16_t sp;

    if (!mem_cpu_get(0, 97, &sp)) return 0;
    if (!mem_cpu_get(0, sp-4, &data)) return 0;
    regs[R_IC] = data;
    if (!mem_cpu_get(0, sp-3, &data)) return 0;
    regs[0] = data;
    if (!mem_cpu_get(0, sp-2, &data)) return 0;
    regs[R_SR] = data;
    int_update_mask(regs[R_SR]);
    if (!mem_cpu_put(0, 97, sp-4)) return 0;

    LOG(L_CPU, 3, "H/W stack pop @ 0x%04x (IC = 0x%04x, R0 = 0x%04x, SR = 0x%04x)",
        sp-4,
        regs[R_IC],
        regs[0],
        regs[R_SR]
       );

    return 1;
}
Exemplo n.º 3
0
// -----------------------------------------------------------------------
void int_serve()
{
	int probe = 31;
	int interrupt;
	uint16_t int_vec;
	uint16_t int_spec = 0;
	uint16_t sr_mask;

	// find highest interrupt to serve
	uint32_t rp = atom_load(&RP);
	while ((probe > 0) && !(rp & (1 << probe))) {
		probe--;
	}
	interrupt = 31 - probe;

	// clear interrupt, we update rp together with mask upon ctx switch
	pthread_mutex_lock(&int_mutex);
	RZ &= ~INT_BIT(interrupt);
	pthread_mutex_unlock(&int_mutex);

	// get interrupt vector
	if (!mem_cpu_get(0, 64+interrupt, &int_vec)) return;

	LOG(L_INT, 1, "Serve interrupt: %d (%s) -> 0x%04x", interrupt, int_names[interrupt], int_vec);

	// get interrupt specification for channel interrupts
	if ((interrupt >= 12) && (interrupt <= 27)) {
		io_get_intspec(interrupt-12, &int_spec);
	}

	// put system status on stack
	sr_mask = int_int2mask[interrupt] & MASK_Q; // calculate mask and clear Q
	if (cpu_mod_active && (interrupt >= 12) && (interrupt <= 27)) sr_mask &= MASK_EX; // put extended mask if cpu_mod

	// switch context
	if (!cpu_ctx_switch(int_spec, int_vec, sr_mask)) return;

	if (LOG_ENABLED) {
		log_intlevel_inc();
	}
}
Exemplo n.º 4
0
Arquivo: cpu.c Projeto: saper/em400
// -----------------------------------------------------------------------
void cpu_step()
{
    struct em400_op *op;
    uint16_t data;

    if (LOG_ENABLED) {
        log_store_cycle_state(regs[R_SR], regs[R_IC]);
    }

    // fetch instruction
    if (!mem_cpu_get(QNB, regs[R_IC], regs+R_IR)) {
        regs[R_MODc] = regs[R_MOD] = 0;
        LOGCPU(L_CPU, 2, "        (NO MEM: instruction fetch)");
        return;
    }
    regs[R_IC]++;

    // find instruction (by design op is always set to something,
    // even for illegal instructions)
    op = em400_op_tab[regs[R_IR]];

    // end cycle if P is set
    if (P) {
        LOGCPU(L_CPU, 2, "    (skip)");
        P = 0;
        // skip also M-arg if present
        if (op->norm_arg && !IR_C) regs[R_IC]++;
        return;
    }

    // process argument
    if (op->norm_arg) {
        if (IR_C) {
            N = regs[IR_C] + regs[R_MOD];
        } else {
            if (!mem_cpu_get(QNB, regs[R_IC], &data)) {
                LOGCPU(L_CPU, 2, "    (no mem: long arg fetch)");
                goto finish;
            } else {
                N = data + regs[R_MOD];
                regs[R_IC]++;
            }
        }
        if (IR_B) {
            N = (uint16_t) N + regs[IR_B];
        }
        if (IR_D) {
            if (!mem_cpu_get(QNB, N, &data)) {
                LOGCPU(L_CPU, 2, "    (no mem: indirect arg fetch)");
                goto finish;
            } else {
                N = data;
            }
        }
    } else if (op->short_arg) {
        N = (uint16_t) IR_T + (uint16_t) regs[R_MOD];
    }

    if (LOG_WANTS(L_CPU, 2)) {
        log_log_dasm(L_CPU, 2, regs[R_MOD], op->norm_arg, op->short_arg, N);
    }

    // execute instruction
    op->fun();

    // clear mod if instruction wasn't md
    if (op->fun != op_77_md) {
finish:
        regs[R_MODc] = 0;
        regs[R_MOD] = 0;
    }
}