unsigned m68000_get_reg(int regnum) { switch( regnum ) { case M68K_PC: return m68k_get_reg(NULL, M68K_REG_PC); case M68K_SP: return m68k_get_reg(NULL, M68K_REG_SP); case M68K_ISP: return m68k_get_reg(NULL, M68K_REG_ISP); case M68K_USP: return m68k_get_reg(NULL, M68K_REG_USP); case M68K_SR: return m68k_get_reg(NULL, M68K_REG_SR); case M68K_D0: return m68k_get_reg(NULL, M68K_REG_D0); case M68K_D1: return m68k_get_reg(NULL, M68K_REG_D1); case M68K_D2: return m68k_get_reg(NULL, M68K_REG_D2); case M68K_D3: return m68k_get_reg(NULL, M68K_REG_D3); case M68K_D4: return m68k_get_reg(NULL, M68K_REG_D4); case M68K_D5: return m68k_get_reg(NULL, M68K_REG_D5); case M68K_D6: return m68k_get_reg(NULL, M68K_REG_D6); case M68K_D7: return m68k_get_reg(NULL, M68K_REG_D7); case M68K_A0: return m68k_get_reg(NULL, M68K_REG_A0); case M68K_A1: return m68k_get_reg(NULL, M68K_REG_A1); case M68K_A2: return m68k_get_reg(NULL, M68K_REG_A2); case M68K_A3: return m68k_get_reg(NULL, M68K_REG_A3); case M68K_A4: return m68k_get_reg(NULL, M68K_REG_A4); case M68K_A5: return m68k_get_reg(NULL, M68K_REG_A5); case M68K_A6: return m68k_get_reg(NULL, M68K_REG_A6); case M68K_A7: return m68k_get_reg(NULL, M68K_REG_A7); case M68K_PREF_ADDR: return m68k_get_reg(NULL, M68K_REG_PREF_ADDR); case M68K_PREF_DATA: return m68k_get_reg(NULL, M68K_REG_PREF_DATA); case REG_PREVIOUSPC: return m68k_get_reg(NULL, M68K_REG_PPC); /* TODO: return contents of [SP + wordsize * (REG_SP_CONTENTS-regnum)] */ default: if( regnum < REG_SP_CONTENTS ) { unsigned offset = m68k_get_reg(NULL, M68K_REG_SP) + 4 * (REG_SP_CONTENTS - regnum); if( offset < 0xfffffd ) return m68k_read_memory_32( offset ); } } return 0; }
// 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 }
unsigned int m68k_read_disassembler_32(unsigned int address) { return m68k_read_memory_32(address); }