From 5686d93123821e06ac2d9f6209c37438303dd4c1 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 19 Jan 2010 22:17:47 +0000 Subject: [PATCH] 32x: drc: new debug facility (pdb). Few fixes thanks to it. git-svn-id: file:///home/notaz/opt/svn/PicoDrive@863 be3aeb3a-fb24-0410-a615-afba39da0efa --- cpu/debug.c | 407 +++++++++++++++++++++++++++++++++++ cpu/debug.h | 31 +++ cpu/debug_net.c | 126 +++++++++++ cpu/debug_net.h | 9 + cpu/drc/emit_arm.c | 30 ++- cpu/drc/emit_x86.c | 7 +- cpu/sh2/compiler.c | 98 +++++++-- cpu/sh2/sh2.c | 2 + cpu/sh2/sh2.h | 1 + platform/common/common.mak | 11 + platform/common/main.c | 7 + platform/linux/Makefile | 6 +- platform/linux/host_dasm.c | 2 +- platform/linux/port_config.h | 4 +- 14 files changed, 708 insertions(+), 33 deletions(-) create mode 100644 cpu/debug.c create mode 100644 cpu/debug.h create mode 100644 cpu/debug_net.c create mode 100644 cpu/debug_net.h diff --git a/cpu/debug.c b/cpu/debug.c new file mode 100644 index 00000000..2811b43a --- /dev/null +++ b/cpu/debug.c @@ -0,0 +1,407 @@ +/* + * vim:shiftwidth=2:expandtab + * PDB, the PicoDrive debugger + */ +#define _GNU_SOURCE +#include + +#include "../pico/pico_int.h" +#include "debug.h" + +static char pdb_pending_cmds[128]; +static char pdb_event_cmds[128]; + +static struct pdb_cpu { + void *context; + int type; + int id; + const char *name; + unsigned int bpts[16]; + int bpt_count; + int icount; +} pdb_cpus[5]; +static int pdb_cpu_count; + +static int pdb_global_icount; + +#ifdef PDB_NET +#include +#include +#include +#include +#include +#include + +#include "debug_net.h" + +static int pdb_net_sock = -1; + +int pdb_net_connect(const char *host, const char *port) +{ + struct sockaddr_in sockadr; + int sock = -1; + int ret; + + sock = socket(PF_INET, SOCK_STREAM, 0); + if (sock == -1) { + perror("socket"); + return -1; + } + + sockadr.sin_addr.s_addr = inet_addr(host); + sockadr.sin_family = AF_INET; + sockadr.sin_port = htons(atoi(port)); + + ret = connect(sock, (struct sockaddr *)&sockadr, sizeof(sockadr)); + if (ret != 0) { + perror("pdb_net: connect"); + close(sock); + return -1; + } + + printf("pdb_net: connected to %s:%s\n", host, port); + + pdb_net_sock = sock; + return 0; +} + +static int pdb_net_send(struct pdb_cpu *cpu, unsigned int pc) +{ + packet_t packet; + int ret; + + if (pdb_net_sock < 0) + return 0; // not connected + + if (cpu->type == PDBCT_SH2) { + SH2 *sh2 = cpu->context; + int rl = offsetof(SH2, macl) + sizeof(sh2->macl); + packet.header.type = PDBCT_SH2; + packet.header.cpuid = cpu->id; + packet.regs[0] = pc; + memcpy(&packet.regs[1], sh2->r, rl); + packet.regs[1+24+0] = sh2->pdb_io_csum[0]; + packet.regs[1+24+1] = sh2->pdb_io_csum[1]; + packet.header.len = 4 + rl + 4*2; + sh2->pdb_io_csum[0] = sh2->pdb_io_csum[1] = 0; + } + + ret = send(pdb_net_sock, &packet, sizeof(packet.header) + packet.header.len, MSG_NOSIGNAL); + if (ret != sizeof(packet.header) + packet.header.len) { + if (ret < 0) + perror("send"); + else + printf("send: %d/%d\n", ret, sizeof(packet.header) + packet.header.len); + close(pdb_net_sock); + pdb_net_sock = -1; + ret = -1; + } + return ret; +} +#else +#define pdb_net_send(a,b) 0 +#endif // PDB_NET + +#ifdef HAVE_READLINE +#include +#include +#endif + +static char *my_readline(const char *prompt) +{ + char *line = NULL; + +#ifdef HAVE_READLINE + line = readline("(pdb) "); + if (line == NULL) + return NULL; + if (line[0] != 0) + add_history(line); +#else + size_t size = 0; + ssize_t ret; + + printf("(pdb) "); + fflush(stdout); + ret = getline(&line, &size, stdin); + if (ret < 0) + return NULL; + if (ret > 0 && line[ret - 1] == '\n') + line[ret - 1] = 0; +#endif + + return line; +} + +static struct pdb_cpu *context2cpu(const void *context) +{ + int i; + for (i = 0; i < pdb_cpu_count; i++) + if (pdb_cpus[i].context == context) + return &pdb_cpus[i]; + return NULL; +} + +static const char *get_token(char *buf, int blen, const char *str) +{ + const char *p, *s, *e; + int len; + + p = str; + while (isspace_(*p)) + p++; + if (*p == 0) + return NULL; + if (*p == ';') { + strcpy(buf, ";"); + return p + 1; + } + + s = p; + while (*p != 0 && *p != ';' && !isspace_(*p)) + p++; + e = p; + while (isspace_(*e)) + e++; + + len = p - s; + if (len > blen - 1) + len = blen - 1; + memcpy(buf, s, len); + buf[len] = 0; + return e; +} + +static const char *get_arg(char *buf, int blen, const char *str) +{ + if (*str == ';') + return NULL; + return get_token(buf, blen, str); +} + +enum cmd_ret_e { + CMDRET_DONE, // ..and back to prompt +// CMDRET_PROMPT, // go to prompt + CMDRET_CONT_DO_NEXT, // continue and do remaining cmds on next event + CMDRET_CONT_REDO, // continue and redo all cmds on next event +}; + +static int do_print(struct pdb_cpu *cpu, const char *args) +{ + int i; + elprintf(EL_STATUS, "cpu %d (%s)", cpu->id, cpu->name); + if (cpu->type == PDBCT_SH2) { + SH2 *sh2 = cpu->context; + printf("PC,SR %08x, %03x\n", sh2->pc, sh2->sr & 0x3ff); + for (i = 0; i < 16/2; i++) + printf("R%d,%2d %08x,%08x\n", i, i + 8, sh2->r[i], sh2->r[i + 8]); + printf("gb,vb %08x,%08x\n", sh2->gbr, sh2->vbr); + printf("IRQs/mask: %02x/%02x\n", Pico32x.sh2irqi[sh2->is_slave], + Pico32x.sh2irq_mask[sh2->is_slave]); + printf("cycles %d/%d (%d)\n", sh2->cycles_done, sh2->cycles_aim, (signed int)sh2->sr >> 12); + } + return CMDRET_DONE; +} + +static int do_step_all(struct pdb_cpu *cpu, const char *args) +{ + char tmp[32]; + if (!get_arg(tmp, sizeof(tmp), args)) { + printf("step_all: missing arg\n"); + return CMDRET_DONE; + } + + pdb_global_icount = atoi(tmp); + return CMDRET_CONT_DO_NEXT; +} + +static int do_continue(struct pdb_cpu *cpu, const char *args) +{ + char tmp[32]; + if (get_arg(tmp, sizeof(tmp), args)) + cpu->icount = atoi(tmp); + return CMDRET_CONT_DO_NEXT; +} + +static int do_step(struct pdb_cpu *cpu, const char *args) +{ + cpu->icount = 1; + return do_continue(cpu, args); +} + +static int do_waitcpu(struct pdb_cpu *cpu, const char *args) +{ + char tmp[32]; + if (!get_arg(tmp, sizeof(tmp), args)) { + printf("waitcpu: missing arg\n"); + return CMDRET_DONE; + } + if (strcmp(tmp, cpu->name) == 0) + return CMDRET_DONE; + + return CMDRET_CONT_REDO; +} + +static int do_help(struct pdb_cpu *cpu, const char *args); + +static struct { + const char *cmd; + const char *help; + int (*handler)(struct pdb_cpu *cpu, const char *args); +} pdb_cmds[] = { + { "help", "", do_help }, + { "continue", "[insns]", do_continue }, + { "step", "[insns]", do_step }, + { "step_all", "", do_step_all }, + { "waitcpu", "", do_waitcpu }, + { "print", "", do_print }, +}; + +static int do_help(struct pdb_cpu *cpu, const char *args) +{ + int i; + for (i = 0; i < ARRAY_SIZE(pdb_cmds); i++) + printf("%s %s\n", pdb_cmds[i].cmd, pdb_cmds[i].help); + return CMDRET_DONE; +} + +static int do_comands(struct pdb_cpu *cpu, const char *cmds) +{ + const char *p = cmds; + while (p != NULL) + { + const char *pcmd; + char cmd[32]; + int i, len; + int ret = 0; + + pcmd = p; + p = get_token(cmd, sizeof(cmd), p); + if (p == NULL) + break; + if (cmd[0] == ';') + continue; + + len = strlen(cmd); + for (i = 0; i < ARRAY_SIZE(pdb_cmds); i++) + if (strncmp(pdb_cmds[i].cmd, cmd, len) == 0) { + ret = pdb_cmds[i].handler(cpu, p); + break; + } + + if (i == ARRAY_SIZE(pdb_cmds)) { + printf("bad cmd: %s\n", cmd); + break; + } + + // skip until next command + while (1) { + p = get_token(cmd, sizeof(cmd), p); + if (p == NULL || cmd[0] == ';') + break; + } + + pdb_event_cmds[0] = 0; + if (ret == CMDRET_CONT_DO_NEXT) { + pdb_pending_cmds[0] = 0; + if (p != NULL) + strcpy(pdb_event_cmds, p); + return 0; + } + if (ret == CMDRET_CONT_REDO) { + if (pcmd != pdb_pending_cmds) + strncpy(pdb_pending_cmds, pcmd, sizeof(pdb_pending_cmds)); + return 0; + } + pdb_pending_cmds[0] = 0; + } + + return 1; +} + +static void do_prompt(struct pdb_cpu *cpu) +{ + static char prev[128]; + int ret; + + while (1) { + char *line, *cline; + + line = my_readline("(pdb) "); + if (line == NULL) + break; + if (line[0] == 0) + cline = prev; + else { + cline = line; + strncpy(prev, line, sizeof(prev)); + } + + ret = do_comands(cpu, cline); + free(line); + + if (ret == 0) + break; + } +} + +void pdb_register_cpu(void *context, int type, const char *name) +{ + int i = pdb_cpu_count; + memset(&pdb_cpus[i], 0, sizeof(pdb_cpus[i])); + pdb_cpus[i].context = context; + pdb_cpus[i].type = type; + pdb_cpus[i].id = pdb_cpu_count; + pdb_cpus[i].name = name; + pdb_cpus[i].icount = -1; + pdb_cpu_count++; +} + +void pdb_step(void *context, unsigned int pc) +{ + struct pdb_cpu *cpu = context2cpu(context); + int i; + + if (pdb_net_send(cpu, pc) < 0) + goto prompt; + + if (pdb_pending_cmds[0] != 0) + if (do_comands(cpu, pdb_pending_cmds)) + goto prompt; + + // breakpoint? + for (i = 0; i < cpu->bpt_count; i++) + if (cpu->bpts[i] == pc) + goto prompt; + + // hit num of insns? + if (pdb_global_icount > 0) + if (--pdb_global_icount == 0) + goto prompt; + + if (cpu->icount > 0) + if (--(cpu->icount) == 0) + goto prompt; + + return; + +prompt: + if (pdb_event_cmds[0] != 0) + if (!do_comands(cpu, pdb_event_cmds)) + return; + + printf("%s @%08x\n", cpu->name, pc); + do_prompt(cpu); +} + +void pdb_command(const char *cmd) +{ + strncpy(pdb_pending_cmds, cmd, sizeof(pdb_pending_cmds)); + pdb_pending_cmds[sizeof(pdb_pending_cmds) - 1] = 0; +} + +void pdb_cleanup(void) +{ + pdb_cpu_count = 0; +} + diff --git a/cpu/debug.h b/cpu/debug.h new file mode 100644 index 00000000..bf3e0688 --- /dev/null +++ b/cpu/debug.h @@ -0,0 +1,31 @@ + +#ifdef PDB + +enum { + PDBCT_SH2, +}; + +void pdb_register_cpu(void *context, int type, const char *name); +void pdb_cleanup(void); +void pdb_step(void *context, unsigned int pc); +void pdb_command(const char *cmd); + +#else + +#define pdb_register_cpu(a,b,c) +#define pdb_cleanup() +#define pdb_step(a,b) +#define pdb_command(a) + +#endif + + +#if defined(PDB) && defined(PDB_NET) + +int pdb_net_connect(const char *host, const char *port); + +#else + +#define pdb_net_connect(a,b) 0 + +#endif diff --git a/cpu/debug_net.c b/cpu/debug_net.c new file mode 100644 index 00000000..0305a1a7 --- /dev/null +++ b/cpu/debug_net.c @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +#include + +#include "debug_net.h" + +static const char * const regnames[] = { + "PC", + "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", + "R8", "R9", "R10", "R11", "R12", "R13", "R14", "SP", + "PC2", "PC3", "PR", "SR", "GBR", "VBR", "MACH", "MACL", + "MEM0", "MEM1", // mem i/o csums +}; + +int main(int argc, char *argv[]) +{ + unsigned int pc_trace[5][4], pc_trace_p[5] = { 0, }; + struct addrinfo *ai, *ais, hints; + int sock = -1, sock1, sock2; + struct sockaddr_in6 sa; + packet_t packet1, packet2; + int i, ret, cnt, cpuid; + socklen_t sal; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + ret = getaddrinfo("::", "1234", &hints, &ais); + if (ret != 0) + return -1; + + for (ai = ais; ai != NULL; ai = ai->ai_next) { + sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sock == -1) + continue; + + ret = bind(sock, ai->ai_addr, ai->ai_addrlen); + if (ret != 0) { + close(sock); + sock = -1; + continue; + } + break; + } + freeaddrinfo(ais); + + if (sock == -1) { + perror("failed to bind"); + return -1; + } + + ret = listen(sock, SOMAXCONN); + if (ret != 0) { + perror("failed to listen"); + return -1; + } + + sal = sizeof(sa); + sock1 = accept(sock, (struct sockaddr *)&sa, &sal); + if (sock1 == -1) { + perror("failed to accept"); + return -1; + } + printf("client1 connected\n"); + + sal = sizeof(sa); + sock2 = accept(sock, (struct sockaddr *)&sa, &sal); + if (sock2 == -1) { + perror("failed to accept"); + return -1; + } + printf("client2 connected\n"); + + for (cnt = 0; ; cnt++) + { +#define tmp_size (4+4 + 24*4 + 2*4) + ret = recv(sock1, &packet1, tmp_size, MSG_WAITALL); + if (ret != tmp_size) { + if (ret < 0) + perror("recv1"); + else + printf("recv1 %d\n", ret); + return -1; + } + ret = recv(sock2, &packet2, tmp_size, MSG_WAITALL); + if (ret != tmp_size) { + if (ret < 0) + perror("recv2"); + else + printf("recv2 %d\n", ret); + return -1; + } + + cpuid = packet1.header.cpuid; + if (memcmp(&packet1, &packet2, sizeof(packet1.header) + packet1.header.len) == 0) { + pc_trace[cpuid][pc_trace_p[cpuid]++ & 3] = packet1.regs[0]; + continue; + } + + if (*(int *)&packet1.header != *(int *)&packet2.header) + printf("%d: header\n", cnt); + + // check regs (and stuff) + for (i = 0; i < 1+24+2; i++) + if (packet1.regs[i] != packet2.regs[i]) + printf("%d: %3s: %08x %08x\n", cnt, regnames[i], packet1.regs[i], packet2.regs[i]); + + break; + } + + printf("--\nCPU %d, trace:", cpuid); + for (i = 0; i < 4; i++) + printf(" %08x", pc_trace[cpuid][pc_trace_p[cpuid]++ & 3]); + printf(" %08x\n", packet1.regs[0]); + + for (i = 0; i < 24+1; i++) + printf("%3s: %08x %08x\n", regnames[i], packet1.regs[i], packet2.regs[i]); + + return 0; +} + diff --git a/cpu/debug_net.h b/cpu/debug_net.h new file mode 100644 index 00000000..beccfa81 --- /dev/null +++ b/cpu/debug_net.h @@ -0,0 +1,9 @@ +typedef struct { + struct { + unsigned char type; + unsigned char cpuid; + unsigned short len; + } header; + unsigned int regs[32]; +} packet_t; + diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index 8627734a..d12db86c 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -241,30 +241,45 @@ #define EOP_MSR_REG(rm) EOP_C_MSR_REG(A_COND_AL,rm) -// XXX: AND, RSB, *C, MVN will break if 1 insn is not enough +// XXX: AND, RSB, *C, will break if 1 insn is not enough static void emith_op_imm2(int cond, int s, int op, int rd, int rn, unsigned int imm) { int ror2; u32 v; - if (op == A_OP_MOV) { + switch (op) { + case A_OP_MOV: rn = 0; - if (~imm < 0x100) { + if (~imm < 0x10000) { imm = ~imm; op = A_OP_MVN; } - } else if (imm == 0) - return; + break; + + case A_OP_EOR: + case A_OP_SUB: + case A_OP_ADD: + case A_OP_ORR: + case A_OP_BIC: + if (s == 0 && imm == 0) + return; + break; + } - for (v = imm, ror2 = 0; v != 0 || op == A_OP_MOV; v >>= 8, ror2 -= 8/2) { + for (v = imm, ror2 = 0; ; ror2 -= 8/2) { /* shift down to get 'best' rot2 */ for (; v && !(v & 3); v >>= 2) ror2--; EOP_C_DOP_IMM(cond, op, s, rn, rd, ror2 & 0x0f, v & 0xff); + v >>= 8; + if (v == 0) + break; if (op == A_OP_MOV) op = A_OP_ORR; + if (op == A_OP_MVN) + op = A_OP_BIC; rn = rd; } } @@ -414,6 +429,9 @@ static int emith_xbranch(int cond, void *target, int is_call) #define emith_add_r_imm(r, imm) \ emith_op_imm(A_COND_AL, 0, A_OP_ADD, r, imm) +#define emith_adc_r_imm(r, imm) \ + emith_op_imm(A_COND_AL, 0, A_OP_ADC, r, imm) + #define emith_sub_r_imm(r, imm) \ emith_op_imm(A_COND_AL, 0, A_OP_SUB, r, imm) diff --git a/cpu/drc/emit_x86.c b/cpu/drc/emit_x86.c index c823cfb0..6c9a4149 100644 --- a/cpu/drc/emit_x86.c +++ b/cpu/drc/emit_x86.c @@ -180,13 +180,18 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI }; EMIT(imm, u32); \ } while (0) -// 2 - adc, 3 - sbb #define emith_add_r_imm(r, imm) \ emith_arith_r_imm(0, r, imm) #define emith_or_r_imm(r, imm) \ emith_arith_r_imm(1, r, imm) +#define emith_adc_r_imm(r, imm) \ + emith_arith_r_imm(2, r, imm) + +#define emith_sbc_r_imm(r, imm) \ + emith_arith_r_imm(3, r, imm) // sbb + #define emith_and_r_imm(r, imm) \ emith_arith_r_imm(4, r, imm) diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 5a9bbed5..eea9a60c 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -29,6 +29,7 @@ #include "sh2.h" #include "compiler.h" #include "../drc/cmn.h" +#include "../debug.h" // features #define PROPAGATE_CONSTANTS 1 @@ -68,12 +69,14 @@ static char sh2dasm_buff[64]; #define do_host_disasm(x) #endif -#if (DRC_DEBUG & 4) -static void REGPARM(3) *sh2_drc_announce_entry(void *block, SH2 *sh2, u32 sr) +#if (DRC_DEBUG & 4) || defined(PDB) +static void REGPARM(3) *sh2_drc_log_entry(void *block, SH2 *sh2, u32 sr) { - if (block != NULL) + if (block != NULL) { dbg(4, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm', sh2->pc, block, (signed int)sr >> 12); + pdb_step(sh2, sh2->pc); + } return block; } #endif @@ -216,10 +219,15 @@ static void REGPARM(1) (*sh2_drc_entry)(SH2 *sh2); static void (*sh2_drc_dispatcher)(void); static void (*sh2_drc_exit)(void); static void (*sh2_drc_test_irq)(void); + +static u32 REGPARM(2) (*sh2_drc_read8)(u32 a, SH2 *sh2); +static u32 REGPARM(2) (*sh2_drc_read16)(u32 a, SH2 *sh2); +static u32 REGPARM(2) (*sh2_drc_read32)(u32 a, SH2 *sh2); static void REGPARM(2) (*sh2_drc_write8)(u32 a, u32 d); static void REGPARM(2) (*sh2_drc_write8_slot)(u32 a, u32 d); static void REGPARM(2) (*sh2_drc_write16)(u32 a, u32 d); static void REGPARM(2) (*sh2_drc_write16_slot)(u32 a, u32 d); +static int REGPARM(3) (*sh2_drc_write32)(u32 a, u32 d, SH2 *sh2); extern void REGPARM(2) sh2_do_op(SH2 *sh2, int opcode); @@ -242,6 +250,7 @@ static void flush_tcache(int tcid) #endif } +#if LINK_BRANCHES // add block links (tracked branches) static int dr_add_block_link(u32 target_pc, void *jump, int tcache_id) { @@ -259,6 +268,7 @@ static int dr_add_block_link(u32 target_pc, void *jump, int tcache_id) return 0; } +#endif static void *dr_find_block(block_desc *tab, u32 addr) { @@ -848,7 +858,7 @@ static int emit_memhandler_read_(int size, int ram_check) arg1 = rcache_get_tmp_arg(1); emith_move_r_r(arg1, CONTEXT_REG); -#if 1 +#ifndef PDB_NET if (ram_check && Pico.rom == (void *)0x02000000 && Pico32xMem->sdram == (void *)0x06000000) { int tmp = rcache_get_tmp(); emith_and_r_r_imm(tmp, arg0, 0xfb000000); @@ -859,14 +869,14 @@ static int emit_memhandler_read_(int size, int ram_check) emith_eor_r_imm_c(DCOND_EQ, arg0, 1); emith_read8_r_r_offs_c(DCOND_EQ, arg0, arg0, 0); EMITH_SJMP3_MID(DCOND_NE); - emith_call_cond(DCOND_NE, p32x_sh2_read8); + emith_call_cond(DCOND_NE, sh2_drc_read8); EMITH_SJMP3_END(); break; case 1: // 16 EMITH_SJMP3_START(DCOND_NE); emith_read16_r_r_offs_c(DCOND_EQ, arg0, arg0, 0); EMITH_SJMP3_MID(DCOND_NE); - emith_call_cond(DCOND_NE, p32x_sh2_read16); + emith_call_cond(DCOND_NE, sh2_drc_read16); EMITH_SJMP3_END(); break; case 2: // 32 @@ -874,7 +884,7 @@ static int emit_memhandler_read_(int size, int ram_check) emith_read_r_r_offs_c(DCOND_EQ, arg0, arg0, 0); emith_ror_c(DCOND_EQ, arg0, arg0, 16); EMITH_SJMP3_MID(DCOND_NE); - emith_call_cond(DCOND_NE, p32x_sh2_read32); + emith_call_cond(DCOND_NE, sh2_drc_read32); EMITH_SJMP3_END(); break; } @@ -884,13 +894,13 @@ static int emit_memhandler_read_(int size, int ram_check) { switch (size) { case 0: // 8 - emith_call(p32x_sh2_read8); + emith_call(sh2_drc_read8); break; case 1: // 16 - emith_call(p32x_sh2_read16); + emith_call(sh2_drc_read16); break; case 2: // 32 - emith_call(p32x_sh2_read32); + emith_call(sh2_drc_read32); break; } } @@ -974,7 +984,7 @@ static void emit_memhandler_write(int size, u32 pc, int delay) break; case 2: // 32 emith_move_r_r(ctxr, CONTEXT_REG); - emith_call(p32x_sh2_write32); + emith_call(sh2_drc_write32); break; } rcache_invalidate(); @@ -1050,10 +1060,11 @@ static void emit_block_entry(void) host_arg2reg(arg1, 1); host_arg2reg(arg2, 2); -#if (DRC_DEBUG & 4) +#if (DRC_DEBUG & 4) || defined(PDB) + emit_do_static_regs(1, arg2); emith_move_r_r(arg1, CONTEXT_REG); emith_move_r_r(arg2, rcache_get_reg(SHR_SR, RC_GR_READ)); - emith_call(sh2_drc_announce_entry); + emith_call(sh2_drc_log_entry); rcache_invalidate(); #endif emith_tst_r_r(arg0, arg0); @@ -1256,10 +1267,6 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) } branch_target_count = tmp; memset(branch_target_ptr, 0, sizeof(branch_target_ptr[0]) * branch_target_count); -#if !LINK_BRANCHES - // for debug - branch_target_count = 0; -#endif // ------------------------------------------------- // 2nd pass: actual compilation @@ -2479,6 +2486,7 @@ end_op: else emith_tst_r_imm(sr, T); +#if LINK_BRANCHES if (find_in_array(branch_target_pc, branch_target_count, target_pc) >= 0) { // local branch // XXX: jumps back can be linked already @@ -2492,7 +2500,9 @@ end_op: break; } } - else { + else +#endif + { // can't resolve branch locally, make a block exit emit_move_r_imm32(SHR_PC, target_pc); rcache_clean(); @@ -2622,6 +2632,11 @@ static void sh2_generate_utils(void) int arg0, arg1, arg2, sr, tmp; void *sh2_drc_write_end, *sh2_drc_write_slot_end; + sh2_drc_write32 = p32x_sh2_write32; + sh2_drc_read8 = p32x_sh2_read8; + sh2_drc_read16 = p32x_sh2_read16; + sh2_drc_read32 = p32x_sh2_read32; + host_arg2reg(arg0, 0); host_arg2reg(arg1, 1); host_arg2reg(arg2, 2); @@ -2679,7 +2694,7 @@ static void sh2_generate_utils(void) tmp = rcache_get_reg_arg(1, SHR_SR); emith_clear_msb(tmp, tmp, 22); emith_move_r_r(arg2, CONTEXT_REG); - emith_call(p32x_sh2_write32); + emith_call(p32x_sh2_write32); // XXX: use sh2_drc_write32? rcache_invalidate(); // push PC rcache_get_reg_arg(0, SHR_SP); @@ -2722,7 +2737,6 @@ static void sh2_generate_utils(void) EMITH_SJMP_START(DCOND_NE); emith_jump_ctx_c(DCOND_EQ, offsetof(SH2, drc_tmp)); // return EMITH_SJMP_END(DCOND_NE); - // since PC is up to date, jump to it's block instead of returning emith_call(sh2_drc_test_irq); emith_jump_ctx(offsetof(SH2, drc_tmp)); @@ -2763,6 +2777,50 @@ static void sh2_generate_utils(void) emith_ctx_read(arg2, offsetof(SH2, write16_tab)); emith_sh2_wcall(arg0, arg2, sh2_drc_write_slot_end); +#ifdef PDB_NET + // debug + #define MAKE_READ_WRAPPER(func) { \ + void *tmp = (void *)tcache_ptr; \ + emith_ret_to_ctx(offsetof(SH2, drc_tmp)); \ + emith_call(func); \ + emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[0])); \ + emith_addf_r_r(arg2, arg0); \ + emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[0])); \ + emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[1])); \ + emith_adc_r_imm(arg2, 0x01000000); \ + emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[1])); \ + emith_jump_ctx(offsetof(SH2, drc_tmp)); \ + func = tmp; \ + } + #define MAKE_WRITE_WRAPPER(func) { \ + void *tmp = (void *)tcache_ptr; \ + emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[0])); \ + emith_addf_r_r(arg2, arg1); \ + emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[0])); \ + emith_ctx_read(arg2, offsetof(SH2, pdb_io_csum[1])); \ + emith_adc_r_imm(arg2, 0x01000000); \ + emith_ctx_write(arg2, offsetof(SH2, pdb_io_csum[1])); \ + emith_move_r_r(arg2, CONTEXT_REG); \ + emith_jump(func); \ + func = tmp; \ + } + + MAKE_READ_WRAPPER(sh2_drc_read8); + MAKE_READ_WRAPPER(sh2_drc_read16); + MAKE_READ_WRAPPER(sh2_drc_read32); + MAKE_WRITE_WRAPPER(sh2_drc_write8); + MAKE_WRITE_WRAPPER(sh2_drc_write8_slot); + MAKE_WRITE_WRAPPER(sh2_drc_write16); + MAKE_WRITE_WRAPPER(sh2_drc_write16_slot); + MAKE_WRITE_WRAPPER(sh2_drc_write32); +#if (DRC_DEBUG & 2) + host_dasm_new_symbol(sh2_drc_read8); + host_dasm_new_symbol(sh2_drc_read16); + host_dasm_new_symbol(sh2_drc_read32); + host_dasm_new_symbol(sh2_drc_write32); +#endif +#endif + rcache_invalidate(); #if (DRC_DEBUG & 2) host_dasm_new_symbol(sh2_drc_entry); diff --git a/cpu/sh2/sh2.c b/cpu/sh2/sh2.c index f0bd9079..a873d183 100644 --- a/cpu/sh2/sh2.c +++ b/cpu/sh2/sh2.c @@ -1,5 +1,6 @@ #include #include "sh2.h" +#include "../debug.h" #include "compiler.h" #define I 0xf0 @@ -12,6 +13,7 @@ int sh2_init(SH2 *sh2, int is_slave) memset(sh2, 0, sizeof(*sh2)); sh2->is_slave = is_slave; + pdb_register_cpu(sh2, PDBCT_SH2, is_slave ? "ssh2" : "msh2"); #ifdef DRC_SH2 ret = sh2_drc_init(sh2); #endif diff --git a/cpu/sh2/sh2.h b/cpu/sh2/sh2.h index 47c61500..4be13d97 100644 --- a/cpu/sh2/sh2.h +++ b/cpu/sh2/sh2.h @@ -37,6 +37,7 @@ typedef struct SH2_ void *p_da; void *p_sdram; void *p_rom; + unsigned int pdb_io_csum[2]; // interpreter stuff int icount; // cycles left in current timeslice diff --git a/platform/common/common.mak b/platform/common/common.mak index 3ddf3fb8..061771e4 100644 --- a/platform/common/common.mak +++ b/platform/common/common.mak @@ -7,6 +7,17 @@ endif ifeq "$(profile)" "2" CFLAGS += -fprofile-use endif +ifeq "$(pdb)" "1" +DEFINES += PDB +OBJS += cpu/debug.o + ifeq "$(pdb_net)" "1" + DEFINES += PDB_NET + endif + ifeq "$(readline)" "1" + DEFINES += HAVE_READLINE + LDFLAGS += -lreadline + endif +endif ifeq "$(pprof)" "1" DEFINES += PPROF OBJS += platform/linux/pprof.o diff --git a/platform/common/main.c b/platform/common/main.c index b0ad4baa..7167df29 100644 --- a/platform/common/main.c +++ b/platform/common/main.c @@ -13,6 +13,7 @@ #include "config.h" #include "input.h" #include "plat.h" +#include #include @@ -34,6 +35,12 @@ void parse_cmd_line(int argc, char *argv[]) else if (strcasecmp(argv[x], "-loadstate") == 0) { if (x+1 < argc) { ++x; load_state_slot = atoi(argv[x]); } } + else if (strcasecmp(argv[x], "-pdb") == 0) { + if (x+1 < argc) { ++x; pdb_command(argv[x]); } + } + else if (strcasecmp(argv[x], "-pdb_connect") == 0) { + if (x+2 < argc) { pdb_net_connect(argv[x+1], argv[x+2]); x += 2; } + } else { unrecognized = 1; break; diff --git a/platform/linux/Makefile b/platform/linux/Makefile index 627c2e21..1fb54d3e 100644 --- a/platform/linux/Makefile +++ b/platform/linux/Makefile @@ -12,6 +12,8 @@ use_sh2drc = 1 #drc_debug_interp = 1 #profile = 1 +all: mkdirs PicoDrive + -include Makefile.local ifndef ARCH @@ -27,7 +29,7 @@ CFLAGS += -mcpu=arm920t DEFINES += ARM endif -CC = $(CROSS)gcc +CC ?= $(CROSS)gcc # frontend OBJS += io.o emu.o blit.o in_evdev.o plat.o sndout_oss.o log_io.o @@ -70,8 +72,6 @@ vpath %.asm = ../.. DIRS += platform/linux zlib unzip -all: mkdirs PicoDrive - include ../common/common.mak include ../common/revision.mak diff --git a/platform/linux/host_dasm.c b/platform/linux/host_dasm.c index 0b978211..a63a9acc 100644 --- a/platform/linux/host_dasm.c +++ b/platform/linux/host_dasm.c @@ -188,7 +188,7 @@ void host_dasm(void *addr, int len) if (name != NULL) printf("%s:\n", name); - printf(" %08lx ", (long)vma); + printf(" %08lx ", (long)vma); vma += print_insn_func(vma, &di); printf("\n"); } diff --git a/platform/linux/port_config.h b/platform/linux/port_config.h index 7e05d7d0..d9ccb478 100644 --- a/platform/linux/port_config.h +++ b/platform/linux/port_config.h @@ -23,8 +23,8 @@ #define SIMPLE_WRITE_SOUND 0 #define mix_32_to_16l_stereo_lvl mix_32_to_16l_stereo -#define EL_LOGMASK (EL_STATUS|EL_ANOMALY|EL_UIO|EL_IDLE) -// EL_VDPDMA|EL_ASVDP|EL_SR | EL_BUSREQ|EL_Z80BNK | EL_32X) +#define EL_LOGMASK (EL_STATUS|EL_ANOMALY|EL_UIO) +// EL_VDPDMA|EL_ASVDP|EL_SR | EL_IDLE | EL_BUSREQ|EL_Z80BNK | EL_32X) //#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__) #define dprintf(x...) -- 2.39.5