#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)
#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
{
#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
}
-#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);
--- /dev/null
+#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);
+}
+
-#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;
}
--- /dev/null
+
+int sh2_drc_init(SH2 *sh2);
--- /dev/null
+#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
--- /dev/null
+unsigned DasmSH2(char *buffer, unsigned pc, unsigned short opcode);
#include "sh2.c"
+#ifndef DRC_TMP
+
void sh2_execute(SH2 *sh2_, int cycles)
{
sh2 = sh2_;
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
+
#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)
\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
--- /dev/null
+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
+
{
elprintf(EL_STATUS|EL_32X, "32X startup");
+ // TODO: OOM handling
PicoAHW |= PAHW_32X;
sh2_init(&msh2, 0);
msh2.irq_callback = sh2_irq_cb;
#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;
#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){}
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 {
}
}
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)
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);
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;
// 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;
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);
{
}
+static void PicoSVPExit(void)
+{
+#ifndef PSP
+ ssp1601_dyn_exit();
+#endif
+}
+
void PicoSVPStartup(void)
{
PicoDmaHook = PicoSVPDma;
PicoResetHook = PicoSVPReset;
PicoLineHook = PicoSVPLine;
+ PicoCartUnloadHook = PicoSVPExit;
// save state stuff
svp_states[0].ptr = svp->iram_rom;
#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
use_musashi = 1
#use_fame = 1
#use_mz80 = 1
-#use_sh2drc = 1
+use_sh2drc = 1
+drc_debug = 1
#profile = 1
#fake_in_gp2x = 1
# 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
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
.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
--- /dev/null
+#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");
+ }
+}
+
--- /dev/null
+void host_dasm(void *addr, int len);
+