/* Pulse the RESET line on the CPU */ void m68k_pulse_reset(m68ki_cpu_core *m68k) { /* Clear all stop levels and eat up all remaining cycles */ m68k->stopped = 0; if (m68k->remaining_cycles > 0) m68k->remaining_cycles = 0; #if M68K_EMULATE_ADDRESS_ERROR m68k->run_mode = RUN_MODE_BERR_AERR_RESET; #endif /* Turn off tracing */ m68k->t1_flag = m68k->t0_flag = 0; m68ki_clear_trace(); /* Interrupt mask to level 7 */ m68k->int_mask = 0x0700; m68k->int_level = 0; m68k->virq_state = 0; /* Reset VBR */ m68k->vbr = 0; /* Go to supervisor mode */ m68ki_set_sm_flag(m68k, SFLAG_SET | MFLAG_CLEAR); /* Invalidate the prefetch queue */ /* Set to arbitrary number since our first fetch is from 0 */ #if M68K_EMULATE_PREFETCH m68k->pref_addr = 0x1000; #endif /* Read the initial stack pointer and program counter */ m68ki_jump(m68k, 0); REG_SP = m68ki_read_imm_32(m68k); REG_PC = m68ki_read_imm_32(m68k); m68ki_jump(m68k, REG_PC); #if M68K_EMULATE_ADDRESS_ERROR m68k->run_mode = RUN_MODE_NORMAL; #endif m68k->reset_cycles = m68k->cyc_exception[EXCEPTION_RESET]; }
// Service an interrupt request and start exception processing void m68ki_exception_interrupt(uint32_t intLevel) { #if 0 uint vector; uint sr; uint new_pc; /* Turn off the stopped state */ CPU_STOPPED &= ~STOP_LEVEL_STOP; /* If we are halted, don't do anything */ if(CPU_STOPPED) return; /* Acknowledge the interrupt */ vector = m68ki_int_ack(int_level); /* Get the interrupt vector */ if(vector == M68K_INT_ACK_AUTOVECTOR) /* Use the autovectors. This is the most commonly used implementation */ vector = EXCEPTION_INTERRUPT_AUTOVECTOR+int_level; else if(vector == M68K_INT_ACK_SPURIOUS) /* Called if no devices respond to the interrupt acknowledge */ vector = EXCEPTION_SPURIOUS_INTERRUPT; else if(vector > 255) { M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n", m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector)); return; } /* Start exception processing */ sr = m68ki_init_exception(); /* Set the interrupt mask to the level of the one being serviced */ FLAG_INT_MASK = int_level<<8; /* Get the new PC */ new_pc = m68ki_read_data_32((vector<<2) + REG_VBR); /* If vector is uninitialized, call the uninitialized interrupt vector */ if(new_pc == 0) new_pc = m68ki_read_data_32((EXCEPTION_UNINITIALIZED_INTERRUPT<<2) + REG_VBR); /* Generate a stack frame */ m68ki_stack_frame_0000(REG_PC, sr, vector); if(FLAG_M && CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { /* Create throwaway frame */ m68ki_set_sm_flag(FLAG_S); /* clear M */ sr |= 0x2000; /* Same as SR in master stack frame except S is forced high */ m68ki_stack_frame_0001(REG_PC, sr, vector); } m68ki_jump(new_pc); /* Defer cycle counting until later */ CPU_INT_CYCLES += CYC_EXCEPTION[vector]; #if !M68K_EMULATE_INT_ACK /* Automatically clear IRQ if we are not using an acknowledge scheme */ CPU_INT_LEVEL = 0; #endif /* M68K_EMULATE_INT_ACK */ #else // Turn off the stopped state (N.B.: normal 68K behavior!) regs.stopped = 0; //JLH: need to add halt state? // prolly, for debugging/alpine mode... :-/ // but then again, this should be handled already by the main execution loop :-P // If we are halted, don't do anything // if (regs.stopped) // return; // Acknowledge the interrupt (NOTE: This is a user supplied function!) uint32_t vector = irq_ack_handler(intLevel); // Get the interrupt vector if (vector == M68K_INT_ACK_AUTOVECTOR) // Use the autovectors. This is the most commonly used implementation vector = EXCEPTION_INTERRUPT_AUTOVECTOR + intLevel; else if (vector == M68K_INT_ACK_SPURIOUS) // Called if no devices respond to the interrupt acknowledge vector = EXCEPTION_SPURIOUS_INTERRUPT; else if (vector > 255) { // M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n", // m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector)); return; } // Start exception processing uint32_t sr = m68ki_init_exception(); // Set the interrupt mask to the level of the one being serviced regs.intmask = intLevel; #if 0 extern int startM68KTracing; if (startM68KTracing) { printf("IRQ: old PC=%06X, ", regs.pc); } #endif // Get the new PC uint32_t newPC = m68k_read_memory_32(vector << 2); #if 0 if (startM68KTracing) { printf("new PC=%06X, vector=%u, ", newPC, vector); } #endif // If vector is uninitialized, call the uninitialized interrupt vector if (newPC == 0) newPC = m68k_read_memory_32(EXCEPTION_UNINITIALIZED_INTERRUPT << 2); // Generate a stack frame m68ki_stack_frame_3word(regs.pc, sr); m68k_setpc(newPC); #if 0 if (startM68KTracing) { printf("(PC=%06X)\n", regs.pc); } #endif // Defer cycle counting until later regs.interruptCycles += 56; // NOT ACCURATE-- !!! FIX !!! // CPU_INT_CYCLES += CYC_EXCEPTION[vector]; #endif }
// Pulse the RESET line on the CPU void m68k_pulse_reset(void) { static uint32_t emulation_initialized = 0; // The first call to this function initializes the opcode handler jump table if (!emulation_initialized) { #if 0 m68ki_build_opcode_table(); m68k_set_int_ack_callback(NULL); m68k_set_bkpt_ack_callback(NULL); m68k_set_reset_instr_callback(NULL); m68k_set_pc_changed_callback(NULL); m68k_set_fc_callback(NULL); m68k_set_instr_hook_callback(NULL); #else // Build opcode handler table here... read_table68k(); do_merges(); BuildCPUFunctionTable(); #endif emulation_initialized = 1; } // if (CPU_TYPE == 0) /* KW 990319 */ // m68k_set_cpu_type(M68K_CPU_TYPE_68000); #if 0 /* Clear all stop levels and eat up all remaining cycles */ CPU_STOPPED = 0; SET_CYCLES(0); /* Turn off tracing */ FLAG_T1 = FLAG_T0 = 0; m68ki_clear_trace(); /* Interrupt mask to level 7 */ FLAG_INT_MASK = 0x0700; /* Reset VBR */ REG_VBR = 0; /* Go to supervisor mode */ m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR); /* Invalidate the prefetch queue */ #if M68K_EMULATE_PREFETCH /* Set to arbitrary number since our first fetch is from 0 */ CPU_PREF_ADDR = 0x1000; #endif /* M68K_EMULATE_PREFETCH */ /* Read the initial stack pointer and program counter */ m68ki_jump(0); REG_SP = m68ki_read_imm_32(); REG_PC = m68ki_read_imm_32(); m68ki_jump(REG_PC); #else regs.spcflags = 0; regs.stopped = 0; regs.remainingCycles = 0; regs.intmask = 0x07; regs.s = 1; // Supervisor mode ON // Read initial SP and PC m68k_areg(regs, 7) = m68k_read_memory_32(0); m68k_setpc(m68k_read_memory_32(4)); refill_prefetch(m68k_getpc(), 0); #endif }