diff --git a/m68k.h b/m68k.h index 555b314..d3e14d9 100644 --- a/m68k.h +++ b/m68k.h @@ -293,7 +293,23 @@ void m68k_set_fc_callback(void (*callback)(unsigned int new_fc)); */ void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc)); - +/* Operation done after aline callback. + * Normal behaviour is triggering a CPU exception. + * If you use the aline hook for own emulator traps + * then you can decide to do nothing in CPU emulation + * or perform an automatic RTS instruction afterwards. + */ +#define M68K_ALINE_NONE 0 +#define M68K_ALINE_EXCEPT 1 +#define M68K_ALINE_RTS 2 + +/* Set the aline callback. It will be executed every + * time an 0xaxxx opcode is encountered. Parameters are + * (opcode, current_pc). The return value is one of + * M68K_ALINE_* (see above). + * Default behaviour: CPU exception. + */ +void m68k_set_aline_hook_callback(int (*callback)(unsigned int, unsigned int)); /* ======================================================================== */ /* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */ diff --git a/m68kconf.h b/m68kconf.h index 8844952..10f93fc 100644 --- a/m68kconf.h +++ b/m68kconf.h @@ -175,6 +175,9 @@ */ #define M68K_EMULATE_ADDRESS_ERROR OPT_OFF +/* Intercept A-Line opcodes and call an own hook. */ +#define M68K_ALINE_HOOK OPT_OFF +#define M68K_ALINE_CALLBACK() your_aline_hook_function() /* Turn ON to enable logging of illegal instruction calls. * M68K_LOG_FILEHANDLE must be #defined to a stdio file stream. diff --git a/m68kcpu.c b/m68kcpu.c index fc43122..b5b8a43 100644 --- a/m68kcpu.c +++ b/m68kcpu.c @@ -599,6 +599,11 @@ static void default_instr_hook_callback(unsigned int pc) (void)pc; } +/* Called every time an 0xaxxx opcode is encountered */ +static int default_aline_hook_callback(unsigned int opcode, unsigned int pc) +{ + return M68K_ALINE_EXCEPT; +} #if M68K_EMULATE_ADDRESS_ERROR #include @@ -776,6 +781,11 @@ void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc)) CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback; } +void m68k_set_aline_hook_callback(int (*callback)(unsigned int, unsigned int)) +{ + CALLBACK_ALINE_HOOK = callback ? callback : default_aline_hook_callback; +} + /* Set the CPU type. */ void m68k_set_cpu_type(unsigned int cpu_type) { @@ -1097,6 +1107,7 @@ void m68k_init(void) m68k_set_pc_changed_callback(NULL); m68k_set_fc_callback(NULL); m68k_set_instr_hook_callback(NULL); + m68k_set_aline_hook_callback(NULL); } /* Trigger a Bus Error exception */ diff --git a/m68kcpu.h b/m68kcpu.h index be88bf8..3894ce1 100644 --- a/m68kcpu.h +++ b/m68kcpu.h @@ -396,6 +396,7 @@ typedef uint32 uint64; #define CALLBACK_PC_CHANGED m68ki_cpu.pc_changed_callback #define CALLBACK_SET_FC m68ki_cpu.set_fc_callback #define CALLBACK_INSTR_HOOK m68ki_cpu.instr_hook_callback +#define CALLBACK_ALINE_HOOK m68ki_cpu.aline_hook_callback @@ -684,6 +685,16 @@ extern jmp_buf m68ki_aerr_trap; #define M68K_DO_LOG_EMU(A) #endif +/* Aline hook */ +#if M68K_ALINE_HOOK + #if M68K_ALINE_HOOK == OPT_SPECIFY_HANDLER + #define m68ki_aline_hook() M68K_ALINE_CALLBACK() + #else + #define m68ki_aline_hook() CALLBACK_ALINE_HOOK() + #endif +#else + #define m68ki_aline_hook() M68K_ALINE_EXCEPT +#endif /* M68K_ALINE_HOOK */ /* -------------------------- EA / Operand Access ------------------------- */ @@ -1000,7 +1011,7 @@ typedef struct void (*pc_changed_callback)(unsigned int new_pc); /* Called when the PC changes by a large amount */ void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */ void (*instr_hook_callback)(unsigned int pc); /* Called every instruction cycle prior to execution */ - + int (*aline_hook_callback)(unsigned int opcode, unsigned int pc); /* Called if invalid a-line opcode occurred */ } m68ki_cpu_core; @@ -1952,6 +1963,10 @@ extern int cpu_log_enabled; /* Exception for A-Line instructions */ static inline void m68ki_exception_1010(void) { +#if M68K_ALINE_HOOK + int res = CALLBACK_ALINE_HOOK(REG_IR,ADDRESS_68K(REG_PPC)); + if(res == M68K_ALINE_EXCEPT) { +#endif uint sr; #if M68K_LOG_1010_1111 == OPT_ON M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: called 1010 instruction %04x (%s)\n", @@ -1965,6 +1980,12 @@ static inline void m68ki_exception_1010(void) /* Use up some clock cycles and undo the instruction's cycles */ USE_CYCLES(CYC_EXCEPTION[EXCEPTION_1010] - CYC_INSTRUCTION[REG_IR]); +#if M68K_ALINE_HOOK + } else if(res == M68K_ALINE_RTS) { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_jump(m68ki_pull_32()); + } +#endif } /* Exception for F-Line instructions */