32x: interpreter-wrap drc works (demos only). SVP drc refactoring.
authornotaz <notasas@gmail.com>
Tue, 13 Oct 2009 10:07:27 +0000 (10:07 +0000)
committernotaz <notasas@gmail.com>
Tue, 13 Oct 2009 10:07:27 +0000 (10:07 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@812 be3aeb3a-fb24-0410-a615-afba39da0efa

19 files changed:
cpu/drc/cmn.c
cpu/drc/cmn.h
cpu/drc/emit_x86.c [new file with mode: 0644]
cpu/sh2/compiler.c
cpu/sh2/compiler.h [new file with mode: 0644]
cpu/sh2/mame/sh2dasm.c [new file with mode: 0644]
cpu/sh2/mame/sh2dasm.h [new file with mode: 0644]
cpu/sh2/mame/sh2pico.c
cpu/sh2/sh2.c
cpu/sh2/sh2.h
cpu/sh2/stub_x86.asm [new file with mode: 0644]
pico/32x/32x.c
pico/carthw/svp/compiler.c
pico/carthw/svp/compiler.h
pico/carthw/svp/svp.c
pico/pico_int.h
platform/linux/Makefile
platform/linux/host_dasm.c [new file with mode: 0644]
platform/linux/host_dasm.h [new file with mode: 0644]

index 1f15a0f..6600325 100644 (file)
@@ -5,12 +5,7 @@
 
 #include "cmn.h"
 
-#ifndef ARM
-unsigned int tcache[SSP_TCACHE_SIZE/4];
-unsigned int *ssp_block_table[0x5090/2];
-unsigned int *ssp_block_table_iram[15][0x800/2];
-char ssp_align[SSP_BLOCKTAB_ALIGN_SIZE];
-#endif
+u32 tcache[DRC_TCACHE_SIZE/4];
 
 
 void drc_cmn_init(void)
@@ -18,7 +13,7 @@ void drc_cmn_init(void)
 #if defined(__linux__) && defined(ARM)
        void *tmp;
 
-       tmp = mmap(tcache, SSP_DRC_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
+       tmp = mmap(tcache, DRC_TCACHE_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
        printf("mmap tcache: %p, asked %p\n", tmp, tcache);
 #endif
 
@@ -29,7 +24,7 @@ void drc_cmn_cleanup(void)
 {
 #if defined(__linux__) && defined(ARM)
        int ret;
-       ret = munmap(tcache, SSP_DRC_SIZE);
+       ret = munmap(tcache, DRC_TCACHE_SIZE);
        printf("munmap tcache: %i\n", ret);
 #endif
 }
index 447c2fc..a4bce32 100644 (file)
@@ -1,12 +1,10 @@
-#define SSP_TCACHE_SIZE         (512*1024)
-#define SSP_BLOCKTAB_SIZE       (0x5090/2*4)
-#define SSP_BLOCKTAB_IRAM_SIZE  (15*0x800/2*4)
-#define SSP_BLOCKTAB_ALIGN_SIZE 3808
-#define SSP_DRC_SIZE (SSP_TCACHE_SIZE + SSP_BLOCKTAB_SIZE + SSP_BLOCKTAB_IRAM_SIZE + SSP_BLOCKTAB_ALIGN_SIZE)
-
-extern unsigned int tcache[SSP_TCACHE_SIZE/4];
-extern unsigned int *ssp_block_table[SSP_BLOCKTAB_SIZE/4];
-extern unsigned int *ssp_block_table_iram[15][0x800/2];
+typedef unsigned char  u8;
+typedef unsigned short u16;
+typedef unsigned int   u32;
+
+#define DRC_TCACHE_SIZE         (512*1024)
+
+extern u32 tcache[DRC_TCACHE_SIZE/4];
 
 void drc_cmn_init(void);
 void drc_cmn_cleanup(void);
diff --git a/cpu/drc/emit_x86.c b/cpu/drc/emit_x86.c
new file mode 100644 (file)
index 0000000..43eba94
--- /dev/null
@@ -0,0 +1,120 @@
+#include <stdarg.h>
+
+// TODO: move
+static int reg_map_g2h[] = {
+       -1, -1, -1, -1,
+       -1, -1, -1, -1,
+       -1, -1, -1, -1,
+       -1, -1, -1, -1,
+       -1, -1, -1, -1,
+       -1, -1, -1, -1,
+};
+
+enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI };
+
+#define EMIT_PTR(ptr, val, type) \
+       *(type *)(ptr) = val
+
+#define EMIT(val, type) { \
+       EMIT_PTR(tcache_ptr, val, type); \
+       tcache_ptr = (char *)tcache_ptr + sizeof(type); \
+}
+
+#define EMIT_MODRM(mod,r,rm) \
+       EMIT(((mod)<<6) | ((r)<<3) | (rm), u8)
+
+#define EMIT_OP_MODRM(op,mod,r,rm) { \
+       EMIT(op, u8); \
+       EMIT_MODRM(mod, r, rm); \
+}
+
+#define emith_move_r_r(dst, src) \
+       EMIT_OP_MODRM(0x8b, 3, dst, src)
+
+#define emith_move_r_imm(r, imm) { \
+       EMIT(0xb8 + (r), u8); \
+       EMIT(imm, u32); \
+}
+
+#define emith_add_r_imm(r, imm) { \
+       EMIT_OP_MODRM(0x81, 3, 0, r); \
+       EMIT(imm, u32); \
+}
+
+#define emith_sub_r_imm(r, imm) { \
+       EMIT_OP_MODRM(0x81, 3, 5, r); \
+       EMIT(imm, u32); \
+}
+
+// XXX: offs is 8bit only
+#define emith_ctx_read(r, offs) { \
+       EMIT_OP_MODRM(0x8b, 1, r, 5); \
+       EMIT(offs, u8);         /* mov tmp, [ebp+#offs] */ \
+}
+
+#define emith_ctx_write(r, offs) { \
+       EMIT_OP_MODRM(0x89, 1, r, 5); \
+       EMIT(offs, u8);         /* mov [ebp+#offs], tmp */ \
+}
+
+#define emith_ctx_sub(val, offs) { \
+       EMIT_OP_MODRM(0x81, 1, 5, 5); \
+       EMIT(offs, u8); \
+       EMIT(val, u32);         /* sub [ebp+#offs], dword val */ \
+}
+
+#define emith_test_t() { \
+       if (reg_map_g2h[SHR_SR] == -1) { \
+               EMIT(0xf6, u8); \
+               EMIT_MODRM(1, 0, 5); \
+               EMIT(SHR_SR * 4, u8); \
+               EMIT(0x01, u8); /* test [ebp+SHR_SR], byte 1 */ \
+       } else { \
+               EMIT(0xf7, u8); \
+               EMIT_MODRM(3, 0, reg_map_g2h[SHR_SR]); \
+               EMIT(0x01, u16); /* test <reg>, word 1 */ \
+       } \
+}
+
+#define emith_jump(ptr) { \
+       u32 disp = (u32)ptr - ((u32)tcache_ptr + 5); \
+       EMIT(0xe9, u8); \
+       EMIT(disp, u32); \
+}
+
+#define emith_call(ptr) { \
+       u32 disp = (u32)ptr - ((u32)tcache_ptr + 5); \
+       EMIT(0xe8, u8); \
+       EMIT(disp, u32); \
+}
+
+#define EMIT_CONDITIONAL(code, is_nonzero) { \
+       char *ptr = tcache_ptr; \
+       tcache_ptr = (char *)tcache_ptr + 2; \
+       code; \
+       EMIT_PTR(ptr, ((is_nonzero) ? 0x75 : 0x74), u8); \
+       EMIT_PTR(ptr + 1, ((char *)tcache_ptr - (ptr + 2)), u8); \
+}
+
+static void emith_pass_arg(int count, ...)
+{
+       va_list vl;
+       int i;
+
+       va_start(vl, count);
+
+       for (i = 0; i < count; i++) {
+               long av = va_arg(vl, long);
+               int r = 7;
+
+               switch (i) {
+               case 0: r = xAX; break;
+               case 1: r = xDX; break;
+               case 2: r = xCX; break;
+               }
+               emith_move_r_imm(r, av);
+       }
+
+       va_end(vl);
+}
+
index 0d2e47e..b9df9b5 100644 (file)
-#include "../sh2.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
 
