drc: support ms ABI
[picodrive.git] / pico / carthw / svp / compiler.c
index 3632b91..b31197c 100644 (file)
@@ -1,7 +1,10 @@
-// SSP1601 to ARM recompiler
-
-// (c) Copyright 2008, Grazvydas "notaz" Ignotas
-// Free for non-commercial use.
+/*
+ * SSP1601 to ARM recompiler
+ * (C) notaz, 2008,2009,2010
+ *
+ * This work is licensed under the terms of MAME license.
+ * See COPYING file in the top-level directory.
+ */
 
 #include "../../pico_int.h"
 #include "../../../cpu/drc/cmn.h"
@@ -28,7 +31,7 @@ extern ssp1601_t *ssp;
 #define SSP_FLAG_Z (1<<0xd)
 #define SSP_FLAG_N (1<<0xf)
 
-#ifndef ARM
+#ifndef __arm__
 //#define DUMP_BLOCK 0x0c9a
 void ssp_drc_next(void){}
 void ssp_drc_next_patch(void){}
@@ -686,6 +689,18 @@ static int tr_aop_ssp2arm(int op)
        return 0;
 }
 
+#ifdef __MACH__
+/* spacial version of call for calling C needed on ios, since we use r9.. */
+static void emith_call_c_func(void *target)
+{
+       EOP_STMFD_SP(A_R7M|A_R9M);
+       emith_call(target);
+       EOP_LDMFD_SP(A_R7M|A_R9M);
+}
+#else
+#define emith_call_c_func emith_call
+#endif
+
 // -----------------------------------------------------
 
 //@ r4:  XXYY
@@ -836,7 +851,7 @@ static void tr_PMX_to_r0(int reg)
        tr_flush_dirty_ST();
        //tr_flush_dirty_pmcrs();
        tr_mov16(0, reg);
-       emith_call(ssp_pm_read);
+       emith_call_c_func(ssp_pm_read);
        hostreg_clear();
 }
 
@@ -1077,7 +1092,7 @@ static void tr_r0_to_PMX(int reg)
        tr_flush_dirty_ST();
        //tr_flush_dirty_pmcrs();
        tr_mov16(1, reg);
-       emith_call(ssp_pm_write);
+       emith_call_c_func(ssp_pm_write);
        hostreg_clear();
 }
 
@@ -1677,9 +1692,14 @@ static void emit_block_prologue(void)
  * >0: direct (un)conditional jump
  * <0: indirect jump
  */
-static void emit_block_epilogue(int cycles, int cond, int pc, int end_pc)
+static void *emit_block_epilogue(int cycles, int cond, int pc, int end_pc)
 {
-       if (cycles > 0xff) { elprintf(EL_ANOMALY, "large cycle count: %i\n", cycles); cycles = 0xff; }
+       void *end_ptr = NULL;
+
+       if (cycles > 0xff) {
+               elprintf(EL_ANOMALY, "large cycle count: %i\n", cycles);
+               cycles = 0xff;
+       }
        EOP_SUB_IMM(11,11,0,cycles);            // sub r11, r11, #cycles
 
        if (cond < 0 || (end_pc >= 0x400 && pc < 0x400)) {
@@ -1694,6 +1714,7 @@ static void emit_block_epilogue(int cycles, int cond, int pc, int end_pc)
                        emith_jump(target);
                else {
                        int ops = emith_jump(ssp_drc_next);
+                       end_ptr = tcache_ptr;
                        // cause the next block to be emitted over jump instruction
                        tcache_ptr -= ops;
                }
@@ -1721,12 +1742,17 @@ static void emit_block_epilogue(int cycles, int cond, int pc, int end_pc)
                        emith_jump(ssp_drc_next);
 #endif
        }
+
+       if (end_ptr == NULL)
+               end_ptr = tcache_ptr;
+
+       return end_ptr;
 }
 
 void *ssp_translate_block(int pc)
 {
        unsigned int op, op1, imm, ccount = 0;
-       unsigned int *block_start;
+       unsigned int *block_start, *block_end;
        int ret, end_cond = A_COND_AL, jump_pc = -1;
 
        //printf("translate %04x -> %04x\n", pc<<1, (tcache_ptr-tcache)<<2);
@@ -1768,7 +1794,7 @@ void *ssp_translate_block(int pc)
        tr_flush_dirty_prs();
        tr_flush_dirty_ST();
        tr_flush_dirty_pmcrs();
-       emit_block_epilogue(ccount, end_cond, jump_pc, pc);
+       block_end = emit_block_epilogue(ccount, end_cond, jump_pc, pc);
 
        if (tcache_ptr - (u32 *)tcache > DRC_TCACHE_SIZE/4) {
                elprintf(EL_ANOMALY|EL_STATUS|EL_SVP, "tcache overflow!\n");
@@ -1791,8 +1817,8 @@ void *ssp_translate_block(int pc)
        exit(0);
 #endif
 
-#ifdef ARM
-       cache_flush_d_inval_i(tcache, tcache_ptr);
+#ifdef __arm__
+       cache_flush_d_inval_i(block_start, block_end);
 #endif
 
        return block_start;
@@ -1836,7 +1862,7 @@ int ssp1601_dyn_startup(void)
        PicoLoadStateHook = ssp1601_state_load;
 
        n_in_ops = 0;
-#ifdef ARM
+#ifdef __arm__
        // hle'd blocks
        ssp_block_table[0x800/2] = (void *) ssp_hle_800;
        ssp_block_table[0x902/2] = (void *) ssp_hle_902;
@@ -1876,8 +1902,8 @@ void ssp1601_dyn_run(int cycles)
 #ifdef DUMP_BLOCK
        ssp_translate_block(DUMP_BLOCK >> 1);
 #endif
-#ifdef ARM
-       ssp_drc_entry(cycles);
+#ifdef __arm__
+       ssp_drc_entry(ssp, cycles);
 #endif
 }