--- /dev/null
+/*
+ * 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
--- /dev/null
+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
--- /dev/null
+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:"
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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");
+}
+
--- /dev/null
+/*
+ * 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);