improve 64bit portability
[picodrive.git] / cpu / fame / famec.c
index 613f58f..60a9e55 100644 (file)
 #include <stdlib.h>\r
 #include <string.h>\r
 \r
+#ifdef __GNUC__\r
+#pragma GCC diagnostic ignored "-Wunused-variable"\r
+#endif\r
+\r
 #include "fame.h"\r
 \r
 \r
@@ -20,7 +24,7 @@
 #define FAMEC_CHECK_BRANCHES\r
 #define FAMEC_EXTRA_INLINE\r
 // #define FAMEC_DEBUG\r
-#define FAMEC_NO_GOTOS\r
+// #define FAMEC_NO_GOTOS\r
 #define FAMEC_ADR_BITS  24\r
 // #define FAMEC_FETCHBITS 8\r
 #define FAMEC_DATABITS  8\r
 #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
 #undef s32\r
 #endif\r
 \r
+#ifdef uptr\r
+#undef uptr\r
+#endif\r
+\r
 #define u8     unsigned char\r
 #define s8     signed char\r
 #define u16    unsigned short\r
 #define s16    signed short\r
 #define u32    unsigned int\r
 #define s32    signed int\r
+#define uptr   uintptr_t\r
 \r
 /*\r
 typedef unsigned char  u8;\r
@@ -209,21 +228,21 @@ typedef signed int        s32;
 // internals core macros\r
 /////////////////////////\r
 \r
-#define DREG(X)         (m68kcontext.dreg[(X)].D)\r
-#define DREGu32(X)      (m68kcontext.dreg[(X)].D)\r
-#define DREGs32(X)      (m68kcontext.dreg[(X)].SD)\r
-#define DREGu16(X)      (m68kcontext.dreg[(X)].W)\r
-#define DREGs16(X)      (m68kcontext.dreg[(X)].SW)\r
-#define DREGu8(X)       (m68kcontext.dreg[(X)].B)\r
-#define DREGs8(X)       (m68kcontext.dreg[(X)].SB)\r
+#define DREG(X)         (ctx->dreg[(X)].D)\r
+#define DREGu32(X)      (ctx->dreg[(X)].D)\r
+#define DREGs32(X)      (ctx->dreg[(X)].SD)\r
+#define DREGu16(X)      (ctx->dreg[(X)].W)\r
+#define DREGs16(X)      (ctx->dreg[(X)].SW)\r
+#define DREGu8(X)       (ctx->dreg[(X)].B)\r
+#define DREGs8(X)       (ctx->dreg[(X)].SB)\r
 \r
-#define AREG(X)         (m68kcontext.areg[(X)].D)\r
-#define AREGu32(X)      (m68kcontext.areg[(X)].D)\r
-#define AREGs32(X)      (m68kcontext.areg[(X)].SD)\r
-#define AREGu16(X)      (m68kcontext.areg[(X)].W)\r
-#define AREGs16(X)      (m68kcontext.areg[(X)].SW)\r
+#define AREG(X)         (ctx->areg[(X)].D)\r
+#define AREGu32(X)      (ctx->areg[(X)].D)\r
+#define AREGs32(X)      (ctx->areg[(X)].SD)\r
+#define AREGu16(X)      (ctx->areg[(X)].W)\r
+#define AREGs16(X)      (ctx->areg[(X)].SW)\r
 \r
-#define ASP             (m68kcontext.asp)\r
+#define ASP             (ctx->asp)\r
 \r
 #define LSL(A, C)       ((A) << (C))\r
 #define LSR(A, C)       ((A) >> (C))\r
@@ -252,42 +271,42 @@ typedef signed int        s32;
 \r
 #ifdef FAMEC_ROLL_INLINE\r
 #define RET(A)                                      \\r
-    m68kcontext.io_cycle_counter -= (A);                        \\r
-    if (m68kcontext.io_cycle_counter <= 0) goto famec_Exec_End;        \\r
+    ctx->io_cycle_counter -= (A);                        \\r
+    if (ctx->io_cycle_counter <= 0) goto famec_Exec_End;       \\r
     NEXT\r
 #else\r
 #define RET(A)                                      \\r
-    m68kcontext.io_cycle_counter -= (A);                        \\r
-    if (m68kcontext.io_cycle_counter <= 0) goto famec_Exec_End;        \\r
+    ctx->io_cycle_counter -= (A);                        \\r
+    if (ctx->io_cycle_counter <= 0) goto famec_Exec_End;       \\r
     goto famec_Exec;\r
 #endif\r
 \r
 #define RET0() \\r
-    m68kcontext.io_cycle_counter = -6; \\r
+    ctx->io_cycle_counter = -6; \\r
     goto famec_End;\r
 \r
 #else\r
 \r
 #define NEXT \\r
-    do{ \\r
-       FETCH_WORD(Opcode); \\r
-       JumpTable[Opcode](); \\r
-    }while(m68kcontext.io_cycle_counter>0);\r
+    do { \\r
+        FETCH_WORD(Opcode); \\r
+        JumpTable[Opcode](ctx); \\r
+    } while (ctx->io_cycle_counter > 0);\r
 \r
 #define RET(A) \\r
-    m68kcontext.io_cycle_counter -= (A);  \\r
+    ctx->io_cycle_counter -= (A);  \\r
     return;\r
 \r
 #define RET0() \\r
-    m68kcontext.io_cycle_counter = -6; \\r
+    ctx->io_cycle_counter = -6; \\r
     return;\r
 \r
 #endif\r
 \r
-#define M68K_PPL (m68kcontext.sr >> 8) & 7\r
+#define M68K_PPL (ctx->sr >> 8) & 7\r
 \r
 #define GET_PC                  \\r
-       ((u32)PC - BasePC)\r
+       (u32)((uptr)PC - BasePC)\r
 \r
 \r
 #ifdef FAMEC_CHECK_BRANCHES\r
@@ -302,7 +321,7 @@ typedef signed int  s32;
 { \\r
     u32 pc = A; \\r
     FORCE_ALIGNMENT(pc); \\r
-    BasePC = m68kcontext.Fetch[(pc >> M68K_FETCHSFT) & M68K_FETCHMASK];    \\r
+    BasePC = ctx->Fetch[(pc >> M68K_FETCHSFT) & M68K_FETCHMASK];    \\r
     PC = (u16*)((pc & M68K_ADR_MASK) + BasePC);        \\r
 }\r
 \r
@@ -312,7 +331,7 @@ typedef signed int  s32;
 { \\r
     u32 pc = A; \\r
     FORCE_ALIGNMENT(pc); \\r
-    BasePC = m68kcontext.Fetch[(pc >> M68K_FETCHSFT) & M68K_FETCHMASK];    \\r
+    BasePC = ctx->Fetch[(pc >> M68K_FETCHSFT) & M68K_FETCHMASK];    \\r
     BasePC -= pc & 0xFF000000;    \\r
     PC = (u16*)(pc + BasePC); \\r
 }\r
@@ -327,29 +346,29 @@ typedef signed int        s32;
 //    CCnt = io_cycle_counter;\r
 \r
 #define READ_BYTE_F(A, D)           \\r
-       D = m68kcontext.read_byte(A) & 0xFF;\r
+       D = ctx->read_byte(A) & 0xFF;\r
 \r
 #define READ_WORD_F(A, D)           \\r
-       D = m68kcontext.read_word(A) & 0xFFFF;\r
+       D = ctx->read_word(A) & 0xFFFF;\r
 \r
 #define READ_LONG_F(A, D)           \\r
-       D = m68kcontext.read_long(A);\r
+       D = ctx->read_long(A);\r
 \r
 #define READSX_LONG_F READ_LONG_F\r
 \r
 #define WRITE_LONG_F(A, D)          \\r
-       m68kcontext.write_long(A, D);\r
+       ctx->write_long(A, D);\r
 \r
 #define WRITE_LONG_DEC_F(A, D)          \\r
-       m68kcontext.write_word((A) + 2, (D) & 0xFFFF);    \\r
-       m68kcontext.write_word((A), (D) >> 16);\r
+       ctx->write_word((A) + 2, (D) & 0xFFFF);    \\r
+       ctx->write_word((A), (D) >> 16);\r
 \r
 #define PUSH_32_F(D)                        \\r
        AREG(7) -= 4;                               \\r
-       m68kcontext.write_long(AREG(7), D);\r
+       ctx->write_long(AREG(7), D);\r
 \r
 #define POP_32_F(D)                         \\r
-       D = m68kcontext.read_long(AREG(7));         \\r
+       D = ctx->read_long(AREG(7));         \\r
        AREG(7) += 4;\r
 \r
 #ifndef FAME_BIG_ENDIAN\r
@@ -421,23 +440,23 @@ typedef signed int        s32;
 #endif\r
 \r
 #define READSX_BYTE_F(A, D)             \\r
-    D = (s8)m68kcontext.read_byte(A);\r
+    D = (s8)ctx->read_byte(A);\r
 \r
 #define READSX_WORD_F(A, D)             \\r
-    D = (s16)m68kcontext.read_word(A);\r
+    D = (s16)ctx->read_word(A);\r
 \r
 \r
 #define WRITE_BYTE_F(A, D)      \\r
-    m68kcontext.write_byte(A, D);\r
+    ctx->write_byte(A, D);\r
 \r
 #define WRITE_WORD_F(A, D)      \\r
-    m68kcontext.write_word(A, D);\r
+    ctx->write_word(A, D);\r
 \r
 #define PUSH_16_F(D)                    \\r
-    m68kcontext.write_word(AREG(7) -= 2, D);   \\r
+    ctx->write_word(AREG(7) -= 2, D);   \\r
 \r
 #define POP_16_F(D)                     \\r
-    D = (u16)m68kcontext.read_word(AREG(7));   \\r
+    D = (u16)ctx->read_word(AREG(7));   \\r
     AREG(7) += 2;\r
 \r
 #define GET_CCR                                     \\r
@@ -482,17 +501,17 @@ typedef signed int        s32;
 #endif\r
 \r
 #define CHECK_INT_TO_JUMP(CLK) \\r
-       if (interrupt_chk__()) \\r
+       if (interrupt_chk__(ctx)) \\r
        { \\r
-               cycles_needed=m68kcontext.io_cycle_counter-(CLK); \\r
-               m68kcontext.io_cycle_counter=(CLK);  \\r
+               cycles_needed=ctx->io_cycle_counter-(CLK); \\r
+               ctx->io_cycle_counter=(CLK);  \\r
        }\r
 \r
 \r
 #ifdef FAMEC_CHECK_BRANCHES\r
 \r
 #ifdef FAMEC_NO_GOTOS\r
-#define CHECK_BRANCH_EXCEPTION_GOTO_END m68kcontext.io_cycle_counter=0; return;\r
+#define CHECK_BRANCH_EXCEPTION_GOTO_END ctx->io_cycle_counter=0; return;\r
 #else\r
 #define CHECK_BRANCH_EXCEPTION_GOTO_END goto famec_Exec_End;\r
 #endif\r
@@ -501,8 +520,8 @@ typedef signed int  s32;
        if ((_PC_)&1) \\r
        { \\r
                u32 new_PC, pr_PC=GET_PC; \\r
-               m68kcontext.execinfo |= FM68K_EMULATE_GROUP_0; \\r
-               new_PC = execute_exception_group_0(M68K_ADDRESS_ERROR_EX, 0, pr_PC, 0x12 ); \\r
+               ctx->execinfo |= FM68K_EMULATE_GROUP_0; \\r
+               new_PC = execute_exception_group_0(ctx, M68K_ADDRESS_ERROR_EX, 0, pr_PC, 0x12 ); \\r
                SET_PC(new_PC); \\r
                CHECK_BRANCH_EXCEPTION_GOTO_END \\r
        }\r
@@ -510,40 +529,33 @@ typedef signed int        s32;
 #define CHECK_BRANCH_EXCEPTION(_PC_)\r
 #endif\r
 \r
-\r
-// global variable\r
-///////////////////\r
-\r
-/* Current CPU context */\r
-M68K_CONTEXT *g_m68kcontext;\r
-#define m68kcontext (*g_m68kcontext)\r
-\r
 #ifdef FAMEC_NO_GOTOS\r
