add 32bit memory access functions for SH2
authorkub <derkub@gmail.com>
Wed, 27 Mar 2019 19:24:48 +0000 (20:24 +0100)
committerkub <derkub@gmail.com>
Tue, 30 Jul 2019 14:34:40 +0000 (16:34 +0200)
cpu/sh2/compiler.c
cpu/sh2/sh2.h
pico/32x/memory.c
pico/32x/sh2soc.c

index af6ca9c..3c82420 100644 (file)
@@ -2906,7 +2906,6 @@ static void sh2_generate_utils(void)
 {
   int arg0, arg1, arg2, sr, tmp;
 
-  sh2_drc_write32 = p32x_sh2_write32;
   sh2_drc_read8  = p32x_sh2_read8;
   sh2_drc_read16 = p32x_sh2_read16;
   sh2_drc_read32 = p32x_sh2_read32;
@@ -3015,6 +3014,11 @@ static void sh2_generate_utils(void)
   emith_ctx_read_ptr(arg2, offsetof(SH2, write16_tab));
   emith_sh2_wcall(arg0, arg2);
 
+  // sh2_drc_write32(u32 a, u32 d)
+  sh2_drc_write32 = (void *)tcache_ptr;
+  emith_ctx_read_ptr(arg2, offsetof(SH2, write32_tab));
+  emith_sh2_wcall(arg0, arg2);
+
 #ifdef PDB_NET
   // debug
   #define MAKE_READ_WRAPPER(func) { \
@@ -3053,7 +3057,6 @@ static void sh2_generate_utils(void)
   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
 
@@ -3065,6 +3068,7 @@ static void sh2_generate_utils(void)
   host_dasm_new_symbol(sh2_drc_test_irq);
   host_dasm_new_symbol(sh2_drc_write8);
   host_dasm_new_symbol(sh2_drc_write16);
+  host_dasm_new_symbol(sh2_drc_write32);
 #endif
 }
 
index 69abf8c..7faa844 100644 (file)
@@ -12,6 +12,7 @@ typedef enum {
 \r
 typedef struct SH2_\r
 {\r
+       // registers. this MUST correlate with enum sh2_reg_e.\r
        unsigned int    r[16];          // 00\r
        unsigned int    pc;             // 40\r
        unsigned int    ppc;\r
@@ -21,17 +22,19 @@ typedef struct SH2_
        unsigned int    mach, macl;     // 58\r
 \r
        // common\r
-       const void      *read8_map;     // 60\r
+       const void      *read8_map;\r
        const void      *read16_map;\r
+       const void      *read32_map;\r
        const void      **write8_tab;\r
        const void      **write16_tab;\r
+       const void      **write32_tab;\r
 \r
        // drc stuff\r
-       int             drc_tmp;        // 70\r
+       int             drc_tmp;\r
        int             irq_cycles;\r
        void            *p_bios;        // convenience pointers\r
        void            *p_da;\r
-       void            *p_sdram;       // 80\r
+       void            *p_sdram;\r
        void            *p_rom;\r
        unsigned int    pdb_io_csum[2];\r
 \r
index c6b89a2..d399d75 100644 (file)
@@ -1087,8 +1087,8 @@ static void m68k_write8_dram1_ow(u32 a, u32 d)
     return; \
   } \
   /* overwrite */ \
-  if (!(d & 0xff00)) d |= *pd & 0xff00; \
   if (!(d & 0x00ff)) d |= *pd & 0x00ff; \
+  if (!(d & 0xff00)) d |= *pd & 0xff00; \
   *pd = d;
 
 static void m68k_write16_dram0_ow(u32 a, u32 d)
@@ -1344,6 +1344,31 @@ static u32 sh2_read16_rom(u32 a, SH2 *sh2)
   return *(u16 *)(Pico.rom + bank + (a & 0x7fffe));
 }
 
