psp bugfixes, refactoring, stuff
[picodrive.git] / cpu / fame / famec.c
index d3cd539..76965fa 100644 (file)
@@ -26,6 +26,7 @@
 #define FAMEC_ADR_BITS  24\r
 // #define FAMEC_FETCHBITS 8\r
 #define FAMEC_DATABITS  8\r
+#define FAMEC_32BIT_PC\r
 \r
 #define USE_CYCLONE_TIMING\r
 #define USE_CYCLONE_TIMING_DIV\r
@@ -289,15 +290,22 @@ static u32 flag_I;
 #define GET_PC                  \\r
        (u32)PC - BasePC;\r
 \r
+\r
+#ifndef FAMEC_32BIT_PC\r
+\r
 #define SET_PC(A)               \\r
     BasePC = g_m68kcontext->Fetch[((A) >> M68K_FETCHSFT) & M68K_FETCHMASK];    \\r
    /*  BasePC -= (A) & 0xFF000000; */   \\r
     PC = (u16*)(((A) & M68K_ADR_MASK) + BasePC);\r
 \r
-#define SET_PC_BASE(P,B,A)               \\r
-    (B) = g_m68kcontext->Fetch[((A) >> M68K_FETCHSFT) & M68K_FETCHMASK];    \\r
-   /* (B) -= (A) & 0xFF000000; */ \\r
-    (P) = (u16*)(((A) & M68K_ADR_MASK) + (B));\r
+#else\r
+\r
+#define SET_PC(A)               \\r
+    BasePC = g_m68kcontext->Fetch[((A) >> M68K_FETCHSFT) & M68K_FETCHMASK];    \\r
+    BasePC -= (A) & 0xFF000000;    \\r
+    PC = (u16*)((A) + BasePC);\r
+\r
+#endif\r
 \r
 \r
 #define PRE_IO                  \\r
@@ -306,44 +314,38 @@ static u32 flag_I;
 #define POST_IO                 \\r
 //    CCnt = io_cycle_counter;\r
 \r
-#ifndef FAME_BIG_ENDIAN\r
+#define READ_BYTE_F(A, D)           \\r
+       D = m68kcontext.read_byte(A) & 0xFF;\r
+\r
+#define READ_WORD_F(A, D)           \\r
+       D = m68kcontext.read_word(A) & 0xFFFF;\r
 \r
-       #define READ_BYTE_F(A, D)           \\r
-               D = m68kcontext.read_byte(A) & 0xFF;\r
+#define READ_LONG_F(A, D)           \\r
+       D = m68kcontext.read_long(A);\r
 \r
-       #define READ_WORD_F(A, D)           \\r
-               D = m68kcontext.read_word(A) & 0xFFFF;\r
+#define READSX_LONG_F READ_LONG_F\r
 \r
-       #define READ_LONG_F(A, D)               \\r
-               D = m68kcontext.read_word((A)) << 16;          \\r
-               D |= m68kcontext.read_word((A) + 2) & 0xFFFF;\r
+#define WRITE_LONG_F(A, D)          \\r
+       m68kcontext.write_long(A, D);\r
 \r
-       #define READSX_LONG_F(A, D)             \\r
-               D = m68kcontext.read_word((A)) << 16;          \\r
-               D |= m68kcontext.read_word((A) + 2) & 0xFFFF;\r
+#define WRITE_LONG_DEC_F(A, D)          \\r
+       m68kcontext.write_word((A) + 2, (D) & 0xFFFF);    \\r
+       m68kcontext.write_word((A), (D) >> 16);\r
 \r
-       #define WRITE_LONG_F(A, D)              \\r
-               m68kcontext.write_word((A), (D) >> 16);        \\r
-               m68kcontext.write_word((A) + 2, (D) & 0xFFFF);\r
+#define PUSH_32_F(D)                        \\r
+       AREG(7) -= 4;                               \\r
+       m68kcontext.write_long(AREG(7), D);\r
 \r
