32x: drc: new debug facility (pdb). Few fixes thanks to it.
[picodrive.git] / cpu / sh2 / compiler.c
index 5a9bbed..eea9a60 100644 (file)
@@ -29,6 +29,7 @@
 #include "sh2.h"
 #include "compiler.h"
 #include "../drc/cmn.h"
+#include "../debug.h"
 
 // features
 #define PROPAGATE_CONSTANTS     1
@@ -68,12 +69,14 @@ static char sh2dasm_buff[64];
 #define do_host_disasm(x)
 #endif
 
-#if (DRC_DEBUG & 4)
-static void REGPARM(3) *sh2_drc_announce_entry(void *block, SH2 *sh2, u32 sr)
+#if (DRC_DEBUG & 4) || defined(PDB)
+static void REGPARM(3) *sh2_drc_log_entry(void *block, SH2 *sh2, u32 sr)
 {
-  if (block != NULL)
+  if (block != NULL) {
     dbg(4, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm',
       sh2->pc, block, (signed int)sr >> 12);
+    pdb_step(sh2, sh2->pc);
+  }
   return block;
 }
 #endif
@@ -216,10 +219,15 @@ static void REGPARM(1) (*sh2_drc_entry)(SH2 *sh2);
 static void            (*sh2_drc_dispatcher)(void);
 static void            (*sh2_drc_exit)(void);
 static void            (*sh2_drc_test_irq)(void);
+
+static u32  REGPARM(2) (*sh2_drc_read8)(u32 a, SH2 *sh2);
+static u32  REGPARM(2) (*sh2_drc_read16)(u32 a, SH2 *sh2);
+static u32  REGPARM(2) (*sh2_drc_read32)(u32 a, SH2 *sh2);
 static void REGPARM(2) (*sh2_drc_write8)(u32 a, u32 d);
 static void REGPARM(2) (*sh2_drc_write8_slot)(u32 a, u32 d);
 static void REGPARM(2) (*sh2_drc_write16)(u32 a, u32 d);
 static void REGPARM(2) (*sh2_drc_write16_slot)(u32 a, u32 d);
+static int  REGPARM(3) (*sh2_drc_write32)(u32 a, u32 d, SH2 *sh2);
 
 extern void REGPARM(2) sh2_do_op(SH2 *sh2, int opcode);
 
@@ -242,6 +250,7 @@ static void flush_tcache(int tcid)
 #endif
 }
 
+#if LINK_BRANCHES
 // add block links (tracked branches)
 static int dr_add_block_link(u32 target_pc, void *jump, int tcache_id)
 {
@@ -259,6 +268,7 @@ static int dr_add_block_link(u32 target_pc, void *jump, int tcache_id)
 
   return 0;
 }
+#endif
 
 static void *dr_find_block(block_desc *tab, u32 addr)
 {
@@ -848,7 +858,7 @@ static int emit_memhandler_read_(int size, int ram_check)
   arg1 = rcache_get_tmp_arg(1);
   emith_move_r_r(arg1, CONTEXT_REG);
 
-#if 1
+#ifndef PDB_NET
   if (ram_check && Pico.rom == (void *)0x02000000 && Pico32xMem->sdram == (void *)0x06000000) {
     int tmp = rcache_get_tmp();
     emith_and_r_r_imm(tmp, arg0, 0xfb000000);
@@ -859,14 +869,14 @@ static int emit_memhandler_read_(int size, int ram_check)
       emith_eor_r_imm_c(DCOND_EQ, arg0, 1);
       emith_read8_r_r_offs_c(DCOND_EQ, arg0, arg0, 0);
       EMITH_SJMP3_MID(DCOND_NE);
-      emith_call_cond(DCOND_NE, p32x_sh2_read8);
+      emith_call_cond(DCOND_NE, sh2_drc_read8);
       EMITH_SJMP3_END();
       break;
     case 1: // 16
       EMITH_SJMP3_START(DCOND_NE);
       emith_read16_r_r_offs_c(DCOND_EQ, arg0, arg0, 0);
       EMITH_SJMP3_MID(DCOND_NE);
-      emith_call_cond(DCOND_NE, p32x_sh2_read16);
+      emith_call_cond(DCOND_NE, sh2_drc_read16);
       EMITH_SJMP3_END();
       break;
     case 2: // 32
@@ -874,7 +884,7 @@ static int emit_memhandler_read_(int size, int ram_check)
       emith_read_r_r_offs_c(DCOND_EQ, arg0, arg0, 0);
       emith_ror_c(DCOND_EQ, arg0, arg0, 16);
       EMITH_SJMP3_MID(DCOND_NE);
-      emith_call_cond(DCOND_NE, p32x_sh2_read32);
+      emith_call_cond(DCOND_NE, sh2_drc_read32);
       EMITH_SJMP3_END();
       break;
     }
@@ -884,13 +894,13 @@ static int emit_memhandler_read_(int size, int ram_check)
   {
     switch (size) {
     case 0: // 8
-      emith_call(p32x_sh2_read8);
+      emith_call(sh2_drc_read8);
       break;
     case 1: // 16
-      emith_call(p32x_sh2_read16);
+      emith_call(sh2_drc_read16);
       break;
     case 2: // 32
-      emith_call(p32x_sh2_read32);
+      emith_call(sh2_drc_read32);
       break;
     }
   }
@@ -974,7 +984,7 @@ static void emit_memhandler_write(int size, u32 pc, int delay)
     break;
   case 2: // 32
     emith_move_r_r(ctxr, CONTEXT_REG);
-    emith_call(p32x_sh2_write32);
+    emith_call(sh2_drc_write32);
     break;
   }
   rcache_invalidate();