+static u32 sh2_read32_unmapped(u32 a, SH2 *sh2)
+{
+  elprintf_sh2(sh2, EL_32X, "unmapped r32 [%08x]     %08x @%06x",
+    a, 0, sh2_pc(sh2));
+  return 0;
+}
+
+static u32 sh2_read32_cs0(u32 a, SH2 *sh2)
+{
+  return (sh2_read16_cs0(a, sh2) << 16) | sh2_read16_cs0(a + 2, sh2);
+}
+
+static u32 sh2_read32_da(u32 a, SH2 *sh2)
+{
+  u32 d = *(u32 *)(sh2->data_array + (a & 0xfff));
+  return (d << 16) | (d >> 16);
+}
+
+static u32 sh2_read32_rom(u32 a, SH2 *sh2)
+{
+  u32 bank = carthw_ssf2_banks[(a >> 19) & 7] << 19;
+  u32 d = *(u32 *)(Pico.rom + bank + (a & 0x7fffc));
+  return (d << 16) | (d >> 16);
+}
+
 // writes
 static void REGPARM(3) sh2_write_ignore(u32 a, u32 d, SH2 *sh2)
 {
@@ -1501,6 +1526,73 @@ static void REGPARM(3) sh2_write16_rom(u32 a, u32 d, SH2 *sh2)
     sh2_write16_unmapped(a, d, sh2);
 }
 
+static void REGPARM(3) sh2_write32_unmapped(u32 a, u32 d, SH2 *sh2)
+{
+  elprintf_sh2(sh2, EL_32X, "unmapped w32 [%08x]     %08x @%06x",
+      a, d, sh2_pc(sh2));
+}
+
+static void REGPARM(3) sh2_write32_cs0(u32 a, u32 d, SH2 *sh2)
+{
+  sh2_write16_cs0(a, d >> 16, sh2);
+  sh2_write16_cs0(a + 2, d, sh2);
+}
+
+#define sh2_write32_dramN(n) \
+  u32 *pd = (u32 *)&Pico32xMem->dram[n][(a & 0x1ffff) / 2]; \
+  if (!(a & 0x20000)) { \
+    *pd = (d << 16) | (d >> 16); \
+    return; \
+  } \
+  /* overwrite */ \
+  u8 *pb = (u8 *)pd; \
+  if (d & 0x000000ff) pb[2] = d; \
+  if (d & 0x0000ff00) pb[3] = d >> 8; \
+  if (d & 0x00ff0000) pb[0] = d >> 16; \
+  if (d & 0xff000000) pb[1] = d >> 24; \
+
+static void REGPARM(3) sh2_write32_dram0(u32 a, u32 d, SH2 *sh2)
+{
+  sh2_write32_dramN(0);
+}
+
+static void REGPARM(3) sh2_write32_dram1(u32 a, u32 d, SH2 *sh2)
+{
+  sh2_write32_dramN(1);
+}
+
+static void REGPARM(3) sh2_write32_sdram(u32 a, u32 d, SH2 *sh2)
+{
+  u32 a1 = a & 0x3ffff;
+  *(u32 *)(sh2->p_sdram + a1) = (d << 16) | (d >> 16);
+#ifdef DRC_SH2
+  unsigned short *p = &Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
+  if (p[0])
+    sh2_drc_wcheck_ram(a, p[0], sh2->is_slave);
+  if (p[1])
+    sh2_drc_wcheck_ram(a, p[1], sh2->is_slave);
+#endif
+}
+
+static void REGPARM(3) sh2_write32_da(u32 a, u32 d, SH2 *sh2)
+{
+  u32 a1 = a & 0xfff;
+  *(u32 *)(sh2->data_array + a1) = (d << 16) | (d >> 16);
+#ifdef DRC_SH2
+  int id = sh2->is_slave;
+  unsigned short *p = &Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
+  if (p[0])
+    sh2_drc_wcheck_da(a, p[0], id);
+  if (p[1])
+    sh2_drc_wcheck_da(a, p[1], id);
+#endif
+}
+
+static void REGPARM(3) sh2_write32_rom(u32 a, u32 d, SH2 *sh2)
+{
+  sh2_write16_rom(a, d >> 16, sh2);
+  sh2_write16_rom(a + 2, d, sh2);
+}
 
 typedef u32 (sh2_read_handler)(u32 a, SH2 *sh2);
 typedef void REGPARM(3) (sh2_write_handler)(u32 a, u32 d, SH2 *sh2);
@@ -1534,30 +1626,21 @@ u32 REGPARM(2) p32x_sh2_read16(u32 a, SH2 *sh2)
   if (map_flag_set(p))
     return ((sh2_read_handler *)(p << 1))(a, sh2);
   else
