--- /dev/null
+/*
+ * vim:shiftwidth=2:expandtab
+ * PDB, the PicoDrive debugger
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+
+#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 <stddef.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#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 <readline/readline.h>
+#include <readline/history.h>
+#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", "<insns>", do_step_all },
+ { "waitcpu", "<cpuname>", 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;
+}
+
--- /dev/null
+
+#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
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <unistd.h>
+
+#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;
+}
+
--- /dev/null
+typedef struct {
+ struct {
+ unsigned char type;
+ unsigned char cpuid;
+ unsigned short len;
+ } header;
+ unsigned int regs[32];
+} packet_t;
+
#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;
}
}
#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)
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)
#include "sh2.h"
#include "compiler.h"
#include "../drc/cmn.h"
+#include "../debug.h"
// features
#define PROPAGATE_CONSTANTS 1
#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
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);
#endif
}
+#if LINK_BRANCHES
// add block links (tracked branches)
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)
{
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);
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
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;
}
{
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;
}
}
break;
case 2: // 32
emith_move_r_r(ctxr, CONTEXT_REG);
- emith_call(p32x_sh2_write32);
+ emith_call(sh2_drc_write32);
break;
}
rcache_invalidate();
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);
}
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
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
break;
}
}
- else {
+ else
+#endif
+ {
// can't resolve branch locally, make a block exit
emit_move_r_imm32(SHR_PC, target_pc);
rcache_clean();
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);
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);
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));
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);
#include <string.h>
#include "sh2.h"
+#include "../debug.h"
#include "compiler.h"
#define I 0xf0
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
void *p_da;\r
void *p_sdram;\r
void *p_rom;\r
+ unsigned int pdb_io_csum[2];\r
\r
// interpreter stuff\r
int icount; // cycles left in current timeslice\r
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
#include "config.h"\r
#include "input.h"\r
#include "plat.h"\r
+#include <cpu/debug.h>\r
#include <version.h>\r
\r
\r
else if (strcasecmp(argv[x], "-loadstate") == 0) {\r
if (x+1 < argc) { ++x; load_state_slot = atoi(argv[x]); }\r
}\r
+ else if (strcasecmp(argv[x], "-pdb") == 0) {\r
+ if (x+1 < argc) { ++x; pdb_command(argv[x]); }\r
+ }\r
+ else if (strcasecmp(argv[x], "-pdb_connect") == 0) {\r
+ if (x+2 < argc) { pdb_net_connect(argv[x+1], argv[x+2]); x += 2; }\r
+ }\r
else {\r
unrecognized = 1;\r
break;\r
#drc_debug_interp = 1
#profile = 1
+all: mkdirs PicoDrive
+
-include Makefile.local
ifndef ARCH
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
DIRS += platform/linux zlib unzip
-all: mkdirs PicoDrive
-
include ../common/common.mak
include ../common/revision.mak
if (name != NULL)
printf("%s:\n", name);
- printf(" %08lx ", (long)vma);
+ printf(" %08lx ", (long)vma);
vma += print_insn_func(vma, &di);
printf("\n");
}
#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...)