-       #define WRITE_LONG_DEC_F(A, D)          \\r
-               m68kcontext.write_word((A), (D) >> 16); \\r
-               m68kcontext.write_word((A) + 2, (D) & 0xFFFF);\r
+#define POP_32_F(D)                         \\r
+       D = m68kcontext.read_long(AREG(7));         \\r
+       AREG(7) += 4;\r
+\r
+#ifndef FAME_BIG_ENDIAN\r
 \r
        #define FETCH_LONG(A)               \\r
                (A) = PC[1] | (PC[0] << 16);    \\r
                PC += 2;\r
 \r
-    #define PUSH_32_F(D)                            \\r
-       AREG(7) -= 4;                                   \\r
-       m68kcontext.write_word(AREG(7), (D) >> 16);     \\r
-       m68kcontext.write_word(AREG(7) + 2, (D) & 0xFFFF);\r
-\r
-    #define POP_32_F(D)                         \\r
-       D = m68kcontext.read_word(AREG(7)) << 16;          \\r
-       D |= m68kcontext.read_word(AREG(7) + 2) & 0xFFFF;  \\r
-       AREG(7) += 4;\r
-\r
        #define GET_SWORD           \\r
                (s16)(*PC)\r
 \r
@@ -372,37 +374,10 @@ static u32 flag_I;
 \r
 #else\r
 \r
-       #define READ_BYTE_F(A, D)           \\r
-               D = m68kcontext.read_byte(A) & 0xFF;\r
-\r
-       #define READ_WORD_F(A, D)           \\r
-               D = m68kcontext.read_word(A) & 0xFFFF;\r
-\r
-       #define READ_LONG_F(A, D)           \\r
-               D = m68kcontext.read_long(A);\r
-\r
-       #define READSX_LONG_F(A, D)         \\r
-               D = m68kcontext.read_long(A);\r
-\r
-       #define WRITE_LONG_F(A, D)          \\r
-               m68kcontext.write_long(A, D);\r
-\r
-       #define WRITE_LONG_DEC_F(A, D)          \\r
-               m68kcontext.write_word((A) + 2, (D) >> 16);    \\r
-               m68kcontext.write_word((A), (D) & 0xFFFF);\r
-\r
        #define FETCH_LONG(A)               \\r
                (A) = PC[0] | (PC[1] << 16);    \\r
                PC += 2;\r
 \r
-       #define PUSH_32_F(D)                        \\r
-               AREG(7) -= 4;                               \\r
-               m68kcontext.write_long(AREG(7), D);\r
-\r
-       #define POP_32_F(D)                         \\r
-               D = m68kcontext.read_long(AREG(7));         \\r
-               AREG(7) += 4;\r
-\r
        #define GET_SWORD                           \\r
                ((s16)(((*PC & 0xFF) << 8) | (*PC >> 8)))\r
 \r
@@ -514,7 +489,7 @@ static u32 flag_I;
        if ((_PC_)&1) \\r
        { \\r
                u32 pr_PC=GET_PC; \\r
-               m68kcontext.execinfo |= M68K_EMULATE_GROUP_0; \\r
+               m68kcontext.execinfo |= FM68K_EMULATE_GROUP_0; \\r
                execute_exception_group_0(M68K_ADDRESS_ERROR_EX, 0, pr_PC, 0x12 ); \\r
                CHECK_BRANCH_EXCEPTION_GOTO_END \\r
        }\r
@@ -626,35 +601,6 @@ static const s32 exception_cycle_table[256] =
 };\r
 \r
 \r