-    return *(u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
+    return *(u16 *)((p << 1) + (a & sh2_map->mask));
 }
 
 u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2)
 {
-  const sh2_memmap *sh2_map = sh2->read16_map;
-  sh2_read_handler *handler;
-  u32 offs;
+  const sh2_memmap *sh2_map = sh2->read32_map;
   uptr p;
 
-  offs = SH2MAP_ADDR2OFFS_R(a);
-  sh2_map += offs;
+  sh2_map += SH2MAP_ADDR2OFFS_R(a);
   p = sh2_map->addr;
   if (!map_flag_set(p)) {
-    // XXX: maybe 32bit access instead with ror?
-    u16 *pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
-    return (pd[0] << 16) | pd[1];
-  }
-
-  if (offs == SH2MAP_ADDR2OFFS_R(0xffffc000))
-    return sh2_peripheral_read32(a, sh2);
-
-  handler = (sh2_read_handler *)(p << 1);
-  return (handler(a, sh2) << 16) | handler(a + 2, sh2);
+    u32 *pd = (u32 *)((p << 1) + (a & sh2_map->mask));
+    return (*pd << 16) | (*pd >> 16);
+  } else
+    return ((sh2_read_handler *)(p << 1))(a, sh2);
 }
 
 void REGPARM(3) p32x_sh2_write8(u32 a, u32 d, SH2 *sh2)
@@ -1580,20 +1663,11 @@ void REGPARM(3) p32x_sh2_write16(u32 a, u32 d, SH2 *sh2)
 
 void REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2)
 {
-  const void **sh2_wmap = sh2->write16_tab;
+  const void **sh2_wmap = sh2->write32_tab;
   sh2_write_handler *wh;
-  u32 offs;
-
-  offs = SH2MAP_ADDR2OFFS_W(a);
 
-  if (offs == SH2MAP_ADDR2OFFS_W(0xffffc000)) {
-    sh2_peripheral_write32(a, d, sh2);
-    return;
-  }
-
-  wh = sh2_wmap[offs];
-  wh(a, d >> 16, sh2);
-  wh(a + 2, d, sh2);
+  wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
+  wh(a, d, sh2);
 }
 
 // -----------------------------------------------------------------
@@ -1801,9 +1875,9 @@ static void get_bios(void)
 #define MAP_MEMORY(m) ((uptr)(m) >> 1)
 #define MAP_HANDLER(h) ( ((uptr)(h) >> 1) | ((uptr)1 << (sizeof(uptr) * 8 - 1)) )
 
-static sh2_memmap sh2_read8_map[0x80], sh2_read16_map[0x80];
+static sh2_memmap sh2_read8_map[0x80], sh2_read16_map[0x80],  sh2_read32_map[0x80];
 // for writes we are using handlers only
-static sh2_write_handler *sh2_write8_map[0x80], *sh2_write16_map[0x80];
+static sh2_write_handler *sh2_write8_map[0x80], *sh2_write16_map[0x80], *sh2_write32_map[0x80];
 
 void Pico32xSwapDRAM(int b)
 {
@@ -1818,10 +1892,12 @@ void Pico32xSwapDRAM(int b)
 
   // SH2
   sh2_read8_map[0x04/2].addr  = sh2_read8_map[0x24/2].addr  =
-  sh2_read16_map[0x04/2].addr = sh2_read16_map[0x24/2].addr = MAP_MEMORY(Pico32xMem->dram[b]);
+  sh2_read16_map[0x04/2].addr = sh2_read16_map[0x24/2].addr =
+  sh2_read32_map[0x04/2].addr = sh2_read32_map[0x24/2].addr = MAP_MEMORY(Pico32xMem->dram[b]);
 
   sh2_write8_map[0x04/2]  = sh2_write8_map[0x24/2]  = b ? sh2_write8_dram1 : sh2_write8_dram0;
   sh2_write16_map[0x04/2] = sh2_write16_map[0x24/2] = b ? sh2_write16_dram1 : sh2_write16_dram0;
+  sh2_write32_map[0x04/2] = sh2_write32_map[0x24/2] = b ? sh2_write32_dram1 : sh2_write32_dram0;
 }
 
 static void bank_switch_rom_sh2(void)
