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