-static u32 Opcode;\r
-static s32 cycles_needed;\r
-static u16 *PC;\r
-static u32 BasePC;\r
-static u32 flag_C;\r
-static u32 flag_V;\r
-static u32 flag_NotZ;\r
-static u32 flag_N;\r
-static u32 flag_X;\r
+#define Opcode ctx->Opcode\r
+#define cycles_needed ctx->cycles_needed\r
+#define PC ctx->PC\r
+#define BasePC ctx->BasePC\r
+#define flag_C ctx->flag_C\r
+#define flag_V ctx->flag_V\r
+#define flag_NotZ ctx->flag_NotZ\r
+#define flag_N ctx->flag_N\r
+#define flag_X ctx->flag_X\r
 #endif\r
 \r
-#ifdef FAMEC_EMULATE_TRACE\r
-static u32 flag_T;\r
-#endif\r
-static u32 flag_S;\r
-static u32 flag_I;\r
+#define flag_T ctx->flag_T\r
+#define flag_S ctx->flag_S\r
+#define flag_I ctx->flag_I\r
+\r
+// global variable\r
+///////////////////\r
 \r
 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
-typedef void (*opcode_func)(void);\r
+typedef void (*opcode_func)(M68K_CONTEXT *ctx);\r
 \r
 static opcode_func JumpTable[0x10000];\r
 \r