-void sh2_execute(SH2 *sh2, int cycles)
+#include "sh2.h"
+#include "compiler.h"
+#include "../drc/cmn.h"
+
+#define BLOCK_CYCLE_LIMIT 100
+
+typedef enum {
+  SHR_R0 = 0, SHR_R15 = 15,
+  SHR_PC,  SHR_PPC, SHR_PR,   SHR_SR,
+  SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL,
+} sh2_reg_e;
+
+typedef struct block_desc_ {
+  u32 addr;                    // SH2 PC address
+  void *tcache_ptr;            // translated block for above PC
+  struct block_desc_ *next;    // next block with the same PC hash
+} block_desc;
+
+#define MAX_BLOCK_COUNT 1024
+static block_desc *block_table;
+static int block_count;
+
+#define MAX_HASH_ENTRIES 1024
+#define HASH_MASK (MAX_HASH_ENTRIES - 1)
+
+#ifdef DRC_DEBUG
+#include "mame/sh2dasm.h"
+#include <platform/linux/host_dasm.h>
+static void *tcache_dsm_ptr = tcache;
+#endif
+
+static void *tcache_ptr;
+
+#include "../drc/emit_x86.c"
+
+extern void sh2_drc_entry(SH2 *sh2, void *block);
+extern void sh2_drc_exit(void);
+
+// tmp
+extern void __attribute__((regparm(2))) sh2_do_op(SH2 *sh2, int opcode);
+
+static void *dr_find_block(block_desc *tab, u32 addr)
+{
+  for (tab = tab->next; tab != NULL; tab = tab->next)
+    if (tab->addr == addr)
+      break;
+
+  if (tab != NULL)
+    return tab->tcache_ptr;
+
+  printf("block miss for %08x\n", addr);
+  return NULL;
+}
+
+static block_desc *dr_add_block(u32 addr, void *tcache_ptr)
+{
+  block_desc *bd;
+
+  if (block_count == MAX_BLOCK_COUNT) {
+    // FIXME: flush cache instead
+    printf("block descriptor overflow\n");
+    exit(1);
+  }
+
+  bd = &block_table[block_count];
+  bd->addr = addr;
+  bd->tcache_ptr = tcache_ptr;
+  block_count++;
+
+  return bd;
+}
+
+#define HASH_FUNC(hash_tab, addr) \
+  ((block_desc **)(hash_tab))[(addr) & HASH_MASK]
+
+// ---------------------------------------------------------------
+
+static void emit_move_r_imm32(sh2_reg_e dst, u32 imm)
 {
+  int host_dst = reg_map_g2h[dst];
+  int tmp = 0;
+
+  if (host_dst != -1)
+    tmp = host_dst;
+  emith_move_r_imm(tmp, imm);
+  if (host_dst == -1)
+    emith_ctx_write(tmp, dst * 4);
+}
+
+static void emit_move_r_r(sh2_reg_e dst, sh2_reg_e src)
+{
+  int host_dst = reg_map_g2h[dst], host_src = reg_map_g2h[src];
+  int tmp = 0;
+
+  if (host_dst != -1 && host_src != -1) {
+    emith_move_r_r(host_dst, host_src);
+    return;
+  }
+
+  if (host_src != -1)
+    tmp = host_src;
+  if (host_dst != -1)
+    tmp = host_dst;
+
+  if (host_src == -1)
+    emith_ctx_read(tmp, src * 4);
+  if (host_dst == -1)
+    emith_ctx_write(tmp, dst * 4);
+}
+
+static void emit_braf(sh2_reg_e reg, u32 pc)
+{
+  int host_reg = reg_map_g2h[reg];
+  if (host_reg == -1) {
+    emith_ctx_read(0, reg * 4);
+  } else
+    emith_move_r_r(0, host_reg);
+  emith_add_r_imm(0, pc);
+
+  emith_ctx_write(0, SHR_PC * 4);
+}
+
+// FIXME: this is broken, delayed insn shouldn't affect branch
+#define DELAYED_OP \
+  if (delayed_op < 0) { \
+    delayed_op = op; \
+    goto next_op; \
+  } \
+  delayed_op = -1; \
+  pc -= 2 /* adjust back */
+
+/*
+static int sh2_translate_op4(int op)
+{
+  switch (op & 0x000f)
+  {
+  case 0x0b:
+  default:
+    emith_pass_arg(2, sh2, op);
+    emith_call(sh2_do_op);
+    break;
+  }
+
+  return 0;
+}
+*/
+
+static void *sh2_translate(SH2 *sh2, block_desc *other_block)
+{
+  void *block_entry = tcache_ptr;
+  block_desc *this_block;
   unsigned int pc = sh2->pc;
-  int op;
+  int op, delayed_op = -1;
+  int cycles = 0;
+  u32 tmp;
+
+  this_block = dr_add_block(pc, block_entry);
+  if (other_block != NULL) {
+    printf("hash collision between %08x and %08x\n", pc, other_block->addr);
+    this_block->next = other_block;
+  }
+  HASH_FUNC(sh2->pc_hashtab, pc) = this_block;
+
+#ifdef DRC_DEBUG
+  printf("== %csh2 block #%d %08x %p\n", sh2->is_slave ? 's' : 'm',
+    block_count, pc, block_entry);
+#endif
+
+  while (cycles < BLOCK_CYCLE_LIMIT)
+  {
+    if (delayed_op >= 0)
+      op = delayed_op;
+    else {
+next_op:
+      op = p32x_sh2_read16(pc, sh2->is_slave);
+
+#ifdef DRC_DEBUG
+      {
+        char buff[64];
+        DasmSH2(buff, pc, op);
+        printf("%08x %04x %s\n", pc, op, buff);
+      }
+#endif
+    }
+
+    pc += 2;
+    cycles++;
+
+    switch ((op >> 12) & 0x0f)
+    {
+    case 0x00:
+      // RTS        0000000000001011
+      if (op == 0x000b) {
+        DELAYED_OP;
+        emit_move_r_r(SHR_PC, SHR_PR);
+        cycles++;
+        goto end_block;
+      }
+      // RTE        0000000000101011
+      if (op == 0x002b) {
+        DELAYED_OP;
+        cycles++;
+        //emit_move_r_r(SHR_PC, SHR_PR);
+        emit_move_r_imm32(SHR_PC, pc - 4);
+        emith_pass_arg(2, sh2, op);
+        emith_call(sh2_do_op);
+        goto end_block;
+      }
+      // BRAF Rm    0000mmmm00100011
+      if (op == 0x0023) {
+        DELAYED_OP;
+        cycles++;
+        emit_braf((op >> 8) & 0x0f, pc);
+        goto end_block;
+      }
+      // BSRF Rm    0000mmmm00000011
+      if (op == 0x0003) {
+        DELAYED_OP;
+        emit_move_r_imm32(SHR_PR, pc);
+        emit_braf((op >> 8) & 0x0f, pc);
+        cycles++;
+        goto end_block;
+      }
+      goto default_;
+
+    case 0x04:
+      // JMP  @Rm   0100mmmm00101011
+      if ((op & 0xff) == 0x2b) {
+        DELAYED_OP;
+        emit_move_r_r(SHR_PC, (op >> 8) & 0x0f);
+        cycles++;
+        goto end_block;
+      }
+      // JSR  @Rm   0100mmmm00001011
+      if ((op & 0xff) == 0x0b) {
+        DELAYED_OP;
+        emit_move_r_imm32(SHR_PR, pc);
+        emit_move_r_r(SHR_PC, (op >> 8) & 0x0f);
+        cycles++;
+        goto end_block;
+      }
+      goto default_;
+
+    case 0x08: {
+      int adj = 2;
+      switch (op & 0x0f00) {
+      // BT/S label 10001101dddddddd
+      case 0x0d00:
+      // BF/S label 10001111dddddddd
+      case 0x0f00:
+        DELAYED_OP;
+        cycles--;
+        adj = 0;
+        // fallthrough
+      // BT   label 10001001dddddddd
+      case 0x0900:
+      // BF   label 10001011dddddddd
+      case 0x0b00:
+        cycles += 2;
+        emit_move_r_imm32(SHR_PC, pc);
+        emith_test_t();
+        tmp = ((signed int)(op << 24) >> 23);
+        EMIT_CONDITIONAL(emit_move_r_imm32(SHR_PC, pc + tmp + adj), (op & 0x0200) ? 1 : 0);
+        goto end_block;
+      }
+      goto default_;
+    }
+
+    case 0x0a:
+      // BRA  label 1010dddddddddddd
+      DELAYED_OP;
+    do_bra:
+      tmp = ((signed int)(op << 20) >> 19);
+      emit_move_r_imm32(SHR_PC, pc + tmp);
+      cycles++;
+      goto end_block;
+
+    case 0x0b:
+      // BSR  label 1011dddddddddddd
+      DELAYED_OP;
+      emit_move_r_imm32(SHR_PR, pc);
+      goto do_bra;
+
+    default:
+    default_:
+      emit_move_r_imm32(SHR_PC, pc - 2);
+      emith_pass_arg(2, sh2, op);
+      emith_call(sh2_do_op);
+      break;
+    }
+
+#ifdef DRC_DEBUG
+    host_dasm(tcache_dsm_ptr, (char *)tcache_ptr - (char *)tcache_dsm_ptr);
+    tcache_dsm_ptr = tcache_ptr;
+#endif
+  }
+
+end_block:
+  if ((char *)tcache_ptr - (char *)tcache > DRC_TCACHE_SIZE) {
+    printf("tcache overflow!\n");
+    fflush(stdout);
+    exit(1);
+  }
+
+  if (reg_map_g2h[SHR_SR] == -1) {
+    emith_ctx_sub(cycles << 12, SHR_SR * 4);
+  } else
+    emith_sub_r_imm(reg_map_g2h[SHR_SR], cycles << 12);
+  emith_jump(sh2_drc_exit);
+
+#ifdef DRC_DEBUG
+  host_dasm(tcache_dsm_ptr, (char *)tcache_ptr - (char *)tcache_dsm_ptr);
+  tcache_dsm_ptr = tcache_ptr;
+#endif
+  return block_entry;
+
+unimplemented:
+  // last op
+#ifdef DRC_DEBUG
+  host_dasm(tcache_dsm_ptr, (char *)tcache_ptr - (char *)tcache_dsm_ptr);
+  tcache_dsm_ptr = tcache_ptr;
+#endif
+  exit(1);
+}
+
+void __attribute__((noinline)) sh2_drc_dispatcher(SH2 *sh2)
+{
+  while (((signed int)sh2->sr >> 12) > 0)
+  {
+    block_desc *bd = HASH_FUNC(sh2->pc_hashtab, sh2->pc);
+    void *block = NULL;
+
+    if (bd != NULL) {
+      if (bd->addr == sh2->pc)
+        block = bd->tcache_ptr;
+      else
+        block = dr_find_block(bd, sh2->pc);
+    }
+
+    if (block == NULL)
+      block = sh2_translate(sh2, bd);
+
+#ifdef DRC_DEBUG
+    printf("= %csh2 enter %08x %p\n", sh2->is_slave ? 's' : 'm', sh2->pc, block);
+#endif
+    sh2_drc_entry(sh2, block);
+  }
+}
+
+void sh2_execute(SH2 *sh2, int cycles)
+{
+  sh2->cycles_aim += cycles;
+  cycles = sh2->cycles_aim - sh2->cycles_done;
+
+  // cycles are kept in SHR_SR unused bits (upper 20)
+  sh2->sr &= 0x3f3;
+  sh2->sr |= cycles << 12;
+  sh2_drc_dispatcher(sh2);
+
+  sh2->cycles_done += cycles - ((signed int)sh2->sr >> 12);
+}
+
+
+static int cmn_init_done;
+
+static int common_init(void)
+{
+  block_count = 0;
+  block_table = calloc(MAX_BLOCK_COUNT, sizeof(*block_table));
+  if (block_table == NULL)
+    return -1;
+
+  tcache_ptr = tcache;
+
+  cmn_init_done = 1;
+  return 0;
+}
+
+int sh2_drc_init(SH2 *sh2)
+{
+  if (!cmn_init_done) {
+    int ret = common_init();
+    if (ret)
+      return ret;
+  }
+
+  assert(sh2->pc_hashtab == NULL);
+  sh2->pc_hashtab = calloc(sizeof(sh2->pc_hashtab[0]), MAX_HASH_ENTRIES);
+  if (sh2->pc_hashtab == NULL)
+    return -1;
 
-  op = p32x_sh2_read16(pc);
+  return 0;
 }
 
