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
This commit is contained in:
notaz 2010-01-19 22:17:47 +00:00
parent 2368651527
commit 5686d93123
14 changed files with 708 additions and 33 deletions

407
cpu/debug.c Normal file
View file

@ -0,0 +1,407 @@
/*
* 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;
}

31
cpu/debug.h Normal file
View file

@ -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

126
cpu/debug_net.c Normal file
View file

@ -0,0 +1,126 @@
#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;
}

9
cpu/debug_net.h Normal file
View file

@ -0,0 +1,9 @@
typedef struct {
struct {
unsigned char type;
unsigned char cpuid;
unsigned short len;
} header;
unsigned int regs[32];
} packet_t;

View file

@ -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;
for (v = imm, ror2 = 0; v != 0 || op == A_OP_MOV; v >>= 8, ror2 -= 8/2) {
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; ; 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)

View file

@ -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)

View file

@ -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);

View file

@ -1,5 +1,6 @@
#include <string.h>
#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

View file

@ -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