diff options
| -rw-r--r-- | lib/cp-usb.h | 36 | ||||
| -rw-r--r-- | s51/Makefile.am | 10 | ||||
| -rw-r--r-- | s51/commands | 61 | ||||
| -rw-r--r-- | s51/s51-command.c | 171 | ||||
| -rw-r--r-- | s51/s51-main.c | 143 | ||||
| -rw-r--r-- | s51/s51-parse.c | 232 | ||||
| -rw-r--r-- | s51/s51.h | 78 | 
7 files changed, 731 insertions, 0 deletions
diff --git a/lib/cp-usb.h b/lib/cp-usb.h new file mode 100644 index 00000000..3e5f25ff --- /dev/null +++ b/lib/cp-usb.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _CP_USB_H_ +#define _CP_USB_H_ +#include <usb.h> + +struct cp_usb * +cp_usb_open(void); + +void +cp_usb_close(struct cp_usb *cp); + +void +cp_usb_write(struct cp_usb *cp, uint8_t mask, uint8_t value); + +uint8_t +cp_usb_read(struct cp_usb *cp); + + +#endif diff --git a/s51/Makefile.am b/s51/Makefile.am new file mode 100644 index 00000000..cfa183d4 --- /dev/null +++ b/s51/Makefile.am @@ -0,0 +1,10 @@ +bin_PROGRAMS=s51 + +AM_CFLAGS=-I$(top_srcdir)/lib +S51_LIBS=../lib/libcc.a + +s51_DEPENDENCIES = $(S51_LIBS) + +s51_LDADD=$(S51_LIBS) $(USB_LIBS) + +s51_SOURCES = s51-parse.c s51-command.c s51-main.c diff --git a/s51/commands b/s51/commands new file mode 100644 index 00000000..77a98493 --- /dev/null +++ b/s51/commands @@ -0,0 +1,61 @@ +Listens on port 9756 for a command stream. + +Dump commands: +	di <start> <end> 	- dump imem +	ds <start> <end>	- dump sprs +	dx <start> <end>	- dump xaddr + +	Returns a string of hex pairs, each preceded by a space, +	with 8 pairs per line + +Memory access commands: +	set mem <prefix> <start> <end> +	dump <prefix> <start> <end> + +	<prefix> is one of: + +		xram	- external ram or external stack +		rom	- code space +		iram	- internal ram or stack +		sfr	- special function register + + +	dump <addr> +	set bit <addr> + +		bit addressable space + +Set PC: + +	pc <addr> + +	Sets PC to specified address + +	pc + +	Returns current PC + +Breakpoints + +	break <addr> +	clear <addr> + +Load a file + +	file "<filename>" + +Execution control: + +	run <start>		- run starting at <start> +	run <start> <stop>	- set temporary bp at <stop>  +	run			- continue +	next			- step over calls(?) +	step			- step one instruction +	 +	reset			- reset the simulator +	res			- synonym? +	 +Error messages: + +	start with "Error:" +	 diff --git a/s51/s51-command.c b/s51/s51-command.c new file mode 100644 index 00000000..8a5d4c08 --- /dev/null +++ b/s51/s51-command.c @@ -0,0 +1,171 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "s51.h" + +static enum command_result +parse_int(char *value, int *result) +{ +	char *endptr; + +	*result = strtol(value, &endptr, 0); +	if (endptr == value) +		return command_syntax; +	return command_proceed; +} + +static enum command_result +parse_uint16(char *value, uint16_t *uint16) +{ +	int	v; +	enum command_result result; + +	result = parse_int(value, &v); +	if (result != command_proceed) +		return command_error; +	if (v < 0 || v > 0xffff) +		return command_error; +	*uint16 = v; +	return command_proceed; +} + +enum command_result +command_quit (FILE *output, int argc, char **argv) +{ +	exit(0); +	return command_error; +} + +enum command_result +command_di (FILE *output, int argc, char **argv) +{ +	return command_error; +} + +enum command_result +command_ds (FILE *output, int argc, char **argv) +{ +	return command_error; +} + +enum command_result +command_dx (FILE *output, int argc, char **argv) +{ +	return command_error; +} + +enum command_result +command_set (FILE *output, int argc, char **argv) +{ +	return command_error; +} + +enum command_result +command_dump (FILE *output, int argc, char **argv) +{ +	return command_error; +} + +enum command_result +command_pc (FILE *output, int argc, char **argv) +{ +	uint16_t	pc; +	if (argv[1]) { +		enum command_result result; + +		result = parse_uint16(argv[1], &pc); +		if (result != command_proceed) +			return result; +		ccdbg_set_pc(s51_dbg, pc); +	} else { +		pc = ccdbg_get_pc(s51_dbg); +		printf (" 0x%04x\n", pc); +	} +	return command_proceed; +} + +enum command_result +command_break (FILE *output, int argc, char **argv) +{ +	return command_error; +} + +enum command_result +command_clear (FILE *output, int argc, char **argv) +{ +	return command_error; +} + +enum command_result +command_run (FILE *output, int argc, char **argv) +{ +	uint16_t start, end; +	enum command_result result; +	 +	if (argv[1]) { +		result = parse_uint16(argv[1], &start); +		if (result != command_proceed) +			return result; +		if (argv[2]) { +			result = parse_uint16(argv[2], &end); +			if (result != command_proceed) +				return result; +		} +		ccdbg_set_pc(s51_dbg, start); +	} +	else +		start = ccdbg_get_pc(s51_dbg); +	fprintf(output, "Resume at 0x%04x\n", start); +	ccdbg_resume(s51_dbg); +	return command_proceed; +} + +enum command_result +command_next (FILE *output, int argc, char **argv) +{ +	return command_error; +} + +enum command_result +command_step (FILE *output, int argc, char **argv) +{ +	return command_error; +} + +enum command_result +command_load (FILE *output, int argc, char **argv) +{ +	return command_error; +} + +enum command_result +command_halt (FILE *output, int argc, char **argv) +{ +	uint16_t	pc; +	ccdbg_halt(s51_dbg); +	pc = ccdbg_get_pc(s51_dbg); +	fprintf(output, "Halted at 0x%04x\n", pc); +	return command_proceed; +} + +enum command_result +command_reset (FILE *output, int argc, char **argv) +{ +	ccdbg_debug_mode(s51_dbg); +	return command_proceed; +} diff --git a/s51/s51-main.c b/s51/s51-main.c new file mode 100644 index 00000000..e8bf2d7d --- /dev/null +++ b/s51/s51-main.c @@ -0,0 +1,143 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "s51.h" +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> + +static int s51_port = 0; +static char *cpu = "8051"; +static double freq = 11059200; +char *s51_prompt = "> "; +struct ccdbg *s51_dbg; + +static void +usage(void) +{ +	fprintf(stderr, "You're doing it wrong.\n"); +	exit(1); +} + +int +main(int argc, char **argv) +{ +	int flags, opt; +	FILE *console_in = stdin; +	FILE *console_out = stdout; +	char *endptr; + +	while ((opt = getopt(argc, argv, "PVvHht:X:c:Z:s:S:p:")) != -1) { +		switch (opt) { +		case 't': +			cpu = optarg; +			break; +		case 'X': +			freq = strtod(optarg, &endptr); +			if (endptr == optarg) +				usage(); +			if (endptr[0] != '\0') { +				if (!strcmp(endptr, "k")) +					freq *= 1000; +				else if (!strcmp(endptr, "M") ) +					freq *= 1000000; +				else +					usage (); +			} +			break; +		case 'c': +			break; +		case 'Z': +			s51_port = strtol(optarg, &endptr, 0); +			if (endptr == optarg || strlen(endptr) != 0) +				usage(); +			break; +		case 's': +			break; +		case 'S': +			break; +		case 'p': +			s51_prompt = optarg; +			break; +		case 'P': +			s51_prompt = NULL; +			break; +		case 'V': +			break; +		case 'v': +			break; +		case 'H': +			exit (0); +			break; +		case 'h': +			usage (); +			break; +		} +	} +	if (s51_port) { +		int l, r, one = 1; +		int s; +		struct sockaddr_in in; + +		l = socket(AF_INET, SOCK_STREAM, 0); +		if (l < 0) { +			perror ("socket"); +			exit(1); +		} +		in.sin_family = AF_INET; +		in.sin_port = htons(s51_port); +		in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +		r = bind(l, (struct sockaddr *) &in, sizeof (in)); +		if (r) { +			perror("bind"); +			exit(1); +		} +		r = setsockopt(l, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (int)); +		if (r) { +			perror("setsockopt"); +			exit(1); +		} +		r = listen(l, 5); +		if (r) { +			perror("listen"); +			exit(1); +		} +		for (;;) { +			struct sockaddr_in client_addr; +			socklen_t client_len = sizeof (struct sockaddr_in); +			FILE *client; +			 +			s = accept(r, (struct sockaddr *) +				   &client_addr, &client_len); +			if (s < 0) { +				perror("accept"); +				exit(1); +			} +			client = fdopen(s, "rw"); +			if (!client) { +				perror("fdopen"); +				exit(1); +			} +			command_read(client, client); +			fclose(client); +		} +	} else +		command_read(console_in, console_out); +	exit(0); +} diff --git a/s51/s51-parse.c b/s51/s51-parse.c new file mode 100644 index 00000000..ba0d611c --- /dev/null +++ b/s51/s51-parse.c @@ -0,0 +1,232 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "s51.h" + +struct command_function { +	char			*name; +	char			*alias; +	enum command_result	(*func)(FILE *output, int argc, char **argv); +	char			*usage; +	char			*help; +}; + +static struct command_function functions[] = { +	{ "help",   "?",  command_help,	"help",		"Print this list\n" }, +	{ "quit",   "q",  command_quit,	"[q]uit",	"Quit\n" }, +	{ "di",	    "di", command_di,	"di <start> <end>", +		"Dump imem\n" }, +	{ "ds",	    "ds", command_ds,	"ds <start> <end>", +		"Dump sprs\n" }, +	{ "dx",	    "dx", command_dx,	"dx <start> <end>", +		"Dump xaddr\n" }, +	{ "set",    "t",  command_set,	"se[t] mem <prefix> <start> <end>", +		"Set mem {xram|rom|iram|sfr} <start> <end>\n" +		"set bit <addr>\n" }, +	{ "dump",   "d",  command_dump,	"[d]ump <prefix> <start> <end>", +		"Dump {xram|rom|iram|sfr} <start> <end>\n" }, +	{ "pc",	    "p",  command_pc, "[p]c [addr]", +		"Get or set pc value\n" }, +	{ "break",  "b",  command_break,"[b]reak <addr>", +		"Set break point\n" }, +	{ "clear",  "c",  command_clear,"[c]lear <addr>", +		"Clear break point\n" }, +	{ "run",    "r",  command_run, "[r]un [start] [stop]", +		"Run with optional start and temp breakpoint addresses\n" }, +	{ "next",   "n",  command_next, "[n]ext", +		"Step over one instruction, past any call\n" }, +	{ "step",   "s",  command_step, "[s]tep", +		"Single step\n" }, +	{ "load",   "l",  command_load, "[l]oad <file>", +		"Load a hex file into memory or flash" }, +	{ "halt",   "h",  command_halt, "[h]alt", +		"Halt the processor\n" }, +	{ "reset","res",command_reset,	"[res]et", +		"Reset the CPU\n" }, +}; + +#define NUM_FUNCTIONS (sizeof functions / sizeof functions[0]) + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +static int +string_to_int(char *s, int *v) +{ +	char *endptr; + +	if (isdigit(s[0]) || s[0] == '-' || s[0] == '+') { +		*v = strtol(s, &endptr, 0); +		if (endptr == s) +			return FALSE; +	} else if (*s == '\'') { +		s++; +		if (*s == '\\') { +			s++; +			switch (*s) { +			case 'n': +				*v = '\n'; +				break; +			case 't': +				*v = '\t'; +				break; +			default: +				*v = (int) *s; +				break; +			} +		} else +			*v = (int) *s; +		s++; +		if (*s != '\'') +			return FALSE; +	} +	else +		return FALSE; +    return TRUE; +} + +static struct command_function * +command_string_to_function(char *name) +{ +	int i; +	for (i = 0; i < NUM_FUNCTIONS; i++) +		if (!strcmp(name, functions[i].name) || +		    !strcmp(name, functions[i].alias)) +			return &functions[i]; +	return NULL; +}     + +static int +command_split_into_words(char *line, char **argv) +{ +	char quotechar; +	int argc; + +	argc = 0; +	while (*line) { +		while (isspace(*line)) +			line++; +		if (!*line) +			break; +		if (*line == '"') { +			quotechar = *line++; +			*argv++ = line; +			argc++; +			while (*line && *line != quotechar) +				line++; +			if (*line) +				*line++ = '\0'; +		} else { +			*argv++ = line; +			argc++; +			while (*line && !isspace(*line)) +				line++; +			if (*line) +				*line++ = '\0'; +		} +	} +	*argv = 0; +	return argc; +} + +enum command_result +command_help(FILE *output, int argc, char **argv) +{ +	int i; +	struct command_function *func; + +	if (argc == 1) { +		for (i = 0; i < NUM_FUNCTIONS; i++) +			fprintf(output, "%-10s%s\n", functions[i].name, +			       functions[i].usage); +	} else { +		for (i = 1; i < argc; i++) { +			func = command_string_to_function(argv[i]); +			if (!func) { +				fprintf(output, "%-10s unknown command\n", argv[i]); +				return command_syntax; +			} +			fprintf(output, "%-10s %s\n%s", func->name, +			       func->usage, func->help); +		} +	} +	return command_debug; +} +     +static void +command_syntax_error(FILE *output, int argc, char **argv) +{ +	fprintf(output, "Syntax error in:"); +	while (*argv) +		fprintf(output, " %s", *argv++); +	fprintf(output, "\n"); +} + +void +command_read (FILE *input, FILE *output) +{ +	int argc; +	char line[1024]; +	char *argv[20]; +	enum command_result result; +	struct command_function *func; + +	s51_dbg = ccdbg_open (); +	if (!s51_dbg) { +		perror("ccdbg_open"); +		exit(1); +	} +	ccdbg_debug_mode(s51_dbg); +	fprintf(output, "Welcome to the non-simulated processor\n"); +	for (;;) { +		if (s51_prompt) +			fprintf(output, "%s", s51_prompt); +		else +			putc('\0', output); +		fflush(output); +		if (!fgets (line, sizeof line, input)) +			break; +		argc = command_split_into_words(line, argv); +		if (argc > 0) { +			func = command_string_to_function(argv[0]); +			if (!func) +				command_syntax_error(output, argc, argv); +			else +			{ +				result = (*func->func)(output, argc, argv); +				switch (result) { +				case command_syntax: +					command_syntax_error(output, argc, argv); +					break; +				case command_error: +					fprintf(output, "Error\n"); +					break; +				case command_proceed: +					break; +				default: +					break; +				} +			} +		} +	} +	ccdbg_close(s51_dbg); +	fprintf(output, "...\n"); +} + diff --git a/s51/s51.h b/s51/s51.h new file mode 100644 index 00000000..b916acb6 --- /dev/null +++ b/s51/s51.h @@ -0,0 +1,78 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ccdbg.h> + +extern char *s51_prompt; + +extern struct ccdbg *s51_dbg; + +enum command_result { +	command_proceed, command_debug, command_syntax, command_error +}; + +enum command_result +command_quit (FILE *output, int argc, char **argv); + +enum command_result +command_help (FILE *output, int argc, char **argv); + +enum command_result +command_di (FILE *output, int argc, char **argv); + +enum command_result +command_ds (FILE *output, int argc, char **argv); + +enum command_result +command_dx (FILE *output, int argc, char **argv); + +enum command_result +command_set (FILE *output, int argc, char **argv); + +enum command_result +command_dump (FILE *output, int argc, char **argv); + +enum command_result +command_pc (FILE *output, int argc, char **argv); + +enum command_result +command_break (FILE *output, int argc, char **argv); + +enum command_result +command_clear (FILE *output, int argc, char **argv); + +enum command_result +command_run (FILE *output, int argc, char **argv); + +enum command_result +command_next (FILE *output, int argc, char **argv); + +enum command_result +command_step (FILE *output, int argc, char **argv); + +enum command_result +command_load (FILE *output, int argc, char **argv); + +enum command_result +command_halt (FILE *output, int argc, char **argv); + +enum command_result +command_reset (FILE *output, int argc, char **argv); + +void +command_read (FILE *input, FILE *output);  | 