-/********************/\r
-/* helper functions */\r
-/********************/\r
-\r
-\r
-#if 0\r
-static void famec_SetFetch(u32 low_adr, u32 high_adr, u32 fetch_adr)\r
-{\r
-    u32 i, j;\r
-\r
-       i = (low_adr >> M68K_FETCHSFT) & M68K_FETCHMASK;\r
-       j = (high_adr >> M68K_FETCHSFT) & M68K_FETCHMASK;\r
-\r
-       while (i <= j)\r
-               g_m68kcontext->Fetch[i++] = fetch_adr;\r
-}\r
-\r
-static void famec_SetBanks(void)\r
-{\r
-       u32 i=0;\r
-       while(m68kcontext.fetch[i].low_addr != (u32)-1)\r
-       {\r
-               famec_SetFetch(m68kcontext.fetch[i].low_addr,m68kcontext.fetch[i].high_addr,m68kcontext.fetch[i].offset);\r
-               i++;\r
-       }\r
-}\r
-#endif\r
-\r
-\r
 /***********************/\r
 /* core main functions */\r
 /***********************/\r
@@ -664,14 +610,14 @@ static void famec_SetBanks(void)
 /* Debe ser llamado para inicializar la tabla de saltos de instruccion     */\r
 /* No recibe parametros y no devuelve nada                                 */\r
 /***************************************************************************/\r