@@ -623,6 +635,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
@@ -639,8 +652,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
@@ -656,33 +669,33 @@ 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
        // Si la CPU esta en ejecucion, salir con M68K_RUNNING\r
-       if (m68kcontext.execinfo & M68K_RUNNING)\r
+       if (ctx->execinfo & M68K_RUNNING)\r
                return M68K_RUNNING;\r
 \r
        // Resetear registros\r
-       //memset(&m68kcontext.dreg[0], 0, 16*4);\r
+       //memset(&ctx->dreg[0], 0, 16*4);\r
 \r
        // Resetear interrupts, execinfo y ASP\r
-       m68kcontext.interrupts[0] = 0;\r
-       m68kcontext.execinfo = 0;\r
+       ctx->interrupts[0] = 0;\r
+       ctx->execinfo = 0;\r
        ASP = 0;\r
 \r
        // Fijar registro de estado\r
-       m68kcontext.sr = (m68kcontext.sr & 0xff) | 0x2700;\r
+       ctx->sr = (ctx->sr & 0xff) | 0x2700;\r
 \r
        // Obtener puntero de pila inicial y PC\r
-       AREG(7) = m68kcontext.read_long(0);\r
-       m68kcontext.pc = m68kcontext.read_long(4);\r
+       AREG(7) = ctx->read_long(0);\r
+       ctx->pc = ctx->read_long(4);\r
 \r
 #ifdef FAMEC_DEBUG\r
        puts("Reset 68k done!\n");\r
