famec: split fm68k_emulate
[picodrive.git] / cpu / fame / famec.c
index 6891526..508a12f 100644 (file)
 #define PICODRIVE_HACK\r
 // Options //\r
 \r
-\r
+#ifndef FAMEC_NO_GOTOS\r
+// computed gotos is a GNU extension\r
+#ifndef __GNUC__\r
+#define FAMEC_NO_GOTOS\r
+#endif\r
+// as of 3.3, clang takes over 3h to compile this in computed goto mode..\r
+#ifdef __clang__\r
+#define FAMEC_NO_GOTOS\r
+#endif\r
+#endif\r
\r
 #undef INLINE\r
 #ifdef _MSC_VER\r
 #define INLINE\r
@@ -546,7 +556,7 @@ M68K_CONTEXT *g_m68kcontext;
 static u32 initialised = 0;\r
 \r
 #ifdef PICODRIVE_HACK\r
-extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k;\r
+extern M68K_CONTEXT PicoCpuFS68k;\r
 #endif\r
 \r
 /* Custom function handler */\r
@@ -630,6 +640,7 @@ static const s32 exception_cycle_table[256] =
          4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4\r
 };\r
 \r
+static int init_jump_table(void);\r
 \r
 /***********************/\r
 /* core main functions */\r
@@ -646,8 +657,8 @@ void fm68k_init(void)
        puts("Initializing FAME...");\r
 #endif\r
 \r
-    if (!initialised)\r
-           fm68k_emulate(0, 0, 0);\r
+       if (!initialised)\r
+               init_jump_table();\r
 \r
 #ifdef FAMEC_DEBUG\r
        puts("FAME initialized.");\r
@@ -663,10 +674,12 @@ void fm68k_init(void)
 /*     M68K_NO_SUP_ADDR_SPACE (2):  No se puede resetear porque no hay mapa   */\r
 /*             de memoria supervisor de extraccion de opcodes                 */\r
 /******************************************************************************/\r
-int fm68k_reset(void)\r
+int fm68k_reset(M68K_CONTEXT *ctx)\r
 {\r
        if (!initialised)\r
-               fm68k_emulate(0, 0, 0);\r
+               init_jump_table();\r
+\r
+       g_m68kcontext = ctx;\r
 \r
        // Si la CPU esta en ejecucion, salir con M68K_RUNNING\r
        if (m68kcontext.execinfo & M68K_RUNNING)\r
@@ -721,7 +734,7 @@ static FAMEC_EXTRA_INLINE s32 interrupt_chk__(void)
        return 0;\r
 }\r
 \r
-int fm68k_would_interrupt(void)\r
+int fm68k_would_interrupt(M68K_CONTEXT *ctx)\r
 {\r
        return interrupt_chk__();\r
 }\r
@@ -732,6 +745,9 @@ static FAMEC_EXTRA_INLINE u32 execute_exception(s32 vect, u32 oldPC, u32 oldSR)
        //u32 oldSR = GET_SR;\r
 \r
         m68kcontext.io_cycle_counter -= exception_cycle_table[vect];\r
+#ifdef FAMEC_EMULATE_TRACE\r
+       m68kcontext.execinfo &= ~FM68K_EMULATE_TRACE;\r
+#endif\r
 \r
        PRE_IO\r
 \r
@@ -753,6 +769,7 @@ static FAMEC_EXTRA_INLINE u32 execute_exception(s32 vect, u32 oldPC, u32 oldSR)
 \r
        /* adjust SR */\r
        flag_S = M68K_SR_S;\r
+       flag_T = 0;\r
 \r
 #ifndef FAMEC_32BIT_PC\r
        newPC&=M68K_ADR_MASK\r