@@ -1829,11 +1905,13 @@ static void bank_switch_rom_sh2(void)
   if (!carthw_ssf2_active) {
     // easy
     sh2_read8_map[0x02/2].addr  = sh2_read8_map[0x22/2].addr  =
-    sh2_read16_map[0x02/2].addr = sh2_read16_map[0x22/2].addr = MAP_MEMORY(Pico.rom);
+    sh2_read16_map[0x02/2].addr = sh2_read16_map[0x22/2].addr =
+    sh2_read32_map[0x02/2].addr = sh2_read32_map[0x22/2].addr = MAP_MEMORY(Pico.rom);
   }
   else {
     sh2_read8_map[0x02/2].addr  = sh2_read8_map[0x22/2].addr  = MAP_HANDLER(sh2_read8_rom);
     sh2_read16_map[0x02/2].addr = sh2_read16_map[0x22/2].addr = MAP_HANDLER(sh2_read16_rom);
+    sh2_read32_map[0x02/2].addr = sh2_read32_map[0x22/2].addr = MAP_HANDLER(sh2_read32_rom);
   }
 }
 
@@ -1903,58 +1981,75 @@ void PicoMemSetup32x(void)
   for (i = 0; i < ARRAY_SIZE(sh2_read8_map); i++) {
     sh2_read8_map[i].addr   = MAP_HANDLER(sh2_read8_unmapped);
     sh2_read16_map[i].addr  = MAP_HANDLER(sh2_read16_unmapped);
+    sh2_read32_map[i].addr  = MAP_HANDLER(sh2_read32_unmapped);
   }
 
   for (i = 0; i < ARRAY_SIZE(sh2_write8_map); i++) {
     sh2_write8_map[i]       = sh2_write8_unmapped;
     sh2_write16_map[i]      = sh2_write16_unmapped;
+    sh2_write32_map[i]      = sh2_write32_unmapped;
   }
 
   // "purge area"
   for (i = 0x40; i <= 0x5f; i++) {
     sh2_write8_map[i >> 1]  =
-    sh2_write16_map[i >> 1] = sh2_write_ignore;
+    sh2_write16_map[i >> 1] =
+    sh2_write32_map[i >> 1] = sh2_write_ignore;
   }
 
   // CS0
   sh2_read8_map[0x00/2].addr  = sh2_read8_map[0x20/2].addr  = MAP_HANDLER(sh2_read8_cs0);
   sh2_read16_map[0x00/2].addr = sh2_read16_map[0x20/2].addr = MAP_HANDLER(sh2_read16_cs0);
+  sh2_read32_map[0x00/2].addr = sh2_read32_map[0x20/2].addr = MAP_HANDLER(sh2_read32_cs0);
   sh2_write8_map[0x00/2]  = sh2_write8_map[0x20/2]  = sh2_write8_cs0;
   sh2_write16_map[0x00/2] = sh2_write16_map[0x20/2] = sh2_write16_cs0;
+  sh2_write32_map[0x00/2] = sh2_write32_map[0x20/2] = sh2_write32_cs0;
   // CS1 - ROM
   bank_switch_rom_sh2();
-  sh2_read8_map[0x02/2].mask  = sh2_read8_map[0x22/2].mask  =
-  sh2_read16_map[0x02/2].mask = sh2_read16_map[0x22/2].mask = 0x3fffff; // FIXME
+  sh2_read8_map[0x02/2].mask  = sh2_read8_map[0x22/2].mask  = 0x3fffff; // FIXME
+  sh2_read16_map[0x02/2].mask = sh2_read16_map[0x22/2].mask = 0x3ffffe; // FIXME
+  sh2_read32_map[0x02/2].mask = sh2_read32_map[0x22/2].mask = 0x3ffffc; // FIXME
   sh2_write16_map[0x02/2] = sh2_write16_map[0x22/2] = sh2_write16_rom;
+  sh2_write32_map[0x02/2] = sh2_write32_map[0x22/2] = sh2_write32_rom;
   // CS2 - DRAM - done by Pico32xSwapDRAM()
-  sh2_read8_map[0x04/2].mask  = sh2_read8_map[0x24/2].mask  =
-  sh2_read16_map[0x04/2].mask = sh2_read16_map[0x24/2].mask = 0x01ffff;
+  sh2_read8_map[0x04/2].mask  = sh2_read8_map[0x24/2].mask  = 0x01ffff;
+  sh2_read16_map[0x04/2].mask = sh2_read16_map[0x24/2].mask = 0x01fffe;
+  sh2_read32_map[0x04/2].mask = sh2_read32_map[0x24/2].mask = 0x01fffc;
   // CS3 - SDRAM
   sh2_read8_map[0x06/2].addr   = sh2_read8_map[0x26/2].addr   =