@@ -1050,10 +1060,11 @@ static void emit_block_entry(void)
   host_arg2reg(arg1, 1);
   host_arg2reg(arg2, 2);
 
-#if (DRC_DEBUG & 4)
+#if (DRC_DEBUG & 4) || defined(PDB)
+  emit_do_static_regs(1, arg2);
   emith_move_r_r(arg1, CONTEXT_REG);
   emith_move_r_r(arg2, rcache_get_reg(SHR_SR, RC_GR_READ));
-  emith_call(sh2_drc_announce_entry);
+  emith_call(sh2_drc_log_entry);
   rcache_invalidate();
 #endif
   emith_tst_r_r(arg0, arg0);
@@ -1256,10 +1267,6 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
   }
   branch_target_count = tmp;
   memset(branch_target_ptr, 0, sizeof(branch_target_ptr[0]) * branch_target_count);
-#if !LINK_BRANCHES
-  // for debug
-  branch_target_count = 0;
-#endif
 
   // -------------------------------------------------
   // 2nd pass: actual compilation
@@ -2479,6 +2486,7 @@ end_op:
       else
         emith_tst_r_imm(sr, T);
 
+#if LINK_BRANCHES
       if (find_in_array(branch_target_pc, branch_target_count, target_pc) >= 0) {
         // local branch
         // XXX: jumps back can be linked already
@@ -2492,7 +2500,9 @@ end_op:
           break;
         }
       }
-      else {
+      else
+#endif
+      {
         // can't resolve branch locally, make a block exit
         emit_move_r_imm32(SHR_PC, target_pc);
         rcache_clean();
@@ -2622,6 +2632,11 @@ static void sh2_generate_utils(void)
   int arg0, arg1, arg2, sr, tmp;
   void *sh2_drc_write_end, *sh2_drc_write_slot_end;
 
+  sh2_drc_write32 = p32x_sh2_write32;
+  sh2_drc_read8  = p32x_sh2_read8;
+  sh2_drc_read16 = p32x_sh2_read16;
+  sh2_drc_read32 = p32x_sh2_read32;
+
   host_arg2reg(arg0, 0);
   host_arg2reg(arg1, 1);
   host_arg2reg(arg2, 2);
@@ -2679,7 +2694,7 @@ static void sh2_generate_utils(void)
   tmp = rcache_get_reg_arg(1, SHR_SR);
   emith_clear_msb(tmp, tmp, 22);
   emith_move_r_r(arg2, CONTEXT_REG);
-  emith_call(p32x_sh2_write32);
+  emith_call(p32x_sh2_write32); // XXX: use sh2_drc_write32?
   rcache_invalidate();
   // push PC
   rcache_get_reg_arg(0, SHR_SP);
@@ -2722,7 +2737,6 @@ static void sh2_generate_utils(void)
   EMITH_SJMP_START(DCOND_NE);
   emith_jump_ctx_c(DCOND_EQ, offsetof(SH2, drc_tmp)); // return
   EMITH_SJMP_END(DCOND_NE);
-  // since PC is up to date, jump to it's block instead of returning
   emith_call(sh2_drc_test_irq);
   emith_jump_ctx(offsetof(SH2, drc_tmp));
 
@@ -2763,6 +2777,50 @@ static void sh2_generate_utils(void)
   emith_ctx_read(arg2, offsetof(SH2, write16_tab));
   emith_sh2_wcall(arg0, arg2, sh2_drc_write_slot_end);
 
+#ifdef PDB_NET
+  // debug
+  #define MAKE_READ_WRAPPER(func) { \
+    void *tmp = (void *)tcache_ptr; \
+    emith_ret_to_ctx(offsetof(SH2, drc_tmp)); \
+    emith_call(func); \
+    emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[0]));  \
+    emith_addf_r_r(arg2, arg0);                           \
+    emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[0])); \
+    emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[1]));  \
+    emith_adc_r_imm(arg2, 0x01000000);                    \
+    emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[1])); \
+    emith_jump_ctx(offsetof(SH2, drc_tmp)); \
+    func = tmp; \
+  }
+  #define MAKE_WRITE_WRAPPER(func) { \
+    void *tmp = (void *)tcache_ptr; \
+    emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[0]));  \
+    emith_addf_r_r(arg2, arg1);                           \
+    emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[0])); \
+    emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[1]));  \
+    emith_adc_r_imm(arg2, 0x01000000);                    \
+    emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[1])); \
+    emith_move_r_r(arg2, CONTEXT_REG);                    \
+    emith_jump(func); \
+    func = tmp; \
+  }
+
+  MAKE_READ_WRAPPER(sh2_drc_read8);
+  MAKE_READ_WRAPPER(sh2_drc_read16);
+  MAKE_READ_WRAPPER(sh2_drc_read32);
+  MAKE_WRITE_WRAPPER(sh2_drc_write8);
+  MAKE_WRITE_WRAPPER(sh2_drc_write8_slot);
+  MAKE_WRITE_WRAPPER(sh2_drc_write16);
+  MAKE_WRITE_WRAPPER(sh2_drc_write16_slot);
+  MAKE_WRITE_WRAPPER(sh2_drc_write32);
+#if (DRC_DEBUG & 2)
+  host_dasm_new_symbol(sh2_drc_read8);
+  host_dasm_new_symbol(sh2_drc_read16);
+  host_dasm_new_symbol(sh2_drc_read32);
+  host_dasm_new_symbol(sh2_drc_write32);
+#endif
+#endif
+
   rcache_invalidate();
 #if (DRC_DEBUG & 2)
   host_dasm_new_symbol(sh2_drc_entry);