-       printf("PC = 0x%08X\n",m68kcontext.pc);\r
+       printf("PC = 0x%08X\n",ctx->pc);\r
 #endif\r
 \r
     return M68K_OK;\r
@@ -694,37 +707,40 @@ int fm68k_reset(void)
 /* No recibe parametros                                                     */\r
 /* Retorna 68k PC                                                           */\r
 /****************************************************************************/\r
-u32 fm68k_get_pc(M68K_CONTEXT *context)\r
+u32 fm68k_get_pc(const M68K_CONTEXT *ctx)\r
 {\r
 #ifdef FAMEC_NO_GOTOS\r
-       return (context->execinfo & M68K_RUNNING)?(u32)PC-BasePC:context->pc;\r
+       return (ctx->execinfo & M68K_RUNNING)?(uptr)PC-BasePC:ctx->pc;\r
 #else\r
-       return context->pc; // approximate PC in this mode\r
+       return ctx->pc; // approximate PC in this mode\r
 #endif\r
 }\r
 \r
 \r
 //////////////////////////\r
 // Chequea las interrupciones y las inicia\r
-static FAMEC_EXTRA_INLINE s32 interrupt_chk__(void)\r
+static FAMEC_EXTRA_INLINE s32 interrupt_chk__(M68K_CONTEXT *ctx)\r
 {\r
-       if (m68kcontext.interrupts[0] > flag_I)\r
-               return m68kcontext.interrupts[0];\r
+       if (ctx->interrupts[0] > flag_I)\r
+               return ctx->interrupts[0];\r
 \r
        return 0;\r
 }\r
 \r
