summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2014-02-11 21:52:15 -0800
committerMichael Pavone <pavone@retrodev.com>2014-02-11 21:52:15 -0800
commit90f9f11749badf66785b6fb416d25e72cdc32c2d (patch)
tree9756acada9554b85f72010e67da1eae1c77b91da
parent6ed58ab3da90a6987bf3b8d51c7db27ed1513460 (diff)
parent04b527cd9945160456e8112afb221acef5e1c4fe (diff)
Merge
-rw-r--r--68kinst.c95
-rw-r--r--68kinst.h6
-rw-r--r--Makefile4
-rw-r--r--blastem.c96
-rw-r--r--gdb_remote.c381
-rw-r--r--m68k_to_x86.c2
-rw-r--r--vdp.c2
7 files changed, 447 insertions, 139 deletions
diff --git a/68kinst.c b/68kinst.c
index e72b66b..b9e25aa 100644
--- a/68kinst.c
+++ b/68kinst.c
@@ -1,6 +1,6 @@
/*
Copyright 2013 Michael Pavone
- This file is part of BlastEm.
+ This file is part of BlastEm.
BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
*/
#include "68kinst.h"
@@ -434,8 +434,8 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
}
break;
case 7:
-
-
+
+
break;
}
}
@@ -459,7 +459,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
}
break;
case MISC:
-
+
if ((*istream & 0x1C0) == 0x1C0) {
decoded->op = M68K_LEA;
decoded->extra.size = OPSIZE_LONG;
@@ -682,7 +682,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
}
}
}
- break;
+ break;
case 6:
//MULU, MULS, DIVU, DIVUL, DIVS, DIVSL
#ifdef M68020
@@ -918,7 +918,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
decoded->op = M68K_INVALID;
return start+1;
}
- break;
+ break;
}
} else {
decoded->op = M68K_OR;
@@ -1259,7 +1259,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
}
decoded->dst.addr_mode = MODE_REG;
decoded->dst.params.regs.pri = *istream & 0x7;
-
+
} else {
#ifdef M68020
//TODO: Implement bitfield instructions for M68020+ support
@@ -1273,6 +1273,79 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
return istream+1;
}
+uint32_t m68k_branch_target(m68kinst * inst, uint32_t *dregs, uint32_t *aregs)
+{
+ if(inst->op == M68K_BCC || inst->op == M68K_BSR || inst->op == M68K_DBCC) {
+ return inst->address + 2 + inst->src.params.immed;
+ } else if(inst->op == M68K_JMP || inst->op == M68K_JSR) {
+ uint32_t ret = 0;
+ switch(inst->src.addr_mode)
+ {
+ case MODE_AREG_INDIRECT:
+ ret = aregs[inst->src.params.regs.pri];
+ break;
+ case MODE_AREG_INDEX_DISP8: {
+ uint8_t sec_reg = inst->src.params.regs.sec >> 1 & 0x7;
+ ret = aregs[inst->src.params.regs.pri];
+ uint32_t * regfile = inst->src.params.regs.sec & 0x10 ? aregs : dregs;
+ if (inst->src.params.regs.sec & 1) {
+ //32-bit index register
+ ret += regfile[sec_reg];
+ } else {
+ //16-bit index register
+ if (regfile[sec_reg] & 0x8000) {
+ ret += (0xFFFF0000 | regfile[sec_reg]);
+ } else {
+ ret += regfile[sec_reg];
+ }
+ }
+ ret += inst->src.params.regs.displacement;
+ break;
+ }
+ case MODE_PC_DISPLACE:
+ ret = inst->src.params.regs.displacement + inst->address + 2;
+ break;
+ case MODE_PC_INDEX_DISP8: {
+ uint8_t sec_reg = inst->src.params.regs.sec >> 1 & 0x7;
+ ret = inst->address + 2;
+ uint32_t * regfile = inst->src.params.regs.sec & 0x10 ? aregs : dregs;
+ if (inst->src.params.regs.sec & 1) {
+ //32-bit index register
+ ret += regfile[sec_reg];
+ } else {
+ //16-bit index register
+ if (regfile[sec_reg] & 0x8000) {
+ ret += (0xFFFF0000 | regfile[sec_reg]);
+ } else {
+ ret += regfile[sec_reg];
+ }
+ }
+ ret += inst->src.params.regs.displacement;
+ break;
+ }
+ case MODE_ABSOLUTE:
+ case MODE_ABSOLUTE_SHORT:
+ ret = inst->src.params.immed;
+ break;
+ }
+ return ret;
+ }
+ return 0;
+}
+
+uint8_t m68k_is_branch(m68kinst * inst)
+{
+ return (inst->op == M68K_BCC && inst->extra.cond != COND_FALSE)
+ || (inst->op == M68K_DBCC && inst->extra.cond != COND_TRUE)
+ || inst->op == M68K_BSR || inst->op == M68K_JMP || inst->op == M68K_JSR;
+}
+
+uint8_t m68k_is_noncall_branch(m68kinst * inst)
+{
+ return m68k_is_branch(inst) && inst->op != M68K_BSR && inst->op != M68K_JSR;
+}
+
+
char * mnemonics[] = {
"abcd",
"add",
@@ -1504,7 +1577,7 @@ int m68k_disasm_ex(m68kinst * decoded, char * dst, uint8_t labels)
break;
case M68K_BSR:
if (labels) {
- ret = sprintf(dst, "bsr%s ADR_%X", decoded->variant == VAR_BYTE ? ".s" : "",
+ ret = sprintf(dst, "bsr%s ADR_%X", decoded->variant == VAR_BYTE ? ".s" : "",
decoded->address + 2 + decoded->src.params.immed);
} else {
ret = sprintf(dst, "bsr%s #%d <%X>", decoded->variant == VAR_BYTE ? ".s" : "", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
@@ -1540,9 +1613,9 @@ int m68k_disasm_ex(m68kinst * decoded, char * dst, uint8_t labels)
return ret;
default:
size = decoded->extra.size;
- ret = sprintf(dst, "%s%s%s",
- mnemonics[decoded->op],
- decoded->variant == VAR_QUICK ? "q" : (decoded->variant == VAR_IMMEDIATE ? "i" : ""),
+ ret = sprintf(dst, "%s%s%s",
+ mnemonics[decoded->op],
+ decoded->variant == VAR_QUICK ? "q" : (decoded->variant == VAR_IMMEDIATE ? "i" : ""),
size == OPSIZE_BYTE ? ".b" : (size == OPSIZE_WORD ? ".w" : (size == OPSIZE_LONG ? ".l" : "")));
}
if (decoded->op == M68K_MOVEM) {
diff --git a/68kinst.h b/68kinst.h
index 0dc5a3f..768793f 100644
--- a/68kinst.h
+++ b/68kinst.h
@@ -1,6 +1,6 @@
/*
Copyright 2013 Michael Pavone
- This file is part of BlastEm.
+ This file is part of BlastEm.
BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
*/
#ifndef M68KINST_H_
@@ -230,7 +230,9 @@ typedef enum {
} m68k_vector;
uint16_t * m68k_decode(uint16_t * istream, m68kinst * dst, uint32_t address);
-uint32_t m68k_cycles(m68kinst * inst);
+uint32_t m68k_branch_target(m68kinst * inst, uint32_t *dregs, uint32_t *aregs);
+uint8_t m68k_is_branch(m68kinst * inst);
+uint8_t m68k_is_noncall_branch(m68kinst * inst);
int m68k_disasm(m68kinst * decoded, char * dst);
int m68k_disasm_labels(m68kinst * decoded, char * dst);
diff --git a/Makefile b/Makefile
index 6e3b652..53d1e48 100644
--- a/Makefile
+++ b/Makefile
@@ -26,8 +26,8 @@ CONFIGOBJS=config.o tern.o util.o
all : dis zdis stateview vgmplay blastem
-blastem : blastem.o vdp.o render_sdl.o io.o $(CONFIGOBJS) gst.o $(M68KOBJS) $(Z80OBJS) $(TRANSOBJS) $(AUDIOOBJS)
- $(CC) -ggdb -o blastem blastem.o vdp.o render_sdl.o io.o $(CONFIGOBJS) gst.o $(M68KOBJS) $(Z80OBJS) $(TRANSOBJS) $(AUDIOOBJS) $(LDFLAGS)
+blastem : blastem.o gdb_remote.o vdp.o render_sdl.o io.o $(CONFIGOBJS) gst.o $(M68KOBJS) $(Z80OBJS) $(TRANSOBJS) $(AUDIOOBJS)
+ $(CC) -ggdb -o blastem blastem.o gdb_remote.o vdp.o render_sdl.o io.o $(CONFIGOBJS) gst.o $(M68KOBJS) $(Z80OBJS) $(TRANSOBJS) $(AUDIOOBJS) $(LDFLAGS)
dis : dis.o 68kinst.o
$(CC) -o dis dis.o 68kinst.o
diff --git a/blastem.c b/blastem.c
index e50c79b..847f777 100644
--- a/blastem.c
+++ b/blastem.c
@@ -10,6 +10,7 @@
#include "vdp.h"
#include "render.h"
#include "blastem.h"
+#include "gdb_remote.h"
#include "gst.h"
#include "util.h"
#include <stdio.h>
@@ -1410,7 +1411,7 @@ m68k_context * debugger(m68k_context * context, uint32_t address)
case 'd':
param = find_param(input_buf);
if (!param) {
- fputs("b command requires a parameter\n", stderr);
+ fputs("d command requires a parameter\n", stderr);
break;
}
value = atoi(param);
@@ -1464,16 +1465,80 @@ m68k_context * debugger(m68k_context * context, uint32_t address)
printf(format, param, value);
break;
case 'n':
- //TODO: Deal with jmp, dbcc, rtr and rte
if (inst.op == M68K_RTS) {
after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1);
- } else if(inst.op == M68K_BCC && inst.extra.cond != COND_FALSE) {
- if (inst.extra.cond = COND_TRUE) {
- after = inst.address + 2 + inst.src.params.immed;
+ } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
+ after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1);
+ } else if(m68k_is_noncall_branch(&inst)) {
+ if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
+ branch_f = after;
+ branch_t = m68k_branch_target(&inst, context->dregs, context->aregs);
+ insert_breakpoint(context, branch_t, (uint8_t *)debugger);
+ } else if(inst.op == M68K_DBCC) {
+ if ( inst.extra.cond == COND_FALSE) {
+ if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) {
+ after = m68k_branch_target(&inst, context->dregs, context->aregs);
+ }
+ } else {
+ branch_t = after;
+ branch_f = m68k_branch_target(&inst, context->dregs, context->aregs);
+ insert_breakpoint(context, branch_f, (uint8_t *)debugger);
+ }
} else {
+ after = m68k_branch_target(&inst, context->dregs, context->aregs);
+ }
+ }
+ insert_breakpoint(context, after, (uint8_t *)debugger);
+ debugging = 0;
+ break;
+ case 'o':
+ if (inst.op == M68K_RTS) {
+ after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1);
+ } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
+ after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1);
+ } else if(m68k_is_noncall_branch(&inst)) {
+ if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
+ branch_t = m68k_branch_target(&inst, context->dregs, context->aregs);
+ if (branch_t < after) {
+ branch_t = 0;
+ } else {
+ branch_f = after;
+ insert_breakpoint(context, branch_t, (uint8_t *)debugger);
+ }
+ } else if(inst.op == M68K_DBCC) {
+ uint32_t target = m68k_branch_target(&inst, context->dregs, context->aregs);
+ if (target > after) {
+ if (inst.extra.cond == COND_FALSE) {
+ after = target;
+ } else {
+ branch_f = target;
+ branch_t = after;
+ insert_breakpoint(context, branch_f, (uint8_t *)debugger);
+ }
+ }
+ } else {
+ after = m68k_branch_target(&inst, context->dregs, context->aregs);
+ }
+ }
+ insert_breakpoint(context, after, (uint8_t *)debugger);
+ debugging = 0;
+ break;
+ case 's':
+ if (inst.op == M68K_RTS) {
+ after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1);
+ } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
+ after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1);
+ } else if(m68k_is_branch(&inst)) {
+ if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
branch_f = after;
- branch_t = inst.address + 2 + inst.src.params.immed;
+ branch_t = m68k_branch_target(&inst, context->dregs, context->aregs);
insert_breakpoint(context, branch_t, (uint8_t *)debugger);
+ } else if(inst.op == M68K_DBCC && inst.extra.cond != COND_FALSE) {
+ branch_t = after;
+ branch_f = m68k_branch_target(&inst, context->dregs, context->aregs);
+ insert_breakpoint(context, branch_f, (uint8_t *)debugger);
+ } else {
+ after = m68k_branch_target(&inst, context->dregs, context->aregs);
}
}
insert_breakpoint(context, after, (uint8_t *)debugger);
@@ -1585,7 +1650,7 @@ void save_sram()
printf("Saved SRAM to %s\n", sram_filename);
}
-void init_run_cpu(genesis_context * gen, int debug, FILE * address_log, char * statefile)
+void init_run_cpu(genesis_context * gen, FILE * address_log, char * statefile, uint8_t * debugger)
{
m68k_context context;
x86_68k_options opts;
@@ -1706,15 +1771,15 @@ void init_run_cpu(genesis_context * gen, int debug, FILE * address_log, char * s
exit(1);
}
printf("Loaded %s\n", statefile);
- if (debug) {
- insert_breakpoint(&context, pc, (uint8_t *)debugger);
+ if (debugger) {
+ insert_breakpoint(&context, pc, debugger);
}
adjust_int_cycle(gen->m68k, gen->vdp);
gen->z80->native_pc = z80_get_native_address_trans(gen->z80, gen->z80->pc);
start_68k_context(&context, pc);
} else {
- if (debug) {
- insert_breakpoint(&context, address, (uint8_t *)debugger);
+ if (debugger) {
+ insert_breakpoint(&context, address, debugger);
}
m68k_reset(&context);
}
@@ -1808,6 +1873,7 @@ int main(int argc, char ** argv)
char * romfname = NULL;
FILE *address_log = NULL;
char * statefile = NULL;
+ uint8_t * debuggerfun = NULL;
uint8_t fullscreen = 0, use_gl = 1;
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
@@ -1822,7 +1888,11 @@ int main(int argc, char ** argv)
exit_after = atoi(argv[i]);
break;
case 'd':
- debug = 1;
+ debuggerfun = (uint8_t *)debugger;
+ break;
+ case 'D':
+ gdb_remote_init();
+ debuggerfun = (uint8_t *)gdb_debug_enter;
break;
case 'f':
fullscreen = 1;
@@ -1980,6 +2050,6 @@ int main(int argc, char ** argv)
}
set_keybindings();
- init_run_cpu(&gen, debug, address_log, statefile);
+ init_run_cpu(&gen, address_log, statefile, debuggerfun);
return 0;
}
diff --git a/gdb_remote.c b/gdb_remote.c
index 772a44a..31de3e2 100644
--- a/gdb_remote.c
+++ b/gdb_remote.c
@@ -3,14 +3,15 @@
This file is part of BlastEm.
BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
*/
-#include "blastem.h"
+#include "gdb_remote.h"
#include <unistd.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
-#define INITIAL_BUFFER_SIZE 4096
+#define INITIAL_BUFFER_SIZE (16*1024)
char * buf = NULL;
char * curbuf = NULL;
@@ -20,9 +21,261 @@ int cont = 0;
int expect_break_response=0;
uint32_t resume_pc;
-void gdb_debug_enter(genesis_context * gen, uint32_t pc)
+
+void hex_32(uint32_t num, char * out)
+{
+ for (int32_t shift = 28; shift >= 0; shift -= 4)
+ {
+ uint8_t nibble = num >> shift & 0xF;
+ *(out++) = nibble > 9 ? nibble - 0xA + 'A' : nibble + '0';
+ }
+}
+
+void hex_16(uint16_t num, char * out)
+{
+ for (int16_t shift = 14; shift >= 0; shift -= 4)
+ {
+ uint8_t nibble = num >> shift & 0xF;
+ *(out++) = nibble > 9 ? nibble - 0xA + 'A' : nibble + '0';
+ }
+}
+
+void hex_8(uint8_t num, char * out)
+{
+ uint8_t nibble = num >> 4;
+ *(out++) = nibble > 9 ? nibble - 0xA + 'A' : nibble + '0';
+ nibble = num & 0xF;
+ *out = nibble > 9 ? nibble - 0xA + 'A' : nibble + '0';
+}
+
+void gdb_calc_checksum(char * command, char *out)
+{
+ uint8_t checksum = 0;
+ while (*command)
+ {
+ checksum += *(command++);
+ }
+ hex_8(checksum, out);
+}
+
+void write_or_die(int fd, const void *buf, size_t count)
+{
+ if (write(fd, buf, count) < count) {
+ fputs("Error writing to stdout\n", stderr);
+ exit(1);
+ }
+}
+
+void gdb_send_command(char * command)
+{
+ char end[3];
+ write_or_die(STDOUT_FILENO, "$", 1);
+ write_or_die(STDOUT_FILENO, command, strlen(command));
+ end[0] = '#';
+ gdb_calc_checksum(command, end+1);
+ write_or_die(STDOUT_FILENO, end, 3);
+ fprintf(stderr, "Sent $%s#%c%c\n", command, end[1], end[2]);
+}
+
+uint32_t calc_status(m68k_context * context)
+{
+ uint32_t status = context->status << 3;
+ for (int i = 0; i < 5; i++)
+ {
+ status <<= 1;
+ status |= context->flags[i];
+ }
+ return status;
+}
+
+uint8_t read_byte(m68k_context * context, uint32_t address)
+{
+ uint16_t * word;
+ //TODO: Use generated read/write functions so that memory map is properly respected
+ if (address < 0x400000) {
+ word = context->mem_pointers[0] + address/2;
+ } else if (address >= 0xE00000) {
+ word = context->mem_pointers[1] + (address & 0xFFFF)/2;
+ } else {
+ return 0;
+ }
+ if (address & 1) {
+ return *word;
+ }
+ return *word >> 8;
+}
+
+void gdb_run_command(m68k_context * context, uint32_t pc, char * command)
{
- fcntl(STDIN_FILENO, FD_SETFL, 0);
+ char send_buf[512];
+ fprintf(stderr, "Received command %s\n", command);
+ switch(*command)
+ {
+
+ case 'c':
+ if (*(command+1) != 0) {
+ //TODO: implement resuming at an arbitrary address
+ goto not_impl;
+ }
+ cont = 1;
+ expect_break_response = 1;
+ break;
+ case 'H':
+ if (command[1] == 'g' || command[1] == 'c') {;
+ //no thread suport, just acknowledge
+ gdb_send_command("OK");
+ } else {
+ goto not_impl;
+ }
+ break;
+ case 'Z': {
+ uint8_t type = command[1];
+ if (type < '2') {
+ uint32_t address = strtoul(command+3, NULL, 16);
+ insert_breakpoint(context, address, (uint8_t *)gdb_debug_enter);
+ gdb_send_command("OK");
+ } else {
+ //watchpoints are not currently supported
+ gdb_send_command("");
+ }
+ break;
+ }
+ case 'z': {
+ uint8_t type = command[1];
+ if (type < '2') {
+ uint32_t address = strtoul(command+3, NULL, 16);
+ remove_breakpoint(context, address);
+ gdb_send_command("OK");
+ } else {
+ //watchpoints are not currently supported
+ gdb_send_command("");
+ }
+ break;
+ }
+ case 'g': {
+ char * cur = send_buf;
+ for (int i = 0; i < 8; i++)
+ {
+ hex_32(context->dregs[i], cur);
+ cur += 8;
+ }
+ for (int i = 0; i < 8; i++)
+ {
+ hex_32(context->aregs[i], cur);
+ cur += 8;
+ }
+ hex_32(calc_status(context), cur);
+ cur += 8;
+ hex_32(pc, cur);
+ cur += 8;
+ *cur = 0;
+ gdb_send_command(send_buf);
+ break;
+ }
+ case 'm': {
+ char * rest;
+ uint32_t address = strtoul(command+1, &rest, 16);
+ uint32_t size = strtoul(rest+1, NULL, 16);
+ if (size > sizeof(send_buf-1)/2) {
+ size = sizeof(send_buf-1)/2;
+ }
+ char *cur = send_buf;
+ while (size)
+ {
+ hex_8(read_byte(context, address), cur);
+ cur += 2;
+ address++;
+ size--;
+ }
+ *cur = 0;
+ gdb_send_command(send_buf);
+ break;
+ }
+ case 'p': {
+ unsigned long reg = strtoul(command+1, NULL, 16);
+
+ if (reg < 8) {
+ hex_32(context->dregs[reg], send_buf);
+ } else if (reg < 16) {
+ hex_32(context->aregs[reg-8], send_buf);
+ } else if (reg == 16) {
+ hex_32(calc_status(context), send_buf);
+ } else if (reg == 17) {
+ hex_32(pc, send_buf);
+ } else {
+ send_buf[0] = 0;
+ }
+ send_buf[8] = 0;
+ gdb_send_command(send_buf);
+ break;
+ }
+ case 'q':
+ if (!memcmp("Supported", command+1, strlen("Supported"))) {
+ sprintf(send_buf, "PacketSize=%X", (int)bufsize);
+ gdb_send_command(send_buf);
+ } else if (!memcmp("Attached", command+1, strlen("Supported"))) {
+ //not really meaningful for us, but saying we spawned a new process
+ //is probably closest to the truth
+ gdb_send_command("0");
+ } else if (!memcmp("Offsets", command+1, strlen("Offsets"))) {
+ //no relocations, so offsets are all 0
+ gdb_send_command("Text=0;Data=0;Bss=0");
+ } else if (!memcmp("Symbol", command+1, strlen("Symbol"))) {
+ gdb_send_command("");
+ } else if (!memcmp("TStatus", command+1, strlen("TStatus"))) {
+ //TODO: actual tracepoint support
+ gdb_send_command("T0;tnotrun:0");
+ } else if (!memcmp("TfV", command+1, strlen("TfV")) || !memcmp("TfP", command+1, strlen("TfP"))) {
+ //TODO: actual tracepoint support
+ gdb_send_command("");
+ } else if (command[1] == 'C') {
+ //we only support a single thread currently, so send 1
+ gdb_send_command("1");
+ } else {
+ goto not_impl;
+ }
+ break;
+ case 'v':
+ if (!memcmp("Cont?", command+1, strlen("Cont?"))) {
+ gdb_send_command("vCont;c;C;s;S");
+ } else if (!memcmp("Cont;", command+1, strlen("Cont;"))) {
+ switch (*(command + 1 + strlen("Cont;")))
+ {
+ case 'c':
+ case 'C':
+ //might be interesting to have continue with signal fire a
+ //trap exception or something, but for no we'll treat it as
+ //a normal continue
+ cont = 1;
+ expect_break_response = 1;
+ break;
+ default:
+ goto not_impl;
+ }
+ } else {
+ goto not_impl;
+ }
+ break;
+ case '?':
+ gdb_send_command("S05");
+ break;
+ default:
+ goto not_impl;
+
+ }
+ return;
+not_impl:
+ fprintf(stderr, "Command %s is not implemented, exiting...\n", command);
+ exit(1);
+}
+
+m68k_context * gdb_debug_enter(m68k_context * context, uint32_t pc)
+{
+ fprintf(stderr, "Entered debugger at address %X\n", pc);
+ if (expect_break_response) {
+ gdb_send_command("S05");
+ expect_break_response = 0;
+ }
resume_pc = pc;
cont = 0;
uint8_t partial = 0;
@@ -35,7 +288,7 @@ void gdb_debug_enter(genesis_context * gen, uint32_t pc)
} else if (partial) {
if (curbuf != buf) {
memmove(curbuf, buf, end-curbuf);
- end -= cufbuf - buf;
+ end -= curbuf - buf;
}
int numread = read(STDIN_FILENO, end, bufsize - (end-buf));
end += numread;
@@ -55,10 +308,13 @@ void gdb_debug_enter(genesis_context * gen, uint32_t pc)
if (end-curbuf >= 2) {
//TODO: verify checksum
//Null terminate payload
- *curbuf = 0
+ *curbuf = 0;
//send acknowledgement
- write(FILENO_STDOUT, "+", 1);
- gdb_run_command(genesis_context * gen, start);
+ if (write(STDOUT_FILENO, "+", 1) < 1) {
+ fputs("Error writing to stdout\n", stderr);
+ exit(1);
+ }
+ gdb_run_command(context, pc, start);
curbuf += 2;
}
} else {
@@ -66,115 +322,20 @@ void gdb_debug_enter(genesis_context * gen, uint32_t pc)
partial = 1;
break;
}
- }
- }
- }
- fcntl(STDIN_FILENO, FD_SETFL, O_NONBLOCK);
-}
-
-void gdb_run_command(genesis_context * gen, char * command)
-{
- switch(*command)
- {
- case 'c':
- if (*(command+1) != 0) {
- resume_pc =
- }
- cont = 1;
- expect_break_response = 1;
- break;
- case 's':
-
- }
-}
-
-void gdb_run_commands(genesis_context * gen)
-{
- int enter_debugger = 0;
- char * cur = buf;
- while(cur < curbuf);
- {
- if(*cur == '$') {
- cur++
- char * start = cur;
- while (cur < curbuf && *cur != '#') {
- cur++;
- }
- if (*cur == '#') {
- //check to make sure we've received the checksum bytes
- if (curbuf-cur >= 2) {
- //TODO: verify checksum
- //Null terminate payload
- //send acknowledgement
- write(FILENO_STDOUT, "+", 1);
- gdb_run_command(genesis_context * gen, start);
- cur += 2;
- } else {
- cur = start - 1;
- break;
- }
- } else {
- cur = start - 1;
- break;
- }
- } else {
- if (*cur == 0x03) {
- enter_debugger = 1;
- }
- cur++;
- }
- }
-
- //FIXME
- if (consumed == curbuf-buf) {
- curbuf = buf;
- } else if (consumed > 0) {
- memmove(buf, buf + consumed, curbuf - buf - consumed);
- curbuf -= consumed;
- }
-}
-
-int gdb_command_poll(genesis_context * gen)
-{
- for(;;)
- {
- if (curbuf == buf + bufsize) {
- //buffer is full, expand it
- bufsize *= 2;
- buf = realloc(buf, bufsize);
- if (!buf) {
- fprintf(stderr, "Failed to grow GDB command buffer to %d bytes\n", (int)bufsize);
- exit(1);
- }
- curbuf = buf + bufsize/2;
- }
- int numread = read(STDIN_FILENO, buf, bufsize);
- if (numread < 0) {
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- return 0;
} else {
- fprintf(stderr, "Error %d while reading GDB commands from stdin", errno);
- exit(1);
+ fprintf(stderr, "Ignoring character %c\n", *curbuf);
}
- } else if (numread == 0) {
- exit(0);
}
- for (curbuf = buf, end = buf+numread; curbuf < end; curbuf++)
- {
- if (*curbuf = 0x03)
- {
- curbuf++;
- return 1;
- }
+ if (curbuf == end) {
+ curbuf = NULL;
}
}
- return 0;
+ return context;
}
-void gdb_remote_init()
+void gdb_remote_init(void)
{
- fcntl(STDIN_FILENO, FD_SETFL, O_NONBLOCK);
buf = malloc(INITIAL_BUFFER_SIZE);
- curbuf = buf;
- bufzie = INITIAL_BUFFER_SIZE;
+ curbuf = NULL;
+ bufsize = INITIAL_BUFFER_SIZE;
}
diff --git a/m68k_to_x86.c b/m68k_to_x86.c
index 219d4c9..4a6f7fb 100644
--- a/m68k_to_x86.c
+++ b/m68k_to_x86.c
@@ -1953,6 +1953,7 @@ uint8_t * translate_m68k_jmp(uint8_t * dst, m68kinst * inst, x86_68k_options * o
}
sec_reg = (inst->src.params.regs.sec >> 1) & 0x7;
if (inst->src.params.regs.sec & 1) {
+ //32-bit index register
if (inst->src.params.regs.sec & 0x10) {
if (opts->aregs[sec_reg] >= 0) {
dst = add_rr(dst, opts->aregs[sec_reg], SCRATCH1, SZ_D);
@@ -1967,6 +1968,7 @@ uint8_t * translate_m68k_jmp(uint8_t * dst, m68kinst * inst, x86_68k_options * o
}
}
} else {
+ //16-bit index register
if (inst->src.params.regs.sec & 0x10) {
if (opts->aregs[sec_reg] >= 0) {
dst = movsx_rr(dst, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D);
diff --git a/vdp.c b/vdp.c
index 103ed63..5cf5797 100644
--- a/vdp.c
+++ b/vdp.c
@@ -197,7 +197,7 @@ void vdp_print_sprite_table(vdp_context * context)
uint8_t pal = context->vdpmem[address + 4] >> 5 & 0x3;
uint8_t pri = context->vdpmem[address + 4] >> 7;
uint16_t pattern = ((context->vdpmem[address + 4] << 8 | context->vdpmem[address + 5]) & 0x7FF) << 5;
- //printf("Sprite %d: X=%d(%d), Y=%d(%d), Width=%u, Height=%u, Link=%u, Pal=%u, Pri=%u, Pat=%X\n", current_index, x, x-128, y, y-128, width, height, link, pal, pri, pattern);
+ printf("Sprite %d: X=%d(%d), Y=%d(%d), Width=%u, Height=%u, Link=%u, Pal=%u, Pri=%u, Pat=%X\n", current_index, x, x-128, y, y-128, width, height, link, pal, pri, pattern);
current_index = link;
count++;
} while (current_index != 0 && count < 80);