-  sh2_read16_map[0x06/2].addr  = sh2_read16_map[0x26/2].addr  = MAP_MEMORY(Pico32xMem->sdram);
+  sh2_read16_map[0x06/2].addr  = sh2_read16_map[0x26/2].addr  =
+  sh2_read32_map[0x06/2].addr  = sh2_read32_map[0x26/2].addr  = MAP_MEMORY(Pico32xMem->sdram);
   sh2_write8_map[0x06/2]       = sh2_write8_sdram;
   sh2_write8_map[0x26/2]       = sh2_write8_sdram_wt;
   sh2_write16_map[0x06/2]      = sh2_write16_map[0x26/2]      = sh2_write16_sdram;
-  sh2_read8_map[0x06/2].mask   = sh2_read8_map[0x26/2].mask   =
-  sh2_read16_map[0x06/2].mask  = sh2_read16_map[0x26/2].mask  = 0x03ffff;
+  sh2_write32_map[0x06/2]      = sh2_write32_map[0x26/2]      = sh2_write32_sdram;
+  sh2_read8_map[0x06/2].mask   = sh2_read8_map[0x26/2].mask   = 0x03ffff;
+  sh2_read16_map[0x06/2].mask  = sh2_read16_map[0x26/2].mask  = 0x03fffe;
+  sh2_read32_map[0x06/2].mask  = sh2_read32_map[0x26/2].mask  = 0x03fffc;
   // SH2 data array
   sh2_read8_map[0xc0/2].addr  = MAP_HANDLER(sh2_read8_da);
   sh2_read16_map[0xc0/2].addr = MAP_HANDLER(sh2_read16_da);
+  sh2_read32_map[0xc0/2].addr = MAP_HANDLER(sh2_read32_da);
   sh2_write8_map[0xc0/2]      = sh2_write8_da;
   sh2_write16_map[0xc0/2]     = sh2_write16_da;
+  sh2_write32_map[0xc0/2]     = sh2_write32_da;
   // SH2 IO
   sh2_read8_map[0xff/2].addr  = MAP_HANDLER(sh2_peripheral_read8);
   sh2_read16_map[0xff/2].addr = MAP_HANDLER(sh2_peripheral_read16);
+  sh2_read32_map[0xff/2].addr = MAP_HANDLER(sh2_peripheral_read32);
   sh2_write8_map[0xff/2]      = sh2_peripheral_write8;
   sh2_write16_map[0xff/2]     = sh2_peripheral_write16;
+  sh2_write32_map[0xff/2]     = sh2_peripheral_write32;
 
   // map DRAM area, both 68k and SH2
   Pico32xSwapDRAM(1);
 
   msh2.read8_map   = ssh2.read8_map   = sh2_read8_map;
   msh2.read16_map  = ssh2.read16_map  = sh2_read16_map;
+  msh2.read32_map  = ssh2.read32_map  = sh2_read32_map;
   msh2.write8_tab  = ssh2.write8_tab  = (const void **)(void *)sh2_write8_map;
   msh2.write16_tab = ssh2.write16_tab = (const void **)(void *)sh2_write16_map;
+  msh2.write32_tab = ssh2.write32_tab = (const void **)(void *)sh2_write32_map;
 
   sh2_drc_mem_setup(&msh2);
   sh2_drc_mem_setup(&ssh2);
index b530011..0f75d9b 100644 (file)
@@ -244,7 +244,7 @@ u32 sh2_peripheral_read16(u32 a, SH2 *sh2)
   u16 *r = (void *)sh2->peri_regs;
   u32 d;
 
-  a &= 0x1ff;
+  a &= 0x1fe;
   d = r[(a / 2) ^ 1];
 
   elprintf_sh2(sh2, EL_32XP, "peri r16 [%08x]     %04x @%06x",
@@ -343,7 +343,7 @@ void REGPARM(3) sh2_peripheral_write16(u32 a, u32 d, SH2 *sh2)
   elprintf_sh2(sh2, EL_32XP, "peri w16 [%08x]     %04x @%06x",
     a, d, sh2_pc(sh2));
 
-  a &= 0x1ff;
+  a &= 0x1fe;
 
   // evil WDT
   if (a == 0x80) {