@@ -794,7 +811,7 @@ static FAMEC_EXTRA_INLINE u32 execute_exception_group_0(s32 vect, s32 addr, u16
 // main exec function\r
 //////////////////////\r
 \r
-int fm68k_emulate(s32 cycles, int dualcore, int idle_mode)\r
+int fm68k_emulate(M68K_CONTEXT *ctx, s32 cycles, fm68k_call_reason reason)\r
 {\r
 #ifndef FAMEC_NO_GOTOS\r
        u32 Opcode;\r
@@ -806,19 +823,23 @@ int fm68k_emulate(s32 cycles, int dualcore, int idle_mode)
        u32 flag_NotZ;\r
        u32 flag_N;\r
        u32 flag_X;\r
-#endif\r
 \r
-       if (!initialised)\r
+       switch (reason)\r
        {\r
+       case fm68k_reason_init:\r
                goto init_jump_table;\r
-       }\r
-\r
 #ifdef PICODRIVE_HACK\r
-       if (dualcore) goto dualcore_mode;\r
-       if      (idle_mode == 1) goto idle_install;\r
-       else if (idle_mode == 2) goto idle_remove;\r
-famec_restart:\r
+       case fm68k_reason_idle_install:\r
+               goto idle_install;\r
+       case fm68k_reason_idle_remove:\r
+               goto idle_remove;\r
 #endif\r
+       case fm68k_reason_emulate:\r
+               break;\r
+       }\r
+#endif // FAMEC_NO_GOTOS\r
+\r
+       g_m68kcontext = ctx;\r
 \r
        // won't emulate double fault\r
        // if (m68kcontext.execinfo & M68K_FAULTED) return -1;\r
@@ -908,12 +929,11 @@ famec_Exec:
 #ifdef FAMEC_EMULATE_TRACE\r
        if (m68kcontext.execinfo & FM68K_EMULATE_TRACE)\r
        {\r
-               m68kcontext.io_cycle_counter = cycles_needed;\r
+               m68kcontext.io_cycle_counter += cycles_needed;\r
                cycles_needed = 0;\r
                m68kcontext.execinfo &= ~FM68K_EMULATE_TRACE;\r
                m68kcontext.execinfo |= FM68K_DO_TRACE;\r
                SET_PC(execute_exception(M68K_TRACE_EX, GET_PC, GET_SR));\r
-               flag_T=0;\r
                if (m68kcontext.io_cycle_counter > 0)\r
                {\r
                        //NEXT\r
@@ -925,9 +945,9 @@ famec_Exec:
                if (cycles_needed != 0)\r
                {\r
                        u32 line;\r
-                       m68kcontext.io_cycle_counter = cycles_needed;\r
+                       m68kcontext.io_cycle_counter += cycles_needed;\r
                        cycles_needed = 0;\r
-                       if (m68kcontext.io_cycle_counter <= 0) goto famec_End;\r
+                       //if (m68kcontext.io_cycle_counter <= 0) goto famec_End;\r
                        line=interrupt_chk__();\r
                        if (line>0)\r
                        {\r
@@ -962,60 +982,15 @@ famec_End:
        printf("pc: 0x%08x\n",m68kcontext.pc);\r
 #endif\r
 \r
-#ifdef PICODRIVE_HACK\r
-       if (!dualcore)\r
-#endif\r
-               return cycles - m68kcontext.io_cycle_counter;\r
+       return cycles - m68kcontext.io_cycle_counter;\r
 \r
-#ifdef PICODRIVE_HACK\r
-dualcore_mode:\r
+#ifndef FAMEC_NO_GOTOS\r
+init_jump_table:\r
+#else\r
+}\r
 \r
-       while (1)\r
-       {\r
-               extern int SekCycleAim, SekCycleCnt, SekCycleAimS68k, SekCycleCntS68k;\r
-               #define PS_STEP_M68K ((488<<16)/20) // ~24\r
-               if (dualcore == 1)\r
-               {\r
-                       dualcore = (488<<16); // ~ cycn in Pico.c\r
-                       // adjust for first iteration\r
-                       g_m68kcontext = &PicoCpuFS68k;\r
-                       cycles = m68kcontext.io_cycle_counter = 0;\r
-               }\r
-               if (g_m68kcontext == &PicoCpuFS68k)\r
-               {\r
-                       SekCycleCntS68k += cycles - m68kcontext.io_cycle_counter;\r
-                       // end?\r
-                       dualcore -= PS_STEP_M68K;\r
-                       if (dualcore < 0) return 0;\r
-                       // become main 68k\r
-                       g_m68kcontext = &PicoCpuFM68k;\r
-                       if ((cycles = SekCycleAim-SekCycleCnt-(dualcore>>16)) > 0)\r
-                       {\r
-                               if ((m68kcontext.execinfo & FM68K_HALTED) && m68kcontext.interrupts[0] <= (M68K_PPL))\r
-                                    SekCycleCnt += cycles; // halted\r
-                               else goto famec_restart;\r
-                               //else { printf("go main %i\n", cycles); goto famec_restart; }\r
-                       }\r
-                       cycles = m68kcontext.io_cycle_counter = 0;\r
-               }\r
-               if (g_m68kcontext == &PicoCpuFM68k)\r
-               {\r
-                       int cycn_s68k = (dualcore + dualcore/2 + dualcore/8) >> 16;\r
-                       SekCycleCnt += cycles - m68kcontext.io_cycle_counter;\r
-                       // become sub 68k\r
-                       g_m68kcontext = &PicoCpuFS68k;\r
-                       if ((cycles = SekCycleAimS68k-SekCycleCntS68k-cycn_s68k) > 0)\r
-                       {\r
-                               if ((m68kcontext.execinfo & FM68K_HALTED) && m68kcontext.interrupts[0] <= (M68K_PPL))\r
-                                    SekCycleCntS68k += cycles; // halted\r
-                               else goto famec_restart;\r
-                       }\r
-                       cycles = m68kcontext.io_cycle_counter = 0;\r
-               }\r
-       }\r
+static int init_jump_table(void)\r
 #endif\r
-\r
-init_jump_table:\r
 {\r
        u32 i, j;\r
 \r
@@ -5045,7 +5020,12 @@ init_jump_table:
        JumpTable[fake_op_base] = JumpTable[fake_op_base|0x0200] = CAST_OP(0x4AFC); \\r
        JumpTable[real_op] = CAST_OP(normal_handler)\r
 \r
+#ifndef FAMEC_NO_GOTOS\r
 idle_install:\r
+#else\r
+int fm68k_idle_install(void)\r
+#endif\r
+{\r
        // printf("install..\n");\r
        INSTALL_IDLE(0x71fa, 0x66fa, idle_detector_bcc8, 0x6601_idle, 0x6601);\r
        INSTALL_IDLE(0x71f8, 0x66f8, idle_detector_bcc8, 0x6601_idle, 0x6601);\r
@@ -5058,8 +5038,14 @@ idle_install:
        INSTALL_IDLE(0x7dfe, 0x60fe, idle_detector_bcc8, 0x6001_idle, 0x6001);\r
        INSTALL_IDLE(0x7dfc, 0x60fc, idle_detector_bcc8, 0x6001_idle, 0x6001);\r
        return 0;\r
+}\r
 \r
+#ifndef FAMEC_NO_GOTOS\r
 idle_remove:\r
+#else\r
+int fm68k_idle_remove(void)\r
+#endif\r
+{\r
        // printf("remove..\n");\r
        UNDO_IDLE(0x71fa, 0x66fa, 0x6601);\r
        UNDO_IDLE(0x71f8, 0x66f8, 0x6601);\r
@@ -5072,9 +5058,26 @@ idle_remove:
        UNDO_IDLE(0x7dfe, 0x60fe, 0x6001);\r
        UNDO_IDLE(0x7dfc, 0x60fc, 0x6001);\r
        return 0;\r
+}\r
+#endif // PICODRIVE_HACK\r
 \r
-#endif\r
+#ifndef FAMEC_NO_GOTOS\r
+}\r
+\r
+static int init_jump_table(void)\r
+{\r
+       return fm68k_emulate(NULL, 0, fm68k_reason_init);\r
 }\r
 \r
-void *get_jumptab(void) { return JumpTable; }\r
+#ifdef PICODRIVE_HACK\r
+int fm68k_idle_install(void)\r
+{\r
+       return fm68k_emulate(NULL, 0, fm68k_reason_idle_install);\r
+}\r
 \r
+int fm68k_idle_remove(void)\r
+{\r
+       return fm68k_emulate(NULL, 0, fm68k_reason_idle_remove);\r
+}\r
+#endif\r
+#endif // FAMEC_NO_GOTOS\r