-int fm68k_would_interrupt(void)\r
+int fm68k_would_interrupt(M68K_CONTEXT *ctx)\r
 {\r
-       return interrupt_chk__();\r
+       return interrupt_chk__(ctx);\r
 }\r
 \r
-static FAMEC_EXTRA_INLINE u32 execute_exception(s32 vect, u32 oldPC, u32 oldSR)\r
+static FAMEC_EXTRA_INLINE u32 execute_exception(M68K_CONTEXT *ctx, s32 vect, u32 oldPC, u32 oldSR)\r
 {\r
        u32 newPC;\r
        //u32 oldSR = GET_SR;\r
 \r
-        m68kcontext.io_cycle_counter -= exception_cycle_table[vect];\r
+        ctx->io_cycle_counter -= exception_cycle_table[vect];\r
+#ifdef FAMEC_EMULATE_TRACE\r
+       ctx->execinfo &= ~FM68K_EMULATE_TRACE;\r
+#endif\r
 \r
        PRE_IO\r
 \r
@@ -746,6 +762,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
@@ -761,12 +778,12 @@ static FAMEC_EXTRA_INLINE u32 execute_exception(s32 vect, u32 oldPC, u32 oldSR)
        return newPC;\r
 }\r
 \r
-static FAMEC_EXTRA_INLINE u32 execute_exception_group_0(s32 vect, s32 addr, u16 spec_info, u32 oldSR)\r
+static FAMEC_EXTRA_INLINE u32 execute_exception_group_0(M68K_CONTEXT *ctx, s32 vect, s32 addr, u16 spec_info, u32 oldSR)\r
 {\r
        u32 newPC;\r
        u16 inst_reg = 0;\r
-       newPC = execute_exception(vect, addr, oldSR);\r
-       //if (!(m68kcontext.icust_handler && m68kcontext.icust_handler[vect]))\r
+       newPC = execute_exception(ctx, vect, addr, oldSR);\r
+       //if (!(ctx->icust_handler && ctx->icust_handler[vect]))\r
        {\r
                PUSH_16_F(inst_reg);\r
                PUSH_32_F(addr);\r
@@ -776,11 +793,9 @@ static FAMEC_EXTRA_INLINE u32 execute_exception_group_0(s32 vect, s32 addr, u16
 }\r
 \r
 \r
-static void setup_jumptable(void);\r
-\r
 #ifdef FAMEC_NO_GOTOS\r
 \r
-#define OPCODE(N_OP) static void OP_##N_OP(void)\r
+#define OPCODE(N_OP) static void OP_##N_OP(M68K_CONTEXT *ctx)\r
 #define CAST_OP(N_OP) (opcode_func)&OP_##N_OP\r
 #include "famec_opcodes.h"\r
 #endif\r
@@ -789,45 +804,47 @@ static void setup_jumptable(void);
 // 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
        s32 cycles_needed;\r
        u16 *PC;\r
-       u32 BasePC;\r
+       uptr BasePC;\r
        u32 flag_C;\r
        u32 flag_V;\r
        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
        // won't emulate double fault\r
-       // if (m68kcontext.execinfo & M68K_FAULTED) return -1;\r
+       // if (ctx->execinfo & M68K_FAULTED) return -1;\r
 \r
        // Cache PPL\r
        flag_I = M68K_PPL;\r
 \r
-       if (m68kcontext.execinfo & FM68K_HALTED)\r
+       if (ctx->execinfo & FM68K_HALTED)\r
        {\r
-               if (interrupt_chk__() <= 0)\r
+               if (interrupt_chk__(ctx) <= 0)\r
                {\r
                        return cycles;\r
                }\r
-               m68kcontext.execinfo &= ~FM68K_HALTED;\r
+               ctx->execinfo &= ~FM68K_HALTED;\r
        }\r
 \r
 #ifdef FAMEC_DEBUG\r
@@ -835,13 +852,13 @@ famec_restart:
 #endif\r
 \r
        /* Poner la CPU en estado de ejecucion */\r
-       m68kcontext.execinfo |= M68K_RUNNING;\r
+       ctx->execinfo |= M68K_RUNNING;\r
 \r
        // Cache SR\r
-       SET_SR(m68kcontext.sr)\r
+       SET_SR(ctx->sr)\r
 \r
        // Fijar PC\r
-       SET_PC(m68kcontext.pc)\r
+       SET_PC(ctx->pc)\r
 \r
 #ifdef FAMEC_DEBUG\r
        printf("PC: %p\n",PC);\r
@@ -849,33 +866,33 @@ famec_restart:
 #endif\r
 \r
        /* guardar ciclos de ejecucion solicitados */\r
-       m68kcontext.io_cycle_counter = cycles;\r
+       ctx->io_cycle_counter = cycles;\r
        cycles_needed = 0;\r
 \r
 #ifdef FAMEC_EMULATE_TRACE\r
-       if (!(m68kcontext.execinfo & FM68K_EMULATE_TRACE))\r
+       if (!(ctx->execinfo & FM68K_EMULATE_TRACE))\r
 #endif\r
        {\r
-               s32 line=interrupt_chk__();\r
+               s32 line=interrupt_chk__(ctx);\r
                if (line>0)\r
                {\r
                        /* comprobar si hay rutina de acknowledge */\r
-                       if (m68kcontext.iack_handler != NULL)\r
-                               m68kcontext.iack_handler(line);\r
+                       if (ctx->iack_handler != NULL)\r
+                               ctx->iack_handler(line);\r
                        else\r
-                               m68kcontext.interrupts[0] = 0;\r
+                               ctx->interrupts[0] = 0;\r
 \r
-                       SET_PC(execute_exception(line + 0x18, GET_PC, GET_SR));\r
+                       SET_PC(execute_exception(ctx, line + 0x18, GET_PC, GET_SR));\r
                        flag_I = (u32)line;\r
-                       if (m68kcontext.io_cycle_counter <= 0) goto famec_End;\r
+                       if (ctx->io_cycle_counter <= 0) goto famec_End;\r
                }\r
 #ifdef FAMEC_EMULATE_TRACE\r
                else\r
                        if  (flag_T)\r
                        {\r
-                               m68kcontext.execinfo |= FM68K_EMULATE_TRACE;\r
-                               cycles_needed = m68kcontext.io_cycle_counter;\r
-                               m68kcontext.io_cycle_counter=0;\r
+                               ctx->execinfo |= FM68K_EMULATE_TRACE;\r
+                               cycles_needed = ctx->io_cycle_counter;\r
+                               ctx->io_cycle_counter=0;\r
                        }\r
 #endif\r
        }\r
@@ -901,15 +918,14 @@ famec_Exec:
 #endif\r
 \r
 #ifdef FAMEC_EMULATE_TRACE\r
-       if (m68kcontext.execinfo & FM68K_EMULATE_TRACE)\r
+       if (ctx->execinfo & FM68K_EMULATE_TRACE)\r
        {\r
-               m68kcontext.io_cycle_counter = cycles_needed;\r
+               ctx->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
+               ctx->execinfo &= ~FM68K_EMULATE_TRACE;\r
+               ctx->execinfo |= FM68K_DO_TRACE;\r
+               SET_PC(execute_exception(ctx, M68K_TRACE_EX, GET_PC, GET_SR));\r
+               if (ctx->io_cycle_counter > 0)\r
                {\r
                        //NEXT\r
                        goto famec_Exec;\r
@@ -920,23 +936,24 @@ famec_Exec:
                if (cycles_needed != 0)\r
                {\r
                        u32 line;\r
-                       m68kcontext.io_cycle_counter = cycles_needed;\r
+                       ctx->io_cycle_counter += cycles_needed;\r
                        cycles_needed = 0;\r
-                       line=interrupt_chk__();\r
+                       //if (ctx->io_cycle_counter <= 0) goto famec_End;\r
+                       line=interrupt_chk__(ctx);\r
                        if (line>0)\r
                        {\r
-                               if (m68kcontext.iack_handler != NULL)\r
-                                       m68kcontext.iack_handler(line);\r
+                               if (ctx->iack_handler != NULL)\r
+                                       ctx->iack_handler(line);\r
                                else\r
-                                       m68kcontext.interrupts[0] = 0;\r
+                                       ctx->interrupts[0] = 0;\r
 \r
-                               SET_PC(execute_exception(line + 0x18, GET_PC, GET_SR));\r
+                               SET_PC(execute_exception(ctx, line + 0x18, GET_PC, GET_SR));\r
                                flag_I = (u32)line;\r
                        }\r
 #ifdef FAMEC_EMULATE_TRACE\r
                        if (!(flag_T))\r
 #endif\r
-                       if (m68kcontext.io_cycle_counter > 0)\r
+                       if (ctx->io_cycle_counter > 0)\r
                        {\r
                                //NEXT\r
                                goto famec_Exec;\r
@@ -944,72 +961,27 @@ famec_Exec:
                }\r
 \r
 famec_End:\r
-       m68kcontext.sr = GET_SR;\r
-       m68kcontext.pc = GET_PC;\r
+       ctx->sr = GET_SR;\r
+       ctx->pc = GET_PC;\r
 \r
-       m68kcontext.execinfo &= ~M68K_RUNNING;\r
+       ctx->execinfo &= ~M68K_RUNNING;\r
 \r
 #ifdef FAMEC_DEBUG\r
        printf("En really end...\n");\r
        printf("PC: %p\n",PC);\r
        printf("BasePC: 0x%08x\n",BasePC);\r
-       printf("pc: 0x%08x\n",m68kcontext.pc);\r
+       printf("pc: 0x%08x\n",ctx->pc);\r
 #endif\r
 \r
-#ifdef PICODRIVE_HACK\r
-       if (!dualcore)\r
-#endif\r
-               return cycles - m68kcontext.io_cycle_counter;\r
+       return cycles - ctx->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
@@ -5039,7 +5011,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
@@ -5052,8 +5029,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
@@ -5066,9 +5049,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
-void *get_jumptab(void) { return JumpTable; }\r
+static int init_jump_table(void)\r
+{\r
+       return fm68k_emulate(NULL, 0, fm68k_reason_init);\r
+}\r
 \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