-void m68k_init(void)\r
+void fm68k_init(void)\r
 {\r
 #ifdef FAMEC_DEBUG\r
        puts("Initializing FAME...");\r
 #endif\r
 \r
     if (!initialised)\r
-           m68k_emulate(0);\r
+           fm68k_emulate(0);\r
 \r
 #ifdef FAMEC_DEBUG\r
        puts("FAME initialized.");\r
@@ -687,17 +633,17 @@ void m68k_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 m68k_reset(void)\r
+int fm68k_reset(void)\r
 {\r
        if (!initialised)\r
-               m68k_emulate(0);\r
+               fm68k_emulate(0);\r
 \r
        // Si la CPU esta en ejecucion, salir con M68K_RUNNING\r
        if (m68kcontext.execinfo & M68K_RUNNING)\r
                return M68K_RUNNING;\r
 \r
        // Resetear registros\r
-       memset(&m68kcontext.dreg[0], 0, 16*4);\r
+       //memset(&m68kcontext.dreg[0], 0, 16*4);\r
 \r
        // Resetear interrupts, execinfo y ASP\r
        m68kcontext.interrupts[0] = 0;\r
@@ -705,7 +651,7 @@ int m68k_reset(void)
        ASP = 0;\r
 \r
        // Fijar registro de estado\r
-       m68kcontext.sr = 0x2700;\r
+       m68kcontext.sr = (m68kcontext.sr & 0xff) | 0x2700;\r
 \r
        // Obtener puntero de pila inicial y PC\r
        AREG(7) = m68kcontext.read_long(0);\r
@@ -725,138 +671,12 @@ int m68k_reset(void)
 /* No recibe parametros                                                     */\r
 /* Retorna 68k PC                                                           */\r
 /****************************************************************************/\r
-u32 m68k_get_pc(M68K_CONTEXT *context)\r
+u32 fm68k_get_pc(M68K_CONTEXT *context)\r
 {\r
        return (context->execinfo & M68K_RUNNING)?(u32)PC-BasePC:context->pc;\r
 }\r
 \r
 \r
-/***************************************************************************/\r
-/*  m68k_get_register(register)                                            */\r
-/*  Parametro: Registro a obtener valor (indice)                           */\r
-/*  Retorno: Valor del registro requerido                                  */\r
-/*  Observacion: En caso de que el indice no sea correcto                  */\r
-/*               la funcion devolvera -1                                   */\r
-/***************************************************************************/\r
-u32 m68k_get_register(M68K_CONTEXT *context, m68k_register reg)\r
-{\r
-       M68K_CONTEXT *oldcontext = g_m68kcontext;\r
-       s32 ret;\r
-\r
-       g_m68kcontext = context;\r
-\r
-       switch (reg)\r
-       {\r
-               case M68K_REG_D0:\r
-               case M68K_REG_D1:\r
-               case M68K_REG_D2:\r
-               case M68K_REG_D3:\r
-               case M68K_REG_D4:\r
-               case M68K_REG_D5:\r
-               case M68K_REG_D6:\r
-               case M68K_REG_D7:\r
-                       ret = DREG(reg - M68K_REG_D0);\r
-                       break;\r
-\r
-               case M68K_REG_A0:\r
-               case M68K_REG_A1:\r
-               case M68K_REG_A2:\r
-               case M68K_REG_A3:\r
-               case M68K_REG_A4:\r
-               case M68K_REG_A5:\r
-               case M68K_REG_A6:\r
-               case M68K_REG_A7:\r
-                       ret = AREG(reg - M68K_REG_A0);\r
-                       break;\r
-\r
-               case M68K_REG_ASP:\r
-                       ret = ASP;\r
-                       break;\r
-\r
-               case M68K_REG_PC:\r
-                       ret = m68k_get_pc(context);\r
-                       break;\r
-\r
-               case M68K_REG_SR:\r
-                       ret = m68kcontext.sr;\r
-                       break;\r
-\r
-               default:\r
-                       ret = M68K_INV_REG;\r
-                       break;\r
-       }\r
-\r
-       g_m68kcontext = oldcontext;\r
-       return ret;\r
-}\r
-\r
-/***********************************************************************/\r
-/*  m68k_set_register(register,value)                                  */\r
-/*  Parametros: Registro (indice) y valor a asignar                    */\r
-/*  Retorno: Exito de la operacion                                     */\r
-/*           0  La operacion se ha realizado satisfactoriamente        */\r
-/*           1  El indice del registro no es valido (fuera de limites) */\r
-/***********************************************************************/\r
-u32 m68k_set_register(M68K_CONTEXT *context, m68k_register reg, u32 value)\r
-{\r
-       M68K_CONTEXT *oldcontext = g_m68kcontext;\r
-       s32 ret = M68K_OK;\r
-\r
-       g_m68kcontext = context;\r
-\r
-       switch (reg)\r
-       {\r
-               case M68K_REG_D0:\r
-               case M68K_REG_D1:\r
-               case M68K_REG_D2:\r
-               case M68K_REG_D3:\r
-               case M68K_REG_D4:\r
-               case M68K_REG_D5:\r
-               case M68K_REG_D6:\r
-               case M68K_REG_D7:\r
-                       DREG(reg - M68K_REG_D0) = value;\r
-                       break;\r
-\r
-               case M68K_REG_A0:\r
-               case M68K_REG_A1:\r
-               case M68K_REG_A2:\r
-               case M68K_REG_A3:\r
-               case M68K_REG_A4:\r
-               case M68K_REG_A5:\r
-               case M68K_REG_A6:\r
-               case M68K_REG_A7:\r
-                       AREG(reg - M68K_REG_A0) = value;\r
-                       break;\r
-\r
-               case M68K_REG_ASP:\r
-                       ASP = value;\r
-                       break;\r
-\r
-               case M68K_REG_PC:\r
-                       if (m68kcontext.execinfo & M68K_RUNNING)\r
-                       {\r
-                               SET_PC(value & M68K_ADR_MASK);\r
-                       }\r
-                       else\r
-                       {\r
-                               m68kcontext.pc = value;\r
-                       }\r
-                       break;\r
-\r
-               case M68K_REG_SR:\r
-                       m68kcontext.sr = value & 0xFFFF;\r
-                       break;\r
-\r
-               default:\r
-                       ret = M68K_INV_REG;\r
-                       break;\r
-       }\r
-\r
-       g_m68kcontext = oldcontext;\r
-       return ret;\r
-}\r
-\r
-\r
 //////////////////////////\r
 // Chequea las interrupciones y las inicia\r
 static FAMEC_EXTRA_INLINE s32 interrupt_chk__(void)\r
@@ -867,6 +687,10 @@ static FAMEC_EXTRA_INLINE s32 interrupt_chk__(void)
        return 0;\r
 }\r
 \r
+int fm68k_would_interrupt(void)\r
+{\r
+       return interrupt_chk__();\r
+}\r
 \r
 static FAMEC_EXTRA_INLINE void execute_exception(s32 vect)\r
 {\r
@@ -901,7 +725,10 @@ static FAMEC_EXTRA_INLINE void execute_exception(s32 vect)
                /* adjust SR */\r
                flag_S = M68K_SR_S;\r
 \r
-               newPC&=M68K_ADR_MASK;\r
+#ifndef FAMEC_32BIT_PC\r
+               newPC&=M68K_ADR_MASK\r
+#endif\r
+               newPC&=~1; // don't crash on games with bad vector tables\r
 \r
                SET_PC(newPC)\r
 \r
@@ -935,7 +762,7 @@ static u32 Opcode;
 // main exec function\r
 //////////////////////\r
 \r
-int m68k_emulate(s32 cycles)\r
+int fm68k_emulate(s32 cycles)\r
 {\r
        if (!initialised)\r
        {\r
@@ -947,16 +774,16 @@ int m68k_emulate(s32 cycles)
 #endif\r
        }\r
 \r
-       /* Comprobar si la CPU esta detenida debido a un doble error de bus */\r
-       if (m68kcontext.execinfo & M68K_FAULTED) return -1;\r
+       // won't emulate double fault\r
+       // if (m68kcontext.execinfo & M68K_FAULTED) return -1;\r
 \r
-       if (m68kcontext.execinfo & M68K_HALTED)\r
+       if (m68kcontext.execinfo & FM68K_HALTED)\r
        {\r
                if (interrupt_chk__() <= 0)\r
                {\r
                        return cycles;\r
                }\r
-               m68kcontext.execinfo &= ~M68K_HALTED;\r
+               m68kcontext.execinfo &= ~FM68K_HALTED;\r
        }\r
 \r
 #ifdef FAMEC_DEBUG\r
@@ -985,7 +812,7 @@ int m68k_emulate(s32 cycles)
        cycles_needed = 0;\r
 \r
 #ifdef FAMEC_EMULATE_TRACE\r
-       if (!(m68kcontext.execinfo & M68K_EMULATE_TRACE))\r
+       if (!(m68kcontext.execinfo & FM68K_EMULATE_TRACE))\r
 #endif\r
        {\r
                s32 line=interrupt_chk__();\r
@@ -999,12 +826,13 @@ int m68k_emulate(s32 cycles)
 \r
                        execute_exception(line + 0x18);\r
                        flag_I = (u32)line;\r
+                       if (m68kcontext.io_cycle_counter <= 0) goto famec_End;\r
                }\r
 #ifdef FAMEC_EMULATE_TRACE\r
                else\r
                        if  (flag_T)\r
                        {\r
-                               m68kcontext.execinfo |= M68K_EMULATE_TRACE;\r
+                               m68kcontext.execinfo |= FM68K_EMULATE_TRACE;\r
                                cycles_needed= m68kcontext.io_cycle_counter;\r
                                m68kcontext.io_cycle_counter=0;\r
                        }\r
@@ -1012,9 +840,9 @@ int m68k_emulate(s32 cycles)
        }\r
 \r
 \r
-#ifndef FAMEC_NO_GOTOS\r
+//#ifndef FAMEC_NO_GOTOS\r
 famec_Exec:\r
-#endif\r
+//#endif\r
 \r
 #ifdef FAMEC_DEBUG\r
        printf("Antes de NEXT... PC = %p\n", PC);\r
@@ -1032,11 +860,11 @@ famec_Exec:
 #endif\r
 \r
 #ifdef FAMEC_EMULATE_TRACE\r
-       if (m68kcontext.execinfo & M68K_EMULATE_TRACE)\r
+       if (m68kcontext.execinfo & FM68K_EMULATE_TRACE)\r
        {\r
                m68kcontext.io_cycle_counter= cycles_needed;\r
-               m68kcontext.execinfo &= ~M68K_EMULATE_TRACE;\r
-               m68kcontext.execinfo |= M68K_DO_TRACE;\r
+               m68kcontext.execinfo &= ~FM68K_EMULATE_TRACE;\r
+               m68kcontext.execinfo |= FM68K_DO_TRACE;\r
                execute_exception(M68K_TRACE_EX);\r
                flag_T=0;\r
                if (m68kcontext.io_cycle_counter > 0)\r
@@ -1046,7 +874,7 @@ famec_Exec:
        }\r
        else\r
 #endif\r
-               if (cycles_needed>0)\r
+               if (cycles_needed != 0)\r
                {\r
                        s32 line=interrupt_chk__();\r
                        m68kcontext.io_cycle_counter= cycles_needed;\r
@@ -1065,10 +893,12 @@ famec_Exec:
 #endif\r
                        if (m68kcontext.io_cycle_counter > 0)\r
                        {\r
-                               NEXT\r
+                               //NEXT\r
+                               goto famec_Exec;\r
                        }\r
                }\r
 \r
+famec_End:\r
        m68kcontext.sr = GET_SR;\r
        m68kcontext.pc = GET_PC;\r
 \r
@@ -1094,6 +924,8 @@ init_jump_table:
 #endif\r
        u32 i, j;\r
 \r
+       m68kcontext.sr = 0x2704; // Z flag\r
+\r
        for(i = 0x0000; i <= 0xFFFF; i += 0x0001)\r
                JumpTable[0x0000 + i] = CAST_OP(0x4AFC);\r
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
@@ -1604,6 +1436,7 @@ init_jump_table:
                JumpTable[0x1EC0 + i] = CAST_OP(0x1EC0);\r
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
                JumpTable[0x1F00 + i] = CAST_OP(0x1F00);\r
+#if 0\r
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
                for(j = 0x0000; j <= 0x0E00; j += 0x0200)\r
                        JumpTable[0x1008 + i + j] = CAST_OP(0x1008);\r
@@ -1630,6 +1463,7 @@ init_jump_table:
                JumpTable[0x1EC8 + i] = CAST_OP(0x1EC8);\r
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
                JumpTable[0x1F08 + i] = CAST_OP(0x1F08);\r
+#endif\r
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
                for(j = 0x0000; j <= 0x0E00; j += 0x0200)\r
                        JumpTable[0x1010 + i + j] = CAST_OP(0x1010);\r
@@ -3759,9 +3593,11 @@ init_jump_table:
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
                for(j = 0x0000; j <= 0x0E00; j += 0x0200)\r
                        JumpTable[0x9000 + i + j] = CAST_OP(0x9000);\r
+#if 0\r
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
                for(j = 0x0000; j <= 0x0E00; j += 0x0200)\r
                        JumpTable[0x9008 + i + j] = CAST_OP(0x9008);\r
+#endif\r
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
                for(j = 0x0000; j <= 0x0E00; j += 0x0200)\r
                        JumpTable[0x9010 + i + j] = CAST_OP(0x9010);\r
@@ -4038,9 +3874,11 @@ init_jump_table:
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
                for(j = 0x0000; j <= 0x0E00; j += 0x0200)\r
                        JumpTable[0xB000 + i + j] = CAST_OP(0xB000);\r
+#if 0\r
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
                for(j = 0x0000; j <= 0x0E00; j += 0x0200)\r
                        JumpTable[0xB008 + i + j] = CAST_OP(0xB008);\r
+#endif\r
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
                for(j = 0x0000; j <= 0x0E00; j += 0x0200)\r
                        JumpTable[0xB010 + i + j] = CAST_OP(0xB010);\r
@@ -4564,9 +4402,11 @@ init_jump_table:
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
                for(j = 0x0000; j <= 0x0E00; j += 0x0200)\r
                        JumpTable[0xD000 + i + j] = CAST_OP(0xD000);\r
+#if 0\r
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
                for(j = 0x0000; j <= 0x0E00; j += 0x0200)\r
                        JumpTable[0xD008 + i + j] = CAST_OP(0xD008);\r
+#endif\r
        for(i = 0x0000; i <= 0x0007; i += 0x0001)\r
                for(j = 0x0000; j <= 0x0E00; j += 0x0200)\r
                        JumpTable[0xD010 + i + j] = CAST_OP(0xD010);\r