X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=cpu%2Ffame%2Ffamec.c;h=8469131c8a57b5e3df2b959e1e5684055f7f3c86;hb=5ed2a20eaa264c72c1375943dd153c8c05403504;hp=2549147c27e1bf962a007c43fd2144d236c9940c;hpb=88b3d7c16ae976d332b8462de839b86f856a7180;p=picodrive.git diff --git a/cpu/fame/famec.c b/cpu/fame/famec.c index 2549147..8469131 100644 --- a/cpu/fame/famec.c +++ b/cpu/fame/famec.c @@ -4,7 +4,7 @@ /* Autor: Oscar Orallo Pelaez */ /* Fecha de comienzo: 03-10-2006 */ /* Ultima actualizacion: 08-10-2006 */ -/* Based on the excellent FAMEC emulator by Stèphane Dallongueville */ +/* Based on the excellent C68K emulator by Stèphane Dallongueville */ /****************************************************************************/ #include @@ -28,11 +28,14 @@ #define USE_CYCLONE_TIMING #define USE_CYCLONE_TIMING_DIV +#define PICODRIVE_HACK // Options // #undef INLINE -#ifndef INLINE +#ifdef _MSC_VER +#define INLINE +#else #define INLINE __inline__ #endif @@ -279,11 +282,18 @@ typedef signed int s32; ((u32)PC - BasePC) +#ifdef FAMEC_CHECK_BRANCHES +#define FORCE_ALIGNMENT(pc) +#else +#define FORCE_ALIGNMENT(pc) pc&=~1; +#endif + #ifndef FAMEC_32BIT_PC #define SET_PC(A) \ { \ u32 pc = A; \ + FORCE_ALIGNMENT(pc); \ BasePC = m68kcontext.Fetch[(pc >> M68K_FETCHSFT) & M68K_FETCHMASK]; \ PC = (u16*)((pc & M68K_ADR_MASK) + BasePC); \ } @@ -293,6 +303,7 @@ typedef signed int s32; #define SET_PC(A) \ { \ u32 pc = A; \ + FORCE_ALIGNMENT(pc); \ BasePC = m68kcontext.Fetch[(pc >> M68K_FETCHSFT) & M68K_FETCHMASK]; \ BasePC -= pc & 0xFF000000; \ PC = (u16*)(pc + BasePC); \ @@ -492,8 +503,6 @@ typedef signed int s32; #endif -static int init_jump_table(void); - // global variable /////////////////// @@ -521,6 +530,10 @@ static u32 flag_I; static u32 initialised = 0; +#ifdef PICODRIVE_HACK +extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k; +#endif + /* Custom function handler */ typedef void (*opcode_func)(void); @@ -619,7 +632,7 @@ void fm68k_init(void) #endif if (!initialised) - fm68k_emulate(0); + fm68k_emulate(0, 0, 0); #ifdef FAMEC_DEBUG puts("FAME initialized."); @@ -638,7 +651,7 @@ void fm68k_init(void) int fm68k_reset(void) { if (!initialised) - fm68k_emulate(0); + fm68k_emulate(0, 0, 0); // Si la CPU esta en ejecucion, salir con M68K_RUNNING if (m68kcontext.execinfo & M68K_RUNNING) @@ -729,7 +742,9 @@ static FAMEC_EXTRA_INLINE u32 execute_exception(s32 vect, u32 oldPC, u32 oldSR) #ifndef FAMEC_32BIT_PC newPC&=M68K_ADR_MASK #endif +#ifdef FAMEC_CHECK_BRANCHES newPC&=~1; // don't crash on games with bad vector tables +#endif // SET_PC(newPC) @@ -766,7 +781,7 @@ static void setup_jumptable(void); // main exec function ////////////////////// -int fm68k_emulate(s32 cycles) +int fm68k_emulate(s32 cycles, int dualcore, int idle_mode) { #ifndef FAMEC_NO_GOTOS u32 Opcode; @@ -782,17 +797,22 @@ int fm68k_emulate(s32 cycles) if (!initialised) { -#ifdef FAMEC_NO_GOTOS - init_jump_table(); - return 0; -#else goto init_jump_table; -#endif } +#ifdef PICODRIVE_HACK + if (dualcore) goto dualcore_mode; + if (idle_mode == 1) goto idle_install; + else if (idle_mode == 2) goto idle_remove; +famec_restart: +#endif + // won't emulate double fault // if (m68kcontext.execinfo & M68K_FAULTED) return -1; + // Cache PPL + flag_I = M68K_PPL; + if (m68kcontext.execinfo & FM68K_HALTED) { if (interrupt_chk__() <= 0) @@ -812,9 +832,6 @@ int fm68k_emulate(s32 cycles) // Cache SR SET_SR(m68kcontext.sr) - // Cache PPL - flag_I = M68K_PPL; - // Fijar PC SET_PC(m68kcontext.pc) @@ -894,9 +911,10 @@ famec_Exec: #endif if (cycles_needed != 0) { + u32 line; m68kcontext.io_cycle_counter = cycles_needed; cycles_needed = 0; - s32 line=interrupt_chk__(); + line=interrupt_chk__(); if (line>0) { if (m68kcontext.iack_handler != NULL) @@ -930,21 +948,63 @@ famec_End: printf("pc: 0x%08x\n",m68kcontext.pc); #endif - return cycles - m68kcontext.io_cycle_counter; +#ifdef PICODRIVE_HACK + if (!dualcore) +#endif + return cycles - m68kcontext.io_cycle_counter; -#ifdef FAMEC_NO_GOTOS -} +#ifdef PICODRIVE_HACK +dualcore_mode: + + while (1) + { + extern int SekCycleAim, SekCycleCnt, SekCycleAimS68k, SekCycleCntS68k; + #define PS_STEP_M68K ((488<<16)/20) // ~24 + if (dualcore == 1) + { + dualcore = (488<<16); // ~ cycn in Pico.c + // adjust for first iteration + g_m68kcontext = &PicoCpuFS68k; + cycles = m68kcontext.io_cycle_counter = 0; + } + if (g_m68kcontext == &PicoCpuFS68k) + { + SekCycleCntS68k += cycles - m68kcontext.io_cycle_counter; + // end? + dualcore -= PS_STEP_M68K; + if (dualcore < 0) return 0; + // become main 68k + g_m68kcontext = &PicoCpuFM68k; + if ((cycles = SekCycleAim-SekCycleCnt-(dualcore>>16)) > 0) + { + if ((m68kcontext.execinfo & FM68K_HALTED) && m68kcontext.interrupts[0] <= (M68K_PPL)) + SekCycleCnt += cycles; // halted + else goto famec_restart; + //else { printf("go main %i\n", cycles); goto famec_restart; } + } + cycles = m68kcontext.io_cycle_counter = 0; + } + if (g_m68kcontext == &PicoCpuFM68k) + { + int cycn_s68k = (dualcore + dualcore/2 + dualcore/8) >> 16; + SekCycleCnt += cycles - m68kcontext.io_cycle_counter; + // become sub 68k + g_m68kcontext = &PicoCpuFS68k; + if ((cycles = SekCycleAimS68k-SekCycleCntS68k-cycn_s68k) > 0) + { + if ((m68kcontext.execinfo & FM68K_HALTED) && m68kcontext.interrupts[0] <= (M68K_PPL)) + SekCycleCntS68k += cycles; // halted + else goto famec_restart; + } + cycles = m68kcontext.io_cycle_counter = 0; + } + } +#endif -static int init_jump_table(void) -{{ -#else init_jump_table: { -#endif u32 i, j; - m68kcontext.sr = 0x2704; // Z flag - for(i = 0x0000; i <= 0xFFFF; i += 0x0001) JumpTable[0x0000 + i] = CAST_OP(0x4AFC); for(i = 0x0000; i <= 0x0007; i += 0x0001) @@ -4958,6 +5018,49 @@ init_jump_table: initialised = 1; return 0; -}} +} + +#ifdef PICODRIVE_HACK + +#define INSTALL_IDLE(fake_op_base,real_op,detector,idle_handler,normal_handler) \ + JumpTable[fake_op_base] = CAST_OP(idle_handler); \ + JumpTable[fake_op_base|0x0200] = CAST_OP(normal_handler); \ + JumpTable[real_op] = CAST_OP(detector) + +#define UNDO_IDLE(fake_op_base,real_op,normal_handler) \ + JumpTable[fake_op_base] = JumpTable[fake_op_base|0x0200] = CAST_OP(0x4AFC); \ + JumpTable[real_op] = CAST_OP(normal_handler) + +idle_install: + // printf("install..\n"); + INSTALL_IDLE(0x71fa, 0x66fa, idle_detector_bcc8, 0x6601_idle, 0x6601); + INSTALL_IDLE(0x71f8, 0x66f8, idle_detector_bcc8, 0x6601_idle, 0x6601); + INSTALL_IDLE(0x71f6, 0x66f6, idle_detector_bcc8, 0x6601_idle, 0x6601); + INSTALL_IDLE(0x71f2, 0x66f2, idle_detector_bcc8, 0x6601_idle, 0x6601); + INSTALL_IDLE(0x75fa, 0x67fa, idle_detector_bcc8, 0x6701_idle, 0x6701); + INSTALL_IDLE(0x75f8, 0x67f8, idle_detector_bcc8, 0x6701_idle, 0x6701); + INSTALL_IDLE(0x75f6, 0x67f6, idle_detector_bcc8, 0x6701_idle, 0x6701); + INSTALL_IDLE(0x75f2, 0x67f2, idle_detector_bcc8, 0x6701_idle, 0x6701); + INSTALL_IDLE(0x7dfe, 0x60fe, idle_detector_bcc8, 0x6001_idle, 0x6001); + INSTALL_IDLE(0x7dfc, 0x60fc, idle_detector_bcc8, 0x6001_idle, 0x6001); + return 0; + +idle_remove: + // printf("remove..\n"); + UNDO_IDLE(0x71fa, 0x66fa, 0x6601); + UNDO_IDLE(0x71f8, 0x66f8, 0x6601); + UNDO_IDLE(0x71f6, 0x66f6, 0x6601); + UNDO_IDLE(0x71f2, 0x66f2, 0x6601); + UNDO_IDLE(0x75fa, 0x67fa, 0x6701); + UNDO_IDLE(0x75f8, 0x67f8, 0x6701); + UNDO_IDLE(0x75f6, 0x67f6, 0x6701); + UNDO_IDLE(0x75f2, 0x67f2, 0x6701); + UNDO_IDLE(0x7dfe, 0x60fe, 0x6001); + UNDO_IDLE(0x7dfc, 0x60fc, 0x6001); + return 0; + +#endif +} +void *get_jumptab(void) { return JumpTable; }