diff --git a/cpu/sh2/compiler.h b/cpu/sh2/compiler.h
new file mode 100644 (file)
index 0000000..1d127a1
--- /dev/null
@@ -0,0 +1,2 @@
+
+int sh2_drc_init(SH2 *sh2);
diff --git a/cpu/sh2/mame/sh2dasm.c b/cpu/sh2/mame/sh2dasm.c
new file mode 100644 (file)
index 0000000..e3983eb
--- /dev/null
@@ -0,0 +1,654 @@
+#include <stdio.h>\r
+#include "sh2dasm.h"\r
+\r
+typedef int INT32;\r
+typedef unsigned int   UINT32;\r
+typedef unsigned short UINT16;\r
+typedef unsigned char  UINT8;\r
+\r
+#define DASMFLAG_STEP_OUT 0\r
+#define DASMFLAG_STEP_OVER 0\r
+#define DASMFLAG_STEP_OVER_EXTRA(x) 0\r
+\r
+#define SIGNX8(x)      (((INT32)(x) << 24) >> 24)\r
+#define SIGNX12(x)     (((INT32)(x) << 20) >> 20)\r
+\r
+#define Rn ((opcode >> 8) & 15)\r
+#define Rm ((opcode >> 4) & 15)\r
+\r
+static const char *const regname[16] = {\r
+       "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",\r
+       "R8", "R9", "R10","R11","R12","R13","R14","SP"\r
+};\r
+\r
+static UINT32 op0000(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       UINT32  flags = 0;\r
+       switch(opcode & 0x3f)\r
+       {\r
+       case 0x02:\r
+               sprintf(buffer,"STC     SR,%s", regname[Rn]);\r
+               break;\r
+       case 0x03:\r
+               sprintf(buffer,"BSRF    %s", regname[Rn]);\r
+               break;\r
+       case 0x08:\r
+               sprintf(buffer,"CLRT");\r
+               break;\r
+       case 0x09:\r
+               sprintf(buffer,"NOP");\r
+               break;\r
+       case 0x0A:\r
+               sprintf(buffer,"STS     MACH,%s", regname[Rn]);\r
+               break;\r
+       case 0x0B:\r
+               sprintf(buffer,"RTS");\r
+               flags = DASMFLAG_STEP_OUT;\r
+               break;\r
+       case 0x12:\r
+               sprintf(buffer,"STS     GBR,%s", regname[Rn]);\r
+               break;\r
+       case 0x18:\r
+               sprintf(buffer,"SETT");\r
+               break;\r
+       case 0x19:\r
+               sprintf(buffer,"DIV0U");\r
+               break;\r
+       case 0x1A:\r
+               sprintf(buffer,"STS     MACL,%s", regname[Rn]);\r
+               break;\r
+       case 0x1B:\r
+               sprintf(buffer,"SLEEP");\r
+               break;\r
+       case 0x22:\r
+               sprintf(buffer,"STC     VBR,%s", regname[Rn]);\r
+               break;\r
+       case 0x23:\r
+               sprintf(buffer,"BRAF    %s", regname[Rn]);\r
+               break;\r
+       case 0x28:\r
+               sprintf(buffer,"CLRMAC");\r
+               break;\r
+       case 0x29:\r
+               sprintf(buffer,"MOVT    %s", regname[Rn]);\r
+               break;\r
+       case 0x2A:\r
+               sprintf(buffer,"STS     PR,%s", regname[Rn]);\r
+               break;\r
+       case 0x2B:\r
+               sprintf(buffer,"RTE");\r
+               flags = DASMFLAG_STEP_OUT;\r
+               break;\r
+       default:\r
+               switch(opcode & 15)\r
+               {\r
+               case  0:\r
+                       sprintf(buffer, "??????  $%04X", opcode);\r
+                       break;\r
+               case  1:\r
+                       sprintf(buffer, "??????  $%04X", opcode);\r
+                       break;\r
+               case  2:\r
+                       sprintf(buffer, "??????  $%04X", opcode);\r
+                       break;\r
+               case  3:\r
+                       sprintf(buffer, "??????  $%04X", opcode);\r
+                       break;\r
+               case  4:\r
+                       sprintf(buffer, "MOV.B   %s,@(R0,%s)", regname[Rm], regname[Rn]);\r
+                       break;\r
+               case  5:\r
+                       sprintf(buffer, "MOV.W   %s,@(R0,%s)", regname[Rm], regname[Rn]);\r
+                       break;\r
+               case  6:\r
+                       sprintf(buffer, "MOV.L   %s,@(R0,%s)", regname[Rm], regname[Rn]);\r
+                       break;\r
+               case  7:\r
+                       sprintf(buffer, "MUL.L   %s,%s", regname[Rm], regname[Rn]);\r
+                       break;\r
+               case  8:\r
+                       sprintf(buffer, "??????  $%04X", opcode);\r
+                       break;\r
+               case  9:\r
+                       sprintf(buffer, "??????  $%04X", opcode);\r
+                       break;\r
+               case 10:\r
+                       sprintf(buffer, "??????  $%04X", opcode);\r
+                       break;\r
+               case 11:\r
+                       sprintf(buffer, "??????  $%04X", opcode);\r
+                       break;\r
+               case 12:\r
+                       sprintf(buffer, "MOV.B   @(R0,%s),%s", regname[Rm], regname[Rn]);\r
+                       break;\r
+               case 13:\r
+                       sprintf(buffer, "MOV.W   @(R0,%s),%s", regname[Rm], regname[Rn]);\r
+                       break;\r
+               case 14:\r
+                       sprintf(buffer, "MOV.L   @(R0,%s),%s", regname[Rm], regname[Rn]);\r
+                       break;\r
+               case 15:\r
+                       sprintf(buffer, "MAC.L   @%s+,@%s+", regname[Rn], regname[Rm]);\r
+                       break;\r
+               }\r
+       }\r
+       return flags;\r
+}\r
+\r
+static UINT32 op0001(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       sprintf(buffer, "MOV.L   %s,@($%02X,%s)", regname[Rm], (opcode & 15) * 4, regname[Rn]);\r
+       return 0;\r
+}\r
+\r
+static UINT32 op0010(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       switch (opcode & 15)\r
+       {\r
+       case  0:\r
+               sprintf(buffer, "MOV.B   %s,@%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  1:\r
+               sprintf(buffer, "MOV.W   %s,@%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  2:\r
+               sprintf(buffer, "MOV.L   %s,@%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  3:\r
+               sprintf(buffer, "??????  $%04X", opcode);\r
+               break;\r
+       case  4:\r
+               sprintf(buffer, "MOV.B   %s,@-%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  5:\r
+               sprintf(buffer, "MOV.W   %s,@-%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  6:\r
+               sprintf(buffer, "MOV.L   %s,@-%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  7:\r
+               sprintf(buffer, "DIV0S   %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  8:\r
+               sprintf(buffer, "TST     %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  9:\r
+               sprintf(buffer, "AND     %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 10:\r
+               sprintf(buffer, "XOR     %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 11:\r
+               sprintf(buffer, "OR      %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 12:\r
+               sprintf(buffer, "CMP/STR %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 13:\r
+               sprintf(buffer, "XTRCT   %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 14:\r
+               sprintf(buffer, "MULU.W  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 15:\r
+               sprintf(buffer, "MULS.W  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static UINT32 op0011(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       switch (opcode & 15)\r
+       {\r
+       case  0:\r
+               sprintf(buffer, "CMP/EQ  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  1:\r
+               sprintf(buffer, "??????  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  2:\r
+               sprintf(buffer, "CMP/HS  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  3:\r
+               sprintf(buffer, "CMP/GE  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  4:\r
+               sprintf(buffer, "DIV1    %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  5:\r
+               sprintf(buffer, "DMULU.L %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  6:\r
+               sprintf(buffer, "CMP/HI  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  7:\r
+               sprintf(buffer, "CMP/GT  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  8:\r
+               sprintf(buffer, "SUB     %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case  9:\r
+               sprintf(buffer, "??????  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 10:\r
+               sprintf(buffer, "SUBC    %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 11:\r
+               sprintf(buffer, "SUBV    %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 12:\r
+               sprintf(buffer, "ADD     %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 13:\r
+               sprintf(buffer, "DMULS.L %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 14:\r
+               sprintf(buffer, "ADDC    %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 15:\r
+               sprintf(buffer, "ADDV    %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static UINT32 op0100(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       UINT32 flags = 0;\r
+       switch(opcode & 0x3F)\r
+       {\r
+       case 0x00:\r
+               sprintf(buffer, "SHLL    %s", regname[Rn]);\r
+               break;\r
+       case 0x01:\r
+               sprintf(buffer, "SHLR    %s", regname[Rn]);\r
+               break;\r
+       case 0x02:\r
+               sprintf(buffer, "STS.L   MACH,@-%s", regname[Rn]);\r
+               break;\r
+       case 0x03:\r
+               sprintf(buffer, "STC.L   SR,@-%s", regname[Rn]);\r
+               break;\r
+       case 0x04:\r
+               sprintf(buffer, "ROTL    %s", regname[Rn]);\r
+               break;\r
+       case 0x05:\r
+               sprintf(buffer, "ROTR    %s", regname[Rn]);\r
+               break;\r
+       case 0x06:\r
+               sprintf(buffer, "LDS.L   @%s+,MACH", regname[Rn]);\r
+               break;\r
+       case 0x07:\r
+               sprintf(buffer, "LDC.L   @%s+,SR", regname[Rn]);\r
+               break;\r
+       case 0x08:\r
+               sprintf(buffer, "SHLL2   %s", regname[Rn]);\r
+               break;\r
+       case 0x09:\r
+               sprintf(buffer, "SHLR2   %s", regname[Rn]);\r
+               break;\r
+       case 0x0a:\r
+               sprintf(buffer, "LDS     %s,MACH", regname[Rn]);\r
+               break;\r
+       case 0x0b:\r
+               sprintf(buffer, "JSR     %s", regname[Rn]);\r
+               flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);\r
+               break;\r
+       case 0x0e:\r
+               sprintf(buffer, "LDC     %s,SR", regname[Rn]);\r
+               break;\r
+       case 0x10:\r
+               sprintf(buffer, "DT      %s", regname[Rn]);\r
+               break;\r
+       case 0x11:\r
+               sprintf(buffer, "CMP/PZ  %s", regname[Rn]);\r
+               break;\r
+       case 0x12:\r
+               sprintf(buffer, "STS.L   MACL,@-%s", regname[Rn]);\r
+               break;\r
+       case 0x13:\r
+               sprintf(buffer, "STC.L   GBR,@-%s", regname[Rn]);\r
+               break;\r
+       case 0x15:\r
+               sprintf(buffer, "CMP/PL  %s", regname[Rn]);\r
+               break;\r
+       case 0x16:\r
+               sprintf(buffer, "LDS.L   @%s+,MACL", regname[Rn]);\r
+               break;\r
+       case 0x17:\r
+               sprintf(buffer, "LDC.L   @%s+,GBR", regname[Rn]);\r
+               break;\r
+       case 0x18:\r
+               sprintf(buffer, "SHLL8   %s", regname[Rn]);\r
+               break;\r
+       case 0x19:\r
+               sprintf(buffer, "SHLR8   %s", regname[Rn]);\r
+               break;\r
+       case 0x1a:\r
+               sprintf(buffer, "LDS     %s,MACL", regname[Rn]);\r
+               break;\r
+       case 0x1b:\r
+               sprintf(buffer, "TAS     %s", regname[Rn]);\r
+               break;\r
+       case 0x1e:\r
+               sprintf(buffer, "LDC     %s,GBR", regname[Rn]);\r
+               break;\r
+       case 0x20:\r
+               sprintf(buffer, "SHAL    %s", regname[Rn]);\r
+               break;\r
+       case 0x21:\r
+               sprintf(buffer, "SHAR    %s", regname[Rn]);\r
+               break;\r
+       case 0x22:\r
+               sprintf(buffer, "STS.L   PR,@-%s", regname[Rn]);\r
+               break;\r
+       case 0x23:\r
+               sprintf(buffer, "STC.L   VBR,@-%s", regname[Rn]);\r
+               break;\r
+       case 0x24:\r
+               sprintf(buffer, "ROTCL   %s", regname[Rn]);\r
+               break;\r
+       case 0x25:\r
+               sprintf(buffer, "ROTCR   %s", regname[Rn]);\r
+               break;\r
+       case 0x26:\r
+               sprintf(buffer, "LDS.L   @%s+,PR", regname[Rn]);\r
+               break;\r
+       case 0x27:\r
+               sprintf(buffer, "LDC.L   @%s+,VBR", regname[Rn]);\r
+               break;\r
+       case 0x28:\r
+               sprintf(buffer, "SHLL16  %s", regname[Rn]);\r
+               break;\r
+       case 0x29:\r
+               sprintf(buffer, "SHLR16  %s", regname[Rn]);\r
+               break;\r
+       case 0x2a:\r
+               sprintf(buffer, "LDS     %s,PR", regname[Rn]);\r
+               break;\r
+       case 0x2b:\r
+               sprintf(buffer, "JMP     %s", regname[Rn]);\r
+               break;\r
+       case 0x2e:\r
+               sprintf(buffer, "LDC     %s,VBR", regname[Rn]);\r
+               break;\r
+       default:\r
+               if ((opcode & 15) == 15)\r
+                       sprintf(buffer, "MAC.W   @%s+,@%s+", regname[Rm], regname[Rn]);\r
+               else\r
+                       sprintf(buffer, "??????  $%04X", opcode);\r
+       }\r
+       return flags;\r
+}\r
+\r
+static UINT32 op0101(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       sprintf(buffer, "MOV.L   @($%02X,%s),%s", (opcode & 15) * 4, regname[Rm], regname[Rn]);\r
+       return 0;\r
+}\r
+\r
+static UINT32 op0110(char *buffer, UINT32 pc, UINT16 opcode)\r
+\r
+{\r
+       switch(opcode & 0xF)\r
+       {\r
+       case 0x00:\r
+               sprintf(buffer, "MOV.B   @%s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x01:\r
+               sprintf(buffer, "MOV.W   @%s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x02:\r
+               sprintf(buffer, "MOV.L   @%s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x03:\r
+               sprintf(buffer, "MOV     %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x04:\r
+               sprintf(buffer, "MOV.B   @%s+,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x05:\r
+               sprintf(buffer, "MOV.W   @%s+,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x06:\r
+               sprintf(buffer, "MOV.L   @%s+,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x07:\r
+               sprintf(buffer, "NOT     %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x08:\r
+               sprintf(buffer, "SWAP.B  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x09:\r
+               sprintf(buffer, "SWAP.W  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x0a:\r
+               sprintf(buffer, "NEGC    %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x0b:\r
+               sprintf(buffer, "NEG     %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x0c:\r
+               sprintf(buffer, "EXTU.B  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x0d:\r
+               sprintf(buffer, "EXTU.W  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x0e:\r
+               sprintf(buffer, "EXTS.B  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       case 0x0f:\r
+               sprintf(buffer, "EXTS.W  %s,%s", regname[Rm], regname[Rn]);\r
+               break;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static UINT32 op0111(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       sprintf(buffer, "ADD     #$%02X,%s", opcode & 0xff, regname[Rn]);\r
+       return 0;\r
+}\r
+\r
+static UINT32 op1000(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       switch((opcode >> 8) & 15)\r
+       {\r
+       case  0:\r
+               sprintf(buffer, "MOV.B   R0,@($%02X,%s)", (opcode & 15), regname[Rm]);\r
+               break;\r
+       case  1:\r
+               sprintf(buffer, "MOV.W   R0,@($%02X,%s)", (opcode & 15) * 2, regname[Rm]);\r
+               break;\r
+       case  4:\r
+               sprintf(buffer, "MOV.B   @($%02X,%s),R0", (opcode & 15), regname[Rm]);\r
+               break;\r
+       case  5:\r
+               sprintf(buffer, "MOV.W   @($%02X,%s),R0", (opcode & 15), regname[Rm]);\r
+               break;\r
+       case  8:\r
+               sprintf(buffer, "CMP/EQ  #$%02X,R0", (opcode & 0xff));\r
+               break;\r
+       case  9:\r
+               sprintf(buffer, "BT      $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);\r
+               break;\r
+       case 11:\r
+               sprintf(buffer, "BF      $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);\r
+               break;\r
+       case 13:\r
+               sprintf(buffer, "BTS     $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);\r
+               break;\r
+       case 15:\r
+               sprintf(buffer, "BFS     $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);\r
+               break;\r
+       default :\r
+               sprintf(buffer, "invalid $%04X", opcode);\r
+       }\r
+       return 0;\r
+}\r
+\r
+static UINT32 op1001(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       sprintf(buffer, "MOV.W   @($%04X,PC),%s", (opcode & 0xff) * 2, regname[Rn]);\r
+       return 0;\r
+}\r
+\r
+static UINT32 op1010(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       sprintf(buffer, "BRA     $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2);\r
+       return 0;\r
+}\r
+\r
+static UINT32 op1011(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       sprintf(buffer, "BSR     $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2);\r
+       return DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);\r
+}\r
+\r
+static UINT32 op1100(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       UINT32 flags = 0;\r
+       switch((opcode >> 8) & 15)\r
+       {\r
+       case  0:\r
+               sprintf(buffer, "MOV.B   R0,@($%02X,GBR)", opcode & 0xff);\r
+               break;\r
+       case  1:\r
+               sprintf(buffer, "MOV.W   R0,@($%04X,GBR)", (opcode & 0xff) * 2);\r
+               break;\r
+       case  2:\r
+               sprintf(buffer, "MOV.L   R0,@($%04X,GBR)", (opcode & 0xff) * 4);\r
+               break;\r
+       case  3:\r
+               sprintf(buffer, "TRAPA   #$%02X", opcode & 0xff);\r
+               flags = DASMFLAG_STEP_OVER;\r
+               break;\r
+       case  4:\r
+               sprintf(buffer, "MOV.B   @($%02X,GBR),R0", opcode & 0xff);\r
+               break;\r
+       case  5:\r
+               sprintf(buffer, "MOV.W   @($%04X,GBR),R0", (opcode & 0xff) * 2);\r
+               break;\r
+       case  6:\r
+               sprintf(buffer, "MOV.L   @($%04X,GBR),R0", (opcode & 0xff) * 4);\r
+               break;\r
+       case  7:\r
+               sprintf(buffer, "MOVA    @($%04X,PC),R0", (opcode & 0xff) * 4);\r
+               break;\r
+       case  8:\r
+               sprintf(buffer, "TST     #$%02X,R0", opcode & 0xff);\r
+               break;\r
+       case  9:\r
+               sprintf(buffer, "AND     #$%02X,R0", opcode & 0xff);\r
+               break;\r
+       case 10:\r
+               sprintf(buffer, "XOR     #$%02X,R0", opcode & 0xff);\r
+               break;\r
+       case 11:\r
+               sprintf(buffer, "OR      #$%02X,R0", opcode & 0xff);\r
+               break;\r
+       case 12:\r
+               sprintf(buffer, "TST.B   #$%02X,@(R0,GBR)", opcode & 0xff);\r
+               break;\r
+       case 13:\r
+               sprintf(buffer, "AND.B   #$%02X,@(R0,GBR)", opcode & 0xff);\r
+               break;\r
+       case 14:\r
+               sprintf(buffer, "XOR.B   #$%02X,@(R0,GBR)", opcode & 0xff);\r
+               break;\r
+       case 15:\r
+               sprintf(buffer, "OR.B    #$%02X,@(R0,GBR)", opcode & 0xff);\r
+               break;\r
+       }\r
+       return flags;\r
+}\r
+\r
+static UINT32 op1101(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       sprintf(buffer, "MOV.L   @($%02X,PC),%s  ; #$%06x", (opcode * 4) & 0x3ff, regname[Rn],\r
+               (pc + ((opcode * 4) & 0x3ff) + 2) & ~3);\r
+       return 0;\r
+}\r
+\r
+static UINT32 op1110(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       sprintf(buffer, "MOV     #$%02X,%s", (opcode & 0xff), regname[Rn]);\r
+       return 0;\r
+}\r
+\r
+static UINT32 op1111(char *buffer, UINT32 pc, UINT16 opcode)\r
+{\r
+       sprintf(buffer, "unknown $%04X", opcode);\r
+       return 0;\r
+}\r
+\r
+unsigned DasmSH2(char *buffer, unsigned pc, UINT16 opcode)\r
+{\r
+       UINT32 flags;\r
+\r
+       pc += 2;\r
+\r
+       switch((opcode >> 12) & 15)\r
+       {\r
+       case  0: flags = op0000(buffer,pc,opcode);        break;\r
+       case  1: flags = op0001(buffer,pc,opcode);        break;\r
+       case  2: flags = op0010(buffer,pc,opcode);        break;\r
+       case  3: flags = op0011(buffer,pc,opcode);        break;\r
+       case  4: flags = op0100(buffer,pc,opcode);        break;\r
+       case  5: flags = op0101(buffer,pc,opcode);        break;\r
+       case  6: flags = op0110(buffer,pc,opcode);        break;\r
+       case  7: flags = op0111(buffer,pc,opcode);        break;\r
+       case  8: flags = op1000(buffer,pc,opcode);        break;\r
+       case  9: flags = op1001(buffer,pc,opcode);        break;\r
+       case 10: flags = op1010(buffer,pc,opcode);        break;\r
+       case 11: flags = op1011(buffer,pc,opcode);        break;\r
+       case 12: flags = op1100(buffer,pc,opcode);        break;\r
+       case 13: flags = op1101(buffer,pc,opcode);        break;\r
+       case 14: flags = op1110(buffer,pc,opcode);        break;\r
+       default: flags = op1111(buffer,pc,opcode);        break;\r
+       }\r
+       return 0;//2 | flags | DASMFLAG_SUPPORTED;\r
+}\r
+\r
+#if 0\r
+\r
+#define swab32(x) (((x) << 24) | (((x) << 8) & 0xff0000) | (((x) >> 8) & 0xff00) | ((x) >> 24))\r
+#define swab16(x) ((((x) << 8) & 0xff00) | (((x) >> 8) & 0x00ff))\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+       unsigned short op;\r
+       char buff[256];\r
+       unsigned pc;\r
+       FILE *f;\r
+       int ret;\r
+\r
+       if (argv[1] == NULL) {\r
+               printf("usage\n%s <file>\n", argv[0]);\r
+               return 1;\r
+       }\r
+\r
+       f = fopen(argv[1], "rb");\r
+       if (f == NULL) {\r
+               fprintf(stderr, "can't open %s\n", argv[1]);\r
+               return 1;\r
+       }\r
+\r
+       for (pc = 0x140;; pc += 2)\r
+       {\r
+               fseek(f, pc, SEEK_SET);\r
+\r
+               ret = fread(&op, 1, sizeof(op), f);\r
+               if (ret != sizeof(op))\r
+                       break;\r
+\r
+               DasmSH2(buff, pc, swab16(op));\r
+               printf("%06x %04x %s\n", pc, swab16(op), buff);\r
+       }\r
+\r
+       fclose(f);\r
+       return 0;\r
+}\r
+\r
+#endif\r
diff --git a/cpu/sh2/mame/sh2dasm.h b/cpu/sh2/mame/sh2dasm.h
new file mode 100644 (file)
index 0000000..a143d1d
--- /dev/null
@@ -0,0 +1 @@
+unsigned DasmSH2(char *buffer, unsigned pc, unsigned short opcode);
index 34fd177..fe5b7d7 100644 (file)
@@ -33,6 +33,8 @@ typedef unsigned char  UINT8;
 
 #include "sh2.c"
 
+#ifndef DRC_TMP
+
 void sh2_execute(SH2 *sh2_, int cycles)
 {
        sh2 = sh2_;
@@ -96,3 +98,43 @@ void sh2_execute(SH2 *sh2_, int cycles)
        sh2->cycles_done += cycles - sh2->icount;
 }
 
+#else // DRC_TMP
+
+// tmp
+void __attribute__((regparm(2))) sh2_do_op(SH2 *sh2_, int opcode)
+{
+       sh2 = sh2_;
+       sh2->pc += 2;
+
+       switch (opcode & ( 15 << 12))
+       {
+               case  0<<12: op0000(opcode); break;
+               case  1<<12: op0001(opcode); break;
+               case  2<<12: op0010(opcode); break;
+               case  3<<12: op0011(opcode); break;
+               case  4<<12: op0100(opcode); break;
+               case  5<<12: op0101(opcode); break;
+               case  6<<12: op0110(opcode); break;
+               case  7<<12: op0111(opcode); break;
+               case  8<<12: op1000(opcode); break;
+               case  9<<12: op1001(opcode); break;
+               case 10<<12: op1010(opcode); break;
+               case 11<<12: op1011(opcode); break;
+               case 12<<12: op1100(opcode); break;
+               case 13<<12: op1101(opcode); break;
+               case 14<<12: op1110(opcode); break;
+               default: op1111(opcode); break;
+       }
+
+       if (sh2->test_irq)
+       {
+               if (sh2->pending_irl > sh2->pending_int_irq)
+                       sh2_irl_irq(sh2, sh2->pending_irl);
+               else
+                       sh2_internal_irq(sh2, sh2->pending_int_irq, sh2->pending_int_vector);
+               sh2->test_irq = 0;
+       }
+}
+
+#endif
+
index bda1c93..2ee3c3a 100644 (file)
@@ -1,12 +1,19 @@
 #include <string.h>
 #include "sh2.h"
+#include "compiler.h"
 
 #define I 0xf0
 
-void sh2_init(SH2 *sh2, int is_slave)
+int sh2_init(SH2 *sh2, int is_slave)
 {
+       int ret = 0;
+
        memset(sh2, 0, sizeof(*sh2));
        sh2->is_slave = is_slave;
+#ifdef DRC_SH2
+       ret = sh2_drc_init(sh2);
+#endif
+       return ret;
 }
 
 void sh2_reset(SH2 *sh2)
index 404c19e..22b3bc5 100644 (file)
@@ -13,32 +13,37 @@ void p32x_sh2_write32(unsigned int a, unsigned int d, int id);
 \r
 typedef struct\r
 {\r
-       unsigned int    r[16];\r
+       unsigned int    r[16];          // 00\r
+       unsigned int    pc;             // 40\r
        unsigned int    ppc;\r
-       unsigned int    pc;\r
        unsigned int    pr;\r
        unsigned int    sr;\r
-       unsigned int    gbr, vbr;\r
-       unsigned int    mach, macl;\r
+       unsigned int    gbr, vbr;       // 50\r
+       unsigned int    mach, macl;     // 58\r
 \r
+       // interpreter stuff\r
+       int             icount;         // 60 cycles left in current timeslice\r
        unsigned int    ea;\r
        unsigned int    delay;\r
        unsigned int    test_irq;\r
 \r
+       // drc stuff\r
+       void    **pc_hashtab;           // 70\r
+\r
+       // common\r
        int     pending_irl;\r
        int     pending_int_irq;        // internal irq\r
        int     pending_int_vector;\r
        void    (*irq_callback)(int id, int level);\r
        int     is_slave;\r
 \r
-       int             icount;         // cycles left in current timeslice\r
        unsigned int    cycles_aim;     // subtract sh2_icount to get global counter\r
        unsigned int    cycles_done;\r
 } SH2;\r
 \r
 extern SH2 *sh2; // active sh2\r
 \r
-void sh2_init(SH2 *sh2, int is_slave);\r
+int  sh2_init(SH2 *sh2, int is_slave);\r
 void sh2_reset(SH2 *sh2);\r
 void sh2_irl_irq(SH2 *sh2, int level);\r
 void sh2_internal_irq(SH2 *sh2, int level, int vector);\r
diff --git a/cpu/sh2/stub_x86.asm b/cpu/sh2/stub_x86.asm
new file mode 100644 (file)
index 0000000..256d64a
--- /dev/null
@@ -0,0 +1,16 @@
+section .text
+
+global sh2_drc_entry ; SH2 *sh2, void *block
+
+sh2_drc_entry:
+    push    ebp
+    mov     ebp, [esp+4+4]     ; context
+    mov     eax, [esp+4+8]
+    jmp     eax
+
+global sh2_drc_exit
+
+sh2_drc_exit:
+    pop     ebp
+    ret
+
index c75e3fe..320e6a4 100644 (file)
@@ -38,6 +38,7 @@ void Pico32xStartup(void)
 {
   elprintf(EL_STATUS|EL_32X, "32X startup");
 
+  // TODO: OOM handling
   PicoAHW |= PAHW_32X;
   sh2_init(&msh2, 0);
   msh2.irq_callback = sh2_irq_cb;
index 4fad3d7..32f7e3e 100644 (file)
@@ -7,7 +7,13 @@
 #include "../../../cpu/drc/cmn.h"
 #include "compiler.h"
 
-#define u32 unsigned int
+// FIXME: asm has these hardcoded
+#define SSP_BLOCKTAB_ENTS       (0x5090/2)
+#define SSP_BLOCKTAB_IRAM_ONE   (0x800/2) // table entries
+#define SSP_BLOCKTAB_IRAM_ENTS  (15*SSP_BLOCKTAB_IRAM_ONE)
+
+static u32 **ssp_block_table; // [0x5090/2];
+static u32 **ssp_block_table_iram; // [15][0x800/2];
 
 static u32 *tcache_ptr = NULL;
 
@@ -23,7 +29,7 @@ extern ssp1601_t *ssp;
 #define SSP_FLAG_N (1<<0xf)
 
 #ifndef ARM
-#define DUMP_BLOCK 0x0c9a
+//#define DUMP_BLOCK 0x0c9a
 void ssp_drc_next(void){}
 void ssp_drc_next_patch(void){}
 void ssp_drc_end(void){}
@@ -1677,7 +1683,9 @@ static void emit_block_epilogue(int cycles, int cond, int pc, int end_pc)
                emit_jump(A_COND_AL, ssp_drc_next);
        }
        else if (cond == A_COND_AL) {
-               u32 *target = (pc < 0x400) ? ssp_block_table_iram[ssp->drc.iram_context][pc] : ssp_block_table[pc];
+               u32 *target = (pc < 0x400) ?
+                       ssp_block_table_iram[ssp->drc.iram_context * SSP_BLOCKTAB_IRAM_ONE + pc] :
+                       ssp_block_table[pc];
                if (target != NULL)
                        emit_jump(A_COND_AL, target);
                else {
@@ -1687,8 +1695,12 @@ static void emit_block_epilogue(int cycles, int cond, int pc, int end_pc)
                }
        }
        else {
-               u32 *target1 = (pc     < 0x400) ? ssp_block_table_iram[ssp->drc.iram_context][pc] : ssp_block_table[pc];
-               u32 *target2 = (end_pc < 0x400) ? ssp_block_table_iram[ssp->drc.iram_context][end_pc] : ssp_block_table[end_pc];
+               u32 *target1 = (pc     < 0x400) ?
+                       ssp_block_table_iram[ssp->drc.iram_context * SSP_BLOCKTAB_IRAM_ONE + pc] :
+                       ssp_block_table[pc];
+               u32 *target2 = (end_pc < 0x400) ?
+                       ssp_block_table_iram[ssp->drc.iram_context * SSP_BLOCKTAB_IRAM_ONE + end_pc] :
+                       ssp_block_table[end_pc];
                if (target1 != NULL)
                     emit_jump(cond, target1);
                if (target2 != NULL)
@@ -1754,7 +1766,7 @@ void *ssp_translate_block(int pc)
        tr_flush_dirty_pmcrs();
        emit_block_epilogue(ccount, end_cond, jump_pc, pc);
 
-       if (tcache_ptr - tcache > SSP_TCACHE_SIZE/4) {
+       if (tcache_ptr - tcache > DRC_TCACHE_SIZE/4) {
                elprintf(EL_ANOMALY|EL_STATUS|EL_SVP, "tcache overflow!\n");
                fflush(stdout);
                exit(1);
@@ -1790,13 +1802,29 @@ static void ssp1601_state_load(void)
        ssp->drc.iram_context = 0;
 }
 
+void ssp1601_dyn_exit(void)
+{
+       free(ssp_block_table);
+       free(ssp_block_table_iram);
+       ssp_block_table = ssp_block_table_iram = NULL;
+
+       drc_cmn_cleanup();
+}
+
 int ssp1601_dyn_startup(void)
 {
        drc_cmn_init();
 
-       memset(tcache, 0, SSP_TCACHE_SIZE);
-       memset(ssp_block_table, 0, sizeof(ssp_block_table));
-       memset(ssp_block_table_iram, 0, sizeof(ssp_block_table_iram));
+       ssp_block_table = calloc(sizeof(ssp_block_table[0]), SSP_BLOCKTAB_ENTS);
+       if (ssp_block_table == NULL)
+               return -1;
+       ssp_block_table_iram = calloc(sizeof(ssp_block_table_iram[0]), SSP_BLOCKTAB_IRAM_ENTS);
+       if (ssp_block_table_iram == NULL) {
+               free(ssp_block_table);
+               return -1;
+       }
+
+       memset(tcache, 0, DRC_TCACHE_SIZE);
        tcache_ptr = tcache;
 
        PicoLoadStateHook = ssp1601_state_load;
@@ -1806,12 +1834,12 @@ int ssp1601_dyn_startup(void)
        // hle'd blocks
        ssp_block_table[0x800/2] = (void *) ssp_hle_800;
        ssp_block_table[0x902/2] = (void *) ssp_hle_902;
-       ssp_block_table_iram[ 7][0x030/2] = (void *) ssp_hle_07_030;
-       ssp_block_table_iram[ 7][0x036/2] = (void *) ssp_hle_07_036;
-       ssp_block_table_iram[ 7][0x6d6/2] = (void *) ssp_hle_07_6d6;
-       ssp_block_table_iram[11][0x12c/2] = (void *) ssp_hle_11_12c;
-       ssp_block_table_iram[11][0x384/2] = (void *) ssp_hle_11_384;
-       ssp_block_table_iram[11][0x38a/2] = (void *) ssp_hle_11_38a;
+       ssp_block_table_iram[ 7 * SSP_BLOCKTAB_IRAM_ENTS + 0x030/2] = (void *) ssp_hle_07_030;
+       ssp_block_table_iram[ 7 * SSP_BLOCKTAB_IRAM_ENTS + 0x036/2] = (void *) ssp_hle_07_036;
+       ssp_block_table_iram[ 7 * SSP_BLOCKTAB_IRAM_ENTS + 0x6d6/2] = (void *) ssp_hle_07_6d6;
+       ssp_block_table_iram[11 * SSP_BLOCKTAB_IRAM_ENTS + 0x12c/2] = (void *) ssp_hle_11_12c;
+       ssp_block_table_iram[11 * SSP_BLOCKTAB_IRAM_ENTS + 0x384/2] = (void *) ssp_hle_11_384;
+       ssp_block_table_iram[11 * SSP_BLOCKTAB_IRAM_ENTS + 0x38a/2] = (void *) ssp_hle_11_38a;
 #endif
 
        return 0;
index d145621..abd2394 100644 (file)
@@ -13,6 +13,7 @@ void ssp_hle_11_384(void);
 void ssp_hle_11_38a(void);
 
 int  ssp1601_dyn_startup(void);
+void ssp1601_dyn_exit(void);
 void ssp1601_dyn_reset(ssp1601_t *ssp);
 void ssp1601_dyn_run(int cycles);
 
index 6248120..d1e7f8f 100644 (file)
@@ -99,6 +99,13 @@ void PicoSVPInit(void)
 {
 }
 
+static void PicoSVPExit(void)
+{
+#ifndef PSP
+       ssp1601_dyn_exit();
+#endif
+}
+
 
 void PicoSVPStartup(void)
 {
@@ -133,6 +140,7 @@ void PicoSVPStartup(void)
        PicoDmaHook = PicoSVPDma;
        PicoResetHook = PicoSVPReset;
        PicoLineHook = PicoSVPLine;
+       PicoCartUnloadHook = PicoSVPExit;
 
        // save state stuff
        svp_states[0].ptr = svp->iram_rom;
index 0617397..90731bd 100644 (file)
@@ -243,10 +243,19 @@ extern SH2 sh2s[2];
 #define msh2 sh2s[0]\r
 #define ssh2 sh2s[1]\r
 \r
-#define ash2_end_run(after) if (sh2->icount > (after)) sh2->icount = after\r
-#define ash2_cycles_done() (sh2->cycles_aim - sh2->icount)\r
+#ifndef DRC_SH2\r
+# define ash2_end_run(after) if (sh2->icount > (after)) sh2->icount = after\r
+# define ash2_cycles_done() (sh2->cycles_aim - sh2->icount)\r
+#else\r
+# define ash2_end_run(after) { \\r
+   if ((sh2->sr >> 12) > (after)) \\r
+     { sh2->sr &= 0xfff; sh2->sr |= (after) << 12; } \\r
+}\r
+# define ash2_cycles_done() (sh2->cycles_aim - (sh2->sr >> 12))\r
+#endif\r
 \r
-#define sh2_pc(c)     (c) ? ssh2.ppc : msh2.ppc\r
+//#define sh2_pc(c)     (c) ? ssh2.ppc : msh2.ppc\r
+#define sh2_pc(c)     (c) ? ssh2.pc : msh2.pc\r
 #define sh2_reg(c, x) (c) ? ssh2.r[x] : msh2.r[x]\r
 #define sh2_gbr(c)    (c) ? ssh2.gbr : msh2.gbr\r
 #define sh2_vbr(c)    (c) ? ssh2.vbr : msh2.vbr\r
index 8743a13..5c77220 100644 (file)
@@ -2,7 +2,8 @@
 use_musashi = 1
 #use_fame = 1
 #use_mz80 = 1
-#use_sh2drc = 1
+use_sh2drc = 1
+drc_debug = 1
 #profile = 1
 #fake_in_gp2x = 1
 
@@ -75,6 +76,16 @@ endif
 # sh2
 OBJS += cpu/sh2/sh2.o
 ifeq "$(use_sh2drc)" "1"
+DEFINES += DRC_SH2 DRC_TMP
+OBJS += cpu/sh2/mame/sh2pico.o
+OBJS += cpu/sh2/compiler.o
+OBJS += cpu/sh2/stub_x86.o
+ifeq "$(drc_debug)" "1"
+DEFINES += DRC_DEBUG
+OBJS += cpu/sh2/mame/sh2dasm.o
+OBJS += host_dasm.o
+LDFLAGS += -lbfd -lopcodes
+endif
 else
 OBJS += cpu/sh2/mame/sh2pico.o
 endif
@@ -89,6 +100,7 @@ endif
 CFLAGS += $(addprefix -D,$(DEFINES))
 
 vpath %.c = ../..
+vpath %.asm = ../..
 
 DIRS = platform platform/gp2x platform/common pico pico/cd pico/pico pico/sound pico/carthw/svp \
        pico/32x zlib unzip cpu cpu/musashi cpu/fame cpu/mz80 cpu/cz80 cpu/sh2/mame cpu/drc
@@ -130,6 +142,9 @@ cpu/mz80/mz80.o : ../../cpu/mz80/mz80.asm
 .s.o:
        @echo ">>>" $<
        $(CC) $(CFLAGS) -c $< -o $@
+%.o : %.asm
+       @echo ">>>" $<
+       nasm -f elf $< -o $@
 
 
 cpu/fame/famec.o : ../../cpu/fame/famec.c ../../cpu/fame/famec_opcodes.h
diff --git a/platform/linux/host_dasm.c b/platform/linux/host_dasm.c
new file mode 100644 (file)
index 0000000..38a7e47
--- /dev/null
@@ -0,0 +1,167 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <bfd.h>
+#include <dis-asm.h>
+
+#include "host_dasm.h"
+
+extern char **g_argv;
+
+static struct disassemble_info di;
+
+/* symbols */
+static asymbol **symbols;
+static long symcount;
+
+/* Filter out (in place) symbols that are useless for disassembly.
+   COUNT is the number of elements in SYMBOLS.
+   Return the number of useful symbols.  */
+static long
+remove_useless_symbols (asymbol **symbols, long count)
+{
+  asymbol **in_ptr = symbols, **out_ptr = symbols;
+
+  while (--count >= 0)
+    {
+      asymbol *sym = *in_ptr++;
+
+      if (sym->name == NULL || sym->name[0] == '\0')
+        continue;
+      if (sym->flags & (BSF_DEBUGGING | BSF_SECTION_SYM))
+        continue;
+      if (bfd_is_und_section (sym->section)
+          || bfd_is_com_section (sym->section))
+        continue;
+      if (sym->value + sym->section->vma == 0)
+        continue;
+/*
+      printf("sym: %08lx %04x %08x v %08x \"%s\"\n",
+        (unsigned int)sym->value, (unsigned int)sym->flags, (unsigned int)sym->udata.i,
+        (unsigned int)sym->section->vma, sym->name);
+*/
+      *out_ptr++ = sym;
+    }
+  return out_ptr - symbols;
+}
+
+static void slurp_symtab(const char *filename)
+{
+  bfd *abfd;
+  long storage;
+
+  symcount = 0;
+
+  abfd = bfd_openr(filename, NULL);
+  if (abfd == NULL) {
+    fprintf(stderr, "failed to open: %s\n", filename);
+    goto no_symbols;
+  }
+
+  if (!bfd_check_format(abfd, bfd_object))
+    goto no_symbols;
+
+  if (!(bfd_get_file_flags(abfd) & HAS_SYMS))
+    goto no_symbols;
+
+  storage = bfd_get_symtab_upper_bound(abfd);
+  if (storage <= 0)
+    goto no_symbols;
+
+  symbols = malloc(storage);
+  symcount = bfd_canonicalize_symtab(abfd, symbols);
+  if (symcount < 0)
+    goto no_symbols;
+
+  symcount = remove_useless_symbols(symbols, symcount);
+//  bfd_close(abfd);
+  return;
+
+no_symbols:
+  fprintf(stderr, "no symbols in %s\n", bfd_get_filename(abfd));
+  if (abfd != NULL)
+    bfd_close(abfd);
+}
+
+
+/* Like target_read_memory, but slightly different parameters.  */
+static int
+dis_asm_read_memory(bfd_vma memaddr, bfd_byte *myaddr, unsigned int len,
+                     struct disassemble_info *info)
+{
+  memcpy(myaddr, (void *)(int)memaddr, len);
+  return 0;
+}
+
+static void
+dis_asm_memory_error(int status, bfd_vma memaddr,
+                      struct disassemble_info *info)
+{
+  fprintf(stderr, "memory_error %p\n", (void *)(int)memaddr);
+}
+
+static void
+dis_asm_print_address(bfd_vma addr, struct disassemble_info *info)
+{
+  asymbol **sptr = symbols;
+  int i;
+
+  printf("%08x", (int)addr);
+
+  for (i = 0; i < symcount; i++) {
+    asymbol *sym = *sptr++;
+
+    if (addr == sym->value + sym->section->vma) {
+      printf(" <%s>", sym->name);
+      break;
+    }
+  }
+}
+
+static int insn_printf(void *f, const char *format, ...)
+{
+  va_list args;
+  size_t n;
+
+  va_start(args, format);
+  n = vprintf(format, args);
+  va_end(args);
+
+  return n;
+}
+
+static void host_dasm_init(void)
+{
+  slurp_symtab(g_argv[0]);
+
+  init_disassemble_info(&di, NULL, insn_printf);
+  di.flavour = bfd_target_unknown_flavour;
+  di.memory_error_func = dis_asm_memory_error; 
+  di.print_address_func = dis_asm_print_address;
+//  di.symbol_at_address_func = dis_asm_symbol_at_address;
+  di.read_memory_func = dis_asm_read_memory;
+  di.arch = bfd_arch_i386;
+  di.mach = bfd_mach_i386_i386_intel_syntax;
+  di.endian = BFD_ENDIAN_LITTLE;
+  disassemble_init_for_target(&di);
+}
+
+void host_dasm(void *addr, int len)
+{
+  bfd_vma vma_end, vma = (bfd_vma)(int)addr;
+  static int init_done = 0;
+
+  if (!init_done) {
+    host_dasm_init();
+    init_done = 1;
+  }
+
+  vma_end = vma + len;
+  while (vma < vma_end) {
+    printf("  %p ", (void *)(long)vma);
+    vma += print_insn_i386_intel(vma, &di);
+    printf("\n");
+  }
+}
+
diff --git a/platform/linux/host_dasm.h b/platform/linux/host_dasm.h
new file mode 100644 (file)
index 0000000..bf771d7
--- /dev/null
@@ -0,0 +1,2 @@
+void host_dasm(void *addr, int len);
+