]> cloudbase.mooo.com Git - z180-stamp.git/commitdiff
Merge tag 'fatfs-0.10b'
authorLeo C <erbl259-lmu@yahoo.de>
Tue, 19 Aug 2014 13:35:51 +0000 (15:35 +0200)
committerLeo C <erbl259-lmu@yahoo.de>
Tue, 19 Aug 2014 13:35:51 +0000 (15:35 +0200)
64 files changed:
.gitignore [new file with mode: 0644]
.gitmodules [new file with mode: 0644]
Tupfile.ini [new file with mode: 0644]
Tuprules.tup [new file with mode: 0644]
avr/Tupfile [new file with mode: 0644]
avr/background.c [new file with mode: 0644]
avr/background.h [new file with mode: 0644]
avr/cli.c [new file with mode: 0644]
avr/cli.h [new file with mode: 0644]
avr/cli_readline.c [new file with mode: 0644]
avr/cli_readline.h [new file with mode: 0644]
avr/cmd_boot.c [new file with mode: 0644]
avr/cmd_echo.c [new file with mode: 0644]
avr/cmd_help.c [new file with mode: 0644]
avr/cmd_mem.c [new file with mode: 0644]
avr/cmd_mem.h [new file with mode: 0644]
avr/command.c [new file with mode: 0644]
avr/command.h [new file with mode: 0644]
avr/command_tbl.c [new file with mode: 0644]
avr/common.h [new file with mode: 0644]
avr/con-utils.c [new file with mode: 0644]
avr/con-utils.h [new file with mode: 0644]
avr/config.h [new file with mode: 0644]
avr/crc.h [new file with mode: 0644]
avr/debug.c [new file with mode: 0644]
avr/debug.h [new file with mode: 0644]
avr/env.c [new file with mode: 0644]
avr/env.h [new file with mode: 0644]
avr/main.c [new file with mode: 0644]
avr/ring.h [new file with mode: 0644]
avr/serial.c [new file with mode: 0644]
avr/serial.h [new file with mode: 0644]
avr/timer.c [new file with mode: 0644]
avr/timer.h [new file with mode: 0644]
avr/xmalloc.c [new file with mode: 0644]
avr/xmalloc.h [new file with mode: 0644]
avr/z180-serv.c [new file with mode: 0644]
avr/z180-stamp-avr.c [new file with mode: 0644]
avr/z80-if.c [new file with mode: 0644]
avr/z80-if.h [new file with mode: 0644]
configs/debug.config [new file with mode: 0644]
configs/default.config [new file with mode: 0644]
configs/gcc.tup [new file with mode: 0644]
libopencm3 [new submodule]
stm32/Tupfile [new file with mode: 0644]
stm32/debug.h [new file with mode: 0644]
stm32/serial.c [new file with mode: 0644]
stm32/serial.h [new file with mode: 0644]
stm32/stm32vl-discovery.ld [new file with mode: 0644]
stm32/z180-stamp-stm32.c [new file with mode: 0644]
stm32/z80-if.c [new file with mode: 0644]
stm32/z80-if.h [new file with mode: 0644]
z180/Makefile [new file with mode: 0644]
z180/Tupfile [new file with mode: 0644]
z180/config.inc [new file with mode: 0644]
z180/console.180 [new file with mode: 0644]
z180/ddtz.180 [new file with mode: 0644]
z180/fifoio.180 [new file with mode: 0644]
z180/msgbuf.180 [new file with mode: 0644]
z180/r3init.180 [new file with mode: 0644]
z180/romend.180 [new file with mode: 0644]
z180/ser1-i.180 [new file with mode: 0644]
z180/z180.lib [new file with mode: 0644]
z180/z180reg.inc [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..1dc5864
--- /dev/null
@@ -0,0 +1,10 @@
+#Makefiledev
+/.cproject
+/.project
+/.settings
+/.tup
+/build-debug
+/doc
+/joe
+/scratch
+
diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..6bccd68
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule "libopencm3"]
+       path = libopencm3
+       url = https://github.com/libopencm3/libopencm3
diff --git a/Tupfile.ini b/Tupfile.ini
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Tuprules.tup b/Tuprules.tup
new file mode 100644 (file)
index 0000000..185c6bf
--- /dev/null
@@ -0,0 +1,3 @@
+.gitignore
+TOP = $(TUP_CWD)
+
diff --git a/avr/Tupfile b/avr/Tupfile
new file mode 100644 (file)
index 0000000..199b86c
--- /dev/null
@@ -0,0 +1,70 @@
+include_rules
+
+PROG           = stamp-test
+SRC            = main.c
+SRC            += cli.c cli_readline.c command.c command_tbl.c
+SRC            += cmd_help.c cmd_echo.c cmd_mem.c cmd_boot.c
+SRC            += env.c xmalloc.c
+SRC            += timer.c con-utils.c serial.c
+SRC            += background.c z180-serv.c z80-if.c
+
+SRC_Z          = ../z180/hdrom.c
+
+#TARGETS       = $(PROG).elf
+
+MCU_TARGET     = atmega1281
+F_CPU          = 18432000UL
+DEFS           = -DF_CPU=$(F_CPU) -DBAUD=115200UL
+
+#INCLUDES += ../z180
+
+###############################################################################
+
+TOOLCHAINDIR   = 
+TOOLCHAIN      = avr
+
+CC     = $(TOOLCHAIN)-gcc
+LD     = $(TOOLCHAIN)-gcc
+AR     = $(TOOLCHAIN)-ar
+AS     = $(TOOLCHAIN)-as
+OBJCOPY        = $(TOOLCHAIN)-objcopy
+OBJDUMP        = $(TOOLCHAIN)-objdump
+SIZE   = $(TOOLCHAIN)-size
+GDB    = $(TOOLCHAIN)-gdb
+
+###############################################################################
+
+ifdef DEBUG
+SRC    += debug.c
+DEFS   += -DDEBUG=2
+endif
+
+CFLAGS = -g -Os
+CFLAGS += -mmcu=$(MCU_TARGET)
+CFLAGS += -std=gnu99
+CFLAGS += -Wall -Wextra
+CFLAGS += -Wredundant-decls 
+#CFLAGS        += -fno-common -ffunction-sections -fdata-sections
+#CFLAGS        += -I $(INCLUDES)
+
+CPPFLAGS += $(DEFS)
+
+# Linker flags
+LDFLAGS        += -Wl,--gc-sections
+LDFLAGS        += -Wl,--cref
+
+
+!cc = |> ^ CC %f^ $(CC) $(CFLAGS) $(CPPFLAGS) -c %f -o %o |> %B.o
+!LINK = |> ^ LINK %o^ $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-Map=%O.map %f $(LDLIBS) -o %o |> | %O.map
+!OBJCOPY= |> ^ OBJCOPY %o^ $(OBJCOPY) -Oihex %f %o |>
+!OBJDUMP= |> ^ OBJDUMP %o^ $(OBJDUMP) -h -S %f > %o |> %O.lss
+!SIZE = |> ^ SIZE^ $(SIZE) %f |> 
+
+: foreach $(SRC) | ../z180/hdrom.h |> !cc |>  {objs}
+: $(SRC_Z) |> !cc -D'const=const __flash' |> {objs}
+
+: {objs} |> !LINK |> $(PROG).elf
+: $(PROG).elf |> !OBJCOPY |> %B.hex
+: $(PROG).elf |> !OBJDUMP |> %B.lss
+: $(PROG).elf |> !SIZE |>
+
diff --git a/avr/background.c b/avr/background.c
new file mode 100644 (file)
index 0000000..37e4b02
--- /dev/null
@@ -0,0 +1,31 @@
+#include "common.h"
+#include "background.h"
+
+
+#define BG_FUNC_MAX 5
+
+static bg_func func_tab[BG_FUNC_MAX];
+static int_fast8_t fcount;
+
+int bg_register(bg_func f)
+{
+       if (fcount < BG_FUNC_MAX) { 
+               func_tab[fcount++] = f;
+               return 1;
+       }
+       return 0;
+}
+
+
+void bg_shed(void)
+{
+       static int_fast8_t current;
+       
+       if (func_tab[current]) {
+               func_tab[current](0);
+       }
+       if (++current >= fcount)
+               current = 0;
+}
+
+
diff --git a/avr/background.h b/avr/background.h
new file mode 100644 (file)
index 0000000..a624dbb
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef BACKGROUND_H
+#define BACKGROUND_H
+
+typedef int (*bg_func)(int);
+
+int bg_register(bg_func f);
+void bg_shed(void);
+
+#endif /* BACKGROUND_H */
+
diff --git a/avr/cli.c b/avr/cli.c
new file mode 100644 (file)
index 0000000..4b77499
--- /dev/null
+++ b/avr/cli.c
@@ -0,0 +1,356 @@
+#include "common.h"
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "config.h"
+#include "command.h"
+#include "xmalloc.h"
+#include "debug.h"
+#include "env.h"
+#include "cli_readline.h"
+#include "con-utils.h"
+#include "cli.h"
+
+#define DEBUG_PARSER   0       /* set to 1 to debug */
+
+#define debug_parser(fmt, args...)             \
+       debug_cond(DEBUG_PARSER, fmt, ##args)
+
+static int cli_parse_line(char *line, char *argv[])
+{
+       static const FLASH char delim[] = {" \t"};
+
+       char *ptr;
+       uint_fast8_t nargs = 0;
+
+       debug_parser("parse_line: \"%s\"\n", line);
+
+       ptr = strtok_P(line, delim);
+       while(nargs < CONFIG_SYS_MAXARGS && ptr != NULL) {
+               argv[nargs++] = ptr;
+               ptr = strtok_P(NULL, delim);
+       }
+
+       if (ptr != NULL)
+               printf_P(PSTR("** Too many args (max. %d) **\n"), CONFIG_SYS_MAXARGS);
+
+       argv[nargs] = NULL;
+       debug_parser("parse_line: nargs=%d\n", nargs);
+
+       return nargs;
+}
+
+static void process_macros(const char *input, char *output)
+{
+       char c, prev;
+       const char *varname_start = NULL;
+#if 0 && (CONFIG_SYS_CBSIZE < __UINT_FAST8_MAX__)
+       uint_fast8_t inputcnt = strlen(input);
+       uint_fast8_t outputcnt = CONFIG_SYS_CBSIZE;
+#else
+       int inputcnt = strlen(input);
+       int outputcnt = CONFIG_SYS_CBSIZE;
+#endif
+       uint_fast8_t state = 0;         /* 0 = waiting for '$'  */
+
+       /* 1 = waiting for '(' or '{' */
+       /* 2 = waiting for ')' or '}' */
+       /* 3 = waiting for '''  */
+       char *output_start = output;
+
+       debug_parser("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(input),
+                    input);
+
+       prev = '\0';            /* previous character   */
+
+       while (inputcnt && outputcnt) {
+               c = *input++;
+               inputcnt--;
+
+               if (state != 3) {
+                       /* remove one level of escape characters */
+                       if ((c == '\\') && (prev != '\\')) {
+                               if (inputcnt-- == 0)
+                                       break;
+                               prev = c;
+                               c = *input++;
+                       }
+               }
+
+               switch (state) {
+               case 0: /* Waiting for (unescaped) $    */
+                       if ((c == '\'') && (prev != '\\')) {
+                               state = 3;
+                               break;
+                       }
+                       if ((c == '$') && (prev != '\\')) {
+                               state++;
+                       } else {
+                               *(output++) = c;
+                               outputcnt--;
+                       }
+                       break;
+               case 1: /* Waiting for (        */
+                       if (c == '(' || c == '{') {
+                               state++;
+                               varname_start = input;
+                       } else {
+                               state = 0;
+                               *(output++) = '$';
+                               outputcnt--;
+
+                               if (outputcnt) {
+                                       *(output++) = c;
+                                       outputcnt--;
+                               }
+                       }
+                       break;
+               case 2: /* Waiting for )        */
+                       if (c == ')' || c == '}') {
+                               char envname[CONFIG_SYS_ENV_NAMELEN+1], *envval;
+                               /* Varname # of chars */
+                               uint_fast8_t envcnt = input - varname_start - 1;
+                               if (envcnt > CONFIG_SYS_ENV_NAMELEN)
+                                       envcnt = CONFIG_SYS_ENV_NAMELEN;
+
+                               memcpy(envname, varname_start, envcnt);
+                               envname[envcnt] = '\0';
+
+                               /* Get its value */
+                               envval = getenv(envname);
+
+                               /* Copy into the line if it exists */
+                               if (envval != NULL)
+                                       while ((*envval) && outputcnt) {
+                                               *(output++) = *(envval++);
+                                               outputcnt--;
+                                       }
+                               /* Look for another '$' */
+                               state = 0;
+                       }
+                       break;
+               case 3: /* Waiting for '        */
+                       if ((c == '\'') && (prev != '\\')) {
+                               state = 0;
+                       } else {
+                               *(output++) = c;
+                               outputcnt--;
+                       }
+                       break;
+               }
+               prev = c;
+       }
+
+       if (outputcnt)
+               *output = 0;
+       else
+               *(output - 1) = 0;
+
+       debug_parser("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n",
+                    strlen(output_start), output_start);
+}
+
+ /*
+ * WARNING:
+ *
+ * We must create a temporary copy of the command since the command we get
+ * may be the result from getenv(), which returns a pointer directly to
+ * the environment data, which may change magicly when the command we run
+ * creates or modifies environment variables (like "bootp" does).
+ */
+static int cli_run_command(const char *cmd, int flag)
+{
+       char *cmdbuf;                   /* working copy of cmd          */
+       char *token;                    /* start of token in cmdbuf     */
+       char *sep;                      /* end of token (separator) in cmdbuf */
+       char *finaltoken;
+       char *str;
+       char *argv[CONFIG_SYS_MAXARGS + 1];     /* NULL terminated      */
+       int argc;
+       uint_fast8_t inquotes, repeatable = 1;
+       int rc = 0;
+
+       debug_parser("[RUN_COMMAND] cmd[%p]=\"%s\"\n", 
+                       cmd, cmd ? cmd : "NULL");
+
+       clear_ctrlc();          /* forget any previous Control C */
+
+       if (!cmd || !*cmd)
+               return -1;      /* empty command */
+
+
+       cmdbuf = xmalloc(strlen(cmd) + 1);
+       finaltoken = xmalloc(CONFIG_SYS_CBSIZE);
+
+       strcpy(cmdbuf, cmd);
+       str = cmdbuf;
+
+       /* Process separators and check for invalid
+        * repeatable commands
+        */
+
+       debug_parser("[PROCESS_SEPARATORS] %s\n", cmd);
+       while (*str) {
+               /*
+                * Find separator, or string end
+                * Allow simple escape of ';' by writing "\;"
+                */
+               for (inquotes = 0, sep = str; *sep; sep++) {
+                       if ((*sep == '\'') &&
+                           (*(sep - 1) != '\\'))
+                               inquotes = !inquotes;
+
+                       if (!inquotes &&
+                           (*sep == ';' || *sep == '\n') &&    /* separator            */
+                           (sep != str) &&                     /* past string start    */
+                           (*(sep - 1) != '\\'))               /* and NOT escaped */
+                               break;
+               }
+
+               /*
+                * Limit the token to data between separators
+                */
+               token = str;
+               if (*sep) {
+                       str = sep + 1;  /* start of command for next pass */
+                       *sep = '\0';
+               } else {
+                       str = sep;      /* no more commands for next pass */
+               }
+               debug_parser("token: \"%s\"\n", token);
+
+               /* find macros in this token and replace them */
+               process_macros(token, finaltoken);
+
+               /* Extract arguments */
+               argc = cli_parse_line(finaltoken, argv);
+               if (argc == 0) {
+                       rc = -1;        /* no command at all */
+                       continue;
+               }
+
+               if (cmd_process(flag, argc, argv, &repeatable))
+                       rc = -1;
+
+               /* Did the user stop this? */
+               if (had_ctrlc()) {
+                       rc = -1;        /* if stopped then not repeatable */
+                       break;
+               }
+       }
+
+       free(cmdbuf);
+       free(finaltoken);
+
+       return rc ? rc : repeatable;
+}
+
+static int cli_run_command_list(const char *cmd)
+{
+       return (cli_run_command(cmd, 0) < 0);
+}
+
+/******************************************************************************/
+
+
+/*
+ * Run a command using the selected parser.
+ *
+ * @param cmd  Command to run
+ * @param flag Execution flags (CMD_FLAG_...)
+ * @return 0 on success, or != 0 on error.
+ */
+int run_command(const char *cmd, int flag)
+{
+       /*
+        * cli_run_command can return 0 or 1 for success, so clean up
+        * its result.
+        */
+       if (cli_run_command(cmd, flag) == -1)
+               return 1;
+
+       return 0;
+}
+
+/*
+ * Run a command using the selected parser, and check if it is repeatable.
+ *
+ * @param cmd  Command to run
+ * @param flag Execution flags (CMD_FLAG_...)
+ * @return 0 (not repeatable) or 1 (repeatable) on success, -1 on error.
+ */
+static int run_command_repeatable(const char *cmd, int flag)
+{
+       return cli_run_command(cmd, flag);
+}
+
+int run_command_list(const char *cmd, int len)
+{
+       (void) len;
+       
+       return cli_run_command_list(cmd);
+}
+
+/****************************************************************************/
+
+
+void cli_loop(void)
+{
+       char *lastcommand = NULL;
+       int len;
+       int flag;
+       int rc = 1;
+
+       for (;;) {
+               len = cli_readline(PSTR(CONFIG_SYS_PROMPT));
+
+               flag = 0;       /* assume no special flags for now */
+               if (len > 0) {
+                       lastcommand = (char *) xrealloc(lastcommand, len+1);
+                       if (lastcommand != NULL) {
+                               strncpy(lastcommand, console_buffer, len+1);
+                               lastcommand[len] = '\0';
+                       }
+               } else if (len == 0)
+                       flag |= CMD_FLAG_REPEAT;
+
+               if (len == -1)
+                       my_puts_P(PSTR("<INTERRUPT>\n"));
+               else
+                       rc = run_command_repeatable(lastcommand, flag);
+
+               if (rc <= 0) {
+                       /* invalid command or not repeatable, forget it */
+                       free(lastcommand);
+                       lastcommand = NULL;
+               }
+       }
+}
+
+
+int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       int i;
+       (void) cmdtp;
+
+       if (argc < 2)
+               return CMD_RET_USAGE;
+
+       for (i = 1; i < argc; ++i) {
+               char *arg;
+
+               arg = getenv(argv[i]);
+               if (arg == NULL) {
+                       printf_P(PSTR("## Error: \"%s\" not defined\n"), argv[i]);
+                       return 1;
+               }
+
+               if (run_command(arg, flag) != 0)
+                       return 1;
+       }
+       return 0;
+}
+
diff --git a/avr/cli.h b/avr/cli.h
new file mode 100644 (file)
index 0000000..67ff63b
--- /dev/null
+++ b/avr/cli.h
@@ -0,0 +1,64 @@
+#ifndef CLI_H          
+#define CLI_H
+
+/**
+ * Go into the command loop
+ *
+ * This will return if we get a timeout waiting for a command, but only for
+ * the simple parser (not hush). See CONFIG_BOOT_RETRY_TIME.
+ */
+void cli_loop(void);
+
+/**
+ * cli_simple_run_command() - Execute a command with the simple CLI
+ *
+ * @cmd:       String containing the command to execute
+ * @flag       Flag value - see CMD_FLAG_...
+ * @return 1  - command executed, repeatable
+ *     0  - command executed but not repeatable, interrupted commands are
+ *          always considered not repeatable
+ *     -1 - not executed (unrecognized, bootd recursion or too many args)
+ *           (If cmd is NULL or "" or longer than CONFIG_SYS_CBSIZE-1 it is
+ *           considered unrecognized)
+ */
+//int cli_simple_run_command(const char *cmd, int flag);
+
+/**
+ * cli_simple_run_command_list() - Execute a list of command
+ *
+ * The commands should be separated by ; or \n and will be executed
+ * by the built-in parser.
+ *
+ * This function cannot take a const char * for the command, since if it
+ * finds newlines in the string, it replaces them with \0.
+ *
+ * @param cmd  String containing list of commands
+ * @param flag Execution flags (CMD_FLAG_...)
+ * @return 0 on success, or != 0 on error.
+ */
+//int cli_simple_run_command_list(char *cmd, int flag);
+
+/**
+ * parse_line() - split a command line down into separate arguments
+ *
+ * The argv[] array is filled with pointers into @line, and each argument
+ * is terminated by \0 (i.e. @line is changed in the process unless there
+ * is only one argument).
+ *
+ * #argv is terminated by a NULL after the last argument pointer.
+ *
+ * At most CONFIG_SYS_MAXARGS arguments are permited - if there are more
+ * than that then an error is printed, and this function returns
+ * CONFIG_SYS_MAXARGS, with argv[] set up to that point.
+ *
+ * @line:      Command line to parse
+ * @args:      Array to hold arguments
+ * @return number of arguments
+ */
+//int cli_simple_parse_line(char *line, char *argv[]);
+
+int run_command_list(const char *cmd, int len);
+
+
+#endif /* CLI_H */
+
diff --git a/avr/cli_readline.c b/avr/cli_readline.c
new file mode 100644 (file)
index 0000000..17d5494
--- /dev/null
@@ -0,0 +1,595 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Add to readline cmdline-editing by
+ * (C) Copyright 2005
+ * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include "common.h"
+
+#include <avr/pgmspace.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "config.h"
+#include "con-utils.h"
+#include "command.h"
+#include "cli_readline.h"
+
+char console_buffer[CONFIG_SYS_CBSIZE + 1];    /* console I/O buffer   */
+
+static const FLASH char erase_seq[] = "\b \b";   /* erase sequence */
+static const FLASH char   tab_seq[] = "        "; /* used to expand TABs */
+
+#ifndef CONFIG_CMDLINE_EDITING
+static char *delete_char (char *buffer, char *p, int *colp, int *np, int plen)
+{
+       char *s;
+
+       if (*np == 0)
+               return p;
+
+       if (*(--p) == '\t') {           /* will retype the whole line */
+               while (*colp > plen) {
+                       my_puts_P(erase_seq);
+                       (*colp)--;
+               }
+               for (s = buffer; s < p; ++s) {
+                       if (*s == '\t') {
+                               my_puts_P(tab_seq + ((*colp) & 07));
+                               *colp += 8 - ((*colp) & 07);
+                       } else {
+                               ++(*colp);
+                               putchar(*s);
+                       }
+               }
+       } else {
+               my_puts_P(erase_seq);
+               (*colp)--;
+       }
+       (*np)--;
+
+       return p;
+}
+#endif /* CONFIG_CMDLINE_EDITING */
+
+
+#ifdef CONFIG_CMDLINE_EDITING
+
+/*
+ * cmdline-editing related codes from vivi.
+ * Author: Janghoon Lyu <nandy@mizi.com>
+ */
+
+#define putnstr(str, n)        printf_P(PSTR("%.*s"), (int)n, str)
+
+#define CTL_CH(c)              ((c) - 'a' + 1)
+#define CTL_BACKSPACE          ('\b')
+#define DEL                    ((char)255)
+#define DEL7                   ((char)127)
+#define CREAD_HIST_CHAR                ('!')
+
+#define getcmd_putch(ch)       putchar(ch)
+#define getcmd_getch()         my_getchar()
+#define getcmd_cbeep()         getcmd_putch('\a')
+
+#define HIST_MAX               5
+#define HIST_SIZE              CONFIG_SYS_CBSIZE
+
+static int hist_max;
+static int hist_add_idx;
+static int hist_cur = -1;
+static unsigned hist_num;
+
+static char *hist_list[HIST_MAX];
+static char hist_lines[HIST_MAX][HIST_SIZE + 1];       /* Save room for NULL */
+
+#define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1)
+
+static void hist_init(void)
+{
+       int i;
+
+       hist_max = 0;
+       hist_add_idx = 0;
+       hist_cur = -1;
+       hist_num = 0;
+
+       for (i = 0; i < HIST_MAX; i++) {
+               hist_list[i] = hist_lines[i];
+               hist_list[i][0] = '\0';
+       }
+}
+
+static void cread_add_to_hist(char *line)
+{
+       strcpy(hist_list[hist_add_idx], line);
+
+       if (++hist_add_idx >= HIST_MAX)
+               hist_add_idx = 0;
+
+       if (hist_add_idx > hist_max)
+               hist_max = hist_add_idx;
+
+       hist_num++;
+}
+
+static char *hist_prev(void)
+{
+       char *ret;
+       int old_cur;
+
+       if (hist_cur < 0)
+               return NULL;
+
+       old_cur = hist_cur;
+       if (--hist_cur < 0)
+               hist_cur = hist_max;
+
+       if (hist_cur == hist_add_idx) {
+               hist_cur = old_cur;
+               ret = NULL;
+       } else {
+               ret = hist_list[hist_cur];
+       }
+
+       return ret;
+}
+
+static char *hist_next(void)
+{
+       char *ret;
+
+       if (hist_cur < 0)
+               return NULL;
+
+       if (hist_cur == hist_add_idx)
+               return NULL;
+
+       if (++hist_cur > hist_max)
+               hist_cur = 0;
+
+       if (hist_cur == hist_add_idx)
+               ret = "";
+       else
+               ret = hist_list[hist_cur];
+
+       return ret;
+}
+
+#ifndef CONFIG_CMDLINE_EDITING
+static void cread_print_hist_list(void)
+{
+       int i;
+       unsigned n;
+
+       n = hist_num - hist_max;
+
+       i = hist_add_idx + 1;
+       while (1) {
+               if (i > hist_max)
+                       i = 0;
+               if (i == hist_add_idx)
+                       break;
+               printf_P(PSTR("%s\n"), hist_list[i]);
+               n++;
+               i++;
+       }
+}
+#endif /* CONFIG_CMDLINE_EDITING */
+
+#define BEGINNING_OF_LINE() {                  \
+       while (num) {                           \
+               getcmd_putch(CTL_BACKSPACE);    \
+               num--;                          \
+       }                                       \
+}
+
+#define ERASE_TO_EOL() {                               \
+       if (num < eol_num) {                            \
+               printf_P(PSTR("%*S"), (int)(eol_num - num), PSTR("")); \
+               do {                                    \
+                       getcmd_putch(CTL_BACKSPACE);    \
+               } while (--eol_num > num);              \
+       }                                               \
+}
+
+#define REFRESH_TO_EOL() {                     \
+       if (num < eol_num) {                    \
+               wlen = eol_num - num;           \
+               putnstr(buf + num, wlen);       \
+               num = eol_num;                  \
+       }                                       \
+}
+
+static void cread_add_char(char ichar, int insert, unsigned long *num,
+              unsigned long *eol_num, char *buf, unsigned long len)
+{
+       unsigned long wlen;
+
+       /* room ??? */
+       if (insert || *num == *eol_num) {
+               if (*eol_num > len - 1) {
+                       getcmd_cbeep();
+                       return;
+               }
+               (*eol_num)++;
+       }
+
+       if (insert) {
+               wlen = *eol_num - *num;
+               if (wlen > 1)
+                       memmove(&buf[*num+1], &buf[*num], wlen-1);
+
+               buf[*num] = ichar;
+               putnstr(buf + *num, wlen);
+               (*num)++;
+               while (--wlen)
+                       getcmd_putch(CTL_BACKSPACE);
+       } else {
+               /* echo the character */
+               wlen = 1;
+               buf[*num] = ichar;
+               putnstr(buf + *num, wlen);
+               (*num)++;
+       }
+}
+
+static void cread_add_str(char *str, int strsize, int insert,
+                         unsigned long *num, unsigned long *eol_num,
+                         char *buf, unsigned long len)
+{
+       while (strsize--) {
+               cread_add_char(*str, insert, num, eol_num, buf, len);
+               str++;
+       }
+}
+
+static int cread_line(const FLASH char *const prompt, char *buf, unsigned int *len)
+{
+       unsigned long num = 0;
+       unsigned long eol_num = 0;
+       unsigned long wlen;
+       char ichar;
+       int insert = 1;
+       int esc_len = 0;
+       char esc_save[8];
+       int init_len = strlen(buf);
+
+       (void) prompt;
+
+       if (init_len)
+               cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len);
+
+       while (1) {
+               ichar = getcmd_getch();
+
+               if ((ichar == '\n') || (ichar == '\r')) {
+                       putchar('\n');
+                       break;
+               }
+
+               /*
+                * handle standard linux xterm esc sequences for arrow key, etc.
+                */
+               if (esc_len != 0) {
+                       if (esc_len == 1) {
+                               if (ichar == '[') {
+                                       esc_save[esc_len] = ichar;
+                                       esc_len = 2;
+                               } else {
+                                       cread_add_str(esc_save, esc_len,
+                                                     insert, &num, &eol_num,
+                                                     buf, *len);
+                                       esc_len = 0;
+                               }
+                               continue;
+                       }
+
+                       switch (ichar) {
+                       case 'D':       /* <- key */
+                               ichar = CTL_CH('b');
+                               esc_len = 0;
+                               break;
+                       case 'C':       /* -> key */
+                               ichar = CTL_CH('f');
+                               esc_len = 0;
+                               break;  /* pass off to ^F handler */
+                       case 'H':       /* Home key */
+                               ichar = CTL_CH('a');
+                               esc_len = 0;
+                               break;  /* pass off to ^A handler */
+                       case 'A':       /* up arrow */
+                               ichar = CTL_CH('p');
+                               esc_len = 0;
+                               break;  /* pass off to ^P handler */
+                       case 'B':       /* down arrow */
+                               ichar = CTL_CH('n');
+                               esc_len = 0;
+                               break;  /* pass off to ^N handler */
+                       default:
+                               esc_save[esc_len++] = ichar;
+                               cread_add_str(esc_save, esc_len, insert,
+                                             &num, &eol_num, buf, *len);
+                               esc_len = 0;
+                               continue;
+                       }
+               }
+
+               switch (ichar) {
+               case 0x1b:
+                       if (esc_len == 0) {
+                               esc_save[esc_len] = ichar;
+                               esc_len = 1;
+                       } else {
+                               my_puts_P(PSTR("impossible condition #876\n"));
+                               esc_len = 0;
+                       }
+                       break;
+
+               case CTL_CH('a'):
+                       BEGINNING_OF_LINE();
+                       break;
+               case CTL_CH('c'):       /* ^C - break */
+                       *buf = '\0';    /* discard input */
+                       return -1;
+               case CTL_CH('f'):
+                       if (num < eol_num) {
+                               getcmd_putch(buf[num]);
+                               num++;
+                       }
+                       break;
+               case CTL_CH('b'):
+                       if (num) {
+                               getcmd_putch(CTL_BACKSPACE);
+                               num--;
+                       }
+                       break;
+               case CTL_CH('d'):
+                       if (num < eol_num) {
+                               wlen = eol_num - num - 1;
+                               if (wlen) {
+                                       memmove(&buf[num], &buf[num+1], wlen);
+                                       putnstr(buf + num, wlen);
+                               }
+
+                               getcmd_putch(' ');
+                               do {
+                                       getcmd_putch(CTL_BACKSPACE);
+                               } while (wlen--);
+                               eol_num--;
+                       }
+                       break;
+               case CTL_CH('k'):
+                       ERASE_TO_EOL();
+                       break;
+               case CTL_CH('e'):
+                       REFRESH_TO_EOL();
+                       break;
+               case CTL_CH('o'):
+                       insert = !insert;
+                       break;
+               case CTL_CH('x'):
+               case CTL_CH('u'):
+                       BEGINNING_OF_LINE();
+                       ERASE_TO_EOL();
+                       break;
+               case DEL:
+               case DEL7:
+               case 8:
+                       if (num) {
+                               wlen = eol_num - num;
+                               num--;
+                               memmove(&buf[num], &buf[num+1], wlen);
+                               getcmd_putch(CTL_BACKSPACE);
+                               putnstr(buf + num, wlen);
+                               getcmd_putch(' ');
+                               do {
+                                       getcmd_putch(CTL_BACKSPACE);
+                               } while (wlen--);
+                               eol_num--;
+                       }
+                       break;
+               case CTL_CH('p'):
+               case CTL_CH('n'):
+               {
+                       char *hline;
+
+                       esc_len = 0;
+
+                       if (ichar == CTL_CH('p'))
+                               hline = hist_prev();
+                       else
+                               hline = hist_next();
+
+                       if (!hline) {
+                               getcmd_cbeep();
+                               continue;
+                       }
+
+                       /* nuke the current line */
+                       /* first, go home */
+                       BEGINNING_OF_LINE();
+
+                       /* erase to end of line */
+                       ERASE_TO_EOL();
+
+                       /* copy new line into place and display */
+                       strcpy(buf, hline);
+                       eol_num = strlen(buf);
+                       REFRESH_TO_EOL();
+                       continue;
+               }
+#ifdef CONFIG_AUTO_COMPLETE
+               case '\t': {
+                       int num2, col;
+
+                       /* do not autocomplete when in the middle */
+                       if (num < eol_num) {
+                               getcmd_cbeep();
+                               break;
+                       }
+
+                       buf[num] = '\0';
+                       col = strlen_P(prompt) + eol_num;
+                       num2 = num;
+                       if (cmd_auto_complete(prompt, buf, &num2, &col)) {
+                               col = num2 - num;
+                               num += col;
+                               eol_num += col;
+                       }
+                       break;
+               }
+#endif
+               default:
+                       cread_add_char(ichar, insert, &num, &eol_num, buf,
+                                      *len);
+                       break;
+               }
+       }
+       *len = eol_num;
+       buf[eol_num] = '\0';    /* lose the newline */
+
+       if (buf[0] && buf[0] != CREAD_HIST_CHAR)
+               cread_add_to_hist(buf);
+       hist_cur = hist_add_idx;
+
+       return 0;
+}
+
+#endif /* CONFIG_CMDLINE_EDITING */
+
+/****************************************************************************/
+
+static int cli_readline_into_buffer(const FLASH char *const prompt, char *buffer)
+{
+       char *p = buffer;
+#ifdef CONFIG_CMDLINE_EDITING
+       unsigned int len = CONFIG_SYS_CBSIZE;
+       int rc;
+       static int initted;
+
+       if (!initted) {
+               hist_init();
+               initted = 1;
+       }
+
+       if (prompt)
+               my_puts_P(prompt);
+
+       rc = cread_line(prompt, p, &len);
+       return rc < 0 ? rc : (int) len;
+
+#else  /* CONFIG_CMDLINE_EDITING */
+       char *p_buf = p;
+       int     n = 0;                          /* buffer index         */
+       int     plen = 0;                       /* prompt length        */
+       int     col;                            /* output column cnt    */
+       char    c;
+
+       /* print prompt */
+       if (prompt) {
+               plen = strlen_P(prompt);
+               my_puts_P(prompt);
+       }
+       col = plen;
+
+       for (;;) {
+
+               c = my_getchar();
+
+               /*
+                * Special character handling
+                */
+               switch (c) {
+               case '\r':                      /* Enter                */
+               case '\n':
+                       *p = '\0';
+                       my_puts_P(PSTR("\r\n"));
+                       return p - p_buf;
+
+               case '\0':                      /* nul                  */
+                       continue;
+
+               case 0x03:                      /* ^C - break           */
+                       p_buf[0] = '\0';        /* discard input */
+                       return -1;
+
+               case 0x15:                      /* ^U - erase line      */
+                       while (col > plen) {
+                               my_puts_P(erase_seq);
+                               --col;
+                       }
+                       p = p_buf;
+                       n = 0;
+                       continue;
+
+               case 0x17:                      /* ^W - erase word      */
+                       p = delete_char(p_buf, p, &col, &n, plen);
+                       while ((n > 0) && (*p != ' '))
+                               p = delete_char(p_buf, p, &col, &n, plen);
+                       continue;
+
+               case 0x08:                      /* ^H  - backspace      */
+               case 0x7F:                      /* DEL - backspace      */
+                       p = delete_char(p_buf, p, &col, &n, plen);
+                       continue;
+
+               default:
+                       /*
+                        * Must be a normal character then
+                        */
+                       if (n < CONFIG_SYS_CBSIZE-2) {
+                               if (c == '\t') {        /* expand TABs */
+#ifdef CONFIG_AUTO_COMPLETE
+                                       /*
+                                        * if auto completion triggered just
+                                        * continue
+                                        */
+                                       *p = '\0';
+                                       if (cmd_auto_complete(prompt,
+                                                             console_buffer,
+                                                             &n, &col)) {
+                                               p = p_buf + n;  /* reset */
+                                               continue;
+                                       }
+#endif
+                                       my_puts_P(tab_seq + (col & 07));
+                                       col += 8 - (col & 07);
+                               } else {
+                                       char buf[2];
+
+                                       /*
+                                        * Echo input using puts() to force an
+                                        * LCD flush if we are using an LCD
+                                        */
+                                       ++col;
+                                       buf[0] = c;
+                                       buf[1] = '\0';
+                                       my_puts(buf);
+                               }
+                               *p++ = c;
+                               ++n;
+                       } else {                        /* Buffer full */
+                               putchar('\a');
+                       }
+               }
+       }
+#endif /* CONFIG_CMDLINE_EDITING */
+}
+
+int cli_readline(const FLASH char *const prompt)
+{
+       /*
+        * If console_buffer isn't 0-length the user will be prompted to modify
+        * it instead of entering it from scratch as desired.
+        */
+       console_buffer[0] = '\0';
+
+       return cli_readline_into_buffer(prompt, console_buffer);
+}
+
diff --git a/avr/cli_readline.h b/avr/cli_readline.h
new file mode 100644 (file)
index 0000000..5b25762
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * (C) Copyright 2014 Google, Inc
+ * Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef CLI_READLINE_H
+#define CLI_READLINE_H
+
+extern char console_buffer[];  /* console I/O buffer   */
+
+/**
+ * cli_readline() - read a line into the console_buffer
+ *
+ * This is a convenience function which calls cli_readline_into_buffer().
+ *
+ * @prompt: Prompt to display
+ * @return command line length excluding terminator, or -ve on error
+ */
+int cli_readline(const FLASH char *const prompt);
+
+/**
+ * readline_into_buffer() - read a line into a buffer
+ *
+ * Display the prompt, then read a command line into @buffer. The
+ * maximum line length is CONFIG_SYS_CBSIZE including a \0 terminator, which
+ * will always be added.
+ *
+ * The command is echoed as it is typed. Command editing is supported if
+ * CONFIG_CMDLINE_EDITING is defined. Tab auto-complete is supported if
+ * CONFIG_AUTO_COMPLETE is defined. If CONFIG_BOOT_RETRY_TIME is defined,
+ * then a timeout will be applied.
+ *
+ * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0,
+ * time out when time goes past endtime (timebase time in ticks).
+ *
+ * @prompt:    Prompt to display
+ * @buffer:    Place to put the line that is entered
+ * @timeout:   Timeout in milliseconds, 0 if none
+ * @return command line length excluding terminator, or -ve on error: of the
+ * timeout is exceeded (either CONFIG_BOOT_RETRY_TIME or the timeout
+ * parameter), then -2 is returned. If a break is detected (Ctrl-C) then
+ * -1 is returned.
+ */
+//int cli_readline_into_buffer(const char *const prompt, char *buffer, int timeout);
+
+
+#endif /* CLI_READLINE_H */
+
diff --git a/avr/cmd_boot.c b/avr/cmd_boot.c
new file mode 100644 (file)
index 0000000..1699a5c
--- /dev/null
@@ -0,0 +1,145 @@
+
+/*
+ * Misc boot support
+ */
+#include "common.h"
+#include <stdlib.h>
+#include <util/delay.h>
+#include <avr/pgmspace.h>
+
+#include "command.h"
+#include "z80-if.h"
+
+/* ugly hack to get Z180 loadfile into flash memory */
+#define const const FLASH
+#include "../z180/hdrom.h"
+#undef const
+
+
+
+static void z80_load_mem(void)
+{
+       unsigned sec = 0;
+       uint32_t sec_base = hdrom_start;
+
+       printf_P(PSTR("Loading Z180 memory... \n"));
+
+       while (sec < hdrom_sections) {
+               printf_P(PSTR("   From: 0x%.5lX to: 0x%.5lX    (%5li bytes)\n"),
+                               hdrom_address[sec],
+                               hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
+                               hdrom_length_of_sections[sec]);
+
+               z80_bus_cmd(Request);
+               z80_write_block((const FLASH unsigned char *) &hdrom[sec_base],  /* src */
+                               hdrom_address[sec],                  /* dest */
+                               hdrom_length_of_sections[sec]);      /* len */
+               z80_bus_cmd(Release);
+               sec_base+=hdrom_length_of_sections[sec];
+               sec++;
+       }
+}
+
+int do_loadf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       (void) cmdtp; (void) flag; (void) argc; (void) argv;
+
+       if (z80_bus_state() & ZST_RUNNING) {    
+               printf_P(PSTR("## Can't load while CPU is running!\n"));
+               return 1;       
+       }
+
+       z80_load_mem();
+       
+       return 0;
+}
+
+
+int do_busreq_pulse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       uint16_t count=1;
+
+       (void) cmdtp; (void) flag;
+
+       if (!(z80_bus_state() & ZST_RUNNING)) { 
+               printf_P(PSTR("## CPU is not running!\n"));
+               return 1;
+       }
+
+       if (argc > 1)
+               count = (uint16_t) strtoul(argv[2], NULL, 16);
+
+       z80_bus_cmd(Request);
+       while (count--)
+               z80_bus_cmd(M_Cycle);
+
+       return 0;
+}
+
+
+int do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       uint32_t addr;
+
+       (void) cmdtp; (void) flag;
+       
+       if (argc < 2)
+               return CMD_RET_USAGE;
+       addr = strtoul(argv[1], NULL, 16);
+       if (addr >= (1UL<<16)) {
+               printf_P(PSTR("## Startaddress 0x%05lx too high.\n"
+                       "   (Out of logical address space (0x00000-0x0ffff))\n"),
+                       addr);
+               return 1;
+       } 
+
+       if (z80_bus_state() & ZST_RUNNING) {    
+               printf_P(PSTR("## CPU allready running!\n"));
+               return 1;
+       }
+
+       printf_P(PSTR("## Starting application at 0x%04lx ...\n"), addr);
+
+       if (addr != 0) {
+               uint8_t tmp[3];
+               uint_fast8_t i;
+               
+               z80_bus_cmd(Request);
+               for (i = 0; i < 3; i++)
+                       tmp[i] = z80_read(i);
+               z80_write(0, 0xc3);
+               z80_write(1, addr);
+               z80_write(2, (addr >> 8));
+
+               z80_bus_cmd(Run);
+               z80_bus_cmd(M_Cycle);
+               z80_bus_cmd(M_Cycle);
+               for (i = 0; i < 3; i++)
+                       z80_write(i, tmp[i]);
+       } else
+               z80_bus_cmd(Run);
+               
+       z80_bus_cmd(Release);
+
+       return 0;
+}
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       (void) cmdtp; (void) flag; (void) argc; (void) argv;
+
+       printf_P(PSTR("## CPU now in reset state.\n"));
+
+       z80_bus_cmd(Reset);
+       return 0;
+}
+
+int do_restart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       (void) cmdtp; (void) flag; (void) argc; (void) argv;
+
+       z80_bus_cmd(Restart);
+
+       return 0;
+}
+
diff --git a/avr/cmd_echo.c b/avr/cmd_echo.c
new file mode 100644 (file)
index 0000000..d142ab6
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include "common.h"
+#include "command.h"
+
+
+int do_echo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       uint_fast8_t putnl = 1;
+       
+       (void) cmdtp; (void) flag;
+
+       for (uint_fast8_t i = 1; i < argc; i++) {
+
+               uint_fast8_t backslash = 0;
+               char *p = argv[i];
+               char c;
+               
+               if (i != 1)
+                       putchar(' ');
+               while ((c = *p++) != '\0') {
+               
+                       if(backslash) {
+                               backslash = 0;
+                               if (c == 'c') {
+                                       putnl = 0;
+                                       continue;
+                               } else
+                                       putchar('\\');
+                       } else {
+                               if (c == '\\') {
+                                       backslash = 1;
+                                       continue;
+                               }
+                       }
+                       putchar(c);
+               }
+       }                       
+                                       
+       if (putnl)
+               putchar('\n');
+
+       return 0;
+}
+
+#if 0
+U_BOOT_CMD(
+       echo,   CONFIG_SYS_MAXARGS,     1,      do_echo,
+       "echo args to console",
+       "[args..]\n"
+       "    - echo args to console; \\c suppresses newline"
+);
+#endif
diff --git a/avr/cmd_help.c b/avr/cmd_help.c
new file mode 100644 (file)
index 0000000..317eb5d
--- /dev/null
@@ -0,0 +1,32 @@
+
+#include "common.h"
+#include "command.h"
+
+int do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       const int len = cmd_tbl_item_count();
+       return _do_help(cmd_tbl, len, cmdtp, flag, argc, argv);
+}
+
+
+#if 0
+
+U_BOOT_CMD(
+       help,   CONFIG_SYS_MAXARGS,     1,      do_help,
+       "print command description/usage",
+       "\n"
+       "       - print brief description of all commands\n"
+       "help command ...\n"
+       "       - print detailed usage of 'command'"
+);
+
+/* This does not use the U_BOOT_CMD macro as ? can't be used in symbol names */
+ll_entry_declare(cmd_tbl_t, question_mark, cmd) = {
+       "?",    CONFIG_SYS_MAXARGS,     1,      do_help,
+       "alias for 'help'",
+#ifdef  CONFIG_SYS_LONGHELP
+       ""
+#endif /* CONFIG_SYS_LONGHELP */
+};
+
+#endif
diff --git a/avr/cmd_mem.c b/avr/cmd_mem.c
new file mode 100644 (file)
index 0000000..253f02f
--- /dev/null
@@ -0,0 +1,878 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+/*
+ * Memory Functions
+ *
+ * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
+ */
+
+#include "common.h"
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "config.h"
+#include "debug.h"
+#include "command.h"
+#include "cli_readline.h"
+#include "con-utils.h"
+#include "z80-if.h"
+
+/* 
+ * TODO: printf() --> printf_P() 
+ */
+
+#ifndef CONFIG_SYS_MEMTEST_SCRATCH
+#define CONFIG_SYS_MEMTEST_SCRATCH 0
+#endif
+
+static int mod_mem(cmd_tbl_t *, int, int, int, char * const []);
+
+/* Display values from last command.
+ * Memory modify remembered values are different from display memory.
+ */
+static uint32_t        dp_last_addr;
+static uint32_t        dp_last_length = 0x100;
+static uint32_t        mm_last_addr;
+
+static uint32_t        base_address = 0;
+
+/*--------------------------------------------------------------------------*/
+
+static void print_blanks(uint_fast8_t count)
+{
+       while(count--)
+               putchar(' ');
+}
+
+int z180_dump_mem(uint32_t startaddr, uint32_t len, const char *title)
+{
+       uint8_t buf[16];
+       uint8_t llen = 16;
+       uint8_t pre = startaddr % 16;
+       uint32_t addr = startaddr & ~0x0f;
+       len += pre;
+       uint8_t i;
+       
+       if (title && *title)
+               printf_P(PSTR("%s\n"),title);
+               
+       while (len) {
+               if (len < 16)
+                       llen = len;
+
+               z80_bus_cmd(Request);
+               for (i = pre; i < llen; i++)
+                       buf[i] = z80_read(addr + i);
+               z80_bus_cmd(Release);
+
+               printf_P(PSTR("%.5lx:"), addr);
+#if 0
+               print_blanks(3 * pre);
+
+               /* Print hex values */
+               for (i = pre; i < llen; i++)
+                       printf_P(PSTR(" %.2x"), buf[i]);
+#else
+               for (i = 0; i < llen; i++) {
+                       if ((i % 8) == 0)
+                               putchar(' ');
+                       if (i < pre)
+                               printf_P(PSTR(".. "));
+                       else
+                               printf_P(PSTR("%.2x "), buf[i]);
+               }
+#endif
+               /* fill line with whitespace for nice ASCII print */
+#if 1
+               print_blanks(3 * (16u - i) + (16u-i)/8 + 1 + pre);
+#else
+
+#endif
+               /* Print data in ASCII characters */
+               for (i = pre; i < llen; i++)
+                       printf_P(PSTR("%c"), isprint(buf[i]) ? buf[i] : '.');
+               putchar('\n');
+
+               pre = 0;
+               addr += 16;
+               len -= llen;
+
+               if (ctrlc())
+                       return -1;
+       }
+       return 0;
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+/* Memory Display
+ *
+ * Syntax:
+ *     md {addr} {len}
+ */
+int do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       uint32_t addr, length;
+       
+       (void) cmdtp;
+
+#if 0  
+       printf_P(PSTR("flag: %d, argc: %d"), flag, argc);
+       for (int i = 0; i < argc; i++) {
+               printf_P(PSTR(", argv[%d]: %s"), i, argv[i] ? argv[i] : "<NULL>");
+       }
+       putchar('\n');
+#endif
+
+       /* We use the last specified parameters, unless new ones are
+        * entered.
+        */
+       addr = dp_last_addr;
+       length = dp_last_length;
+
+       if (argc < 2)
+               return CMD_RET_USAGE;
+
+       if ((flag & CMD_FLAG_REPEAT) == 0) {
+               /* Address is specified since argc > 1 */
+               addr = strtoul(argv[1], NULL, 16);
+               addr += base_address;
+
+               /* If another parameter, it is the length to display. */
+               if (argc > 2)
+                       length = strtoul(argv[2], NULL, 16);
+       }
+
+       /* Print the lines. */
+       z180_dump_mem(addr, length, NULL);
+
+       dp_last_addr = addr + length;
+       dp_last_length = length;
+       return 0;
+}
+
+int do_mem_mm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       return mod_mem (cmdtp, 1, flag, argc, argv);
+}
+int do_mem_nm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       return mod_mem (cmdtp, 0, flag, argc, argv);
+}
+
+int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       uint8_t writeval;
+       uint32_t addr, count;
+
+       (void) cmdtp;
+       (void) flag;
+
+       if ((argc < 3) || (argc > 4))
+               return CMD_RET_USAGE;
+
+       /* Address is specified since argc > 1
+       */
+       addr = strtoul(argv[1], NULL, 16);
+       addr += base_address;
+
+       /* Get the value to write.
+       */
+       writeval = (uint8_t) strtoul(argv[2], NULL, 16);
+
+       /* Count ? */
+       if (argc == 4) {
+               count = strtoul(argv[3], NULL, 16);
+       } else {
+               count = 1;
+       }
+
+       z80_bus_cmd(Request);
+       while (count-- > 0) {
+               z80_write(addr, writeval);
+               ++addr; 
+       }
+       z80_bus_cmd(Release);
+
+       return 0;
+}
+
+#ifdef CONFIG_MX_CYCLIC
+int do_mem_mdc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       int i;
+       uint32_t count;
+
+       if (argc < 4)
+               return CMD_RET_USAGE;
+
+       count = strtoul(argv[3], NULL, 10);
+
+       for (;;) {
+               do_mem_md (NULL, 0, 3, argv);
+
+               /* delay for <count> ms... */
+/* TODO: use timer */
+               for (i=0; i<count; i++)
+                       udelay (1000);
+
+               /* check for ctrl-c to abort... */
+               if (ctrlc()) {
+                       my_puts("Abort\n");
+                       return 0;
+               }
+       }
+
+       return 0;
+}
+
+int do_mem_mwc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       int i;
+       uint32_t count;
+
+       if (argc < 4)
+               return CMD_RET_USAGE;
+
+       count = strtoul(argv[3], NULL, 10);
+
+       for (;;) {
+               do_mem_mw (NULL, 0, 3, argv);
+
+               /* delay for <count> ms... */
+/* TODO: use timer */
+               for (i=0; i<count; i++)
+                       udelay (1000);
+
+               /* check for ctrl-c to abort... */
+               if (ctrlc()) {
+                       my_puts("Abort\n");
+                       return 0;
+               }
+       }
+
+       return 0;
+}
+#endif /* CONFIG_MX_CYCLIC */
+
+int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       uint32_t addr1, addr2, count, ngood;
+       int rcode = 0;
+       uint8_t byte1, byte2;
+
+       (void) cmdtp;
+       (void) flag;
+
+       if (argc != 4)
+               return CMD_RET_USAGE;
+
+
+       addr1 = strtoul(argv[1], NULL, 16);
+       addr1 += base_address;
+       addr2 = strtoul(argv[2], NULL, 16);
+       addr2 += base_address;
+       count = strtoul(argv[3], NULL, 16);
+
+       for (ngood = 0; ngood < count; ++ngood) {
+               z80_bus_cmd(Request);
+               byte1 = z80_read(addr1);
+               byte2 = z80_read(addr2);
+               z80_bus_cmd(Release);
+               if (byte1 != byte2) {
+                       printf( "byte at 0x%05lx (%#02x) != "
+                               "byte at 0x%05lx (%#02x)\n",
+                               addr1, byte1, addr2, byte2);
+                       rcode = 1;
+                       break;
+               }
+               addr1++;
+               addr2++;
+
+               /* check for ctrl-c to abort... */
+               if (ctrlc()) {
+                       my_puts("Abort\n");
+                       return 0;
+               }
+       }
+
+       printf("Total of %ld byte(s) (0x%lx) were the same\n", ngood, ngood);
+       return rcode;
+}
+
+int do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       uint32_t src, dest, count;
+       int_fast8_t step;
+
+       (void) cmdtp;
+       (void) flag;
+
+       if (argc != 4)
+               return CMD_RET_USAGE;
+
+       src = strtoul(argv[1], NULL, 16);
+       src += base_address;
+       dest = strtoul(argv[2], NULL, 16);
+       dest += base_address;
+       count = strtoul(argv[3], NULL, 16);
+
+       if (count == 0) {
+               my_puts ("Zero length ???\n");
+               return 1;
+       }
+       
+       if (dest > src) {
+               src += count - 1;
+               dest += count - 1;
+               step = -1;
+       } else
+               step = 1;
+
+       while (count-- > 0) {
+               uint8_t data;
+               z80_bus_cmd(Request);
+               data = z80_read(src);
+               z80_write(dest, data);
+               z80_bus_cmd(Release);
+               src += step;
+               dest += step;
+
+               /* check for ctrl-c to abort... */
+               if (ctrlc()) {
+                       my_puts("Abort\n");
+                       return 0;
+               }
+       }
+       return 0;
+}
+
+int do_mem_base(cmd_tbl_t *cmdtp, int flag, int argc,
+                      char * const argv[])
+{
+       (void) cmdtp;
+       (void) flag;
+
+       if (argc > 1) {
+               /* Set new base address. */
+               base_address = strtoul(argv[1], NULL, 16);
+       }
+       /* Print the current base address. */
+       printf("Base Address: 0x%05lx\n", base_address);
+       return 0;
+}
+
+int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
+                      char * const argv[])
+{
+       uint32_t addr, length;
+
+       (void) cmdtp;
+       (void) flag;
+
+       if (argc < 3)
+               return CMD_RET_USAGE;
+
+       /* Address is always specified. */
+       addr = strtoul(argv[1], NULL, 16);
+
+       /* Length is the number of bytes. */
+       length = strtoul(argv[2], NULL, 16);
+
+
+       /* We want to optimize the loops to run as fast as possible.
+        * If we have only one object, just run infinite loops.
+        */
+       if (length == 1) {
+               z80_bus_cmd(Request);
+               for (;;)
+                       z80_read(addr);
+               z80_bus_cmd(Release);
+       }
+
+       z80_bus_cmd(Request);
+       for (;;) {
+               uint32_t i = length;
+               uint32_t p = addr;
+               while (i-- > 0)
+                       z80_read(p++);
+       }
+       z80_bus_cmd(Release);
+
+       return 0;
+}
+
+#ifdef CONFIG_LOOPW
+int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       uint32_t addr, length;
+       uint8_t data;
+
+       (void) cmdtp;
+       (void) flag;
+
+       if (argc < 4)
+               return CMD_RET_USAGE;
+
+       /* Address is always specified. */
+       addr = strtoul(argv[1], NULL, 16);
+
+       /* Length is the number of bytes. */
+       length = strtoul(argv[2], NULL, 16);
+
+       data = strtoul(argv[3], NULL, 16);
+
+       /* We want to optimize the loops to run as fast as possible.
+        * If we have only one object, just run infinite loops.
+        */
+       if (length == 1) {
+               z80_bus_cmd(Request);
+               for (;;)
+                       z80_write(addr, data);
+       }
+
+       for (;;) {
+               uint32_t i = length;
+               uint32_t p = addr;
+               while (i-- > 0)
+                       z80_write(p++, data);
+       }
+}
+#endif /* CONFIG_LOOPW */
+
+#ifdef CONFIG_CMD_MEMTEST
+static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_addr,
+                         vu_long *dummy)
+{
+       vu_long *addr;
+       uint32_t errs = 0;
+       uint32_t val, readback;
+       int j;
+       vu_long offset;
+       vu_long test_offset;
+       vu_long pattern;
+       vu_long temp;
+       vu_long anti_pattern;
+       vu_long num_words;
+       static const FLASH uint32_t bitpattern[] = {
+               0x00000001,     /* single bit */
+               0x00000003,     /* two adjacent bits */
+               0x00000007,     /* three adjacent bits */
+               0x0000000F,     /* four adjacent bits */
+               0x00000005,     /* two non-adjacent bits */
+               0x00000015,     /* three non-adjacent bits */
+               0x00000055,     /* four non-adjacent bits */
+               0xaaaaaaaa,     /* alternating 1/0 */
+       };
+
+       num_words = (end_addr - start_addr) / sizeof(vu_long);
+
+       /*
+        * Data line test: write a pattern to the first
+        * location, write the 1's complement to a 'parking'
+        * address (changes the state of the data bus so a
+        * floating bus doesn't give a false OK), and then
+        * read the value back. Note that we read it back
+        * into a variable because the next time we read it,
+        * it might be right (been there, tough to explain to
+        * the quality guys why it prints a failure when the
+        * "is" and "should be" are obviously the same in the
+        * error message).
+        *
+        * Rather than exhaustively testing, we test some
+        * patterns by shifting '1' bits through a field of
+        * '0's and '0' bits through a field of '1's (i.e.
+        * pattern and ~pattern).
+        */
+       addr = buf;
+       for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) {
+               val = bitpattern[j];
+               for (; val != 0; val <<= 1) {
+                       *addr = val;
+                       *dummy  = ~val; /* clear the test data off the bus */
+                       readback = *addr;
+                       if (readback != val) {
+                               printf("FAILURE (data line): "
+                                       "expected %05lx, actual %05lx\n",
+                                               val, readback);
+                               errs++;
+                               if (ctrlc())
+                                       return -1;
+                       }
+                       *addr  = ~val;
+                       *dummy  = val;
+                       readback = *addr;
+                       if (readback != ~val) {
+                               printf("FAILURE (data line): "
+                                       "Is %05lx, should be %05lx\n",
+                                               readback, ~val);
+                               errs++;
+                               if (ctrlc())
+                                       return -1;
+                       }
+               }
+       }
+
+       /*
+        * Based on code whose Original Author and Copyright
+        * information follows: Copyright (c) 1998 by Michael
+        * Barr. This software is placed into the public
+        * domain and may be used for any purpose. However,
+        * this notice must not be changed or removed and no
+        * warranty is either expressed or implied by its
+        * publication or distribution.
+        */
+
+       /*
+       * Address line test
+
+        * Description: Test the address bus wiring in a
+        *              memory region by performing a walking
+        *              1's test on the relevant bits of the
+        *              address and checking for aliasing.
+        *              This test will find single-bit
+        *              address failures such as stuck-high,
+        *              stuck-low, and shorted pins. The base
+        *              address and size of the region are
+        *              selected by the caller.
+
+        * Notes:       For best results, the selected base
+        *              address should have enough LSB 0's to
+        *              guarantee single address bit changes.
+        *              For example, to test a 64-Kbyte
+        *              region, select a base address on a
+        *              64-Kbyte boundary. Also, select the
+        *              region size as a power-of-two if at
+        *              all possible.
+        *
+        * Returns:     0 if the test succeeds, 1 if the test fails.
+        */
+       pattern = (vu_long) 0xaaaaaaaa;
+       anti_pattern = (vu_long) 0x55555555;
+
+       debug("%s:%d: length = 0x%.5lx\n", __func__, __LINE__, num_words);
+       /*
+        * Write the default pattern at each of the
+        * power-of-two offsets.
+        */
+       for (offset = 1; offset < num_words; offset <<= 1)
+               addr[offset] = pattern;
+
+       /*
+        * Check for address bits stuck high.
+        */
+       test_offset = 0;
+       addr[test_offset] = anti_pattern;
+
+       for (offset = 1; offset < num_words; offset <<= 1) {
+               temp = addr[offset];
+               if (temp != pattern) {
+                       printf("\nFAILURE: Address bit stuck high @ 0x%.5lx:"
+                               " expected 0x%.5lx, actual 0x%.5lx\n",
+                               start_addr + offset*sizeof(vu_long),
+                               pattern, temp);
+                       errs++;
+                       if (ctrlc())
+                               return -1;
+               }
+       }
+       addr[test_offset] = pattern;
+
+       /*
+        * Check for addr bits stuck low or shorted.
+        */
+       for (test_offset = 1; test_offset < num_words; test_offset <<= 1) {
+               addr[test_offset] = anti_pattern;
+
+               for (offset = 1; offset < num_words; offset <<= 1) {
+                       temp = addr[offset];
+                       if ((temp != pattern) && (offset != test_offset)) {
+                               printf("\nFAILURE: Address bit stuck low or"
+                                       " shorted @ 0x%.5lx: expected 0x%.5lx,"
+                                       " actual 0x%.5lx\n",
+                                       start_addr + offset*sizeof(vu_long),
+                                       pattern, temp);
+                               errs++;
+                               if (ctrlc())
+                                       return -1;
+                       }
+               }
+               addr[test_offset] = pattern;
+       }
+
+       /*
+        * Description: Test the integrity of a physical
+        *              memory device by performing an
+        *              increment/decrement test over the
+        *              entire region. In the process every
+        *              storage bit in the device is tested
+        *              as a zero and a one. The base address
+        *              and the size of the region are
+        *              selected by the caller.
+        *
+        * Returns:     0 if the test succeeds, 1 if the test fails.
+        */
+       num_words++;
+
+       /*
+        * Fill memory with a known pattern.
+        */
+       for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+               addr[offset] = pattern;
+       }
+
+       /*
+        * Check each location and invert it for the second pass.
+        */
+       for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+               temp = addr[offset];
+               if (temp != pattern) {
+                       printf("\nFAILURE (read/write) @ 0x%.5lx:"
+                               " expected 0x%.5lx, actual 0x%.5lx)\n",
+                               start_addr + offset*sizeof(vu_long),
+                               pattern, temp);
+                       errs++;
+                       if (ctrlc())
+                               return -1;
+               }
+
+               anti_pattern = ~pattern;
+               addr[offset] = anti_pattern;
+       }
+
+       /*
+        * Check each location for the inverted pattern and zero it.
+        */
+       for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+               WATCHDOG_RESET();
+               anti_pattern = ~pattern;
+               temp = addr[offset];
+               if (temp != anti_pattern) {
+                       printf("\nFAILURE (read/write): @ 0x%.5lx:"
+                               " expected 0x%.5lx, actual 0x%.5lx)\n",
+                               start_addr + offset*sizeof(vu_long),
+                               anti_pattern, temp);
+                       errs++;
+                       if (ctrlc())
+                               return -1;
+               }
+               addr[offset] = 0;
+       }
+
+       return 0;
+}
+
+static uint32_t mem_test_quick(vu_long *buf, uint32_t start_addr, uint32_t end_addr,
+                           vu_long pattern, int iteration)
+{
+       vu_long *end;
+       vu_long *addr;
+       uint32_t errs = 0;
+       uint32_t incr, length;
+       uint32_t val, readback;
+
+       /* Alternate the pattern */
+       incr = 1;
+       if (iteration & 1) {
+               incr = -incr;
+               /*
+                * Flip the pattern each time to make lots of zeros and
+                * then, the next time, lots of ones.  We decrement
+                * the "negative" patterns and increment the "positive"
+                * patterns to preserve this feature.
+                */
+               if (pattern & 0x80000000)
+                       pattern = -pattern;     /* complement & increment */
+               else
+                       pattern = ~pattern;
+       }
+       length = (end_addr - start_addr) / sizeof(uint32_t);
+       end = buf + length;
+       printf("\rPattern %08lX  Writing..."
+               "%12s"
+               "\b\b\b\b\b\b\b\b\b\b",
+               pattern, "");
+
+       for (addr = buf, val = pattern; addr < end; addr++) {
+               *addr = val;
+               val += incr;
+       }
+
+       my_puts("Reading...");
+
+       for (addr = buf, val = pattern; addr < end; addr++) {
+               readback = *addr;
+               if (readback != val) {
+                       uint32_t offset = addr - buf;
+
+                       printf("\nMem error @ 0x%08X: "
+                               "found %08lX, expected %08lX\n",
+                               (unsigned int)(uintptr_t)(start_addr + offset*sizeof(vu_long)),
+                               readback, val);
+                       errs++;
+                       if (ctrlc())
+                               return -1;
+               }
+               val += incr;
+       }
+
+       return 0;
+}
+
+/*
+ * Perform a memory test. A more complete alternative test can be
+ * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
+ * interrupted by ctrl-c or by a failure of one of the sub-tests.
+ */
+int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,
+                       char * const argv[])
+{
+       uint32_t start, end;
+       vu_long *buf, *dummy;
+       int iteration_limit;
+       int ret;
+       uint32_t errs = 0;      /* number of errors, or -1 if interrupted */
+       uint32_t pattern;
+       int iteration;
+#if defined(CONFIG_SYS_ALT_MEMTEST)
+       const int alt_test = 1;
+#else
+       const int alt_test = 0;
+#endif
+
+       if (argc > 1)
+               start = strtoul(argv[1], NULL, 16);
+       else
+               start = CONFIG_SYS_MEMTEST_START;
+
+       if (argc > 2)
+               end = strtoul(argv[2], NULL, 16);
+       else
+               end = CONFIG_SYS_MEMTEST_END;
+
+       if (argc > 3)
+               pattern = (uint32_t)strtoul(argv[3], NULL, 16);
+       else
+               pattern = 0;
+
+       if (argc > 4)
+               iteration_limit = (uint32_t)strtoul(argv[4], NULL, 16);
+       else
+               iteration_limit = 0;
+
+       printf("Testing %08x ... %08x:\n", (unsigned int)start, (unsigned int)end);
+       debug("%s:%d: start %#05lx end %#05lx\n", __func__, __LINE__,
+             start, end);
+
+/* TODO: */
+//     buf = map_sysmem(start, end - start);
+//     dummy = map_sysmem(CONFIG_SYS_MEMTEST_SCRATCH, sizeof(vu_long));
+       for (iteration = 0;
+                       !iteration_limit || iteration < iteration_limit;
+                       iteration++) {
+               if (ctrlc()) {
+                       errs = -1UL;
+                       break;
+               }
+
+               printf("Iteration: %6d\r", iteration + 1);
+               debug("\n");
+               if (alt_test) {
+                       errs = mem_test_alt(buf, start, end, dummy);
+               } else {
+                       errs = mem_test_quick(buf, start, end, pattern,
+                                             iteration);
+               }
+               if (errs == -1UL)
+                       break;
+       }
+
+       if (errs == -1UL) {
+               /* Memory test was aborted - write a newline to finish off */
+               putc('\n');
+               ret = 1;
+       } else {
+               printf("Tested %d iteration(s) with %lu errors.\n",
+                       iteration, errs);
+               ret = errs != 0;
+       }
+
+       return ret;     /* not reached */
+}
+#endif /* CONFIG_CMD_MEMTEST */
+
+/* Modify memory.
+ *
+ * Syntax:
+ *     mm {addr}
+ *     nm {addr}
+ */
+static int
+mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
+{
+       uint32_t addr;
+       uint8_t data;
+       int nbytes;
+
+       (void) cmdtp;
+
+       if (argc != 2)
+               return CMD_RET_USAGE;
+
+       /* We use the last specified parameters, unless new ones are
+        * entered.
+        */
+       addr = mm_last_addr;
+
+       if ((flag & CMD_FLAG_REPEAT) == 0) {
+               /* New command specified.  
+                */
+
+               /* Address is specified since argc > 1
+               */
+               addr = strtoul(argv[1], NULL, 16);
+               addr += base_address;
+       }
+
+       /* Print the address, followed by value.  Then accept input for
+        * the next value.  A non-converted value exits.
+        */
+       do {
+               z80_bus_cmd(Request);
+               data = z80_read(addr);
+               printf("%05lx: %02x", addr, data);
+               z80_bus_cmd(Release);
+
+               nbytes = cli_readline(PSTR(" ? "));
+               if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
+                       /* <CR> pressed as only input, don't modify current
+                        * location and move to next. "-" pressed will go back.
+                        */
+                       if (incrflag)
+                               addr += nbytes ? -1 : 1;
+                       nbytes = 1;
+               }
+               else {
+                       char *endp;
+                       data = strtoul(console_buffer, &endp, 16);
+                       nbytes = endp - console_buffer;
+                       if (nbytes) {
+                               z80_bus_cmd(Request);
+                               z80_write(addr, data);
+                               z80_bus_cmd(Release);
+                               if (incrflag)
+                                       addr++;
+                       }
+               }
+       } while (nbytes);
+
+       mm_last_addr = addr;
+       return 0;
+}
+
diff --git a/avr/cmd_mem.h b/avr/cmd_mem.h
new file mode 100644 (file)
index 0000000..9803fd2
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef CMD_MEM_H
+#define CMD_MEM_H
+
+//#include "common.h"
+
+#include "command.h"
+#include "cmd_mem.h"
+
+
+extern int do_mem_md(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_mm(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_nm(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_mw(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_cp(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_cmp(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_base(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_loop(cmd_tbl_t *, int, int, char * const []);
+#ifdef CONFIG_LOOPW
+extern int do_mem_loopw(cmd_tbl_t *, int, int, char * const []);
+#endif
+#ifdef CONFIG_CMD_MEMTEST
+extern int do_mem_mtest(cmd_tbl_t *, int, int, char * const []);
+#endif
+#ifdef CONFIG_MX_CYCLIC
+extern int do_mem_mdc(cmd_tbl_t *, int, int, char * const []);
+extern int do_mem_mwc(cmd_tbl_t *, int, int, char * const []);
+#endif /* CONFIG_MX_CYCLIC */
+
+#endif /* CMD_MEM_H */
+
diff --git a/avr/command.c b/avr/command.c
new file mode 100644 (file)
index 0000000..df4bb98
--- /dev/null
@@ -0,0 +1,526 @@
+
+/*
+ *  Command Processor Table
+ */
+
+#include "common.h"
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "config.h"
+#include "debug.h"
+#include "con-utils.h"
+#include "env.h"
+#include "timer.h"
+#include "command.h"
+
+
+static void print_blanks(int_fast8_t count)
+{
+       while(count--)
+               my_puts_P(PSTR(" "));
+}
+
+static void print_usage_line(const FLASH char *name, const FLASH char *usage)
+{
+       my_puts_P(name);
+       print_blanks(CONFIG_SYS_MAXARGS - strlen_P(name));
+       my_puts_P(PSTR(" - "));
+       my_puts_P(usage);
+       my_puts_P(PSTR("\n"));
+}
+
+int strcmp_PP(const FLASH char *s1, const FLASH char *s2)
+{
+       unsigned char c1, c2;
+
+       while ((c1 = *(const FLASH unsigned char *)s1++) 
+                       == (c2 = *(const FLASH unsigned char *)s2++))
+               if (c1 == 0)
+                       return 0;
+
+       return c1 - c2;
+}
+
+int cmpstringp(const void *p1, const void *p2)
+{
+       return strcmp_PP((*(const FLASH cmd_tbl_t **) p1)->name, 
+                        (*(const FLASH cmd_tbl_t **) p2)->name);
+}
+
+int cmd_tbl_item_count(void)
+{
+       cmd_tbl_t * p = cmd_tbl;
+       int count = 0;
+
+       while (p->name != NULL) {
+               p++; count++;
+       }
+       return count;
+}
+
+/*
+ * Use puts() instead of printf() to avoid printf buffer overflow
+ * for long help messages
+ */
+
+int _do_help(cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp,
+               int flag, int argc, char * const argv[])
+{
+       uint_fast8_t i;
+       int rcode = 0;
+
+       (void) flag;
+
+       if (argc == 1) {        /*show list of commands */
+               cmd_tbl_t *cmd_array[cmd_items];
+               int i;
+
+               /* Make array of commands from .uboot_cmd section */
+               cmdtp = cmd_start;
+               for (i = 0; i < cmd_items; i++) {
+                       cmd_array[i] = cmdtp++;
+               }
+
+               /* Sort command list */
+               qsort(cmd_array, cmd_items, sizeof (cmd_tbl_t *), cmpstringp);
+
+               /* print short help (usage) */
+               for (i = 0; i < cmd_items; i++) {
+                       const FLASH char *usage = cmd_array[i]->usage;
+
+                       /* allow user abort */
+                       if (ctrlc ())
+                               return 1;
+                       if (usage == NULL)
+                               continue;
+#ifdef GCC_BUG_61443 
+                       print_usage_line(cmd_array[i]->name, usage);
+#else
+                       printf_P(PSTR("%-" stringify(CONFIG_SYS_MAXARGS) "S - %S\n"), 
+                                       cmd_array[i]->name, usage);
+#endif
+               }
+               return 0;
+       }
+       /*
+        * command help (long version)
+        */
+       for (i = 1; i < argc; ++i) {
+               if ((cmdtp = find_cmd_tbl (argv[i], cmd_start, cmd_items )) != NULL) {
+                       rcode |= cmd_usage(cmdtp);
+               } else {
+                       printf_P(PSTR("Unknown command '%s' - try 'help'"
+                               " without arguments.\n\n"), argv[i]
+                               );
+                       rcode = 1;
+               }
+       }
+       return rcode;
+}
+
+/***************************************************************************
+ * find command table entry for a command
+ */
+cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len)
+{
+       cmd_tbl_t *cmdtp;
+       cmd_tbl_t *cmdtp_temp = table;  /*Init value */
+       size_t len;
+       uint_fast8_t n_found = 0;
+
+       if (!cmd)
+               return NULL;
+
+       len = strlen(cmd);
+
+       for (cmdtp = table;
+            cmdtp != table + table_len;
+            cmdtp++) {
+               if (strncmp_P (cmd, cmdtp->name, len) == 0) {
+                       if (len == strlen (cmdtp->name))
+                               return cmdtp;   /* full match */
+
+                       cmdtp_temp = cmdtp;     /* abbreviated command ? */
+                       n_found++;
+               }
+       }
+       if (n_found == 1) {                     /* exactly one match */
+               return cmdtp_temp;
+       }
+
+       return NULL;    /* not found or ambiguous command */
+}
+
+
+cmd_tbl_t *find_cmd (const char *cmd)
+{
+       return find_cmd_tbl(cmd, cmd_tbl, cmd_tbl_item_count());
+}
+
+
+int cmd_usage(const FLASH cmd_tbl_t *cmdtp)
+{
+//     printf("%s - %s\n\n", cmdtp->name, cmdtp->usage);
+       print_usage_line(cmdtp->name, cmdtp->usage);
+#if 0
+       my_puts_P(cmdtp->name);
+       print_blanks(CONFIG_SYS_MAXARGS - strlen_P(cmdtp->name));
+       my_puts_P(PSTR(" - "));
+       my_puts_P(cmdtp->usage);
+       my_puts_P(PSTR("\n\n"));
+#endif
+#ifdef CONFIG_SYS_LONGHELP
+//     printf("Usage:\n%s ", cmdtp->name);
+       my_puts_P(PSTR("Usage:\n"));
+       my_puts_P(cmdtp->name);
+       my_puts_P(PSTR(" "));
+
+       if (!cmdtp->help) {
+               my_puts_P(PSTR(" - No additional help available.\n"));
+               return 1;
+       }
+
+       my_puts_P(cmdtp->help);
+       my_puts_P(PSTR("\n"));
+#endif /* CONFIG_SYS_LONGHELP */
+       return 1;
+}
+
+#ifdef CONFIG_AUTO_COMPLETE
+
+int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[])
+{
+       static char tmp_buf[512];
+       int space;
+
+       space = last_char == '\0' || isblank(last_char);
+
+       if (space && argc == 1)
+               return env_complete("", maxv, cmdv, sizeof(tmp_buf), tmp_buf);
+
+       if (!space && argc == 2)
+               return env_complete(argv[1], maxv, cmdv, sizeof(tmp_buf), tmp_buf);
+
+       return 0;
+}
+
+/*************************************************************************************/
+
+static int complete_cmdv(int argc, char * const argv[], char last_char, int maxv, char *cmdv[])
+{
+       cmd_tbl_t *cmdtp = cmd_tbl;
+//     const int count = ARRAY_SIZE(cmd_tbl);
+//     const cmd_tbl_t *cmdend = cmdtp + count;
+//     const char *p;
+       int len, clen;
+       int n_found = 0;
+       const char *cmd;
+
+       /* sanity? */
+       if (maxv < 2)
+               return -2;
+
+       cmdv[0] = NULL;
+
+       if (argc == 0) {
+               /* output full list of commands */
+               for (; cmdtp->name[0] != '\0'; cmdtp++) {
+                       if (n_found >= maxv - 2) {
+                               cmdv[n_found++] = "...";
+                               break;
+                       }
+                       cmdv[n_found++] = cmdtp->name;
+               }
+               cmdv[n_found] = NULL;
+               return n_found;
+       }
+
+       /* more than one arg or one but the start of the next */
+       if (argc > 1 || (last_char == '\0' || isblank(last_char))) {
+               cmdtp = find_cmd(argv[0]);
+               if (cmdtp == NULL || cmdtp->complete == NULL) {
+                       cmdv[0] = NULL;
+                       return 0;
+               }
+               return (*cmdtp->complete)(argc, argv, last_char, maxv, cmdv);
+       }
+
+       cmd = argv[0];
+
+       len = strlen(cmd);
+
+       /* return the partial matches */
+       for (; cmdtp->name[0] != '\0'; cmdtp++) {
+
+               clen = strlen(cmdtp->name);
+               if (clen < len)
+                       continue;
+
+               if (memcmp(cmd, cmdtp->name, len) != 0)
+                       continue;
+
+               /* too many! */
+               if (n_found >= maxv - 2) {
+                       cmdv[n_found++] = "...";
+                       break;
+               }
+
+               cmdv[n_found++] = cmdtp->name;
+       }
+
+       cmdv[n_found] = NULL;
+       return n_found;
+}
+
+static int make_argv(char *s, int argvsz, char *argv[])
+{
+       int argc = 0;
+
+       /* split into argv */
+       while (argc < argvsz - 1) {
+
+               /* skip any white space */
+               while (isblank(*s))
+                       ++s;
+
+               if (*s == '\0') /* end of s, no more args       */
+                       break;
+
+               argv[argc++] = s;       /* begin of argument string     */
+
+               /* find end of string */
+               while (*s && !isblank(*s))
+                       ++s;
+
+               if (*s == '\0')         /* end of s, no more args       */
+                       break;
+
+               *s++ = '\0';            /* terminate current arg         */
+       }
+       argv[argc] = NULL;
+
+       return argc;
+}
+
+static void print_argv(const char *banner, const char *leader, const char *sep, int linemax, char * const argv[])
+{
+       int ll = leader != NULL ? strlen(leader) : 0;
+       int sl = sep != NULL ? strlen(sep) : 0;
+       int len, i;
+
+       if (banner) {
+               my_puts_P(PSTR("\n"));
+               my_puts(banner);
+       }
+
+       i = linemax;    /* force leader and newline */
+       while (*argv != NULL) {
+               len = strlen(*argv) + sl;
+               if (i + len >= linemax) {
+                       my_puts_P(PSTR("\n"));
+                       if (leader)
+                               my_puts(leader);
+                       i = ll - sl;
+               } else if (sep)
+                       my_puts(sep);
+               my_puts(*argv++);
+               i += len;
+       }
+       my_puts_P(PSTR("\n"));
+}
+
+static int find_common_prefix(char * const argv[])
+{
+       int i, len;
+       char *anchor, *s, *t;
+
+       if (*argv == NULL)
+               return 0;
+
+       /* begin with max */
+       anchor = *argv++;
+       len = strlen(anchor);
+       while ((t = *argv++) != NULL) {
+               s = anchor;
+               for (i = 0; i < len; i++, t++, s++) {
+                       if (*t != *s)
+                               break;
+               }
+               len = s - anchor;
+       }
+       return len;
+}
+
+static char tmp_buf[CONFIG_SYS_CBSIZE];        /* copy of console I/O buffer   */
+
+int cmd_auto_complete(const FLASH char *const prompt, char *buf, int *np, int *colp)
+{
+       int n = *np, col = *colp;
+       char *argv[CONFIG_SYS_MAXARGS + 1];             /* NULL terminated      */
+       char *cmdv[20];
+       char *s, *t;
+       const char *sep;
+       int i, j, k, len, seplen, argc;
+       int cnt;
+       char last_char;
+
+       if (strcmp_PP(prompt, CONFIG_SYS_PROMPT) != 0)
+               return 0;       /* not in normal console */
+
+       cnt = strlen(buf);
+       if (cnt >= 1)
+               last_char = buf[cnt - 1];
+       else
+               last_char = '\0';
+
+       /* copy to secondary buffer which will be affected */
+       strcpy(tmp_buf, buf);
+
+       /* separate into argv */
+       argc = make_argv(tmp_buf, sizeof(argv)/sizeof(argv[0]), argv);
+
+       /* do the completion and return the possible completions */
+       i = complete_cmdv(argc, argv, last_char, sizeof(cmdv)/sizeof(cmdv[0]), cmdv);
+
+       /* no match; bell and out */
+       if (i == 0) {
+               if (argc > 1)   /* allow tab for non command */
+                       return 0;
+               putchar('\a');
+               return 1;
+       }
+
+       s = NULL;
+       len = 0;
+       sep = NULL;
+       seplen = 0;
+       if (i == 1) { /* one match; perfect */
+               k = strlen(argv[argc - 1]);
+               s = cmdv[0] + k;
+               len = strlen(s);
+               sep = " ";
+               seplen = 1;
+       } else if (i > 1 && (j = find_common_prefix(cmdv)) != 0) {      /* more */
+               k = strlen(argv[argc - 1]);
+               j -= k;
+               if (j > 0) {
+                       s = cmdv[0] + k;
+                       len = j;
+               }
+       }
+
+       if (s != NULL) {
+               k = len + seplen;
+               /* make sure it fits */
+               if (n + k >= CONFIG_SYS_CBSIZE - 2) {
+                       putchar('\a');
+                       return 1;
+               }
+
+               t = buf + cnt;
+               for (i = 0; i < len; i++)
+                       *t++ = *s++;
+               if (sep != NULL)
+                       for (i = 0; i < seplen; i++)
+                               *t++ = sep[i];
+               *t = '\0';
+               n += k;
+               col += k;
+               my_puts(t - k);
+               if (sep == NULL)
+                       putchar('\a');
+               *np = n;
+               *colp = col;
+       } else {
+               print_argv(NULL, "  ", " ", 78, cmdv);
+
+               my_puts_P(prompt);
+               my_puts(buf);
+       }
+       return 1;
+}
+
+#endif /* CONFIG_AUTO_COMPLETE */
+
+
+
+/**
+ * Call a command function. This should be the only route in U-Boot to call
+ * a command, so that we can track whether we are waiting for input or
+ * executing a command.
+ *
+ * @param cmdtp                Pointer to the command to execute
+ * @param flag         Some flags normally 0 (see CMD_FLAG_.. above)
+ * @param argc         Number of arguments (arg 0 must be the command text)
+ * @param argv         Arguments
+ * @return 0 if command succeeded, else non-zero (CMD_RET_...)
+ */
+static int cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       int result;
+
+       result = (cmdtp->cmd)(cmdtp, flag, argc, argv);
+       if (result)
+               debug("Command failed, result=%d\n", result);
+       return result;
+}
+
+enum command_ret_t cmd_process(int flag, int argc, char * const argv[],
+                              uint_fast8_t *repeatable)
+{
+       enum command_ret_t rc = CMD_RET_SUCCESS;
+       cmd_tbl_t *cmdtp;
+
+       /* Look up command in command table */
+       cmdtp = find_cmd(argv[0]);
+       if (cmdtp == NULL) {
+               printf_P(PSTR("Unknown command '%s' - try 'help'\n"), argv[0]);
+               return 1;
+       }
+       if (!cmdtp->cmd) {
+               debug("### Command '%s' found, but ->cmd == NULL \n", argv[0]);
+               return 1;
+       }
+
+       /* found - check max args */
+       if (argc > cmdtp->maxargs)
+               rc = CMD_RET_USAGE;
+
+#if defined(CONFIG_CMD_BOOTD)
+       /* avoid "bootd" recursion */
+       else if (cmdtp->cmd == do_bootd) {
+               if (flag & CMD_FLAG_BOOTD) {
+                       my_puts_P(PSTR("'bootd' recursion detected\n"));
+                       rc = CMD_RET_FAILURE;
+               } else {
+                       flag |= CMD_FLAG_BOOTD;
+               }
+       }
+#endif
+
+       /* If OK so far, then do the command */
+       if (!rc) {
+               rc = cmd_call(cmdtp, flag, argc, argv);
+               *repeatable &= cmdtp->repeatable;
+       }
+       if (rc == CMD_RET_USAGE)
+               rc = cmd_usage(cmdtp);
+       return rc;
+}
+
+int cmd_process_error(cmd_tbl_t *cmdtp, int err)
+{
+       char buf[strlen_P(cmdtp->name) + 1];
+       strcpy_P(buf, cmdtp->name);
+
+       if (err) {
+               printf_P(PSTR("Command '%s' failed: Error %d\n"), buf, err);
+               return 1;
+       }
+
+       return 0;
+}
diff --git a/avr/command.h b/avr/command.h
new file mode 100644 (file)
index 0000000..82b83ba
--- /dev/null
@@ -0,0 +1,157 @@
+
+/*
+ *  Definitions for Command Processor
+ */
+#ifndef __COMMAND_H
+#define __COMMAND_H
+
+#include "common.h"
+#include "config.h"
+
+#ifndef NULL
+#define NULL   0
+#endif
+
+/* Default to a width of 8 characters for help message command width */
+#ifndef CONFIG_SYS_HELP_CMD_WIDTH
+#define CONFIG_SYS_HELP_CMD_WIDTH      8
+#endif
+
+/*
+ * Monitor Command Table
+ */
+
+struct cmd_tbl_s {
+       const FLASH char *name;         /* Command Name                 */
+       int             maxargs;        /* maximum number of arguments  */
+       int             repeatable;     /* autorepeat allowed?          */
+                                       /* Implementation function      */
+       int             (*cmd)(const FLASH struct cmd_tbl_s *, int, int, char * const []);
+       const FLASH char *usage;                /* Usage message        (short) */
+#ifdef CONFIG_SYS_LONGHELP
+       const FLASH char *help;         /* Help  message        (long)  */
+#endif
+#ifdef CONFIG_AUTO_COMPLETE
+       /* do auto completion on the arguments */
+       int             (*complete)(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]);
+#endif
+};
+
+typedef const FLASH struct cmd_tbl_s cmd_tbl_t;
+
+extern int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+
+/* command.c */
+int _do_help (cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp, int
+             flag, int argc, char * const argv[]);
+cmd_tbl_t *find_cmd(const char *cmd);
+cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len);
+
+int cmd_tbl_item_count(void);
+int cmd_usage(cmd_tbl_t *cmdtp);
+
+#ifdef CONFIG_AUTO_COMPLETE
+extern int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]);
+extern int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp);
+#endif
+
+/**
+ * cmd_process_error() - report and process a possible error
+ *
+ * @cmdtp: Command which caused the error
+ * @err: Error code (0 if none, -ve for error, like -EIO)
+ * @return 0 if there is not error, 1 (CMD_RET_FAILURE) if an error is found
+ */
+int cmd_process_error(cmd_tbl_t *cmdtp, int err);
+
+/*
+ * Monitor Command
+ *
+ * All commands use a common argument format:
+ *
+ * void function (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+ */
+
+
+#ifdef CONFIG_CMD_BOOTD
+extern int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+#endif
+#ifdef CONFIG_CMD_BOOTM
+extern int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+extern int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd);
+#else
+static inline int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
+{
+       (void) cmdtp; (void) cmd;
+
+       return 0;
+}
+#endif
+
+extern int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc,
+                          char *const argv[]);
+
+extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+
+/*
+ * Error codes that commands return to cmd_process(). We use the standard 0
+ * and 1 for success and failure, but add one more case - failure with a
+ * request to call cmd_usage(). But the cmd_process() function handles
+ * CMD_RET_USAGE itself and after calling cmd_usage() it will return 1.
+ * This is just a convenience for commands to avoid them having to call
+ * cmd_usage() all over the place.
+ */
+enum command_ret_t {
+       CMD_RET_SUCCESS,        /* 0 = Success */
+       CMD_RET_FAILURE,        /* 1 = Failure */
+       CMD_RET_USAGE = -1,     /* Failure, please report 'usage' error */
+};
+
+/**
+ * Process a command with arguments. We look up the command and execute it
+ * if valid. Otherwise we print a usage message.
+ *
+ * @param flag         Some flags normally 0 (see CMD_FLAG_.. above)
+ * @param argc         Number of arguments (arg 0 must be the command text)
+ * @param argv         Arguments
+ * @param repeatable   This function sets this to 0 if the command is not
+ *                     repeatable. If the command is repeatable, the value
+ *                     is left unchanged.
+ * @return 0 if the command succeeded, 1 if it failed
+ */
+int cmd_process(int flag, int argc, char * const argv[], uint_fast8_t *repeatable);
+
+
+/*
+ * Command Flags:
+ */
+#define CMD_FLAG_REPEAT                0x0001  /* repeat last command          */
+#define CMD_FLAG_BOOTD         0x0002  /* command is from bootd        */
+
+#ifdef CONFIG_AUTO_COMPLETE
+# define _CMD_COMPLETE(x) x,
+#else
+# define _CMD_COMPLETE(x)
+#endif
+#ifdef CONFIG_SYS_LONGHELP
+# define _CMD_HELP(x) x,
+#else
+# define _CMD_HELP(x)
+#endif
+
+
+#define CMD_TBL_ITEM_COMPLETE(_name, _maxargs, _rep, _cmd,             \
+                               _usage, _help, _comp)                   \
+               { FSTR(#_name), _maxargs, _rep, _cmd, FSTR(_usage),     \
+                       _CMD_HELP(FSTR(_help)) _CMD_COMPLETE(_comp) }
+
+#define CMD_TBL_ITEM(_name, _maxargs, _rep, _cmd, _usage, _help)       \
+       CMD_TBL_ITEM_COMPLETE(_name, _maxargs, _rep, _cmd,              \
+                                       _usage, _help, NULL)
+
+typedef int (*do_cmd_t)(cmd_tbl_t *, int, int, char * const []);
+
+extern  cmd_tbl_t cmd_tbl[];
+
+
+#endif /* __COMMAND_H */
diff --git a/avr/command_tbl.c b/avr/command_tbl.c
new file mode 100644 (file)
index 0000000..69f6273
--- /dev/null
@@ -0,0 +1,201 @@
+
+#include "common.h"
+
+#include "command.h"
+#include "cmd_mem.h"
+
+
+extern int do_help(cmd_tbl_t *, int, int, char * const []);
+extern int do_echo(cmd_tbl_t *, int, int, char * const []);
+extern int do_env_print(cmd_tbl_t *, int, int, char * const []);
+extern int do_env_set(cmd_tbl_t *, int, int, char * const []);
+extern int do_env_save(cmd_tbl_t *, int, int, char * const []);
+extern int do_loadf(cmd_tbl_t *, int, int, char * const []);
+extern int do_go(cmd_tbl_t *, int, int, char * const []);
+extern int do_restart(cmd_tbl_t *, int, int, char * const []);
+extern int do_dump_mem(cmd_tbl_t *, int, int, char * const []);
+extern int do_eep_cp(cmd_tbl_t *, int, int, char * const []);
+extern int do_busreq_pulse(cmd_tbl_t *, int, int, char * const []);
+
+
+cmd_tbl_t cmd_tbl[] = {
+
+#ifdef DEBUG
+CMD_TBL_ITEM(
+       !mdr,   3,      1,      do_dump_mem,
+       "RAM dump",
+       "address [count]"
+),
+CMD_TBL_ITEM(
+       !mde,   3,      1,      do_dump_mem,
+       "EEPROM dump",
+       "address [count]"
+),
+CMD_TBL_ITEM(
+       !cpe,   4,      0,      do_eep_cp,
+       "EEPROM copy",
+       "source target count"
+),
+#endif
+CMD_TBL_ITEM(
+       mstep,  2,      1,      do_busreq_pulse,
+       "execute one M cycle",
+       "[count]\n"
+       "     - repeat count times"
+),
+CMD_TBL_ITEM(
+       echo,   CONFIG_SYS_MAXARGS,     1,      do_echo,
+       "echo args to console",
+       "[args..]\n"
+       "     - echo args to console; \\c suppresses newline"
+),
+CMD_TBL_ITEM_COMPLETE(
+       run,    CONFIG_SYS_MAXARGS,     1,      do_run,
+       "run commands in an environment variable",
+       "var [...]\n"
+       "    - run the commands in the environment variable(s) 'var'",
+       var_complete
+),
+CMD_TBL_ITEM_COMPLETE(
+       printenv, CONFIG_SYS_MAXARGS,   1,      do_env_print,
+       "print environment variables",
+       "\n"
+       "    - print values of all environment variables\n"
+       "printenv name ...\n"
+       "    - print value of environment variable 'name'",
+       var_complete
+),
+CMD_TBL_ITEM_COMPLETE(
+       setenv, CONFIG_SYS_MAXARGS,     0,      do_env_set,
+       "set environment variables",
+       "name value ...\n"
+       "    - set environment variable 'name' to 'value ...'\n"
+       "setenv name\n"
+       "    - delete environment variable 'name'",
+       var_complete
+),
+CMD_TBL_ITEM(
+       saveenv,        1,      0,      do_env_save,
+       "save environment variables to persistent storage",
+       ""
+),
+
+CMD_TBL_ITEM(
+       loadf,  1,      0,      do_loadf,
+       "load srec_cat prepared image from controller flash",
+       ""
+),
+CMD_TBL_ITEM(
+       go,     2,      0,      do_go,
+       "start application at address 'addr'",
+       "addr\n"
+       "    - start application at address 'addr'"
+//     "\n"
+//     "      passing 'arg' as arguments"
+),
+CMD_TBL_ITEM(
+       reset,  1,      0,      do_reset,
+       "Keep CPU in RESET state",
+       ""
+),
+CMD_TBL_ITEM(
+       restart, 1, 0,  do_restart,
+       "Perform RESET of the CPU",
+       ""
+),
+
+CMD_TBL_ITEM(
+       md,     3,      1,      do_mem_md,
+       "memory display",
+       "address [# of objects]"
+),
+CMD_TBL_ITEM(
+       mm,     2,      1,      do_mem_mm,
+       "memory modify (auto-incrementing address)",
+       "address"
+),
+CMD_TBL_ITEM(
+       nm,     2,      1,      do_mem_nm,
+       "memory modify (constant address)",
+       "address"
+),
+CMD_TBL_ITEM(
+       mw,     4,      1,      do_mem_mw,
+       "memory write (fill)",
+       "address value [count]"
+),
+CMD_TBL_ITEM(
+       cp,     4,      1,      do_mem_cp,
+       "memory copy",
+       "source target count"
+),
+CMD_TBL_ITEM(
+       cmp,    4,      1,      do_mem_cmp,
+       "memory compare",
+       "addr1 addr2 count"
+),
+CMD_TBL_ITEM(
+       base,   2,      1,      do_mem_base,
+       "print or set address offset",
+       "\n"
+       "    - print address offset for memory commands\n"
+       "base offset\n"
+       "    - set address offset for memory commands to 'offset'"
+),
+CMD_TBL_ITEM(
+       loop,   3,      1,      do_mem_loop,
+       "infinite loop on address range",
+       "address number_of_bytes"
+),
+#ifdef CONFIG_LOOPW
+CMD_TBL_ITEM(
+       loopw,  4,      1,      do_mem_loopw,
+       "infinite write loop on address range",
+       "address number_of_bytes data_to_write"
+),
+#endif /* CONFIG_LOOPW */
+
+#ifdef CONFIG_CMD_MEMTEST
+CMD_TBL_ITEM(
+       mtest,  5,      1,      do_mem_mtest,
+       "simple RAM read/write test",
+       "[start [end [pattern [iterations]]]]"
+),
+#endif /* CONFIG_CMD_MEMTEST */
+
+#ifdef CONFIG_MX_CYCLIC
+CMD_TBL_ITEM(
+       mdc,    4,      1,      do_mem_mdc,
+       "memory display cyclic",
+       "address count delay(ms)"
+),
+CMD_TBL_ITEM(
+       mwc,    4,      1,      do_mem_mwc,
+       "memory write cyclic",
+       "address value delay(ms)"
+),
+#endif /* CONFIG_MX_CYCLIC */
+
+
+CMD_TBL_ITEM(
+       help,   CONFIG_SYS_MAXARGS,     1,      do_help,
+       "print command description/usage",
+       "\n"
+       "       - print brief description of all commands\n"
+       "help command ...\n"
+       "       - print detailed usage of 'command'"
+),
+
+/* This does not use the CMD_TBL_ITEM macro as ? can't be used in symbol names */
+       {FSTR("?"),   CONFIG_SYS_MAXARGS, 1, do_help,
+        FSTR("alias for 'help'"),
+#ifdef  CONFIG_SYS_LONGHELP
+       FSTR(""),
+#endif /* CONFIG_SYS_LONGHELP */
+#ifdef CONFIG_AUTO_COMPLETE
+       0,
+#endif
+},
+/* Mark end of table */
+{ 0 },
+};
diff --git a/avr/common.h b/avr/common.h
new file mode 100644 (file)
index 0000000..a92f62c
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#ifdef __AVR__
+#include <avr/io.h>
+
+//TODO:
+//  Known to work: 4.8.4, 4.9.1
+//  Known to fail: 4.8.3, 4.9.0
+#define GCC_BUG_61443 1
+
+#else
+// TODO: stm32
+#endif /* __AVR__ */
+
+#include <stdio.h>
+
+#ifdef __FLASH
+#define FLASH __flash
+#else
+#define FLASH
+#endif 
+
+#define stringify(s)   tostring(s)
+#define tostring(s)    #s
+
+#define FSTR(X) ((const FLASH char[]) { X } )
+#define ARRAY_SIZE(x)  (sizeof(x) / sizeof((x)[0]))
+
+
+#ifdef __AVR__
+#define Stat GPIOR0
+#else
+extern volatile uint_least8_t Stat;
+#endif /* __AVR__ */
+
+#define S_10MS_TO      (1<<0)
+#define S_Z180_RUNNING (2<<0)
+
+static inline 
+void my_puts(const char *s)
+{
+       fputs(s, stdout);
+}
+
+#ifdef __AVR__
+static inline 
+void my_puts_P(const char *s)
+{
+       fputs_P(s, stdout);
+}
+
+#else
+static inline
+void my_puts_P(const char *s)
+{
+       fputs(s, stdout);
+}
+#endif /* __AVR__ */
+#endif /* COMMON_H */
+
diff --git a/avr/con-utils.c b/avr/con-utils.c
new file mode 100644 (file)
index 0000000..02657b9
--- /dev/null
@@ -0,0 +1,95 @@
+
+#include <string.h>
+#include "common.h"
+
+#include "serial.h"
+#include "background.h"
+#include "con-utils.h"
+
+uint_fast8_t tstc(void)
+{
+       bg_shed();
+       return serial_tstc();
+}
+
+int my_getchar(void)
+{
+       int c;
+       
+       do {
+               bg_shed();
+               c = serial_getc();
+       } while (c < 0);
+
+       return c;
+}
+
+
+/* test if ctrl-c was pressed */
+
+static uint_fast8_t ctrlc_disabled;    /* see disable_ctrl() */
+static uint_fast8_t ctrlc_was_pressed;
+
+uint_fast8_t ctrlc(void)
+{
+       if (!ctrlc_disabled) {
+               switch (serial_getc()) {
+               case 0x03:              /* ^C - Control C */
+                       ctrlc_was_pressed = 1;
+                       return 1;
+               default:
+                       break;
+               }
+       }
+       return 0;
+}
+
+/* Reads user's confirmation.
+   Returns 1 if user's input is "y", "Y", "yes" or "YES"
+*/
+uint_fast8_t confirm_yesno(void)
+{
+       unsigned int i;
+       char str_input[5];
+
+       /* Flush input */
+       while (serial_getc())
+               ;
+       i = 0;
+       while (i < sizeof(str_input)) {
+               str_input[i] = my_getchar();
+               putchar(str_input[i]);
+               if (str_input[i] == '\r')
+                       break;
+               i++;
+       }
+       putchar('\n');
+       if (strncmp(str_input, "y\r", 2) == 0 ||
+           strncmp(str_input, "Y\r", 2) == 0 ||
+           strncmp(str_input, "yes\r", 4) == 0 ||
+           strncmp(str_input, "YES\r", 4) == 0)
+               return 1;
+       return 0;
+}
+
+/* pass 1 to disable ctrlc() checking, 0 to enable.
+ * returns previous state
+ */
+uint_fast8_t disable_ctrlc(uint_fast8_t disable)
+{
+       uint_fast8_t prev = ctrlc_disabled;     /* save previous state */
+
+       ctrlc_disabled = disable;
+       return prev;
+}
+
+uint_fast8_t had_ctrlc (void)
+{
+       return ctrlc_was_pressed;
+}
+
+void clear_ctrlc(void)
+{
+       ctrlc_was_pressed = 0;
+}
+
diff --git a/avr/con-utils.h b/avr/con-utils.h
new file mode 100644 (file)
index 0000000..f03dfb3
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef CON_UTILS_H            
+#define CON_UTILS_H
+
+uint_fast8_t tstc(void);
+
+int my_getchar(void);
+
+/* test if ctrl-c was pressed */
+uint_fast8_t ctrlc(void);
+
+
+/* pass 1 to disable ctrlc() checking, 0 to enable.
+ * returns previous state
+ */
+uint_fast8_t disable_ctrlc(uint_fast8_t disable);
+
+uint_fast8_t had_ctrlc (void);
+void clear_ctrlc(void);
+
+#endif /* CON_UTILS_H */
+
+
diff --git a/avr/config.h b/avr/config.h
new file mode 100644 (file)
index 0000000..13de63b
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef CONFIG_H               
+#define CONFIG_H
+
+#define CONFIG_ENV_SIZE                1600
+#define CONFIG_ENV_OFFSET      0
+#define CONFIG_ENVVAR_MAX      20
+
+#define CONFIG_BOOTDELAY       4
+//#define CONFIG_ZERO_BOOTDELAY_CHECK  1
+
+//#define CONFIG_LOOPW
+//#define CONFIG_CMD_MEMTEST
+//#define CONFIG_MX_CYCLIC
+
+#define CONFIG_SYS_CBSIZE      250
+#define CONFIG_SYS_ENV_NAMELEN 16
+#define CONFIG_SYS_MAXARGS     8
+
+#define CONFIG_SYS_PROMPT      "=> "
+
+
+//#define CONFIG_CMDLINE_EDITING       1
+//#define CONFIG_AUTO_COMPLETE 1
+
+#define CONFIG_SYS_LONGHELP    1
+
+#endif /* CONFIG_H */
+
diff --git a/avr/crc.h b/avr/crc.h
new file mode 100644 (file)
index 0000000..c38bae4
--- /dev/null
+++ b/avr/crc.h
@@ -0,0 +1,12 @@
+#ifndef CRC_H
+#define CRC_H
+
+#include <util/crc16.h>
+
+static inline
+uint16_t crc16(uint16_t crc, uint8_t data) 
+{
+       return _crc_ccitt_update(crc, data);
+}
+
+#endif /* CRC_H */
diff --git a/avr/debug.c b/avr/debug.c
new file mode 100644 (file)
index 0000000..e62869b
--- /dev/null
@@ -0,0 +1,227 @@
+#include "common.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <avr/eeprom.h>
+
+#include "command.h"
+#include "debug.h"
+
+/*
+ * Debugging
+ */
+#ifdef DEBUG
+
+//uint8_t eeprom_read_byte (const uint8_t *__p)
+
+static void print_blanks(uint_fast8_t count)
+{
+       while(count--)
+               putchar(' ');
+}
+
+static uint8_t ram_read_byte(const uint8_t *p)
+{
+       return *p;
+}
+
+void dump_mem(const uint8_t *startaddr, int len, 
+               uint8_t (*readfkt)(const uint8_t *), char *title)
+{
+       uint8_t buf[16];
+       uint8_t llen = 16;
+       uint8_t pre = (size_t) startaddr % 16;
+       const uint8_t *addr = (uint8_t *) ((size_t) startaddr & ~0x0f);
+       len += pre;
+       uint8_t i;
+       
+       if (title && *title)
+               printf_P(PSTR("%s\n"),title);
+               
+       while (len) {
+               if (len < 16)
+                       llen = len;
+
+               for (i = pre; i < llen; i++)
+                       buf[i] = readfkt(addr + i);
+
+               printf_P(PSTR("%04x:"), addr);
+               for (i = 0; i < llen; i++) {
+                       if ((i % 8) == 0)
+                               putchar(' ');
+                       if (i < pre)
+                               printf_P(PSTR(".. "));
+                       else
+                               printf_P(PSTR("%.2x "), buf[i]);
+               }
+               /* fill line with whitespace for nice ASCII print */
+               print_blanks(3 * (16u - i) + (16u-i)/8 + 1 + pre);
+               /* Print data in ASCII characters */
+               for (i = pre; i < llen; i++)
+                       printf_P(PSTR("%c"), isprint(buf[i]) ? buf[i] : '.');
+               putchar('\n');
+
+               pre = 0;
+               addr += 16;
+               len -= llen;
+       }
+}
+
+#if 0
+void dump_ram(const uint8_t *startaddr, int len, char *title)
+{
+       uint8_t llen = 16;
+       uint8_t pre = (size_t) startaddr % 16;
+       const uint8_t *addr = (uint8_t *) ((size_t) startaddr & ~0x0f);
+       len += pre;
+       uint8_t i;
+
+       if (title && *title)
+               printf_P(PSTR("%s\n"),title);
+
+       while (len) {
+               if (len < 16)
+                       llen = len;
+
+               printf_P(PSTR("    %.4x:"), (size_t) addr);
+               print_blanks(3 * pre);
+               for (i = pre; i < llen; i++)
+                       printf_P(PSTR(" %.2x"), addr[i]);
+               print_blanks(3 * (16 - i + 1) + pre);
+               for (i = pre; i < llen; i++)
+                       printf_P(PSTR("%c"), isprint(addr[i]) ? addr[i] : '.');
+               putchar('\n');
+
+               pre = 0;
+               addr += 16;
+               len -= llen;
+       }
+}
+#endif
+#if 0
+void dump_heap(void)
+{
+       extern unsigned int __brkval;
+
+       dump_ram((uint8_t *) __malloc_heap_start,
+               __brkval - (unsigned int) __malloc_heap_start,
+               "=== Heap:");
+}
+#endif
+
+#if 0
+/* TODO: combine with dump_ram() */
+void dump_eep(const uint8_t *addr, unsigned int len, 
+                       uint8_t (*readfkt)(const uint8_t *))
+{
+       uint_fast8_t i;
+       uint8_t buf[16];
+
+       printf_P(PSTR("eeprom dump:"));
+       while (len) {
+               printf_P(PSTR("\n    0x%.4x:"), (unsigned int) addr);
+               for (i = 0; i<16; i++)
+                       buf[i] = readfkt(addr + i);
+               for (i = 0; i<16; i++)
+                       printf_P(PSTR(" %.2x"), buf[i]);
+               printf_P(PSTR("   "));
+               for (i = 0; i<16; i++)
+                       printf_P(PSTR("%c"), isprint(buf[i]) ? buf[i] : '.');
+
+               addr += 16;
+               len -= len > 16 ? 16 : len;
+       }
+       putchar('\n');
+}
+#endif
+
+
+/*
+ * EEPROM Display
+ *     md addr {len}
+ */
+int do_dump_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+//     static const uint8_t *addr;
+//     static uint16_t length = 128;
+       uint8_t (*readhow)(const uint8_t *);
+               
+       (void) cmdtp; (void) flag;
+
+       if (argc < 2)
+               return CMD_RET_USAGE;
+
+       const uint8_t *addr;
+       uint16_t length = 128;
+       
+       if (strchr(argv[0],'r') != NULL)
+               readhow = ram_read_byte;
+       else if (strchr(argv[0],'e') != NULL)
+               readhow = eeprom_read_byte;
+       else
+               return CMD_RET_USAGE;
+
+       /* Address is specified since argc > 1 */
+       addr = (const uint8_t *) (size_t) strtoul(argv[1], NULL, 16);
+
+       /* If another parameter, it is the length to display. */
+       if (argc > 2)
+               length = (uint16_t) strtoul(argv[2], NULL, 16);
+
+       /* Print the lines. */
+       dump_mem(addr, length, readhow, NULL);
+
+       return 0;
+}
+
+int do_eep_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       uint16_t src, dest, count;
+       int_fast8_t step;
+
+       (void) cmdtp;
+       (void) flag;
+
+       if (argc != 4)
+               return CMD_RET_USAGE;
+
+       src = (size_t) strtoul(argv[1], NULL, 16);
+       dest = (size_t) strtoul(argv[2], NULL, 16);
+       count = (size_t) strtoul(argv[3], NULL, 16);
+
+       if (src > E2END) {
+               debug("src > EEPROM size: 0x%04x\n", src);
+               return 1;
+       }
+       if (dest > E2END) {
+               debug("dest > EEPROM size: 0x%04x\n", dest);
+               return 1;
+       }
+       if (count > E2END+1) {
+               debug("count > EEPROM size: 0x%04x\n", count);
+               return 1;
+       }
+       if (count == 0) {
+               debug("Zero length ???\n");
+               return 1;
+       }
+
+       if (dest > src) {
+               src += count - 1;
+               dest += count - 1;
+               step = -1;
+       } else
+               step = 1;
+
+       while (count-- > 0) {
+               uint8_t data;
+               data = eeprom_read_byte((uint8_t *) src);
+               eeprom_write_byte((uint8_t *) dest, data);
+               src += step;
+               dest += step;
+
+       }
+       return 0;
+}
+#endif /* DEBUG */
+
diff --git a/avr/debug.h b/avr/debug.h
new file mode 100644 (file)
index 0000000..1815166
--- /dev/null
@@ -0,0 +1,34 @@
+
+#ifndef DEBUG_H_
+#define DEBUG_H_
+
+#include "common.h"
+#include <avr/pgmspace.h>
+
+#ifdef DEBUG
+#define _DEBUG 1
+#else
+#define _DEBUG 0
+#endif
+
+#define debug_cond(cond, fmt, args...)         \
+       do {                                    \
+               if (cond)                       \
+                       printf_P(PSTR(fmt), ##args);    \
+       } while (0)
+
+#define debug(fmt, args...)                    \
+       debug_cond(_DEBUG, fmt, ##args)
+
+
+#if 1
+#ifdef DEBUG
+#define DBG_P(lvl, format, ...) if (DEBUG>=lvl) \
+                               fprintf_P( stdout, PSTR(format), ##__VA_ARGS__ )
+#else
+#define DBG_P(lvl, ...)
+#endif
+#endif /* 0 */
+
+#endif /* DEBUG_H_ */
+
diff --git a/avr/env.c b/avr/env.c
new file mode 100644 (file)
index 0000000..7cf33ac
--- /dev/null
+++ b/avr/env.c
@@ -0,0 +1,833 @@
+#include "common.h"
+#include <string.h>
+#include <stdlib.h>
+
+#include <avr/eeprom.h>
+
+#include "config.h"
+#include "debug.h"
+#include "xmalloc.h"
+#include "crc.h"
+#include "command.h"
+
+#include "env.h"
+
+
+#define ENV_SIZE       (CONFIG_ENV_SIZE - sizeof(uint16_t) -1)
+#define ACTIVE_FLAG    1
+#define OBSOLETE_FLAG  0
+#define ENV_GET_VAL    (1<<0)
+
+
+/*
+ * Default Environment
+ */
+
+#define DELIM          "\0"
+
+const FLASH char default_env[] = {
+       "bootdelay="    "3"             DELIM
+       "bootcmd="      "reset; loadf; go $(startaddr)" DELIM
+       "baudrate="     "115200"        DELIM
+       "startaddr="    "0"             DELIM
+       DELIM
+};
+
+/* EEPROM storage */
+typedef struct environment_s {
+       uint16_t        crc;            /* CRC16 over data bytes        */
+       uint8_t         flags;          /* active/obsolete flags        */
+       char            data[ENV_SIZE]; /* Environment data             */
+} env_t;
+
+
+/* */
+typedef struct env_item_s {
+#define EF_N_EEP       (1<<7)          /* Variable name is in EEPROM */
+#define EF_V_EEP       (1<<6)          /* Variable value is in EEPROM */
+#define EF_DIRTY       (1<<0)          /* Variable is new or value changed */
+       uint8_t flags;
+       union {
+               uint16_t eep;
+               char     *ram;
+       } name;
+       union {
+               uint16_t eep;
+               char     *ram;
+       } val;
+} env_item_t;
+
+
+static uint8_t env_valid;
+static env_item_t env_list[CONFIG_ENVVAR_MAX];
+static int entrycount;
+
+
+static
+char env_get_char(uint16_t index)
+{
+       unsigned int off = CONFIG_ENV_OFFSET;
+
+       if (env_valid == 2)
+               off = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
+
+       return (char) eeprom_read_byte((const uint8_t *)off + index + 
+                               offsetof(env_t, data));
+}
+
+
+static
+uint16_t varname_get(char *buf, env_item_t *ep)
+{
+       int i = 0;
+       char c;
+       
+       if (ep->flags & EF_N_EEP) {
+
+               while ((c = env_get_char(ep->name.eep + i)) != '=' &&
+                               c != '\0' && i < CONFIG_SYS_ENV_NAMELEN) {
+
+                       buf[i] = c;
+                       i++;
+               }
+               if (i > 0 && c != '=') {
+                       debug("** ee_name: '%s' not '=' terminated!\n", buf);
+               }
+       } else {
+               strncpy(buf, ep->name.ram, CONFIG_SYS_ENV_NAMELEN);
+               i = strnlen(buf, CONFIG_SYS_ENV_NAMELEN);
+       }
+       buf[i] = '\0';
+       return i;
+}
+
+
+static
+uint16_t varval_get(char *buf, uint16_t index, int len)
+{
+       int i = 0;
+       char c;
+       
+       while ((c = env_get_char (index + i)) != '\0' && i < len) {
+               buf[i] = c;
+               i++;
+       };
+               
+       buf[i] = '\0';
+       
+       /* TODO: len check */
+       
+       return i;
+}
+
+static
+int comp_env_key_item(const void *key, const void *item)
+{
+       char buf[CONFIG_SYS_ENV_NAMELEN+1];
+       env_item_t *ep = (env_item_t *) item;
+       
+       varname_get(buf, ep);
+       
+       return strcmp((char *) key, buf);
+}
+
+static
+int comp_env_items(const void *m1, const void *m2)
+{
+       char b1[CONFIG_SYS_ENV_NAMELEN+1];
+       char b2[CONFIG_SYS_ENV_NAMELEN+1];
+       
+       env_item_t *ep1 = (env_item_t *) m1;
+       env_item_t *ep2 = (env_item_t *) m2;
+       
+       varname_get(b1, ep1);
+       varname_get(b2, ep2);
+       
+       return strcmp(b1, b2);
+}
+
+
+static
+int envlist_import(void)
+{
+       char name[CONFIG_SYS_ENV_NAMELEN+1];
+       uint16_t idx = 0;
+       int nlen;
+       env_item_t e;
+       
+       e.flags = EF_N_EEP | EF_V_EEP;
+       e.name.eep = idx;
+       while ((nlen = varname_get(name, &e)) != 0 && idx < ENV_SIZE) {
+       
+               if (entrycount <= CONFIG_ENVVAR_MAX) {
+                       e.val.eep = idx + nlen + 1;
+       
+                       env_list[entrycount++] = e;
+
+                       idx += nlen + 1;
+                       while (env_get_char(idx++) != 0 && idx < ENV_SIZE)
+                               ;
+                       e.name.eep = idx;
+               } else {
+                       debug("** Too many environment variables!\n");
+                       break;
+               }
+       }
+       qsort(env_list, entrycount, sizeof(env_item_t), comp_env_items);
+
+       return 0;
+}
+
+
+static
+int set_default_env(void)
+{
+       char buf[56];
+       uint16_t eep = CONFIG_ENV_OFFSET + offsetof(env_t, data);
+       unsigned int len = ENV_SIZE;
+       unsigned int i, src = 0;
+       char c = 0xff, c0 = c;
+
+       if (env_valid == 1) {
+               eep = CONFIG_ENV_OFFSET + offsetof(env_t, data) + CONFIG_ENV_SIZE;
+       }
+
+       while (len)  {
+               memcpy_P(buf, default_env+src, sizeof(buf));
+               for (i=0; i < (len < sizeof(buf) ? len : sizeof(buf)) &&
+                               !(c == 0 && c0 == 0);
+                               i++) {
+                       c0 = c; c = buf[i];
+               }
+               eeprom_update_block(buf, (char *) eep, i);
+               if (c == 0 && c0 == 0)
+                       len = 0;
+               if (len > sizeof(buf))
+                       len -= sizeof(buf);
+               src += sizeof(buf);
+               eep += sizeof(buf);
+       }
+
+       return 0;
+}
+
+
+static
+uint16_t env_crc(uint16_t data_offset)
+{
+       uint16_t crc; 
+       uint16_t i;
+       char c, c0;
+
+       crc = 0xffff;
+       c = 0xff;
+       for (i = 0; !(c == 0 && c0 == 0) && i < ENV_SIZE; i++)
+       {
+               c0 = c; 
+               c = eeprom_read_byte((const uint8_t *) data_offset + i);
+               crc = crc16(crc, c);
+       }
+       return crc ;
+}
+
+
+/**
+ * return valid env
+ */
+static
+int env_check_valid(void)
+{
+       const uint16_t offset[2] = {CONFIG_ENV_OFFSET,
+                                   CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE};
+       uint_fast8_t flags[2], crc_ok[2];
+       int rc;
+
+       /* read FLAGS */
+       flags[0] = eeprom_read_byte ((uint8_t *) offset[0] +
+                               offsetof(env_t, flags));
+       flags[1] = eeprom_read_byte ((uint8_t *) offset[1] +
+                               offsetof(env_t, flags));
+
+       /* check CRC */
+       crc_ok[0] = (
+               eeprom_read_word((uint16_t *) offset[0] +
+                               offsetof(env_t, crc))
+               == env_crc(offset[0] + offsetof(env_t, data))
+       );
+       crc_ok[1] = (
+               eeprom_read_word((uint16_t *) offset[1] +
+                               offsetof(env_t, crc))
+               == env_crc(offset[1] + offsetof(env_t, data))
+       );
+
+       if (!crc_ok[0] && !crc_ok[1]) {
+               rc = 0;
+
+       } else if (crc_ok[0] && !crc_ok[1]) {
+               rc = 1;
+       } else if (!crc_ok[0] && crc_ok[1]) {
+               rc = 2;
+       } else {
+               /* both ok - check serial */
+#if 1
+               if      (flags[1] == ACTIVE_FLAG && flags[0] != ACTIVE_FLAG)
+                       rc = 2;
+               else if (flags[1] == OBSOLETE_FLAG && flags[0] == 0xFF)
+                       rc = 2;
+               else
+                       rc = 1;
+#else
+               if (flags[0] == ACTIVE_FLAG && flags[1] == OBSOLETE_FLAG)
+                       rc = 1;
+               else if (flags[0] == OBSOLETE_FLAG && flags[1] == ACTIVE_FLAG)
+                       rc = 2;
+               else if (flags[0] == 0xFF && flags[1] == 0)
+                       rc = 2;
+               else if (flags[1] == 0xFF && flags[0] == 0)
+                       rc = 1;
+               else /* flags are equal - almost impossible */
+                       rc = 1;
+#endif
+       }
+       
+       return rc;
+}
+
+
+int env_init(void)
+{
+       env_valid = env_check_valid();
+       if (env_valid == 0) {
+               printf_P(PSTR("*** Warning - bad CRC, "
+                               "using default environment\n\n"));
+               set_default_env();
+       }
+       entrycount = 0;
+       envlist_import();
+       return 0; 
+}      
+
+
+static
+env_item_t *envlist_search(const char *name)
+{
+       return bsearch(name, env_list, entrycount, 
+                               sizeof(env_item_t), comp_env_key_item);
+}
+                       
+
+static
+env_item_t *envlist_enter(env_item_t *e)
+{
+       char *key = e->name.ram;
+       const size_t size = sizeof(env_item_t);
+       env_item_t *ep;
+       
+       ep = bsearch(key, env_list, entrycount, 
+                       size, comp_env_key_item);
+                                       
+       if (ep == NULL) {
+               if (entrycount < CONFIG_ENVVAR_MAX) {
+                       
+                       env_list[entrycount++] = *e;
+                       qsort(env_list, entrycount, size, comp_env_items);
+                       ep = bsearch(key, env_list, entrycount, 
+                                               size, comp_env_key_item);
+               }
+       } else { 
+               if ((ep->flags & EF_V_EEP) == 0) {
+                       free(ep->val.ram);
+               }
+               ep->val.ram = e->val.ram;
+       }               
+
+       if (ep != NULL) {
+               ep->flags |= EF_DIRTY;
+               ep->flags &= ~EF_V_EEP;
+               
+               if ((ep->flags & EF_N_EEP) == 0) {
+                       int nlen = strnlen(key, CONFIG_SYS_ENV_NAMELEN);
+                       char *name = xmalloc(nlen + 1);
+                       if (name == NULL) {
+                               printf_P(PSTR("## Can't malloc %d bytes\n"), 
+                                       nlen + 1);
+                               return NULL;
+                       }
+                       strcpy(name, key);
+                       name[nlen] = '\0';
+                       ep->name.ram = name;
+               }
+       }
+
+       return ep;              
+}      
+
+
+static
+int env_item_delete(env_item_t *ep)
+{
+       if (entrycount == 0)
+               return -1;
+       if ((ep->flags & EF_V_EEP) == 0) 
+               free(ep->val.ram);
+       if ((ep->flags & EF_N_EEP) == 0) 
+               free(ep->name.ram); 
+
+       entrycount--;
+       size_t size = sizeof(env_item_t);
+       memmove(ep, ep + 1, (env_list - ep)*size + entrycount*size);
+
+       return 0;               
+}
+
+static
+int envlist_delete(const char *name)
+{
+       env_item_t *ep = bsearch(name, env_list, entrycount, 
+                               sizeof(env_item_t), comp_env_key_item);
+
+       if (ep != NULL)
+               return env_item_delete(ep);
+
+       return 1;
+}
+
+       
+static
+env_item_t *envlist_get(const char *name, uint_fast8_t flag)
+{
+       env_item_t *ep;
+       
+       ep = envlist_search(name);
+
+       if (ep != NULL && (flag & ENV_GET_VAL)) {
+               if (ep->flags & EF_V_EEP) {
+                       char *vp;
+                       uint_fast8_t len;
+                       /* TODO: function that gets len of val, 
+                          to get rid of xrealloc */ 
+                       vp = xmalloc(CONFIG_SYS_CBSIZE);
+                       len = varval_get(vp, ep->val.eep, CONFIG_SYS_CBSIZE);
+                       ep->val.ram = xrealloc(vp, len + 1);
+                       ep->flags &= ~EF_V_EEP;
+               }
+       }                       
+       
+       return ep;
+}
+
+
+char *getenv(const char *name)
+{
+       env_item_t *ep;
+       char *ret = NULL;
+
+       ep = envlist_get(name, ENV_GET_VAL);
+       if (ep != NULL)
+               ret = ep->val.ram;
+       return ret;
+}
+
+static
+int env_item_save(env_item_t *ep, uint16_t offset, int space_left)
+{
+       char buf[CONFIG_SYS_ENV_NAMELEN+1];
+       int len;
+       env_item_t e = *ep;
+
+       len = varname_get(buf, ep);
+       if (len == 0)
+               return 0;
+       buf[len++] = '=';
+       space_left -= len;
+
+       if (space_left <= 0)
+               return 0;
+       
+       eeprom_update_block(buf, (uint8_t *) offset, len);
+       offset += len;
+       
+       if (e.val.ram != NULL) {
+               char c;
+               do {
+                       if (e.flags & EF_V_EEP) 
+                               c = env_get_char(e.val.eep++);
+                       else
+                               c = *e.val.ram++;
+                       
+                       eeprom_update_byte((uint8_t *) offset, c);
+                       offset++;
+                       space_left--;
+                       len++;
+               } while ((c != '\0') && space_left );
+       }
+       return len;
+}      
+
+
+static
+int saveenv(void)
+{
+       unsigned int off     = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
+       unsigned int off_red = CONFIG_ENV_OFFSET;
+       unsigned int pos;
+       int len, left;
+       uint16_t crc;
+       int rc = 0;
+
+       if (env_valid == 2) {
+               off     = CONFIG_ENV_OFFSET;
+               off_red = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
+       }
+
+       eeprom_update_byte((uint8_t *) off + offsetof(env_t, flags), 0xff); 
+
+       pos = off + offsetof(env_t, data);
+       left = ENV_SIZE - 1;
+       for (int i = 0 ; i < entrycount; i++) {
+               len = env_item_save(&env_list[i], pos, left);
+               if (len == 0) {
+                       return 1;
+               }
+               pos += len;
+               left -= len;
+       }
+       /* terminate list */
+       eeprom_update_byte((uint8_t *) pos, 0);
+       crc = env_crc(off + offsetof(env_t, data));
+       eeprom_update_word((uint16_t *) off + offsetof(env_t, crc), crc);
+       eeprom_update_byte((uint8_t *) off + offsetof(env_t, flags), 
+                                       ACTIVE_FLAG);
+
+       if (rc == 0) {
+               while (entrycount != 0) {
+                       env_item_delete(&env_list[entrycount-1]);
+               }
+               eeprom_update_byte((uint8_t *) off_red + offsetof(env_t, flags), 
+                                       OBSOLETE_FLAG);
+               env_valid = (env_valid == 2) ? 1 : 2;
+
+               envlist_import();
+       }
+       
+       return rc;
+}
+
+
+static
+int env_item_print(env_item_t *ep)
+{
+       char buf[CONFIG_SYS_ENV_NAMELEN+1];
+       int len;
+       env_item_t e = *ep;
+       
+       varname_get(buf, ep);
+       len = printf_P(PSTR("%s="), buf);
+       
+       if (e.val.ram != NULL) {
+               while (1) {
+                       char c;
+                       if (e.flags & EF_V_EEP) 
+                               c = env_get_char(e.val.eep++);
+                       else
+                               c = *e.val.ram++;
+                       
+                       if (c != '\0') {
+                               putchar(c);
+                               len++;
+                       } else
+                               break;
+               }
+       }
+       putchar('\n');
+       len ++;
+
+       return len;
+}      
+
+
+/*
+ * Command interface: print one or all environment variables
+ *
+ * Returns -1 in case of error, or length of printed string
+ */
+static 
+int env_print(char *name)
+{
+       int len = -1;
+
+       if (name) {             /* print a single name */
+       
+               env_item_t *ep = envlist_search(name);
+               if (ep != NULL)
+                       len = env_item_print(ep);
+
+       } else {                /* print whole list */
+               len = 0;
+               for (int i = 0 ; i < entrycount; i++) {
+                       len += env_item_print(&env_list[i]);
+               }
+       }
+       return len;
+}
+
+static
+int env_print_ramsize(void)
+{
+       int size = 0;
+       uint8_t name_cnt = 0;
+       uint8_t val_cnt = 0;
+       
+       for (int i = 0 ; i < entrycount; i++) {
+               if ((env_list[i].flags & EF_N_EEP) == 0 &&
+                               (env_list[i].name.ram != NULL)) {
+                       name_cnt++;
+                       size += strlen(env_list[i].name.ram) + 3;
+               }
+               if ((env_list[i].flags & EF_V_EEP) == 0 &&
+                               (env_list[i].val.ram != NULL)) {
+                       val_cnt++;
+                       size += strlen(env_list[i].val.ram) + 3;
+               }
+       }
+       printf_P(PSTR("%d bytes RAM used for %u names and %u values\n"),
+                       size, name_cnt, val_cnt);
+       return size;
+}
+
+
+int do_env_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       int i;
+       int rcode = 0;
+
+       (void) cmdtp; (void) flag;
+
+       if (argc == 1) {
+               /* print all env vars */
+               rcode = env_print(NULL);
+               if (rcode < 0)
+                       return 1;
+               printf_P(PSTR("\nEnvironment size: %d/%d bytes\n"),
+                       rcode, ENV_SIZE);
+               env_print_ramsize();
+               return 0;
+       }
+
+       /* print selected env vars */
+       for (i = 1; i < argc; ++i) {
+               int rc = env_print(argv[i]);
+               if (rc < 0) {
+                       printf_P(PSTR("## Error: \"%s\" not defined\n"), argv[i]);
+                       ++rcode;
+               }
+       }
+
+       return rcode;
+}
+
+
+/**
+ * Set or delete environment variable
+ *
+ * Set a new environment variable,
+ * or replace or delete an existing one.
+ *
+ * @param flag         (not used)
+ * @param argc
+ * @param argv[1]      Environment variable to set or delete
+ *                     if no more args
+ * @param argv[2] ...  Value to set it to
+ *
+ * @return 0 if ok, 1 on error
+ */
+static
+int _do_env_set(int flag, int argc, char * const argv[])
+{
+       int i, len;
+       char *name, *value, *s;
+       env_item_t e, *ep;
+
+       (void) flag;
+       debug("Initial value for argc=%d\n", argc);
+
+       name = argv[1];
+       value = argv[2];
+
+       if (strchr(name, '=')) {
+               printf_P(PSTR("## Error: illegal character '='"
+                      "in variable name \"%s\"\n"), name);
+               return 1;
+       }
+       if (strlen(name) > CONFIG_SYS_ENV_NAMELEN) {
+               printf_P(PSTR("## Error: Variable name \"%s\" too long. "
+                      "(max %d characters)\n"), name, CONFIG_SYS_ENV_NAMELEN);
+               return 1;
+       }
+/*
+       env_id++;
+*/
+       /* Delete only ? */
+       if (argc < 3 || argv[2] == NULL) {
+               int rc = envlist_delete(name);
+               return rc != 0;
+       }
+
+       /*
+        * Insert / replace new value
+        */
+       for (i = 2, len = 0; i < argc; ++i)
+               len += strlen(argv[i]) + 1;
+
+       value = xmalloc(len);
+       if (value == NULL) {
+               printf_P(PSTR("## Can't malloc %d bytes\n"), len);
+               return 1;
+       }
+       for (i = 2, s = value; i < argc; ++i) {
+               char *v = argv[i];
+
+               while ((*s++ = *v++) != '\0')
+                       ;
+               *(s - 1) = ' ';
+       }
+       if (s != value)
+               *--s = '\0';
+
+       e.flags = EF_DIRTY;
+       e.name.ram = name;
+       e.val.ram = value;
+       ep = envlist_enter(&e);
+       if (!ep) {
+               printf_P(PSTR("## Error inserting \"%s\" variable.\n"),
+                       name);
+               return 1;
+       }
+
+       return 0;
+}
+
+/**
+ * Set an environment variable
+ *
+ * @param varname      Environment variable to set
+ * @param varvalue     Value to set it to
+ * @return 0 if ok, 1 on error
+ */
+static
+int setenv(const char *varname, const char *varvalue)
+{
+       const char * const argv[3] = { NULL, varname, varvalue };
+       int argc = 3;
+
+       if (varvalue == NULL || varvalue[0] == '\0')
+               --argc;
+               
+       return _do_env_set(0, argc, (char * const *)argv);
+}
+
+#if 0
+/**
+ * Set an environment variable to an integer value
+ *
+ * @param varname      Environment variable to set
+ * @param value                Value to set it to
+ * @return 0 if ok, 1 on error
+ */
+int setenv_ulong(const char *varname, unsigned long value)
+{
+       /* TODO: this should be unsigned */
+       char *str = simple_itoa(value);
+
+       return setenv(varname, str);
+}
+#endif
+
+
+/**
+ * Set an environment variable to an value in hex
+ *
+ * @param varname      Environment variable to set
+ * @param value                Value to set it to
+ * @return 0 if ok, 1 on error
+ */
+int setenv_hex(const char *varname, unsigned long value)
+{
+       char str[sizeof(unsigned long) *2 + 1];
+
+       sprintf_P(str, PSTR("%lx"), value);
+       return setenv(varname, str);
+}
+
+/**
+ * Get an environment variable as a hex value
+ *
+ * @param varname      Environment variable to get
+ * @param default_val  Return this, if variable does not exist
+ * @return hex value of variable or default_val
+ */
+unsigned long getenv_hex(const char *varname, unsigned long default_val)
+{
+       const char *s;
+       unsigned long value;
+       char *endp;
+
+       s = getenv(varname);
+       if (s)
+               value = strtoul(s, &endp, 16);
+       if (!s || endp == s)
+               return default_val;
+
+       return value;
+}
+
+int do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       (void) cmdtp;
+
+       if (argc < 2)
+               return CMD_RET_USAGE;
+
+       return _do_env_set(flag, argc, argv);
+}
+
+
+int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       (void) cmdtp; (void) flag; (void) argc; (void) argv;
+
+       printf_P(PSTR("Saving Environment ...\n"));
+       return saveenv() ? 1 : 0;
+}
+
+#if defined(CONFIG_AUTO_COMPLETE) 
+int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf)
+{
+       ENTRY *match;
+       int found, idx;
+
+       idx = 0;
+       found = 0;
+       cmdv[0] = NULL;
+
+       while ((idx = hmatch_r(var, idx, &match, &env_htab))) {
+               int vallen = strlen(match->key) + 1;
+
+               if (found >= maxv - 2 || bufsz < vallen)
+                       break;
+
+               cmdv[found++] = buf;
+               memcpy(buf, match->key, vallen);
+               buf += vallen;
+               bufsz -= vallen;
+       }
+
+       qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar);
+
+       if (idx)
+               cmdv[found++] = "...";
+
+       cmdv[found] = NULL;
+       return found;
+}
+#endif
diff --git a/avr/env.h b/avr/env.h
new file mode 100644 (file)
index 0000000..9d55273
--- /dev/null
+++ b/avr/env.h
@@ -0,0 +1,10 @@
+#ifndef ENV_H
+#define ENV_H
+
+int env_init(void);
+
+char *getenv(const char *name);
+int env_complete(char *var, int maxv, char *cmdv[], int maxsz, char *buf);
+
+#endif /* ENV_H */
+
diff --git a/avr/main.c b/avr/main.c
new file mode 100644 (file)
index 0000000..5c4cd0c
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ */
+
+
+#include "common.h"
+
+#include <util/delay.h>
+//#include <avr/power.h>
+//#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+//#include <util/atomic.h>
+//#include <avr/sleep.h>
+//#include <string.h>
+
+#include <util/delay.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+#include "config.h"
+#include "debug.h"
+#include "z80-if.h"
+#include "con-utils.h"
+#include "serial.h"
+#include "timer.h"
+#include "cli.h"
+#include "env.h"
+
+/*--------------------------------------------------------------------------*/
+
+static uint8_t mcusr;
+
+static
+void setup_avr(void)
+{
+       /* save and clear reset reason(s) */
+       mcusr = MCUSR;
+       MCUSR = 0;
+       
+       /* WD */
+
+       /* CPU */
+
+       /* Disable JTAG Interface regardless of the JTAGEN fuse setting. */
+       MCUCR = _BV(JTD);
+       MCUCR = _BV(JTD);
+
+       /* disable unused periphels */
+       PRR0 = _BV(PRTIM2) | _BV(PRTIM0) | _BV(PRADC);
+       PRR1 = _BV(PRTIM5) | _BV(PRTIM4) | _BV(PRTIM3) | 
+               _BV(PRUSART3) | _BV(PRUSART2) | _BV(PRUSART1);
+
+       /* disable analog comparator */
+       ACSR = _BV(ACD);
+       /* Ports */
+
+       /* Clock */
+       CLKPR = _BV(CLKPCE);
+       CLKPR = 0;
+
+       /* Timer */
+
+       OCR1A = F_CPU / 8 / 1000 - 1; // Timer1: 1000Hz interval (OC1A)
+       TCCR1B = 0b00001010;
+       TIMSK1 = _BV(OCIE1A); // Enable TC1.oca interrupt
+}
+
+static const FLASH char * const FLASH rreasons[] = {
+                       FSTR("Power on"),
+                       FSTR("External"),
+                       FSTR("Brown out"),
+                       FSTR("Watchdog"),
+                       FSTR("JTAG"),
+               };
+
+static
+void print_reset_reason(void)
+{
+       uint8_t r = mcusr & 0x1f;
+       const FLASH char * const FLASH *p = rreasons;
+
+       printf_P(PSTR("Reset reason(s): "));
+       for ( ; r; p++, r >>= 1) {
+               if (r & 1) {
+                       my_puts_P(*p);
+                       if (r & ~1)
+                               printf_P(PSTR(", "));
+               }
+       }
+       printf_P(PSTR(".\n"));
+}
+
+
+/*******************************************************************************/
+/*******************************************************************************/
+
+#define udelay(n)  _delay_us(n)
+
+
+/* Stored value of bootdelay, used by autoboot_command() */
+static int  stored_bootdelay;
+
+
+/***************************************************************************
+ * Watch for 'delay' seconds for autoboot stop.
+ * returns: 0 - no key, allow autoboot 
+ *          1 - got key, abort
+ */
+
+static int abortboot(int  bootdelay)
+{
+       int abort = 0;
+       uint32_t ts;
+
+       if (bootdelay >= 0)
+               printf_P(PSTR("Hit any key to stop autoboot: %2d "), bootdelay);
+
+#if defined CONFIG_ZERO_BOOTDELAY_CHECK
+       /*
+        * Check if key already pressed
+        * Don't check if bootdelay < 0
+        */
+       if (bootdelay >= 0) {
+               if (tstc()) {   /* we got a key press   */
+                       (void) my_getchar();  /* consume input  */
+                       my_puts_P(PSTR("\b\b\b 0"));
+                       abort = 1;      /* don't auto boot      */
+               }
+       }
+#endif
+
+       while ((bootdelay > 0) && (!abort)) {
+               --bootdelay;
+               /* delay 1000 ms */
+               ts = get_timer(0);
+               do {
+                       if (tstc()) {   /* we got a key press   */
+                               abort  = 1;     /* don't auto boot      */
+                               bootdelay = 0;  /* no more delay        */
+                               break;
+                       }
+                       udelay(10000);
+               } while (!abort && get_timer(ts) < 1000);
+
+               printf_P(PSTR("\b\b\b%2d "), bootdelay);
+       }
+
+       putchar('\n');
+
+       return abort;
+}
+
+static
+const char *bootdelay_process(void)
+{
+       char *s;
+       int bootdelay;
+
+       s = getenv("bootdelay");
+       bootdelay = s ? atoi(s) : CONFIG_BOOTDELAY;
+
+
+       debug("### main_loop entered: bootdelay=%d\n\n", bootdelay);
+       _delay_ms(20);
+
+       s = getenv("bootcmd");
+       stored_bootdelay = bootdelay;
+       return s;
+}
+
+static
+void autoboot_command(const char *s)
+{
+       debug("### main_loop: bootcmd=\"%s\"\n", s ? s : PSTR("<UNDEFINED>"));
+       _delay_ms(20);
+
+       if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
+               run_command_list(s, -1);
+       }
+}
+
+
+static
+void main_loop(void)
+{
+       const char *s;
+
+       s = bootdelay_process();
+       autoboot_command(s);
+       cli_loop();
+}
+
+int main(void)
+{
+       setup_avr();
+       z80_setup_bus();
+       
+       serial_setup();
+       sei();
+
+       debug("\n=========================<  (RE)START DEBUG  >=========================\n");
+#if DEBUG
+       print_reset_reason();
+#endif
+               
+       env_init();
+
+       printf_P(PSTR("\n(ATMEGA1281+HD64180)_stamp Tester\n"));
+       
+       main_loop();
+}
diff --git a/avr/ring.h b/avr/ring.h
new file mode 100644 (file)
index 0000000..d57f9aa
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef RING_H
+#define RING_H
+
+struct ring {
+       uint8_t *data;
+       uint_fast8_t mask;
+       volatile uint_fast8_t begin;
+       volatile uint_fast8_t end;
+};
+
+
+static inline
+void ring_init(struct ring *ring, uint8_t *buf, int size)
+{
+       ring->data = buf;
+       ring->mask = (size-1) & 0xff;
+       ring->begin = 0;
+       ring->end = 0;
+}
+
+static inline
+int ring_write_ch(struct ring *ring, uint8_t ch)
+{
+       uint_fast8_t ep = ring->end;
+
+       ring->data[ep] = ch;
+       ep = (ep + 1) & ring->mask;
+
+       if ((ep) != ring->begin) {
+               ring->end = ep;
+               return 1;
+       }
+
+       return -1;
+}
+
+#if 0
+static inline
+int ring_write(struct ring *ring, uint8_t *data, int size)
+{
+       int i;
+
+       for (i = 0; i < size; i++) {
+               if (ring_write_ch(ring, data[i]) < 0)
+                       return -i;
+       }
+
+       return i;
+}
+#endif
+
+static inline
+int ring_read_ch(struct ring *ring)
+{
+       int ret = -1;
+       uint_fast8_t bp = ring->begin;
+
+       if (bp != ring->end) {
+               ret = ring->data[bp];
+               ring->begin = (bp + 1) & ring->mask;
+       }
+
+       return ret;
+}
+
+
+static inline
+int_fast8_t ring_is_empty(struct ring *ring)
+{
+       return ring->begin == ring->end;
+}
+
+#endif /* RING_H */
+
diff --git a/avr/serial.c b/avr/serial.c
new file mode 100644 (file)
index 0000000..b2fea51
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ */
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/atomic.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "ring.h"
+#include "serial.h"
+
+
+static int _write(char c, FILE *stream);
+static FILE mystdout = FDEV_SETUP_STREAM(_write, 
+               NULL, _FDEV_SETUP_WRITE);
+
+
+
+#define BUFFER_SIZE 64
+
+#if ((BUFFER_SIZE-1) & BUFFER_SIZE)
+# error: BUFFER_SIZE not power of 2
+#endif
+
+#if ((BUFFER_SIZE) > 256)
+# error: BUFFER_SIZE 
+#endif
+
+struct ring rx_ring;
+struct ring tx_ring;
+uint8_t rx_ring_buffer[BUFFER_SIZE];
+uint8_t tx_ring_buffer[BUFFER_SIZE];
+
+
+
+/* Initialize UART */
+
+void usart0_setup(void) {
+
+       ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+
+               PRR0 &= ~_BV(PRUSART0);
+               UCSR0B = 0;
+
+               /* Initialize ring buffers. */
+               ring_init(&rx_ring, rx_ring_buffer, BUFFER_SIZE);
+               ring_init(&tx_ring, tx_ring_buffer, BUFFER_SIZE);
+
+               UCSR0A = 0;
+               UBRR0  = F_CPU / BAUD / 16 - 1;
+               UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
+               UCSR0C = 3 << UCSZ00;
+       };
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* UART RXC interrupt */
+
+ISR(USART0_RX_vect)
+{
+       uint8_t d;
+
+       d = UDR0;
+       ring_write_ch(&rx_ring, d);
+}
+
+/* UART UDRE interrupt */
+
+ISR(USART0_UDRE_vect)
+{
+       int d = ring_read_ch(&tx_ring);
+
+       if (d < 0) {
+               /* Disable TX empty interrupt. */
+               UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
+       } else {
+               UDR0 = d;
+       }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void serial_setup(void)
+{
+       stdout = &mystdout;
+       usart0_setup();
+}
+
+/*--------------------------------------------------------------------------*/
+
+int _write(char c, FILE *stream)
+{
+       (void) stream;
+
+       if (c == '\n')
+               serial_putc('\r');
+       serial_putc(c);
+
+       return 0;
+}
+
+int serial_getc(void)
+{
+       return ring_read_ch(&rx_ring);
+}
+
+void serial_putc(char data)
+{
+       while (ring_write_ch(&tx_ring, data) < 0)
+               ;
+
+       /* Enable the TXE interrupt. */
+       UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0) | _BV(UDRIE0);
+}
+
+uint_fast8_t serial_tstc(void)
+{
+       return !ring_is_empty(&rx_ring);
+}
+
+
diff --git a/avr/serial.h b/avr/serial.h
new file mode 100644 (file)
index 0000000..7414ef1
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef SERIAL_H
+#define SERIAL_H
+
+void serial_setup(void);
+void serial_putc(char);
+int serial_getc(void);
+uint_fast8_t serial_tstc(void);
+
+#endif /* SERIAL_H */
diff --git a/avr/timer.c b/avr/timer.c
new file mode 100644 (file)
index 0000000..84a9737
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ */
+
+
+#include "common.h"
+
+//#include <avr/power.h>
+//#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include <util/atomic.h>
+
+//#include <stdio.h>
+
+
+#include "timer.h"
+
+/* timer interrupt/overflow counter */
+static volatile uint32_t timestamp;
+
+
+/*---------------------------------------------------------*/
+/* 1000Hz timer interrupt generated by OC1A                 */
+/*---------------------------------------------------------*/
+
+ISR(TIMER1_COMPA_vect)
+{
+       static int_fast8_t tick_10ms;
+       int_fast8_t i;
+
+
+       timestamp++;
+
+       i = tick_10ms + 1;
+       if (i == 10) {
+               i = 0;
+               Stat |= S_10MS_TO;
+               
+               /* Drive timer procedure of low level disk I/O module */
+               //disk_timerproc();
+       }
+       tick_10ms = i;
+       
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+
+#if 0
+
+void do_10ms(void) 
+{
+               if (to_counter)
+                       to_counter--;
+}
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+
+void timer_setup(void)
+{
+
+       /* Clock */
+       CLKPR = _BV(CLKPCE);
+       CLKPR = 0;
+
+       /* Timer */
+
+       OCR1A = F_CPU / 1000 - 1; // Timer1: 1000Hz interval (OC1A)
+       TCCR1B = 0b00001001;
+       TIMSK1 = _BV(OCIE1A); // Enable TC1.oca interrupt
+}
+
+
+uint32_t get_timer(uint32_t base)
+{
+       uint32_t ret;
+       
+       ATOMIC_BLOCK(ATOMIC_FORCEON)
+       {
+               ret = timestamp;
+       }
+       return ret - base;
+}
+
diff --git a/avr/timer.h b/avr/timer.h
new file mode 100644 (file)
index 0000000..bed3eb0
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef TIMER_H                
+#define TIMER_H
+
+uint32_t get_timer(uint32_t);
+
+#endif /* TIMER_H */
+
diff --git a/avr/xmalloc.c b/avr/xmalloc.c
new file mode 100644 (file)
index 0000000..9bf2684
--- /dev/null
@@ -0,0 +1,27 @@
+#include <stdlib.h>
+
+#include "debug.h"
+#include "xmalloc.h"
+
+void* xmalloc(size_t size)
+{
+       void *p;
+
+       p = malloc(size);
+
+       if (p == NULL)
+               debug("*** Out of memory!\n");
+       
+       return p;
+}
+
+
+void* xrealloc(void *p, size_t size)
+{
+       p = realloc(p, size);
+
+       if (p == NULL)
+               debug("*** Out of memory!\n");
+       
+       return p;
+}
diff --git a/avr/xmalloc.h b/avr/xmalloc.h
new file mode 100644 (file)
index 0000000..cb0019f
--- /dev/null
@@ -0,0 +1,8 @@
+
+#ifndef XMALLOC_H
+#define XMALLOC_H
+
+void* xmalloc(size_t size);
+void* xrealloc(void *p, size_t size);
+
+#endif /* XMALLOC_H */
diff --git a/avr/z180-serv.c b/avr/z180-serv.c
new file mode 100644 (file)
index 0000000..193b23f
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ */
+
+#include "common.h"
+//#include <avr/power.h>
+//#include <avr/pgmspace.h>
+//#include <util/atomic.h>
+//#include <avr/sleep.h>
+//#include <string.h>
+
+
+#include "debug.h"
+#include "serial.h"
+#include "z80-if.h"
+
+
+
+/*--------------------------------------------------------------------------*/
+
+uint32_t z80_sram_cmp(uint32_t addr, uint32_t length, uint8_t wval, int inc)
+{
+       uint8_t rval;
+       int_fast8_t errors = 0;
+       
+       DBG_P(1, "SRAM: Check 0x%.5lx byte... ", length);
+       while (length--) {
+               if ((rval = z80_read(addr)) != wval) {
+                       if (errors == 0) { 
+                               DBG_P(1, "\nSRAM: Address   W    R\n" \
+                                        "      ------------------\n");
+                       }
+                       errors++;
+                       if (errors > 20) {
+                               DBG_P(1, "      ...\n");
+                               break;
+                       }
+                       DBG_P(1, "      0x%.5lx  0x%.2x 0x%.2x\n", addr, wval, rval);
+               }
+               addr++;
+               wval += inc;
+       }
+       DBG_P(1, "Done.\n");
+
+       return addr;
+}
+
+void z80_sram_fill(uint32_t addr, uint32_t length, uint8_t startval, int inc)
+{
+       printf("SRAM: Write 0x%.5lx byte... ", length);
+       while (length--) {
+               z80_write(addr, startval);
+               ++addr; 
+               startval += inc;
+       }
+       printf("Done.\n");
+}
+
+
+#if 0
+void z80_sram_fill_string(uint32_t addr, int length, const char *text)
+{
+       char c;
+       const char *p = text;
+
+       while (length--) {
+               z80_write(addr++, c = *p++);
+               if (c == 0)
+                       p = text;
+       }
+}
+
+
+uint32_t z80_sram_cmp_string(uint32_t addr, int length, const char *text)
+{
+       char c;
+       const char *p = text;
+
+       while (length--) {
+               c = *p++;
+               if (z80_read(addr) != c)
+                       break;
+               ++addr;
+               if (c == 0)
+                       p = text;
+       }
+       return addr;
+}
+
+const char * const qbfox = "Zhe quick brown fox jumps over the lazy dog!";
+const char * const qbcat = "Zhe quick brown fox jumps over the lazy cat!";
+
+#endif
+
+uint8_t z80_get_byte(uint32_t adr)
+{
+       uint8_t data;
+       
+       z80_bus_cmd(Request);
+       data = z80_read(adr),
+       z80_bus_cmd(Release);
+       
+       return data;
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+struct msg_item {
+       uint8_t fct;
+       uint8_t sub_min, sub_max;
+       void (*func)(uint8_t, int, uint8_t *);
+};
+
+uint32_t msg_to_addr(uint8_t *msg)
+{
+       union {
+               uint32_t as32;
+               uint8_t as8[4];
+       } addr;
+
+       addr.as8[0] = msg[0];
+       addr.as8[1] = msg[1];
+       addr.as8[2] = msg[2];
+       addr.as8[3] = 0;
+
+       return addr.as32;
+}
+
+void do_msg_ini_msgfifo(uint8_t subf, int len, uint8_t * msg)
+{
+       (void)subf; (void)len;
+
+       z80_init_msg_fifo(msg_to_addr(msg));
+}
+
+
+void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg)
+{
+       (void)len;
+
+       z80_memfifo_init(subf - 1, msg_to_addr(msg));
+}
+
+
+void do_msg_char_out(uint8_t subf, int len, uint8_t * msg)
+{
+       (void)subf;
+
+       while (len--)
+               putchar(*msg++);
+}
+
+
+const FLASH struct msg_item z80_messages[] =
+{
+       { 0,                    /* fct nr. */
+         0, 0,                 /* sub fct nr. from, to */
+         do_msg_ini_msgfifo},
+       { 0,
+         1, 2,
+         do_msg_ini_memfifo},
+       { 1,
+         1, 1,
+         do_msg_char_out},
+       { 0xff,                         /* end mark */
+         0, 0,
+         0},
+
+};
+
+
+
+
+void do_message(int len, uint8_t *msg)
+{
+       uint8_t fct, sub_fct;
+       int_fast8_t i = 0;
+
+       if (len >= 2) {
+               fct = *msg++;
+               sub_fct = *msg++;
+               len -= 2;
+
+               while (fct != z80_messages[i].fct)
+                       ++i;
+
+               if (z80_messages[i].fct == 0xff) {
+                       DBG_P(1, "do_message: Unknown function: %i, %i\n",
+                                       fct, sub_fct);
+                       return; /* TODO: unknown message # */
+               }
+
+               while (fct == z80_messages[i].fct) {
+                       if (sub_fct >= z80_messages[i].sub_min && sub_fct <= z80_messages[i].sub_max )
+                               break;
+                       ++i;
+               }
+
+               if (z80_messages[i].fct != fct) {
+                       DBG_P(1, "do_message: Unknown sub function: %i, %i\n",
+                                       fct, sub_fct);
+                       return; /* TODO: unknown message sub# */
+               }
+
+               (z80_messages[i].func)(sub_fct, len, msg);
+
+
+       } else {
+               /* TODO: error */
+               DBG_P(1, "do_message: to few arguments (%i); this shouldn't happen!\n", len);
+       }
+}
+
+
+
+#define CTRBUF_LEN 256
+
+void check_msg_fifo(void)
+{
+       int ch;
+       static int_fast8_t state;
+       static int msglen,idx;
+       static uint8_t buffer[CTRBUF_LEN];
+
+       while (state != 3 && (ch = z80_msg_fifo_getc()) >= 0) {
+               switch (state) {
+               case 0:         /* wait for start of message */
+                       if (ch == 0x81) {
+                               msglen = 0;
+                               idx = 0;
+                               state = 1;
+                       }
+                       break;
+               case 1:         /* get msg len */
+                       if (ch > 0 && ch <= CTRBUF_LEN) {
+                               msglen = ch;
+                               state = 2;
+                       } else
+                               state = 0;
+                       break;
+               case 2:         /* get message */
+                       buffer[idx++] = ch;
+                       if (idx == msglen)
+                               state = 3;
+                       break;
+               }
+       }
+
+       if (state == 3) {
+               do_message(msglen, buffer);
+               state = 0;
+       }
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+#if 0
+void dump_mem(const FLASH uint8_t *addr, uint32_t len)
+{
+       DBG_P(1, "hdrom dump:");
+       while (len) {
+               DBG_P(1, "\n    %.5x:", addr);
+               for (unsigned i = 0; i<16; i++)
+                       DBG_P(1, " %.2x", *addr++);
+               len -= len > 16 ? 16 : len;
+       }
+       DBG_P(1, "\n");
+}
+#endif
+/*--------------------------------------------------------------------------*/
+
+
+const FLASH uint8_t iniprog[] = {
+       0xAF,                   // xor     a
+       0xED, 0x39, 0x36,       // out0    (rcr),a         ;disable  DRAM refresh
+       0x3E, 0x30,             // ld      a,030h
+       0xED, 0x39, 0x32        //out0    (dcntl),a       ;0 mem, max i/0 wait states
+};
+
+const FLASH uint8_t sertest[] = {
+       0xAF,              //   xor     a
+       0xED, 0x39, 0x36,  //   out0    (rcr),a         ;disable  DRAM refresh
+       0x3E, 0x30,        //   ld      a,030h
+       0xED, 0x39, 0x32,  //   out0    (dcntl),a       ;0 mem, max i/0 wait states
+       0x3E, 0x80,        //   ld      a,M_MPBT                ;no MP, PS=10, DR=16, SS=0
+       0xED, 0x39, 0x03,  //   out0    (cntlb1),a
+       0x3E, 0x64,        //   ld      a,M_RE + M_TE + M_MOD2  ;
+       0xED, 0x39, 0x01,  //   out0    (cntla1),a
+       0x3E, 0x00,        //   ld      a,0
+       0xED, 0x39, 0x05,  //   out0    (stat1),a       ;Enable rx interrupts
+       0xED, 0x38, 0x05,  //l0:in0     a,(stat1)
+       0xE6, 0x80,        //   and     80h
+       0x28, 0xF9,        //   jr      z,l0
+       0xED, 0x00, 0x09,  //   in0     b,(rdr1)
+       0xED, 0x38, 0x05,  //l1:in0     a,(stat1)
+       0xE6, 0x02,        //   and     02h
+       0x28, 0xF9,        //   jr      z,l1
+       0xED, 0x01, 0x07,  //   out0    (tdr1),b
+       0x18, 0xEA,        //   jr      l0
+};
+
+const FLASH uint8_t test1[] = {
+       0xAF,              //   xor     a
+       0xED, 0x39, 0x36,  //   out0    (rcr),a         ;disable  DRAM refresh
+       0x3E, 0x30,        //   ld      a,030h
+       0xED, 0x39, 0x32,  //   out0    (dcntl),a       ;0 mem, max i/0 wait states
+       0x21, 0x1E, 0x00,  //   ld      hl,dmclrt       ;load DMA registers
+       0x06, 0x08,        //   ld      b,dmct_e-dmclrt
+       0x0E, 0x20,        //   ld      c,sar0l
+       0xED, 0x93,        //   otimr   
+       0x3E, 0xC3,        //   ld      a,0c3h          ;dst +1, src +1, burst
+       0xED, 0x39, 0x31,  //   out0    (dmode),a       ;
+       0x3E, 0x62,        //   ld      a,062h          ;enable dma0, 
+       0xED, 0x39, 0x30,  //cl_1:      out0    (dstat),a       ;copy 64k
+       0x18, 0xFB,        //   jr      cl_1            ;
+       0x00, 0x00,        //dmclrt:    dw      0               ;src (inc) 
+       0x00,              //   db      0               ;src
+       0x00, 0x00,        //   dw      0               ;dst (inc),
+       0x00,              //   db      0               ;dst
+       0x00, 0x00,        //   dw      0               ;count (64k)
+};
+
+
+
+//             check_msg_fifo();
+
diff --git a/avr/z180-stamp-avr.c b/avr/z180-stamp-avr.c
new file mode 100644 (file)
index 0000000..e6edb33
--- /dev/null
@@ -0,0 +1,591 @@
+/*
+ */
+
+
+#include <avr/io.h>
+//#include <avr/power.h>
+//#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+//#include <util/atomic.h>
+//#include <avr/sleep.h>
+//#include <string.h>
+
+#include <stdio.h>
+
+
+#include "debug.h"
+#include "serial.h"
+#include "z80-if.h"
+
+#define const const __flash
+#include "../z180/hdrom.h"
+#undef const
+
+#define FLASH __flash
+//#define FLASH 
+
+#define ESCCHAR                ('^'-0x40)
+
+#define S_10MS_TO      (1<<0)
+
+
+volatile int_fast8_t timeout_1s;
+//volatile uint_least8_t Stat;
+#define Stat GPIOR0
+
+unsigned int to_counter;
+
+/****************************************************************/
+
+#define P_ADL          PORTA
+#define P_ADH          PORTC
+#define P_ADB          PORTE
+#define PIN_ADB                PINE
+
+#define ADB_WIDTH      3
+#define ADB_SHIFT      2
+//#define ADB_PORT     GPIOE
+
+#define MASK(n)        ((1<<(n))-1)
+#define SMASK(w,s) (MASK(w) << (s))
+
+typedef union {
+       uint32_t l;
+       uint16_t w[2];
+       uint8_t b[4];
+} addr_t;
+
+
+/*--------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------*/
+/* 1000Hz timer interrupt generated by OC1A                 */
+/*---------------------------------------------------------*/
+
+ISR(TIMER1_COMPA_vect)
+{
+       static int_fast8_t tick_10ms;
+//     static int_fast16_t count_ms;
+
+       int_fast8_t i;
+
+
+       i = tick_10ms + 1;
+       if (i == 10) {
+               i = 0;
+               Stat |= S_10MS_TO;
+               
+               /* Drive timer procedure of low level disk I/O module */
+               //disk_timerproc();
+       }
+       tick_10ms = i;
+       
+#if 0
+       count_ms++;
+       if (count_ms == 1000) {
+               count_ms = 0;
+
+               i = timeout_1s;
+               if (i)
+                       timeout_1s = i - 1;
+       }
+#endif
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+static uint32_t z80_sram_cmp(uint32_t addr, uint32_t length, uint8_t wval, int inc)
+{
+       uint8_t rval;
+       int_fast8_t errors = 0;
+       
+       DBG_P(1, "SRAM: Check 0x%.5lx byte... ", length);
+       while (length--) {
+               if ((rval = z80_read(addr)) != wval) {
+                       if (errors == 0) { 
+                               DBG_P(1, "\nSRAM: Address   W    R\n" \
+                                        "      ------------------\n");
+                       }
+                       errors++;
+                       if (errors > 20) {
+                               DBG_P(1, "      ...\n");
+                               break;
+                       }
+                       DBG_P(1, "      0x%.5lx  0x%.2x 0x%.2x\n", addr, wval, rval);
+               }
+               addr++;
+               wval += inc;
+       }
+       DBG_P(1, "Done.\n");
+
+       return addr;
+}
+
+static void z80_sram_fill(uint32_t addr, uint32_t length, uint8_t startval, int inc)
+{
+       printf("SRAM: Write 0x%.5lx byte... ", length);
+       while (length--) {
+               z80_write(addr, startval);
+               ++addr; 
+               startval += inc;
+       }
+       printf("Done.\n");
+}
+
+
+#if 0
+void z80_sram_fill_string(uint32_t addr, int length, const char *text)
+{
+       char c;
+       const char *p = text;
+
+       while (length--) {
+               z80_write(addr++, c = *p++);
+               if (c == 0)
+                       p = text;
+       }
+}
+
+
+uint32_t z80_sram_cmp_string(uint32_t addr, int length, const char *text)
+{
+       char c;
+       const char *p = text;
+
+       while (length--) {
+               c = *p++;
+               if (z80_read(addr) != c)
+                       break;
+               ++addr;
+               if (c == 0)
+                       p = text;
+       }
+       return addr;
+}
+
+const char * const qbfox = "Zhe quick brown fox jumps over the lazy dog!";
+const char * const qbcat = "Zhe quick brown fox jumps over the lazy cat!";
+
+#endif
+
+uint8_t z80_get_byte(uint32_t adr)
+{
+       uint8_t data;
+       
+       z80_request_bus();
+       data = z80_read(adr),
+       z80_release_bus();
+       
+       return data;
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+static void do_10ms(void) 
+{
+               if (to_counter)
+                       to_counter--;
+}
+
+/*--------------------------------------------------------------------------*/
+
+struct msg_item {
+       uint8_t fct;
+       uint8_t sub_min, sub_max;
+       void (*func)(uint8_t, int, uint8_t *);
+};
+
+uint32_t msg_to_addr(uint8_t *msg)
+{
+       union {
+               uint32_t as32;
+               uint8_t as8[4];
+       } addr;
+
+       addr.as8[0] = msg[0];
+       addr.as8[1] = msg[1];
+       addr.as8[2] = msg[2];
+       addr.as8[3] = 0;
+
+       return addr.as32;
+}
+
+void do_msg_ini_msgfifo(uint8_t subf, int len, uint8_t * msg)
+{
+       (void)subf; (void)len;
+
+       z80_init_msg_fifo(msg_to_addr(msg));
+}
+
+
+void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg)
+{
+       (void)len;
+
+       z80_memfifo_init(subf - 1, msg_to_addr(msg));
+}
+
+
+void do_msg_char_out(uint8_t subf, int len, uint8_t * msg)
+{
+       (void)subf;
+
+       while (len--)
+               putchar(*msg++);
+}
+
+
+const FLASH struct msg_item z80_messages[] =
+{
+       { 0,                    /* fct nr. */
+         0, 0,                 /* sub fct nr. from, to */
+         do_msg_ini_msgfifo},
+       { 0,
+         1, 2,
+         do_msg_ini_memfifo},
+       { 1,
+         1, 1,
+         do_msg_char_out},
+       { 0xff,                         /* end mark */
+         0, 0,
+         0},
+
+};
+
+
+
+
+void do_message(int len, uint8_t *msg)
+{
+       uint8_t fct, sub_fct;
+       int_fast8_t i = 0;
+
+       if (len >= 2) {
+               fct = *msg++;
+               sub_fct = *msg++;
+               len -= 2;
+
+               while (fct != z80_messages[i].fct)
+                       ++i;
+
+               if (z80_messages[i].fct == 0xff) {
+                       DBG_P(1, "do_message: Unknown function: %i, %i\n",
+                                       fct, sub_fct);
+                       return; /* TODO: unknown message # */
+               }
+
+               while (fct == z80_messages[i].fct) {
+                       if (sub_fct >= z80_messages[i].sub_min && sub_fct <= z80_messages[i].sub_max )
+                               break;
+                       ++i;
+               }
+
+               if (z80_messages[i].fct != fct) {
+                       DBG_P(1, "do_message: Unknown sub function: %i, %i\n",
+                                       fct, sub_fct);
+                       return; /* TODO: unknown message sub# */
+               }
+
+               (z80_messages[i].func)(sub_fct, len, msg);
+
+
+       } else {
+               /* TODO: error */
+               DBG_P(1, "do_message: to few arguments (%i); this shouldn't happen!\n", len);
+       }
+}
+
+
+
+#define CTRBUF_LEN 256
+
+void check_msg_fifo(void)
+{
+       int ch;
+       static int_fast8_t state;
+       static int msglen,idx;
+       static uint8_t buffer[CTRBUF_LEN];
+
+       while (state != 3 && (ch = z80_msg_fifo_getc()) >= 0) {
+               switch (state) {
+               case 0:         /* wait for start of message */
+                       if (ch == 0x81) {
+                               msglen = 0;
+                               idx = 0;
+                               state = 1;
+                       }
+                       break;
+               case 1:         /* get msg len */
+                       if (ch > 0 && ch <= CTRBUF_LEN) {
+                               msglen = ch;
+                               state = 2;
+                       } else
+                               state = 0;
+                       break;
+               case 2:         /* get message */
+                       buffer[idx++] = ch;
+                       if (idx == msglen)
+                               state = 3;
+                       break;
+               }
+       }
+
+       if (state == 3) {
+               do_message(msglen, buffer);
+               state = 0;
+       }
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+void dump_mem(const __flash uint8_t *addr, uint32_t len)
+{
+       DBG_P(1, "hdrom dump:");
+       while (len) {
+               DBG_P(1, "\n    %.5x:", addr);
+               for (unsigned i = 0; i<16; i++)
+                       DBG_P(1, " %.2x", *addr++);
+               len -= len > 16 ? 16 : len;
+       }
+       DBG_P(1, "\n");
+}
+
+/*--------------------------------------------------------------------------*/
+
+void z80_load_mem(void)
+{
+       unsigned sec = 0;
+       uint32_t sec_base = hdrom_start;
+
+       DBG_P(1, "Loading z80 memory... \n");
+
+       while (sec < hdrom_sections) {
+               DBG_P(2, "  From: 0x%.5lX to: 0x%.5lX    (%5li bytes)\n",
+                               hdrom_address[sec],
+                               hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
+                               hdrom_length_of_sections[sec]);
+
+               z80_write_block((const __flash unsigned char *) &hdrom[sec_base],  /* src */
+                               hdrom_address[sec],                  /* dest */
+                               hdrom_length_of_sections[sec]);      /* len */
+               sec_base+=hdrom_length_of_sections[sec];
+               sec++;
+       }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void z80_dump_mem(uint32_t addr, uint32_t len)
+{
+       DBG_P(1, "Memory dump:");
+       while (len) {
+               DBG_P(1, "\n    %.5lx:", addr);
+               for (unsigned i = 0; i<16; i++)
+                       DBG_P(1, " %.2x", z80_read(addr++));
+               len -= len > 16 ? 16 : len;
+       }
+       DBG_P(1, "\n");
+}
+
+/*--------------------------------------------------------------------------*/
+
+void setup_rtc(void)
+{
+       /* TODO: */
+}
+
+void setup_avr(void)
+{
+       /* WD */
+
+       /* CPU */
+
+       /* Disable JTAG Interface regardless of the JTAGEN fuse setting. */
+       MCUCR = _BV(JTD);
+       MCUCR = _BV(JTD);
+
+       /* disable unused periphels */
+       PRR0 = _BV(PRTIM2) | _BV(PRTIM0) | _BV(PRADC);
+       PRR1 = _BV(PRTIM5) | _BV(PRTIM4) | _BV(PRTIM3) | 
+               _BV(PRUSART3) | _BV(PRUSART2) | _BV(PRUSART1);
+
+       /* disable analog comparator */
+       ACSR = _BV(ACD);
+       /* Ports */
+
+       /* Clock */
+       CLKPR = _BV(CLKPCE);
+       CLKPR = 0;
+
+       /* Timer */
+
+       OCR1A = F_CPU / 8 / 1000 - 1; // Timer1: 1000Hz interval (OC1A)
+       TCCR1B = 0b00001010;
+       TIMSK1 = _BV(OCIE1A); // Enable TC1.oca interrupt
+}
+
+const __flash uint8_t iniprog[] = {
+       0xAF,                   // xor     a
+       0xED, 0x39, 0x36,       // out0    (rcr),a         ;disable  DRAM refresh
+       0x3E, 0x30,             // ld      a,030h
+       0xED, 0x39, 0x32        //out0    (dcntl),a       ;0 mem, max i/0 wait states
+};
+
+const __flash uint8_t sertest[] = {
+       0xAF,              //   xor     a
+       0xED, 0x39, 0x36,  //   out0    (rcr),a         ;disable  DRAM refresh
+       0x3E, 0x30,        //   ld      a,030h
+       0xED, 0x39, 0x32,  //   out0    (dcntl),a       ;0 mem, max i/0 wait states
+       0x3E, 0x80,        //   ld      a,M_MPBT                ;no MP, PS=10, DR=16, SS=0
+       0xED, 0x39, 0x03,  //   out0    (cntlb1),a
+       0x3E, 0x64,        //   ld      a,M_RE + M_TE + M_MOD2  ;
+       0xED, 0x39, 0x01,  //   out0    (cntla1),a
+       0x3E, 0x00,        //   ld      a,0
+       0xED, 0x39, 0x05,  //   out0    (stat1),a       ;Enable rx interrupts
+       0xED, 0x38, 0x05,  //l0:in0     a,(stat1)
+       0xE6, 0x80,        //   and     80h
+       0x28, 0xF9,        //   jr      z,l0
+       0xED, 0x00, 0x09,  //   in0     b,(rdr1)
+       0xED, 0x38, 0x05,  //l1:in0     a,(stat1)
+       0xE6, 0x02,        //   and     02h
+       0x28, 0xF9,        //   jr      z,l1
+       0xED, 0x01, 0x07,  //   out0    (tdr1),b
+       0x18, 0xEA,        //   jr      l0
+};
+
+const __flash uint8_t test1[] = {
+       0xAF,              //   xor     a
+       0xED, 0x39, 0x36,  //   out0    (rcr),a         ;disable  DRAM refresh
+       0x3E, 0x30,        //   ld      a,030h
+       0xED, 0x39, 0x32,  //   out0    (dcntl),a       ;0 mem, max i/0 wait states
+       0x21, 0x1E, 0x00,  //   ld      hl,dmclrt       ;load DMA registers
+       0x06, 0x08,        //   ld      b,dmct_e-dmclrt
+       0x0E, 0x20,        //   ld      c,sar0l
+       0xED, 0x93,        //   otimr   
+       0x3E, 0xC3,        //   ld      a,0c3h          ;dst +1, src +1, burst
+       0xED, 0x39, 0x31,  //   out0    (dmode),a       ;
+       0x3E, 0x62,        //   ld      a,062h          ;enable dma0, 
+       0xED, 0x39, 0x30,  //cl_1:      out0    (dstat),a       ;copy 64k
+       0x18, 0xFB,        //   jr      cl_1            ;
+       0x00, 0x00,        //dmclrt:    dw      0               ;src (inc) 
+       0x00,              //   db      0               ;src
+       0x00, 0x00,        //   dw      0               ;dst (inc),
+       0x00,              //   db      0               ;dst
+       0x00, 0x00,        //   dw      0               ;count (64k)
+};
+
+
+int main(void)
+{
+       int_fast8_t state = 0;
+       int ch;
+
+       setup_avr();
+       serial_setup();
+       setup_rtc();
+       sei();
+
+       printf_P(PSTR("\n(ATMEGA1281+HD64180)_stamp Tester\n"));
+
+       DBG_P(1, "z80_setup_bus... ");
+       z80_setup_msg_fifo();
+       z80_setup_bus();
+       DBG_P(1, "done.\n");
+
+       DBG_P(1, "Get bus... ");
+/* Now done via S_Z180_RUNNING
+       z80_busreq(LOW);
+       z80_reset(HIGH);
+*/
+       z80_request_bus();
+       DBG_P(1, "got it!\n");
+       
+//     z80_sram_fill(0, (uint32_t)512 * 1024, 0x00, 3);
+//     z80_sram_cmp(0, (uint32_t)512 * 1024, 0x00, 3);
+//     z80_dump_mem(0, 0x400);
+       
+       z80_memset(0, 0x76, 0x80000);
+//     z80_memset(0, 0x00, 0x80000);
+//     z80_write_block(test1, 0, sizeof(test1));
+
+//     z80_dump_mem(0, 0x100);
+       
+//     z80_sram_cmp(0, (uint32_t)512 * 1024, 0x76, 0);
+       
+       z80_load_mem();
+//     z80_write(0, 0x76);
+//     z80_dump_mem(0, 0x200);
+
+
+/* Now done via S_Z180_RUNNING
+       z80_reset(LOW);
+*/
+       z80_release_bus();
+       DBG_P(1, "Bus released!\n");
+       z80_reset(HIGH);
+       DBG_P(1, "Reset released!\n");
+       
+       to_counter = 200;
+
+       while (1) {
+
+               if (Stat & S_10MS_TO) {
+                       Stat &= ~S_10MS_TO;
+                       do_10ms();
+               }
+               
+
+               if ((ch = serial_getc()) >= 0) {
+                       switch (state) {
+                       case 0:
+                               if (ch == ESCCHAR) {
+                                       state = 1;
+                                       /* TODO: Timer starten */
+                               } else {
+//                                     z80_memfifo_putc(fifo_out, ch);
+                                       serial_putc(ch);
+                                       if (ch == '\r')
+                                               serial_putc('\n');
+                               }       
+                               break;
+                       case 1:
+                               switch (ch) {
+
+                               case 'r':
+                                       z80_reset_pulse();
+                                       break;
+
+                               case 'b':
+                                       z80_request_bus();
+                                       z80_dump_mem(0, 0x2d20);
+                                       z80_release_bus();
+                                       break;
+
+                               case 'e':
+                                       z80_request_bus();
+                                       z80_dump_mem(0x80000-0x4000, 0x800);
+                                       z80_dump_mem(0x80000-0x200, 0x200);
+                                       z80_release_bus();
+                                       break;
+
+                               case ESCCHAR:
+                               default:
+//                                     z80_memfifo_putc(fifo_out, ch);
+                                       serial_putc(ch);
+                                       if (ch == '\r')
+                                               serial_putc('\n');
+                               }
+                               state = 0;
+                               break;
+                       }
+               }
+
+//             check_msg_fifo();
+       }
+
+       return 0;
+}
diff --git a/avr/z80-if.c b/avr/z80-if.c
new file mode 100644 (file)
index 0000000..392597e
--- /dev/null
@@ -0,0 +1,672 @@
+/**
+ *
+ * Pin assignments
+ *
+ * | Z180-Sig  |   AVR-Port    | Dir   |   Special Function    |
+ * +------------+---------------+-------+-----------------------+
+ * |   A0      | PA    0       |  O    |                       |
+ * |   A1      | PA    1       |  O    |                       |
+ * |   A2      | PA    2       |  O    |                       |
+ * |   A3      | PA    3       |  O    |                       |
+ * |   A4      | PA    4       |  O    |                       |
+ * |   A5      | PA    5       |  O    |                       |
+ * |   A6      | PA    6       |  O    |                       |
+ * |   A7      | PA    7       |  O    |                       |
+ * |   A8      | PC    0       |  O    |                       |
+ * |   A9      | PC    1       |  O    |                       |
+ * |   A10     | PC    2       |  O    |                       |
+ * |   A11     | PC    3       |  O    |                       |
+ * |   A12     | PC    4       |  O    |                       |
+ * |   A13     | PC    5       |  O    |                       |
+ * |   A14     | PC    6       |  O    |                       |
+ * |   A15     | PC    7       |  O    |                       |
+ * |   A16     | PE    2       |  O    |                       |
+ * |   A17     | PE    3       |  O    |                       |
+ * |   A18     | PE    4       |  O    |                       |
+ * |   D0      | PF    0       |  I/O  |                       |
+ * |   D1      | PF    1       |  I/O  |                       |
+ * |   D2      | PF    2       |  I/O  |                       |
+ * |   D3      | PF    3       |  I/O  |                       |
+ * |   D4      | PF    4       |  I/O  |                       |
+ * |   D5      | PF    5       |  I/O  |                       |
+ * |   D6      | PF    6       |  I/O  |                       |
+ * |   D7      | PF    7       |  I/O  |                       |
+ * |   RD      | PD    3       |  O    |                       |
+ * |   WR      | PD    2       |  O    |                       |
+ * |   MREQ    | PD    4       |  O    |                       |
+ * |   RST     | PD    5       |  O    |                       |
+ * |   BUSREQ  | PD    7       |  O    |                       |
+ * |   BUSACK  | PD    6       |  I    |                       |
+ * |   IOCS1   | PE    5       |  I    |                       |
+ * |*  HALT    | P             |       |                       |
+ * |*  NMI     | P             |       |                       |
+ * |           | P             |       |                       |
+ * |           | P             |       |  af1   USART1_TX      |
+ * |           | P             |       |  af1   USART1_RX      |
+ * |           | P             |JTDI   |  remap SPI1_NSS'      |
+ * |           | P             |JTDO   |  remap SPI1_SCK'      |
+ * |           | P             |JTRST  |  remap SPI1_MISO'     |
+ * |           | P             |       |  remap SPI1_MOSI'     |
+ * |           | P             |       |  af1   OSC32          |
+ * |           | P             |       |  af1   OSC32          |
+
+
+ */
+
+#include <avr/io.h>
+#include <util/delay.h>
+#include <util/atomic.h>
+#include <stdio.h>
+#include "debug.h"
+#include "z80-if.h"
+
+
+/* Number of array elements */
+#define NELEMS(x)  (sizeof x/sizeof *x)
+
+
+#define CONCAT(x,y) x ## y
+#define EVALUATOR(x,y)  CONCAT(x,y)
+
+#define GPIO_(X)       CONCAT(GPIO, X)
+
+struct bits {
+  uint8_t b0:1;
+  uint8_t b1:1;
+  uint8_t b2:1;
+  uint8_t b3:1;
+  uint8_t b4:1;
+  uint8_t b5:1;
+  uint8_t b6:1;
+  uint8_t b7:1;
+} __attribute__((__packed__));
+
+#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
+
+
+
+#define P_MREQ         PORTD
+#define MREQ           4
+#define DDR_MREQ       DDRD
+#define P_RD           PORTD
+#define RD             3
+#define P_WR           PORTD
+#define WR             2
+#define P_BUSREQ       PORTD
+#define BUSREQ         7
+#define DDR_BUSREQ     DDRD
+#define P_BUSACK       PORTD
+#define PIN_BUSACK     PIND
+#define BUSACK         6
+#define DDR_BUSACK     DDRD
+//#define P_HALT               PORTA
+//#define HALT         12
+#define P_IOCS1                PORTE
+#define IOCS1          5
+#define DDR_IOCS1              DDRE
+//#define P_NMI                PORTB
+//#define NMI          7
+#define P_RST          PORTD
+#define DDR_RST                DDRD
+#define RST            5
+
+
+#define P_DB           PORTF
+#define PIN_DB         PINF
+#define DDR_DB         DDRF
+
+#define P_ADL          PORTA
+#define P_ADH          PORTC
+#define P_ADB          PORTE
+#define PIN_ADB                PINE
+#define DDR_ADL                DDRA
+#define DDR_ADH                DDRC
+#define DDR_ADB                DDRE
+
+#define ADB_WIDTH      3
+#define ADB_SHIFT      2
+//#define ADB_PORT     PORTE
+
+
+#define        Z80_O_MREQ      SBIT(P_MREQ, 4)
+#define Z80_O_RD       SBIT(P_RD, 3)
+#define Z80_O_WR       SBIT(P_WR, 2)
+#define Z80_O_BUSREQ   SBIT(P_BUSREQ, 7)
+//#define Z80_O_NMI    SBIT(P_NMI, )
+#define Z80_O_RST      SBIT(P_RST, 5)
+#define Z80_I_BUSACK   SBIT(PIN_BUSACK, 6)
+//#define Z80_I_HALT   SBIT(P_HALT, )
+
+
+#define MASK(n)        ((1<<(n))-1)
+#define SMASK(w,s) (MASK(w) << (s))
+
+
+
+typedef union {
+       uint32_t l;
+       uint16_t w[2];
+       uint8_t b[4];
+} addr_t;
+
+
+static zstate_t zstate;
+
+/*--------------------------------------------------------------------------*/
+
+
+static void z80_setup_addrbus_tristate(void)
+{
+       /* /MREQ, /RD, /WR: Input, no pullup */
+       DDR_MREQ &= ~(_BV(MREQ) | _BV(RD) | _BV(WR));
+       Z80_O_MREQ = 0;
+       Z80_O_RD = 0;
+       Z80_O_WR = 0;
+
+       P_ADL = 0;
+       DDR_ADL = 0;
+       P_ADH = 0;
+       DDR_ADH = 0;
+       PIN_ADB = P_ADB & ~(MASK(ADB_WIDTH) << ADB_SHIFT);
+       DDR_ADB = DDR_ADB & ~(MASK(ADB_WIDTH) << ADB_SHIFT);
+}
+
+       
+static void z80_setup_addrbus_active(void)
+{
+       /* /MREQ, /RD, /WR: Output and high */
+       Z80_O_MREQ = 1;
+       Z80_O_RD = 1;
+       Z80_O_WR = 1;
+       DDR_MREQ |= _BV(MREQ) | _BV(RD) | _BV(WR);
+
+       DDR_ADL = 0xff;
+       DDR_ADH = 0xff;
+       DDR_ADB = DDR_ADB | (MASK(ADB_WIDTH) << ADB_SHIFT);
+}
+
+
+static void z80_setup_dbus_in(void)
+{
+       DDR_DB = 0;
+       P_DB = 0;
+}
+
+
+static void z80_setup_dbus_out(void)
+{
+       DDR_DB = 0xff;
+}
+
+
+static void z80_reset_pulse(void)
+{
+       Z80_O_RST = 0;
+       _delay_us(10);
+       Z80_O_RST = 1;
+}
+
+
+void z80_setup_bus(void)
+{
+       /* /ZRESET: Output and low */
+       Z80_O_RST = 0;
+       DDR_RST |= _BV(RST);
+
+       /* /BUSREQ: Output and high */
+       Z80_O_BUSREQ = 1;
+       DDR_BUSREQ |= _BV(BUSREQ);
+
+       /* /BUSACK: Input, no pullup */
+       DDR_BUSACK &= ~_BV(BUSACK);
+       P_BUSACK &= ~_BV(BUSACK);
+
+       /* /IOCS1: Input, no pullup */
+       DDR_IOCS1 &= ~_BV(IOCS1);
+       P_IOCS1 &= ~_BV(IOCS1);
+
+       z80_setup_addrbus_tristate();
+       z80_setup_dbus_in();
+
+       zstate = RESET;
+}
+
+
+zstate_t z80_bus_state(void)
+{
+       return zstate;
+}
+
+
+static void z80_busreq_hpulse(void)
+{
+       z80_setup_dbus_in();
+       z80_setup_addrbus_tristate();
+
+       ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+               Z80_O_BUSREQ = 1;
+               Z80_O_BUSREQ = 1;       /* 2 AVR clock cycles */
+               Z80_O_BUSREQ = 0;       /* 2 AVR clock cycles */
+       }
+
+       if (zstate & ZST_ACQUIRED) {
+               while(Z80_I_BUSACK == 1)
+                       ;
+               z80_setup_addrbus_active();
+       }
+}
+
+
+/*
+
+ +              |              |               |               |               |
+    +   State   |     RESET     |  RESET_AQRD   |    RUNNING    | RUNNING_AQRD  |
+       +        |              |               |               |               |
+          +     |      0       |       1       |       2       |       3       |
+Event        +  |              |               |               |               |
+----------------+---------------+---------------+---------------+---------------+
+               |               |               |               |               |
+Reset          |       0       |       0       |       0       |       0       |
+               |               |               |               |               |
+               |               |               |               |               |
+Request                |       1       |               |       3       |               |
+               |               |               |               |               |
+               |               |               |               |               |
+Release                |               |       0       |               |       2       |
+               |               |               |               |               |
+               |               |               |               |               |
+Run            |       2       |       3       |               |               |
+               |               |               |               |               |
+               |               |               |               |               |
+Restart                |               |               |       2       |       3       |
+               |               |               |               |               |
+               |               |               |               |               |
+M_Cycle                |               |               |               |       3       |
+               |               |               |               |               |
+               |               |               |               |               |
+*/
+
+zstate_t z80_bus_cmd(bus_cmd_t cmd)
+{
+       switch (cmd) {
+
+       case Reset:
+               z80_setup_dbus_in();
+               z80_setup_addrbus_tristate();
+               Z80_O_RST = 0;
+               Z80_O_BUSREQ = 1;
+               zstate = RESET;
+               break;
+
+       case Request:
+               switch (zstate) {
+               case RESET:
+                       Z80_O_BUSREQ = 0;
+                       Z80_O_RST = 1;
+                       while(Z80_I_BUSACK == 1)
+                               ;
+                       z80_setup_addrbus_active();
+                       zstate = RESET_AQRD;
+                       break;
+
+               case RUNNING:
+                       Z80_O_BUSREQ = 0;
+                       while(Z80_I_BUSACK == 1)
+                               ;
+                       z80_setup_addrbus_active();
+                       zstate = RUNNING_AQRD;
+                       break;
+
+               default:
+                       break;
+               }
+               break;
+
+       case Release:
+               switch (zstate) {
+               case RESET_AQRD:
+                       z80_setup_dbus_in();
+                       z80_setup_addrbus_tristate();
+                       Z80_O_RST = 0;
+                       Z80_O_BUSREQ = 1;
+                       zstate = RESET;
+                       break;
+               case RUNNING_AQRD:
+                       z80_setup_dbus_in();
+                       z80_setup_addrbus_tristate();
+                       Z80_O_BUSREQ = 1;
+                       zstate = RUNNING;
+                       break;
+               default:
+                       break;
+               }
+               break;
+
+       case Run:
+               switch (zstate) {
+               case RESET:
+                       Z80_O_RST = 1;
+                       zstate = RUNNING;
+                       break;
+
+               case RESET_AQRD:
+                       z80_setup_dbus_in();
+                       z80_setup_addrbus_tristate();
+                       z80_reset_pulse();
+                       z80_setup_addrbus_active();
+                       zstate = RUNNING_AQRD;
+                       break;
+               default:
+                       break;
+               }
+               break;
+
+       case Restart:
+               switch (zstate) {
+               case RUNNING:
+               case RUNNING_AQRD:
+                       z80_reset_pulse();
+                       break;
+               default:
+                       break;
+               }
+               break;
+
+       case M_Cycle:
+               switch (zstate) {
+               case RUNNING_AQRD:
+                       z80_busreq_hpulse();
+                       break;
+               default:
+                       break;
+               }
+       }
+       return zstate;
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+static 
+//inline __attribute__ ((always_inline))
+void z80_setaddress(uint32_t addr)
+{
+       addr_t x; x.l = addr;
+
+       P_ADL = x.b[0];
+       P_ADH = x.b[1];
+       PIN_ADB = ((x.b[2] << ADB_SHIFT) ^ P_ADB) & MASK(ADB_WIDTH) << ADB_SHIFT ;
+}
+
+void z80_write(uint32_t addr, uint8_t data)
+{
+       z80_setaddress(addr);
+       Z80_O_MREQ = 0;
+       z80_setup_dbus_out();
+       P_DB = data;
+       P_DB = data;
+       Z80_O_WR = 0;
+       Z80_O_WR = 0;
+       Z80_O_WR = 1;
+       Z80_O_MREQ = 1;
+}
+
+uint8_t z80_read(uint32_t addr)
+{
+       uint8_t data;
+
+       z80_setaddress(addr);
+       Z80_O_MREQ = 0;
+       z80_setup_dbus_in();
+       Z80_O_RD = 0;
+       Z80_O_RD = 0;
+       Z80_O_RD = 0;
+       data = PIN_DB;
+       Z80_O_RD = 1;
+       Z80_O_MREQ = 1;
+
+       return data;
+}
+
+
+void z80_memset(uint32_t addr, uint8_t data, uint32_t length)
+{
+       z80_setup_dbus_out();
+       Z80_O_MREQ = 0;
+       while(length--) {
+               z80_setaddress(addr++);
+               P_DB = data;
+               P_DB = data;
+               Z80_O_WR = 0;
+               Z80_O_WR = 0;
+               Z80_O_WR = 1;
+       }
+       Z80_O_MREQ = 1;
+}
+
+void z80_write_block(const __flash uint8_t *src, uint32_t dest, uint32_t length)
+{
+       uint8_t data;
+       
+       z80_setup_dbus_out();
+       Z80_O_MREQ = 0;
+       while(length--) {
+               z80_setaddress(dest++);
+               data = *src++;
+               P_DB = data;
+               P_DB = data;
+               Z80_O_WR = 0;
+               Z80_O_WR = 0;
+               Z80_O_WR = 1;
+       }
+       Z80_O_MREQ = 1;
+}
+
+/*
+  0179'                         rx.bs_mask:    ds      1               ; (buf_len - 1)
+  017A'                         rx.in_idx:     ds      1               ;
+  017B'                         rx.out_idx:    ds      1               ;
+  017C'                         rx.buf:                ds      rx.buf_len      ;
+  018B'                         rx.buf_end     equ     $-1             ; last byte (start+len-1)
+                                
+  018C'                         tx.bs_mask:    ds      1               ; (buf_len - 1)
+  018D'                         tx.in_idx:     ds      1               ;
+  018E'                         tx.out_idx:    ds      1               ;
+  018F'                         tx.buf:                ds      tx.buf_len      ;
+  019E'                         tx.buf_end     equ     $-1             ; last byte
+*/
+
+
+typedef struct __attribute__((packed)) {
+       uint8_t mask;
+       uint8_t in_idx;
+       uint8_t out_idx;
+       uint8_t buf[];
+} zfifo_t;
+
+
+
+#define FIFO_BUFSIZE_MASK      -3
+#define FIFO_INDEX_IN          -2
+#define FIFO_INDEX_OUT         -1
+
+
+static struct {
+       uint32_t base;
+       uint8_t idx_out,
+               idx_in,
+               mask;
+       } fifo_dsc[NUM_FIFOS];
+       
+
+void z80_memfifo_init(const fifo_t f, uint32_t adr)
+{
+
+DBG_P(2, "z80_memfifo_init: %i, %lx\n", f, adr);
+
+       fifo_dsc[f].base = adr;
+
+       z80_bus_cmd(Request);
+
+       fifo_dsc[f].mask = z80_read(adr + FIFO_BUFSIZE_MASK);
+       fifo_dsc[f].idx_in = z80_read(adr + FIFO_INDEX_IN);
+       fifo_dsc[f].idx_out = z80_read(adr + FIFO_INDEX_OUT);
+
+       z80_bus_cmd(Release);
+}
+
+
+int z80_memfifo_is_empty(const fifo_t f)
+{
+       int rc = 1;
+
+       if (fifo_dsc[f].base != 0) {
+
+               uint32_t adr = fifo_dsc[f].base + FIFO_INDEX_IN;
+               uint8_t idx;
+
+               z80_bus_cmd(Request);
+               idx = z80_read(adr);
+               z80_bus_cmd(Release);
+               rc = idx == fifo_dsc[f].idx_out;
+       }
+
+       return rc;
+}
+
+int z80_memfifo_is_full(const fifo_t f)
+{
+       int rc = 1;
+       
+       if (fifo_dsc[f].base != 0) {
+               z80_bus_cmd(Request);
+               rc = ((fifo_dsc[f].idx_in + 1) & fifo_dsc[f].mask)
+                       == z80_read(fifo_dsc[f].base+FIFO_INDEX_OUT);
+               z80_bus_cmd(Release);
+       }
+       return rc;
+}
+
+uint8_t z80_memfifo_getc(const fifo_t f)
+{
+       uint8_t rc, idx;
+       
+       while (z80_memfifo_is_empty(f))
+               ;
+
+       z80_bus_cmd(Request);
+       idx = fifo_dsc[f].idx_out;
+       rc = z80_read(fifo_dsc[f].base+idx);
+       fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
+       z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
+       z80_bus_cmd(Release);
+       
+       return rc;
+}
+
+
+void z80_memfifo_putc(fifo_t f, uint8_t val)
+{
+       int idx;
+       
+       while (z80_memfifo_is_full(f))
+               ;
+
+       z80_bus_cmd(Request);
+       idx = fifo_dsc[f].idx_in;
+       z80_write(fifo_dsc[f].base+idx, val);
+       fifo_dsc[f].idx_in = ++idx & fifo_dsc[f].mask;
+       z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in);
+       z80_bus_cmd(Release);
+}
+
+/*--------------------------------------------------------------------------*/
+/*
+       TODO: Rewrite msg_fifo routines for AVR
+*/
+
+static struct {
+       uint32_t base;
+       //uint8_t  idx_out, idx_in;
+       uint16_t count;
+       uint8_t  buf[256];
+       } msg_fifo;
+
+/*--------------------------------------------------------------------------*/
+
+#if 0
+
+static void tim1_setup(void)
+{
+       RCC_APB2RSTR |= RCC_APB2RSTR_TIM1RST;
+       RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM1RST;
+
+       TIM1_CR1 = 0;
+
+       TIM1_SMCR = 0
+       /*      | TIM_SMCR_ETP                  */
+       /*      | TIM_SMCR_ETF_CK_INT_N_2       */
+               | TIM_SMCR_TS_ETRF
+               | TIM_SMCR_SMS_OFF
+               ;
+
+       TIM1_DIER = TIM_DIER_TDE;
+
+
+       TIM1_CCMR1 = 0
+               | TIM_CCMR1_OC1M_FORCE_LOW
+               | TIM_CCMR1_CC1S_OUT;
+
+       TIM1_SMCR |= TIM_SMCR_SMS_TM;
+}
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+void z80_setup_msg_fifo(void)
+{
+//     gpio_set_mode(P_BUSACK, GPIO_MODE_INPUT,
+//             GPIO_CNF_INPUT_FLOAT, GPIO_BUSACK | GPIO_IOCS1);
+
+//...
+
+//     msg_fifo.count = NELEMS(msg_fifo.buf);
+       msg_fifo.count = 0;
+       msg_fifo.base = 0;
+
+}
+
+
+void z80_init_msg_fifo(uint32_t addr)
+{
+
+DBG_P(1, "z80_init_msg_fifo: %lx\n", addr);
+
+       z80_bus_cmd(Request);
+       z80_write(addr+FIFO_INDEX_OUT, z80_read(addr+FIFO_INDEX_IN));
+       z80_bus_cmd(Release);
+       msg_fifo.base = addr;
+}
+
+
+int z80_msg_fifo_getc(void)
+{
+       int c = -1;
+       
+#if 0
+       if (msg_fifo.count != (NELEMS(msg_fifo.buf) /*- DMA1_CNDTR4 */ )) {
+               c = msg_fifo.buf[msg_fifo.count];
+               if (++msg_fifo.count == NELEMS(msg_fifo.buf))
+                       msg_fifo.count = 0;
+
+               if (msg_fifo.base != 0) {
+                       z80_bus_cmd(Request);
+                       z80_write(msg_fifo.base+FIFO_INDEX_OUT, msg_fifo.count);
+                       z80_bus_cmd(Release);
+               }
+       }
+#endif
+
+       return c;
+}
diff --git a/avr/z80-if.h b/avr/z80-if.h
new file mode 100644 (file)
index 0000000..b02fe23
--- /dev/null
@@ -0,0 +1,46 @@
+
+#define ZST_ACQUIRED   0x01
+#define ZST_RUNNING    0x02
+
+typedef enum { 
+       RESET           = 0x00,
+       RESET_AQRD      = ZST_ACQUIRED,
+       RUNNING         = ZST_RUNNING,
+       RUNNING_AQRD    = ZST_RUNNING | ZST_ACQUIRED,
+} zstate_t;
+
+typedef enum { 
+       Reset,
+       Request,
+       Release,
+       Run,
+       Restart,
+       M_Cycle
+} bus_cmd_t;
+
+typedef enum {LOW, HIGH} level_t;
+
+zstate_t z80_bus_state(void);
+zstate_t z80_bus_cmd(bus_cmd_t cmd);
+void z80_setup_bus(void);
+int z80_stat_reset(void);
+//void z80_busreq(level_t level);
+int z80_stat_halt(void);
+
+void z80_write(uint32_t addr, uint8_t data);
+uint8_t z80_read(uint32_t addr);
+void z80_memset(uint32_t addr, uint8_t data, uint32_t length);
+void z80_write_block(const FLASH uint8_t *src, uint32_t dest, uint32_t length);
+
+
+typedef enum fifo_t {fifo_in, fifo_out, NUM_FIFOS} fifo_t;
+
+void z80_memfifo_init(const fifo_t f, uint32_t adr);
+int z80_memfifo_is_empty(const fifo_t f);
+int z80_memfifo_is_full(const fifo_t f);
+uint8_t z80_memfifo_getc(const fifo_t f);
+void z80_memfifo_putc(fifo_t f, uint8_t val);
+
+void z80_setup_msg_fifo(void);
+void z80_init_msg_fifo(uint32_t addr);
+int z80_msg_fifo_getc(void);
diff --git a/configs/debug.config b/configs/debug.config
new file mode 100644 (file)
index 0000000..1a54f76
--- /dev/null
@@ -0,0 +1 @@
+CONFIG_DEBUG=0
diff --git a/configs/default.config b/configs/default.config
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/configs/gcc.tup b/configs/gcc.tup
new file mode 100644 (file)
index 0000000..ad2d788
--- /dev/null
@@ -0,0 +1,40 @@
+CC     = $(TOOLCHAIN)-gcc
+LD     = $(TOOLCHAIN)-gcc
+AR     = $(TOOLCHAIN)-ar
+AS     = $(TOOLCHAIN)-as
+OBJCOPY        = $(TOOLCHAIN)-objcopy
+OBJDUMP        = $(TOOLCHAIN)-objdump
+SIZE   = $(TOOLCHAIN)-size
+GDB    = $(TOOLCHAIN)-gdb
+
+
+CFLAGS += -g -Os
+CFLAGS += -std=gnu99
+CFLAGS += -Wall -Wextra
+CFLAGS += -Wredundant-decls 
+#CFLAGS        += -fno-common -ffunction-sections -fdata-sections
+
+
+LDFLAGS        += -Wl,--gc-sections
+LDFLAGS        += -Wl,--cref
+
+ifneq ($(LDSCRIPT),)
+LDFLAGS        += -T$(LDSCRIPT)
+endif
+
+
+!cc = |> ^ CC %f^ $(CC) $(CFLAGS) $(CPPFLAGS) -c %f -o %o |> %B.o
+!LINK = |> ^ LINK %o^ $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-Map=%O.map %f $(LDLIBS) -o %o |> | %O.map
+!OBJCOPY= |> ^ OBJCOPY %o^ $(OBJCOPY) -Oihex %f %o |> 
+!OBJDUMP= |> ^ OBJDUMP %o^ $(OBJDUMP) -h -S %f > %o |> %O.lss
+!SIZE = |> ^ SIZE %f^ $(SIZE) %f |> 
+
+
+: foreach $(SRC) | $(PREDEP) |> !cc |>  {objs}
+: $(SRC_Z) |> !cc $(CPPFLAGS_Z) |> {objs}
+
+: {objs} |> !LINK |> $(PROG).elf {elf}
+: {elf}  |> !OBJCOPY |> %B.hex {aux}
+: {elf}  |> !OBJDUMP |> %B.lss {aux}
+: {elf}  | {aux} |> !SIZE |>
+
diff --git a/libopencm3 b/libopencm3
new file mode 160000 (submodule)
index 0000000..69726cd
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 69726cd1a5baf455d247d3e2469e53cd26856c28
diff --git a/stm32/Tupfile b/stm32/Tupfile
new file mode 100644 (file)
index 0000000..1778623
--- /dev/null
@@ -0,0 +1,74 @@
+include_rules
+
+PROG           = z180-stamp-stm32
+SRC            = z180-stamp-stm32.c serial.c z80-if.c
+SRC_Z          = ../z180/hdrom.c
+#TARGETS       = $(PROG).elf
+
+FP_FLAGS       = -msoft-float
+DEFS           = -DSTM32F1 -DBAUD=115200
+
+LIBNAME                = opencm3_stm32f1
+OPENCM3_DIR    = $(TOP)/libopencm3
+LDSCRIPT       = stm32vl-discovery.ld
+
+###############################################################################
+# Executables
+
+TOOLCHAINDIR   = /usr/local/gcc-arm-none-eabi-4_8-2014q2/bin
+TOOLCHAIN      = $(TOOLCHAINDIR)/arm-none-eabi
+
+CC     = $(TOOLCHAIN)-gcc
+LD     = $(TOOLCHAIN)-gcc
+AR     = $(TOOLCHAIN)-ar
+AS     = $(TOOLCHAIN)-as
+OBJCOPY        = $(TOOLCHAIN)-objcopy
+OBJDUMP        = $(TOOLCHAIN)-objdump
+SIZE   = $(TOOLCHAIN)-size
+GDB    = $(TOOLCHAIN)-gdb
+
+###############################################################################
+
+INCLUDES += $(OPENCM3_DIR)/include 
+LIBDIRS  += $(OPENCM3_DIR)/lib
+
+SCRIPT_DIR = $(OPENCM3_DIR)/scripts
+
+
+ifdef DEBUG
+DEFS   += -DDEBUG=2
+endif
+
+CFLAGS += -g -Os
+CFLAGS += -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd
+CFLAGS += -std=gnu99
+CFLAGS += -Wall -Wextra -Wimplicit-function-declaration
+CFLAGS += -Wredundant-decls 
+#CFLAGS        += -fno-common -ffunction-sections -fdata-sections
+CFLAGS += -I $(INCLUDES)
+
+CPPFLAGS += $(DEFS)
+
+# Linker flags
+LDFLAGS        += --static -nostartfiles
+LDFLAGS        += -T$(LDSCRIPT)
+LDFLAGS        += -Wl,--gc-sections
+LDFLAGS        += -Wl,--cref
+
+LDLIBS         += -L$(LIBDIRS) -l$(LIBNAME)
+LDLIBS         += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
+
+
+!cc = |> ^ CC %f^ $(CC) $(CFLAGS) $(CPPFLAGS) -c %f -o %o |> %B.o
+!LINK = |> ^ LINK %o^ $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-Map=%O.map %f $(LDLIBS) -o %o |> | %O.map
+!OBJCOPY= |> ^ OBJCOPY %o^ $(OBJCOPY) -Oihex %f %o |>
+!OBJDUMP= |> ^ OBJDUMP %o^ $(OBJDUMP) -h -S %f > %o |> %O.lss
+!SIZE = |> ^ SIZE^ $(SIZE) %f |> 
+
+: foreach $(SRC) $(SRC_Z) | ../z180/hdrom.h |> !cc |>  {objs}
+
+: {objs} |> !LINK |> $(PROG).elf
+: $(PROG).elf |> !OBJCOPY |> %B.hex
+: $(PROG).elf |> !OBJDUMP |> %B.lss
+: $(PROG).elf |> !SIZE |>
+
diff --git a/stm32/debug.h b/stm32/debug.h
new file mode 100644 (file)
index 0000000..d542317
--- /dev/null
@@ -0,0 +1,11 @@
+
+#ifndef DEBUG_H_
+#define DEBUG_H_
+
+#ifdef DEBUG
+#define DBG_P(lvl, ...) if (DEBUG>=lvl) fprintf( stderr,  __VA_ARGS__ )
+#else
+#define DBG_P(lvl, ...)
+#endif
+
+#endif /* DEBUG_H_ */
diff --git a/stm32/serial.c b/stm32/serial.c
new file mode 100644 (file)
index 0000000..9193005
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * serial.c
+ *
+ *  Created on: 04.05.2014
+ *      Author: leo
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/usart.h>
+#include <libopencm3/cm3/nvic.h>
+#include "serial.h"
+
+
+#define USART_CONSOLE USART1
+
+int _write(int fd, char *ptr, int len)  __attribute__((used));
+
+
+struct ring {
+       uint8_t *data;
+       int size;
+       volatile int begin;
+       volatile int end;
+};
+
+
+#define BUFFER_SIZE 256
+
+struct ring rx_ring;
+struct ring tx_ring;
+uint8_t rx_ring_buffer[BUFFER_SIZE];
+uint8_t tx_ring_buffer[BUFFER_SIZE];
+
+
+static void ring_init(struct ring *ring, uint8_t *buf, int size)
+{
+       ring->data = buf;
+       ring->size = size;
+       ring->begin = 0;
+       ring->end = 0;
+}
+
+static int ring_write_ch(struct ring *ring, uint8_t ch)
+{
+       int ep = (ring->end + 1) % ring->size;
+
+       if ((ep) != ring->begin) {
+               ring->data[ring->end] = ch;
+               ring->end = ep;
+               return 1;
+       }
+
+       return -1;
+}
+
+static int ring_write(struct ring *ring, uint8_t *data, int size)
+{
+       int i;
+
+       for (i = 0; i < size; i++) {
+               if (ring_write_ch(ring, data[i]) < 0)
+                       return -i;
+       }
+
+       return i;
+}
+
+static int ring_read_ch(struct ring *ring)
+{
+       int ret = -1;
+
+       if (ring->begin != ring->end) {
+               ret = ring->data[ring->begin];
+               ring->begin = (ring->begin +1) % ring->size;
+       }
+
+       return ret;
+}
+
+void usart_setup(void)
+{
+       /* Initialize output ring buffer. */
+       ring_init(&rx_ring, rx_ring_buffer, BUFFER_SIZE);
+       ring_init(&tx_ring, tx_ring_buffer, BUFFER_SIZE);
+
+       /* Enable the USART1 interrupt. */
+       nvic_enable_irq(NVIC_USART1_IRQ);
+
+       /* Setup GPIO pin GPIO_USART1_TX/LED_GREEN_PIN on GPIO port A for transmit. */
+       /* TODO: USART1 --> USART_CONSOLE */
+
+       gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
+                     GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX);
+
+       /* Setup GPIO pin GPIO_USART1_RE_RX on GPIO port B for receive. */
+       gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
+                     GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX);
+
+       /* Setup UART parameters. */
+//     usart_set_baudrate(USART_CONSOLE, 38400);
+       usart_set_baudrate(USART_CONSOLE, 115200);
+       usart_set_databits(USART_CONSOLE, 8);
+       usart_set_stopbits(USART_CONSOLE, USART_STOPBITS_1);
+       usart_set_parity(USART_CONSOLE, USART_PARITY_NONE);
+       usart_set_flow_control(USART_CONSOLE, USART_FLOWCONTROL_NONE);
+       usart_set_mode(USART_CONSOLE, USART_MODE_TX_RX);
+
+       /* Enable USART1 Receive interrupt. */
+       USART_CR1(USART1) |= USART_CR1_RXNEIE;
+
+       /* Finally enable the USART. */
+       usart_enable(USART_CONSOLE);
+}
+
+void usart1_isr(void)
+{
+       /* Check if we were called because of RXNE. */
+       if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&
+           ((USART_SR(USART1) & USART_SR_RXNE) != 0)) {
+
+               /* Retrieve the data from the peripheral. */
+               ring_write_ch(&rx_ring, usart_recv(USART1));
+
+       }
+
+       /* Check if we were called because of TXE. */
+       if (((USART_CR1(USART1) & USART_CR1_TXEIE) != 0) &&
+           ((USART_SR(USART1) & USART_SR_TXE) != 0)) {
+
+               int data;
+
+               data = ring_read_ch(&tx_ring);
+
+               if (data == -1) {
+                       /* Disable the TXE interrupt, it's no longer needed. */
+                       USART_CR1(USART1) &= ~USART_CR1_TXEIE;
+               } else {
+                       /* Put data into the transmit register. */
+                       usart_send(USART1, data);
+               }
+       }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void serial_setup(void)
+{
+       usart_setup();
+}
+
+/*--------------------------------------------------------------------------*/
+
+/**
+ * Use USART_CONSOLE as a console.
+ * This is a syscall for newlib
+ * @param fd
+ * @param ptr
+ * @param len
+ * @return
+ */
+int _write(int fd, char *ptr, int len)
+{
+       int i;
+
+       if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
+               for (i = 0; i < len; i++) {
+                       if (ptr[i] == '\n') {
+                               serial_putc('\r');
+                       }
+                       serial_putc(ptr[i]);
+               }
+               return i;
+       }
+       errno = EIO;
+       return -1;
+}
+
+int serial_getc(void)
+{
+       return ring_read_ch(&rx_ring);
+}
+
+void serial_putc(uint8_t data)
+{
+       while (ring_write_ch(&tx_ring, data) < 0)
+               ;
+
+       /* Enable the TXE interrupt. */
+       USART_CR1(USART1) |= USART_CR1_TXEIE;
+}
diff --git a/stm32/serial.h b/stm32/serial.h
new file mode 100644 (file)
index 0000000..1a0f510
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef SERIAL_H
+#define SERIAL_H
+
+void serial_setup(void);
+void serial_putc(uint8_t);
+int serial_getc(void);
+
+#endif /* SERIAL_H */
diff --git a/stm32/stm32vl-discovery.ld b/stm32/stm32vl-discovery.ld
new file mode 100644 (file)
index 0000000..40de3d3
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Linker script for ST STM32VLDISCOVERY (STM32F100RB, 128K flash, 8K RAM). */
+
+/* Define memory regions. */
+MEMORY
+{
+       rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
+       ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
+}
+
+/* Include the common ld script. */
+INCLUDE libopencm3_stm32f1.ld
+
diff --git a/stm32/z180-stamp-stm32.c b/stm32/z180-stamp-stm32.c
new file mode 100644 (file)
index 0000000..15d732d
--- /dev/null
@@ -0,0 +1,763 @@
+/*
+ */
+
+#include <stdio.h>
+
+#include <libopencmsis/core_cm3.h>
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/cm3/systick.h>
+#include <libopencm3/stm32/rtc.h>
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/timer.h>
+
+#define ODR    0x0c
+#define IDR    0x08
+
+
+#include "debug.h"
+#include "serial.h"
+#include "z80-if.h"
+#include "../z180/hdrom.h"
+
+#define ESCCHAR                ('^'-0x40)
+
+#define S_10MS_TO      (1<<0)
+
+/*
+ * LED Connections
+ */
+
+#define LED_PORT       GPIOC
+#define LED_BLUE_PIN   GPIO8
+#define BLUE           8
+#define LED_GREEN_PIN  GPIO9
+#define GREEN          9
+
+
+#define LED_BLUE_ON()     BBIO_PERIPH(LED_PORT+ODR, BLUE) = 1
+#define LED_BLUE_OFF()    BBIO_PERIPH(LED_PORT+ODR, BLUE) = 0
+#define LED_BLUE_TOGGLE() BBIO_PERIPH(LED_PORT+ODR, BLUE) = !BBIO_PERIPH(LED_PORT+ODR, BLUE)
+
+#define LED_GREEN_ON()     BBIO_PERIPH(LED_PORT+ODR, GREEN) = 1
+#define LED_GREEN_OFF()    BBIO_PERIPH(LED_PORT+ODR, GREEN) = 0
+#define LED_GREEN_TOGGLE() BBIO_PERIPH(LED_PORT+ODR, GREEN) = !BBIO_PERIPH(LED_PORT+ODR, GREEN)
+
+
+/*
+ * Button connections
+ */
+
+//BBIO_PERIPH(GPIOA+IDR, 0);
+
+#define KEY_PORT       GPIOA_IDR
+#define KEY0           GPIO0
+//#define KEY1         GPIO1
+//#define KEY2         GPIO2
+
+#define REPEAT_MASK    KEY0            // repeat: key0
+#define REPEAT_START   100             // after 1s
+#define REPEAT_NEXT    20              // every 200ms
+
+
+typedef enum {
+       NOTHING, PULSE, BLINK1, BLINK2
+} LED_MODE;
+
+typedef struct {
+       uint8_t mode;
+       uint8_t ontime, offtime;
+} led_stat_t;
+
+volatile uint8_t led_timer[2];
+led_stat_t led_stat[2];
+
+volatile int timeout_1s;
+volatile uint32_t Stat;
+
+
+/*--------------------------------------------------------------------------*/
+
+
+static void clock_setup(void)
+{
+       //rcc_clock_setup_in_hse_8mhz_out_24mhz();
+       rcc_clock_setup_in_hsi_out_24mhz();
+
+       /* Enable clocks for:
+               GPIO port A (for GPIO_USART1_TX and Button)
+               GPIO port C (LEDs) 
+               USART1
+               TIM16 (RST-Pin) 
+               TIM1  (IOCS1)
+       */
+       rcc_peripheral_enable_clock(&RCC_APB2ENR, 
+                         RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN 
+                       | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN 
+                       | RCC_APB2ENR_USART1EN | RCC_APB2ENR_AFIOEN
+                       | RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM16EN);
+       /* Enable clocks for:
+               TIM3
+       */
+       rcc_peripheral_enable_clock(&RCC_APB1ENR, 
+                       RCC_APB1ENR_TIM3EN);
+
+       /* Enable clocks for:
+               DMA1
+       */
+       rcc_peripheral_enable_clock(&RCC_AHBENR, 
+                       RCC_AHBENR_DMA1EN);
+}
+
+static void systick_setup(void)
+{
+       /* SysTick interrupt every N clock pulses: set reload to N-1 */
+       STK_RVR = 24000000/1000 - 1;
+
+       /* Set source to core clock, enable int and start counting. */
+       STK_CSR = STK_CSR_CLKSOURCE_AHB | STK_CSR_TICKINT | STK_CSR_ENABLE;
+}
+
+#if 0
+static void nvic_setup(void)
+{
+//     nvic_enable_irq(NVIC_RTC_IRQ);
+//     nvic_set_priority(NVIC_RTC_IRQ, 1);
+}
+#endif
+
+static void tim3_setup(void)
+{
+       TIM3_CR1 = TIM_CR1_CMS_EDGE | TIM_CR1_DIR_UP;
+               
+       TIM3_CCMR2 = 0
+               | TIM_CCMR2_OC4M_FORCE_LOW      
+       /*      | TIM_CCMR2_OC4M_FORCE_HIGH     */
+       /*      | TIM_CCMR2_OC4M_PWM2           */
+               
+       /*      | TIM_CCMR2_OC4PE               */
+       /*      | TIM_CCMR2_OC4FE               */
+               | TIM_CCMR2_CC4S_OUT;
+               
+       TIM3_CCER = TIM_CCER_CC4E
+               | TIM_CCER_CC4P;
+       
+       TIM3_ARR = 48;  /* default */
+       TIM3_CCR4 = 1;  /*  */
+}
+
+static void gpio_setup(void)
+{
+
+       /* Disable JTAG-DP, but leave SW-DP Enabled. (free PA15, PB3, PB4)
+          Remap SPI1 to PB3, PB4, PB5 and PA15.
+          Remap TIM3 (CH1/PC6, CH2/PC7, CH3/PC8, CH4/PC9)
+          Port D0/Port D1 mapping on OSC_IN/OSC_OUT
+       */
+       gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON, 
+                       AFIO_MAPR_SPI1_REMAP
+                       | AFIO_MAPR_TIM3_REMAP_FULL_REMAP
+                       | AFIO_MAPR_PD01_REMAP);
+
+       /* LEDs and User Button. */
+       gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ,
+                     GPIO_CNF_OUTPUT_PUSHPULL, LED_BLUE_PIN);
+       gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_10_MHZ,
+                     GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, LED_GREEN_PIN);
+       gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
+                     GPIO_CNF_INPUT_FLOAT, GPIO0);
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+void delay_systicks(int ticks)
+{
+       int start, stop, now;
+       
+       start = STK_CVR;
+       stop = start - ticks;
+       if (stop < 0) {
+               stop += STK_RVR;
+               do {
+                       now = STK_CVR;
+               } while ((now > stop) || (now <= start));
+       } else {
+               do {
+                       now = STK_CVR;
+               } while ((now > stop) && (now <= start));
+       }
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+static void led_toggle(uint8_t lednr) {
+       if (lednr == 0)
+               LED_BLUE_TOGGLE();
+       else if (lednr == 1)
+               LED_GREEN_TOGGLE();
+}
+
+static void led_on(uint8_t lednr) {
+       if (lednr == 0)
+               LED_BLUE_ON();
+       else if (lednr == 1)
+               LED_GREEN_ON();
+}
+
+static void led_off(uint8_t lednr) {
+       if (lednr == 0)
+               LED_BLUE_OFF();
+       else if (lednr == 1)
+               LED_GREEN_OFF();
+}
+
+static uint8_t led_is_on(uint8_t lednr) {
+       if (lednr == 0)
+               return BBIO_PERIPH(LED_PORT+ODR, BLUE);
+       else if (lednr == 1)
+               return BBIO_PERIPH(LED_PORT+ODR, GREEN);
+       else
+               return 0;
+}
+
+static void ledset(uint8_t lednr, uint8_t what, uint8_t len) {
+
+       led_stat[lednr].mode = what;
+       switch (what) {
+       case PULSE:
+               led_stat[lednr].ontime = len;
+               led_stat[lednr].offtime = 0;
+               led_timer[lednr] = len;
+               led_on(lednr);
+               break;
+       case BLINK1:
+       case BLINK2:
+               if (what == BLINK1)
+                       led_stat[lednr].offtime = 100 - len;
+               else
+                       led_stat[lednr].offtime = 200 - len;
+               led_stat[lednr].ontime = len;
+               led_timer[lednr] = len;
+               led_on(lednr);
+               break;
+       default:
+               break;
+       }
+}
+
+/*--------------------------------------------------------------------------*/
+
+static volatile uint16_t key_state,
+               key_press, // key press detect
+               key_rpt; // key long press and repeat
+
+
+static uint16_t get_key_press(uint16_t key_mask) {
+       __disable_irq();
+       // read and clear atomic !
+       key_mask &= key_press; // read key(s)
+       key_press ^= key_mask; // clear key(s)
+       __enable_irq();
+       return key_mask;
+}
+
+/*
+static uint16_t get_key_rpt(uint16_t key_mask) {
+       __disable_irq();
+       // read and clear atomic !
+       key_mask &= key_rpt; // read key(s)
+       key_rpt ^= key_mask; // clear key(s)
+       __enable_irq();
+       return key_mask;
+}
+*/
+
+static uint16_t get_key_short(uint16_t key_mask) {
+       __disable_irq();
+       // read key state and key press atomic !
+       return get_key_press(key_state & key_mask);
+}
+
+/*
+static uint16_t get_key_long(uint16_t key_mask) {
+       return get_key_press(get_key_rpt(key_mask));
+}
+*/
+
+static void key_timerproc() {
+       static uint16_t key_in_last, rpt;
+       uint16_t key_in, c;
+
+       key_in = KEY_PORT;
+
+       c = key_in_last & key_in & ~key_state;
+
+//     key_state = key_state  & key_in_last | (key_state  | key_in_last) & key_in;
+//     key_state = key_state  & key_in      | (key_state  | key_in)      & key_in_last;
+
+       key_state = c | ((key_in_last | key_in) & key_state);
+               
+//     key_state = (key_state&key_in_last) | (key_state&key_in) | (key_in_last&key_in);
+
+       key_press |= c;
+       
+       key_in_last = key_in;
+       
+
+       if ((key_state & REPEAT_MASK) == 0) // check repeat function
+               rpt = REPEAT_START;
+       if (--rpt == 0) {
+               rpt = REPEAT_NEXT; // repeat delay
+               key_rpt |= key_state & REPEAT_MASK;
+       }
+
+}
+
+/*--------------------------------------------------------------------------*/
+
+void sys_tick_handler(void)
+{
+       static int_fast8_t tick_10ms = 0;
+       static int_fast16_t count_ms = 0;
+
+       int_fast8_t i;
+
+       ++tick_10ms;
+       if (tick_10ms == 10)
+       {
+               Stat |= S_10MS_TO;
+
+               tick_10ms = 0;
+               
+               i = led_timer[0];
+               if (i)
+                       led_timer[0] = i - 1;
+               i = led_timer[1];
+               if (i)
+                       led_timer[1] = i - 1;
+
+               key_timerproc();
+               
+               /* Drive timer procedure of low level disk I/O module */
+               //disk_timerproc();
+       }
+       
+       count_ms++;
+       if (count_ms == 1000) {
+               count_ms = 0;
+
+               i = timeout_1s;
+               if (i)
+                       timeout_1s = i - 1;
+       }
+}
+
+void rtc_isr(void)
+{
+       /* The interrupt flag isn't cleared by hardware, we have to do it. */
+       rtc_clear_flag(RTC_SEC);
+
+}
+
+/*--------------------------------------------------------------------------*/
+
+void tim3_set(int mode)
+{
+       uint16_t cc_mode;
+       
+       cc_mode = TIM_CCMR2_CC4S_OUT;
+
+       TIM3_CR1 = TIM_CR1_CMS_EDGE | TIM_CR1_DIR_UP /*| TIM_CR1_OPM */ ;
+
+       if (mode < 0)
+               cc_mode |= TIM_CCMR2_OC4M_FORCE_LOW;
+       else if (mode == 0)
+               cc_mode |= TIM_CCMR2_OC4M_FORCE_HIGH;
+       else {
+               TIM3_ARR = mode;
+               TIM3_CCR4 = mode/2;
+               cc_mode |= TIM_CCMR2_OC4M_PWM2;
+       }
+                       
+       TIM3_CCMR2 = cc_mode;
+               
+       if (mode > 0)
+               TIM3_CR1 |= TIM_CR1_CEN;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static uint32_t z80_sram_cmp(uint32_t addr, uint32_t length, uint8_t wval, int inc)
+{
+       uint8_t rval;
+       int_fast8_t errors = 0;
+       
+       DBG_P(1, "SRAM: Check %#.5x byte... ", length);
+       while (length--) {
+               if ((rval = z80_read(addr)) != wval) {
+                       if (errors == 0) { 
+                               printf("\nSRAM: Address  W  R\n" \
+                                      "      -------------\n");
+//                                            12345  00 11
+                       }
+                       printf("       %.5lx  %.2x %.2x\n", addr, wval, rval);
+                       
+                       if (++errors > 16 )
+                               break;
+               }
+               addr++;
+               wval += inc;
+       }
+       DBG_P(1, "Done.\n");
+
+       return addr;
+}
+
+#if 0
+static void z80_sram_fill(uint32_t addr, int length, uint8_t startval, int inc)
+{
+       printf("SRAM: Write %#.5x byte... ", length); //fflush(stdout);
+       while (length--) {
+               z80_write(addr, startval);
+               ++addr; 
+               startval += inc;
+       }
+       printf("Done.\n");
+}
+
+
+void z80_sram_fill_string(uint32_t addr, int length, const char *text)
+{
+       char c;
+       const char *p = text;
+
+       while (length--) {
+               z80_write(addr++, c = *p++);
+               if (c == 0)
+                       p = text;
+       }
+}
+
+
+uint32_t z80_sram_cmp_string(uint32_t addr, int length, const char *text)
+{
+       char c;
+       const char *p = text;
+
+       while (length--) {
+               c = *p++;
+               if (z80_read(addr) != c)
+                       break;
+               ++addr;
+               if (c == 0)
+                       p = text;
+       }
+       return addr;
+}
+
+const char * const qbfox = "Zhe quick brown fox jumps over the lazy dog!";
+const char * const qbcat = "Zhe quick brown fox jumps over the lazy cat!";
+
+#endif
+
+uint8_t z80_get_byte(uint32_t adr)
+{
+       uint8_t data;
+       
+       z80_request_bus();
+       data = z80_read(adr),
+       z80_release_bus();
+       
+       return data;
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+static void do_10ms(void) 
+{
+       for (uint_fast8_t i = 0; i < 2; i++) {
+               switch (led_stat[i].mode) {
+               case PULSE:
+                       if (led_timer[i] == 0) {
+                               led_off(i);
+                               led_stat[i].mode = NOTHING;
+                       }
+                       break;
+               case BLINK1:
+               case BLINK2:
+                       if (led_timer[i] == 0) {
+                               if (led_is_on(i))
+                                       led_timer[i] = led_stat[i].offtime;
+                               else
+                                       led_timer[i] = led_stat[i].ontime;
+                               led_toggle(i);
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
+struct msg_item {
+       uint8_t fct;
+       uint8_t sub_min, sub_max;
+       void (*func)(uint8_t, int, uint8_t *);
+};
+
+uint32_t msg_to_addr(uint8_t *msg)
+{
+       uint32_t addr = msg[0] | (msg[1] << 8) | ((uint32_t)msg[2] << 16);
+
+       return addr;
+
+}
+
+void do_msg_ini_msgfifo(uint8_t subf, int len, uint8_t * msg)
+{
+       (void)subf; (void)len;
+
+       z80_init_msg_fifo(msg_to_addr(msg));
+}
+
+
+void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg)
+{
+       (void)len;
+
+       z80_memfifo_init(subf - 1, msg_to_addr(msg));
+}
+
+
+void do_msg_char_out(uint8_t subf, int len, uint8_t * msg)
+{
+       (void)subf;
+
+       while (len--)
+               putchar(*msg++);
+}
+
+
+const struct msg_item z80_messages[] =
+{
+       { 0,                    /* fct nr. */
+         0, 0,                 /* sub fct nr. from, to */
+         &do_msg_ini_msgfifo},
+       { 0,
+         1, 2,
+         &do_msg_ini_memfifo},
+       { 1,
+         1, 1,
+         &do_msg_char_out},
+       { 0xff,                         /* end mark */
+         0, 0,
+         0},
+
+};
+
+
+
+
+void do_message(int len, uint8_t *msg)
+{
+       uint8_t fct, sub_fct;
+       int_fast8_t i = 0;
+
+       if (len >= 2) {
+               fct = *msg++;
+               sub_fct = *msg++;
+               len -= 2;
+
+               while (fct != z80_messages[i].fct)
+                       ++i;
+
+               if (z80_messages[i].fct == 0xff) {
+                       DBG_P(1, "do_message: Unknown function: %i, %i\n",
+                                       fct, sub_fct);
+                       return; /* TODO: unknown message # */
+               }
+
+               while (fct == z80_messages[i].fct) {
+                       if (sub_fct >= z80_messages[i].sub_min && sub_fct <= z80_messages[i].sub_max )
+                               break;
+                       ++i;
+               }
+
+               if (z80_messages[i].fct != fct) {
+                       DBG_P(1, "do_message: Unknown sub function: %i, %i\n",
+                                       fct, sub_fct);
+                       return; /* TODO: unknown message sub# */
+               }
+
+               (z80_messages[i].func)(sub_fct, len, msg);
+
+
+       } else {
+               /* TODO: error */
+               DBG_P(1, "do_message: to few arguments (%i); this shouldn't happen!\n", len);
+       }
+}
+
+
+
+#define CTRBUF_LEN 256
+
+void check_msg_fifo(void)
+{
+       int ch;
+       static int_fast8_t state;
+       static int msglen,idx;
+       static uint8_t buffer[CTRBUF_LEN];
+
+       while (state != 3 && (ch = z80_msg_fifo_getc()) >= 0) {
+               switch (state) {
+               case 0:         /* wait for start of message */
+                       if (ch == 0x81) {
+                               msglen = 0;
+                               idx = 0;
+                               state = 1;
+                       }
+                       break;
+               case 1:         /* get msg len */
+                       if (ch > 0 && ch <= CTRBUF_LEN) {
+                               msglen = ch;
+                               state = 2;
+                       } else
+                               state = 0;
+                       break;
+               case 2:         /* get message */
+                       buffer[idx++] = ch;
+                       if (idx == msglen)
+                               state = 3;
+                       break;
+               }
+       }
+
+       if (state == 3) {
+               do_message(msglen, buffer);
+               state = 0;
+       }
+}
+
+
+void z80_load_mem(void)
+{
+       unsigned sec = 0;
+       uint32_t sec_base = hdrom_start;
+
+       DBG_P(1, "Loading z80 memory... \n");
+
+       while (sec < hdrom_sections) {
+               DBG_P(2, "  From: 0x%.5lX to: 0x%.5lX    (%5li bytes)\n",
+                               hdrom_address[sec],
+                               hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
+                               hdrom_length_of_sections[sec]);
+
+               z80_write_block((unsigned char *) &hdrom[sec_base],  /* src */
+                               hdrom_address[sec],                  /* dest */
+                               hdrom_length_of_sections[sec]);      /* len */
+               sec_base+=hdrom_length_of_sections[sec];
+               sec++;
+       }
+}
+/*--------------------------------------------------------------------------*/
+
+int main(void)
+{
+       int_fast8_t state = 0;
+       int ch;
+
+       clock_setup();
+       gpio_setup();
+       tim3_setup();
+       setvbuf(stdout, NULL, _IONBF, 0);
+       serial_setup();
+       printf("\n(STM32F100+HD64180)_stamp Tester\n");
+
+       DBG_P(1, "z80_setup_bus... ");
+       z80_setup_msg_fifo();
+       z80_setup_bus();
+       DBG_P(1, "done.\n");
+
+       /*
+        * If the RTC is pre-configured just allow access, don't reconfigure.
+        * Otherwise enable it with the LSE as clock source and 0x7fff as
+        * prescale value.
+        */
+       rtc_auto_awake(LSE, 0x7fff);
+
+       systick_setup();
+
+       DBG_P(1, "Get bus... ");
+       z80_busreq(LOW);
+       z80_reset(HIGH);
+       z80_request_bus();
+       DBG_P(1, "got it!\n");
+       
+       z80_memset(0, 0x76, 0x80000);
+       //z80_sram_fill(0, 512 * 1024, 0x76, 0);
+       z80_sram_cmp(0, (uint32_t)512 * 1024, 0x76, 0);
+       
+       z80_load_mem();
+       z80_reset(LOW);
+       DBG_P(1, "Bus released!\n");
+       z80_release_bus();
+       z80_reset(HIGH);
+       DBG_P(1, "Reset released!\n");
+       
+       
+       ledset(0, BLINK1, 50);
+
+       while (1) {
+
+               if (Stat & S_10MS_TO) {
+                       Stat &= ~S_10MS_TO;
+                       do_10ms();
+               }
+
+               if (get_key_short(KEY0)) {
+                       z80_reset_pulse();
+               }
+
+               if ((ch = serial_getc()) >= 0) {
+                       switch (state) {
+                       case 0:
+                               if (ch == ESCCHAR) {
+                                       state = 1;
+                                       /* TODO: Timer starten */
+                               } else
+                                       z80_memfifo_putc(fifo_out, ch);
+                               break;
+                       case 1:
+                               switch (ch) {
+
+                               case 'h': /* test: green led on */
+                                       tim3_set(-1);
+                                       break;
+                               case 'l': /* test: green led off */
+                                       tim3_set(0);
+                                       break;
+                               case 'p': /* test: pulse on led pin */
+                                       tim3_set(24000000 / 1000000 * 5); /* 5 us */
+                                       break;
+                               case 'r':
+                                       z80_reset_pulse();
+                                       break;
+
+                               case ESCCHAR:
+                               default:
+                                       z80_memfifo_putc(fifo_out, ch);
+                               }
+                               state = 0;
+                               break;
+                       }
+               }
+
+               check_msg_fifo();
+       }
+
+       return 0;
+}
diff --git a/stm32/z80-if.c b/stm32/z80-if.c
new file mode 100644 (file)
index 0000000..171fea9
--- /dev/null
@@ -0,0 +1,731 @@
+/**
+ *
+ * Pin assignments
+ *
+ * | Z180-Sig  |  STM32-Port   |Buffer |  Dir  |   Special Function    |
+ * +------------+---------------+-------+-------+-----------------------+
+ * |   A0      | A     1       |   P   |  O    |                       |
+ * |   A1      | A     2       |   P   |  O    |                       |
+ * |   A2      | A     3       |   P   |  O    |                       |
+ * |   A3      | A     4       |   P   |  O    |                       |
+ * |   A4      | A     5       |   P   |  O    |                       |
+ * |   A5      | A     6       |   P   |  O    |                       |
+ * |   A6      | A     7       |   P   |  O    |                       |
+ * |   A7      | A     8       |       |  O    |                       |
+ * |   A8      | C     0       |   P   |  O    |                       |
+ * |   A9      | C     1       |   P   |  O    |                       |
+ * |   A10     | C     2       |   P   |  O    |                       |
+ * |   A11     | C     3       |   P   |  O    |                       |
+ * |   A12     | C     4       |   P   |  O    |                       |
+ * |   A13     | C     5       |   P   |  O    |                       |
+ * |   A14     | C     6       |       |  O    |                       |
+ * |   A15     | C     7       |       |  O    |                       |
+ * |   A16     | C     10      |       |  O    |                       |
+ * |   A17     | C     11      |       |  O    |                       |
+ * |   A18     | C     12      |       |  O    |                       |
+ * |   D0      | B     8       |       |  I/O  |                       |
+ * |   D1      | B     9       |       |  I/O  |                       |
+ * |   D2      | B     10      |       |  I/O  |                       |
+ * |   D3      | B     11      |       |  I/O  |                       |
+ * |   D4      | B     12      |       |  I/O  |                       |
+ * |   D5      | B     13      |       |  I/O  |                       |
+ * |   D6      | B     14      |       |  I/O  |                       |
+ * |   D7      | B     15      |       |  I/O  |                       |
+ * |   ME      | C     13      |   P   |  O    |                       |
+ * |   RD      | B     0       |   P   |  O    |                       |
+ * |   WR      | B     1       |   P   |  O    |                       |
+ * |   BUSREQ  | D     2       |       |  O    |                       |
+ * |   IOCS1   | A     11      |       |  I    |  TIM1_CH4             |
+ * |   BUSACK  | A     12      |       |  I    |                       |
+ * |   HALT    | A     12      |       |  I    |                       |
+ * |   NMI     | B     7       |       |  O    |                       |
+ * |   RST     | B     6       |       |  O    |  TIM16_CH1N           |
+ * |           |               |       |       |                       |
+ * |           | A     9       |       |       |  af1   USART1_TX      |
+ * |           | A     10      |       |       |  af1   USART1_RX      |
+ * |           | A     15      |       | JTDI  |  remap SPI1_NSS'      |
+ * |           | B     3       |       | JTDO  |  remap SPI1_SCK'      |
+ * |           | B     4       |       |NJTRST |  remap SPI1_MISO'     |
+ * |           | B     5       |       |       |  remap SPI1_MOSI'     |
+ * |           | C     14      |       |       |  af1   OSC32          |
+ * |           | C     15      |       |       |  af1   OSC32          |
+
+
+AFIO_MAPR2 =
+AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON  (frees
+AFIO_MAPR_SPI1_REMAP
+
+ */
+
+/**
+ *
+ * Pin assignments
+ *
+ * | Z180-Sig | STM32-Port | Buffer | Dir |Special Function |
+ * | -------- | ---------- | ------ | --- | --------------- |
+ * |   A0      |A      1       |P      |O | |
+ * |   A1      |A      2       |P      |O | |
+ * |   A2      |A      3       |P      |O | |
+ * |   A3      |A      4       |P      |O | |
+ * |   A4      |A      5       |P      |O | |
+ * |   A5      |A      6       |P      |O | |
+ * |   A6      |A      7       |P      |O | |
+ * |   A7      |A      8       |       |O | |
+ * |   A8      |C      0       |P      |O | |
+ * |   A9      |C      1       |P      |O | |
+ * |   A10     |C      2       |P      |O | |
+ * |   A11     |C      3       |P      |O | |
+ * |   A12     |C      4       |P      |O | |
+ * |   A13     |C      5       |P      |O | |
+ * |   A14     |C      6       |       |O | |
+ * |   A15     |C      7       |       |O | |
+ * |   A16     |C      10      |       |O | |
+ * |   A17     |C      11      |       |O | |
+ * |   A18     |C      12      |       |O | |
+ * |   D0      |B      8       |       |I/O | |
+ * |   D1      |B      9       |       |I/O | |
+ * |   D2      |B      10      |       |I/O | |
+ * |   D3      |B      11      |       |I/O | |
+ * |   D4      |B      12      |       |I/O | |
+ * |   D5      |B      13      |       |I/O | |
+ * |   D6      |B      14      |       |I/O | |
+ * |   D7      |B      15      |       |I/O | |
+ * |   ME      |C      13      |P      |O | |
+ * |   RD      |B      0       |P      |O | |
+ * |   WR      |B      1       |P      |O | |
+ * |   BUSREQ  |D      2       |       |O | |
+ * |   IOCS1   |A      11      |       |I      |TIM1_CH4 |
+ * |   BUSACK  |A      12      |       |I | |
+ * |   HALT    |A      12      |       |I | |
+ * |   NMI     |B      7       |       |O | |
+ * |   RST     |B      6       |       |O      |TIM16_CH1N |
+ * |           |               |       |       | |
+ * |           |A 9            |       |       |af1    USART1_TX |
+ * |           |A 10           |       |       |af1    USART1_RX |
+ * |           |A 15           |       |JTDI   |       remap   SPI1_NSS' |
+ * |           |B 3            |       |JTDO   |remap   SPI1_SCK' |
+ * |           |B 4            |       |NJTRST |remap  SPI1_MISO' |
+ * |           |B 5            |       |       |remap  SPI1_MOSI' |
+ * |           |C 14           |       |       |af1    OSC32 |
+ * |           |C 15           |       |       |af1    OSC32 |
+
+
+AFIO_MAPR2 =
+AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON  (frees 
+AFIO_MAPR_SPI1_REMAP 
+
+ */
+
+#include <stdio.h>
+
+
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/timer.h>
+#include <libopencm3/stm32/dma.h>
+#include "debug.h"
+#include "z80-if.h"
+
+
+/* Number of array elements */
+#define NELEMS(x)  (sizeof x/sizeof *x)
+
+#define ODR    0x0c
+#define IDR    0x08
+
+#define CONCAT(x,y) x ## y
+#define EVALUATOR(x,y)  CONCAT(x,y)
+
+#define GPIO_(X)       CONCAT(GPIO, X)
+
+
+
+
+#define P_ME           GPIOC
+#define ME             13
+#define P_RD           GPIOB
+#define RD             0
+#define P_WR           GPIOB
+#define WR             1
+#define P_BUSREQ       GPIOD
+#define BUSREQ         2
+#define P_BUSACK       GPIOA
+#define BUSACK         12
+//#define P_HALT               GPIOA
+//#define HALT         12
+#define P_IOCS1                GPIOA
+#define IOCS1          11
+#define P_NMI          GPIOB
+#define NMI            7
+#define P_RST          GPIOB
+#define RST            6
+
+#define ADp1_OFS       0
+#define ADp1_WIDTH     8
+#define ADp1_SHIFT     1
+#define ADp1_PORT      GPIOA
+
+#define ADp2_OFS       ADp1_WIDTH
+#define ADp2_WIDTH     8
+#define ADp2_SHIFT     0
+#define ADp2_PORT      GPIOC
+
+#define ADp3_OFS       (ADp2_OFS+ADp2_WIDTH)
+#define ADp3_WIDTH     3
+#define ADp3_SHIFT     10
+#define ADp3_PORT      GPIOC
+
+#define ADunbuff1_WIDTH        1
+#define ADunbuff1_SHIFT        8
+#define ADunbuff1_PORT GPIOA
+
+#define ADunbuff2_WIDTH        2
+#define ADunbuff2_SHIFT        6
+#define ADunbuff2_PORT GPIOC
+
+#define ADunbuff3_WIDTH        3
+#define ADunbuff3_SHIFT        10
+#define ADunbuff3_PORT GPIOC
+
+#define DB_OFS         0
+#define DB_WIDTH       8
+#define DB_SHIFT       8
+#define DB_PORT                GPIOB
+
+#define GPIO_ME                GPIO_(ME)
+#define GPIO_RD                GPIO_(RD)
+#define GPIO_WR                GPIO_(WR)
+#define GPIO_BUSREQ    GPIO_(BUSREQ)
+#define GPIO_BUSACK    GPIO_(BUSACK)
+//#define GPIO_HALT    GPIO_(HALT)
+#define GPIO_IOCS1     GPIO_(IOCS1)
+#define GPIO_NMI       GPIO_(NMI)
+#define GPIO_RST       GPIO_(RST)
+
+#define        Z80_O_ME        BBIO_PERIPH(P_ME+ODR, ME)
+#define Z80_O_RD       BBIO_PERIPH(P_RD+ODR, RD)
+#define Z80_O_WR       BBIO_PERIPH(P_WR+ODR, WR)
+#define Z80_O_BUSREQ   BBIO_PERIPH(P_BUSREQ+ODR, BUSREQ)
+#define Z80_O_NMI      BBIO_PERIPH(P_NMI+ODR, NMI)
+#define Z80_O_RST      BBIO_PERIPH(P_RST+ODR, RST)
+
+#define Z80_I_BUSACK   BBIO_PERIPH(P_BUSACK+IDR, BUSACK)
+//#define Z80_I_HALT   BBIO_PERIPH(P_HALT+IDR, HALT)
+
+
+#define MASK(n)        ((1<<n)-1)
+
+#define IOFIELD_SET(src, ofs, width, shift) \
+               ((((src>>ofs) & MASK(width)) << shift) | ((((~src>>ofs) & MASK(width)) << shift) << 16))
+
+#define IOFIELD_GET(src, width, shift) \
+               ((src>>shift) & MASK(width))
+               
+#define CNF_MODE_I_F       (GPIO_CNF_INPUT_FLOAT<<2 |GPIO_MODE_INPUT)
+#define CNF_MODE_O_PP  (GPIO_CNF_OUTPUT_PUSHPULL<<2 | GPIO_MODE_OUTPUT_10_MHZ)
+
+#define DB_MODE_INPUT  ( (CNF_MODE_I_F << (4 * 0)) \
+                       | (CNF_MODE_I_F << (4 * 1)) \
+                       | (CNF_MODE_I_F << (4 * 2)) \
+                       | (CNF_MODE_I_F << (4 * 3)) \
+                       | (CNF_MODE_I_F << (4 * 4)) \
+                       | (CNF_MODE_I_F << (4 * 5)) \
+                       | (CNF_MODE_I_F << (4 * 6)) \
+                       | (CNF_MODE_I_F << (4 * 7)))
+
+#define DB_MODE_OUTPUT ( (CNF_MODE_O_PP << (4 * 0)) \
+                       | (CNF_MODE_O_PP << (4 * 1)) \
+                       | (CNF_MODE_O_PP << (4 * 2)) \
+                       | (CNF_MODE_O_PP << (4 * 3)) \
+                       | (CNF_MODE_O_PP << (4 * 4)) \
+                       | (CNF_MODE_O_PP << (4 * 5)) \
+                       | (CNF_MODE_O_PP << (4 * 6)) \
+                       | (CNF_MODE_O_PP << (4 * 7)))
+
+
+/*--------------------------------------------------------------------------*/
+
+static void tim16_setup(void)
+{
+       RCC_APB2RSTR |= RCC_APB2RSTR_TIM16RST;
+       RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM16RST;
+       
+       TIM16_BDTR = TIM_BDTR_MOE;
+               
+       TIM16_CCMR1 = 0
+               | TIM_CCMR1_OC1M_FORCE_LOW      
+               | TIM_CCMR1_CC1S_OUT;
+               
+       TIM16_CCER = TIM_CCER_CC1NE
+               | TIM_CCER_CC1NP;
+       
+       TIM16_ARR = 48; /* default */
+       TIM16_CCR1 = 1; /*  */
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void tim16_set(int mode)
+{
+       uint16_t cc_mode;
+       
+       cc_mode = TIM_CCMR1_CC1S_OUT;
+
+       TIM16_CR1 = TIM_CR1_OPM;
+
+       if (mode < 0)
+               cc_mode |= TIM_CCMR1_OC1M_FORCE_LOW;
+       else if (mode == 0)
+               cc_mode |= TIM_CCMR1_OC1M_FORCE_HIGH;
+       else {
+               TIM16_ARR = mode;
+               cc_mode |= TIM_CCMR1_OC1M_PWM2;
+       }
+                       
+       TIM16_CCMR1 = cc_mode;
+               
+       if (mode > 0)
+               TIM16_CR1 |= TIM_CR1_CEN;
+}
+
+/*--------------------------------------------------------------------------*/
+
+
+
+/* 
+ * A0..A6, A8..A13 are buffered. No need to disable.
+ * A7, A14..A18: set to input.
+ */
+static void z80_setup_adrbus_tristate(void)
+{
+#if 0
+       gpio_set_mode(ADunbuff1_PORT, GPIO_MODE_INPUT,
+               GPIO_CNF_INPUT_FLOAT, MASK(ADunbuff1_WIDTH) << ADunbuff1_SHIFT);
+       gpio_set_mode(ADunbuff2_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, 
+               (MASK(ADunbuff2_WIDTH) << ADunbuff2_SHIFT) | (MASK(ADunbuff3_WIDTH) << ADunbuff3_SHIFT));
+#else
+       GPIO_CRH(GPIOA) = (GPIO_CRH(GPIOA) & ~(0x0f << (4 * 0))) 
+                       | (CNF_MODE_I_F << (4 * 0));
+       GPIO_CRL(GPIOC) = (GPIO_CRL(GPIOC) & ~((0x0f << (4 * 6)) | (0x0f << (4 * 7))))
+                       | ((CNF_MODE_I_F << (4 * 6)) | (CNF_MODE_I_F << (4 * 7)));
+       GPIO_CRH(GPIOC) = (GPIO_CRH(GPIOC) & ~((0x0f << (4*2)) | (0x0f << (4*3)) | (0x0f << (4*4))))
+                       | ((CNF_MODE_I_F << (4*2)) | (CNF_MODE_I_F << (4*3)) | (CNF_MODE_I_F << (4*4)));
+#endif 
+}
+
+       
+static void z80_setup_adrbus_active(void)
+{
+#if 0
+       gpio_set_mode(ADunbuff1_PORT, GPIO_MODE_OUTPUT_10_MHZ,
+               GPIO_CNF_OUTPUT_PUSHPULL, MASK(ADunbuff1_WIDTH) << ADunbuff1_SHIFT);
+       gpio_set_mode(ADunbuff2_PORT, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, 
+               (MASK(ADunbuff2_WIDTH) << ADunbuff2_SHIFT) | (MASK(ADunbuff3_WIDTH) << ADunbuff3_SHIFT));
+#else
+       GPIO_CRH(GPIOA) = (GPIO_CRH(GPIOA) & ~(0x0f << (4 * 0))) 
+                       | (CNF_MODE_O_PP << (4 * 0));
+       GPIO_CRL(GPIOC) = (GPIO_CRL(GPIOC) & ~((0x0f << (4 * 6)) | (0x0f << (4 * 7))))
+                       | ((CNF_MODE_O_PP << (4 * 6)) | (CNF_MODE_O_PP << (4 * 7)));
+       GPIO_CRH(GPIOC) = (GPIO_CRH(GPIOC) & ~((0x0f << (4*2)) | (0x0f << (4*3)) | (0x0f << (4*4))))
+                       | ((CNF_MODE_O_PP << (4*2)) | (CNF_MODE_O_PP << (4*3)) | (CNF_MODE_O_PP << (4*4)));
+#endif 
+}
+
+
+static void z80_setup_dbus_in(void)
+{
+       GPIO_CRH(DB_PORT) = DB_MODE_INPUT;
+}
+
+static void z80_setup_dbus_out(void)
+{
+       GPIO_CRH(DB_PORT) = DB_MODE_OUTPUT;
+}
+
+
+static void z80_setaddress(uint32_t addr)
+{
+       GPIO_BSRR(ADp1_PORT) = IOFIELD_SET(addr, ADp1_OFS, ADp1_WIDTH, ADp1_SHIFT);
+       GPIO_BSRR(ADp2_PORT) = IOFIELD_SET(addr, ADp2_OFS, ADp2_WIDTH, ADp2_SHIFT);
+       GPIO_BSRR(ADp3_PORT) = IOFIELD_SET(addr, ADp3_OFS, ADp3_WIDTH, ADp3_SHIFT);
+}
+
+void z80_setup_bus(void)
+{
+       tim16_setup();
+
+       gpio_set_mode(P_RST, GPIO_MODE_OUTPUT_10_MHZ,
+               GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_RST);
+       Z80_O_BUSREQ = 1;
+       gpio_set_mode(P_BUSREQ, GPIO_MODE_OUTPUT_10_MHZ,
+               GPIO_CNF_OUTPUT_PUSHPULL, GPIO_BUSREQ);
+       Z80_O_NMI = 1;
+       gpio_set_mode(P_NMI, GPIO_MODE_OUTPUT_10_MHZ,
+               GPIO_CNF_OUTPUT_PUSHPULL, GPIO_NMI);
+       Z80_O_ME = 1;
+       Z80_O_RD = 1;
+       Z80_O_WR = 1;
+       gpio_set_mode(P_ME, GPIO_MODE_OUTPUT_2_MHZ,
+               GPIO_CNF_OUTPUT_PUSHPULL, GPIO_ME);
+       gpio_set_mode(P_RD, GPIO_MODE_OUTPUT_10_MHZ,
+               GPIO_CNF_OUTPUT_PUSHPULL, GPIO_RD | GPIO_WR);
+
+       //Z80_O_BUSREQ = 0;
+       //while(Z80_I_BUSACK == 1);
+
+       gpio_set_mode(ADp1_PORT, GPIO_MODE_OUTPUT_10_MHZ,
+               GPIO_CNF_OUTPUT_PUSHPULL, MASK(ADp1_WIDTH) << ADp1_SHIFT);
+       gpio_set_mode(ADp2_PORT, GPIO_MODE_OUTPUT_10_MHZ,
+               GPIO_CNF_OUTPUT_PUSHPULL, MASK(ADp2_WIDTH) << ADp2_SHIFT);
+       gpio_set_mode(ADp3_PORT, GPIO_MODE_OUTPUT_10_MHZ,
+               GPIO_CNF_OUTPUT_PUSHPULL, MASK(ADp3_WIDTH) << ADp3_SHIFT);
+
+       z80_setup_dbus_in();
+}
+
+void z80_request_bus(void)
+{
+       Z80_O_BUSREQ = 0;
+       while(Z80_I_BUSACK == 1);
+       z80_setup_adrbus_active();
+}
+
+void z80_release_bus(void)
+{
+       z80_setup_dbus_in();
+       z80_setup_adrbus_tristate();
+       Z80_O_BUSREQ = 1;
+       while(Z80_I_BUSACK == 0);
+}
+
+void z80_reset(level_t level)
+{
+       int x = level ? -1 : 0;
+       
+       tim16_set(x);
+       
+//     Z80_O_RST = level;
+}
+
+void z80_reset_pulse(void)
+{
+       tim16_set(48);
+}
+
+void z80_busreq(level_t level)
+{
+       Z80_O_BUSREQ = level;
+}
+
+#if 0
+int z80_stat_halt(void)
+{
+       return Z80_I_HALT;
+}
+#endif
+
+void z80_write(uint32_t addr, uint8_t data)
+{
+       z80_setaddress(addr);
+       Z80_O_ME = 0;
+       GPIO_BSRR(DB_PORT) = IOFIELD_SET(data, DB_OFS, DB_WIDTH, DB_SHIFT);
+       z80_setup_dbus_out();
+       Z80_O_WR = 0;
+       Z80_O_WR = 1;
+       Z80_O_ME = 1;
+}
+
+uint8_t z80_read(uint32_t addr)
+{
+       uint8_t data;
+
+       z80_setaddress(addr);
+       Z80_O_ME = 0;
+       z80_setup_dbus_in();
+       Z80_O_RD = 0;
+       Z80_O_RD = 0;
+       data = IOFIELD_GET(GPIO_IDR(DB_PORT),DB_WIDTH, DB_SHIFT);
+       Z80_O_RD = 1;
+       Z80_O_ME = 1;
+
+       return data;
+}
+
+
+void z80_memset(uint32_t addr, uint8_t data, int length)
+{
+       z80_setup_dbus_out();
+       Z80_O_ME = 0;
+       while(length--) {
+               z80_setaddress(addr++);
+               GPIO_BSRR(DB_PORT) = IOFIELD_SET(data, DB_OFS, DB_WIDTH, DB_SHIFT);
+               Z80_O_WR = 0;
+               Z80_O_WR = 1;
+       }
+       Z80_O_ME = 1;
+}
+
+void z80_write_block(uint8_t *src, uint32_t dest, uint32_t length)
+{
+       uint8_t data;
+       
+       z80_setup_dbus_out();
+       Z80_O_ME = 0;
+       while(length--) {
+               z80_setaddress(dest++);
+               data = *src++;
+               GPIO_BSRR(DB_PORT) = IOFIELD_SET(data, DB_OFS, DB_WIDTH, DB_SHIFT);
+               Z80_O_WR = 0;
+               Z80_O_WR = 1;
+       }
+       Z80_O_ME = 1;
+}
+
+/*
+  0179'                         rx.bs_mask:    ds      1               ; (buf_len - 1)
+  017A'                         rx.in_idx:     ds      1               ;
+  017B'                         rx.out_idx:    ds      1               ;
+  017C'                         rx.buf:                ds      rx.buf_len      ;
+  018B'                         rx.buf_end     equ     $-1             ; last byte (start+len-1)
+                                
+  018C'                         tx.bs_mask:    ds      1               ; (buf_len - 1)
+  018D'                         tx.in_idx:     ds      1               ;
+  018E'                         tx.out_idx:    ds      1               ;
+  018F'                         tx.buf:                ds      tx.buf_len      ;
+  019E'                         tx.buf_end     equ     $-1             ; last byte
+*/
+
+
+typedef struct __attribute__((packed)) {
+       uint8_t mask;
+       uint8_t in_idx;
+       uint8_t out_idx;
+       uint8_t buf[];
+} zfifo_t;
+
+
+
+#define FIFO_BUFSIZE_MASK      -3
+#define FIFO_INDEX_IN          -2
+#define FIFO_INDEX_OUT         -1
+
+
+static struct {
+       uint32_t base;
+       uint8_t idx_out,
+               idx_in,
+               mask;
+       } fifo_dsc[NUM_FIFOS];
+       
+
+void z80_memfifo_init(const fifo_t f, uint32_t adr)
+{
+
+DBG_P(2, "z80_memfifo_init: %i, %lx\n", f, adr);
+
+       fifo_dsc[f].base = adr;
+
+       z80_request_bus();
+
+       fifo_dsc[f].mask = z80_read(adr + FIFO_BUFSIZE_MASK);
+       fifo_dsc[f].idx_in = z80_read(adr + FIFO_INDEX_IN);
+       fifo_dsc[f].idx_out = z80_read(adr + FIFO_INDEX_OUT);
+
+       z80_release_bus();
+}
+
+
+int z80_memfifo_is_empty(const fifo_t f)
+{
+       int rc = 1;
+
+       if (fifo_dsc[f].base != 0) {
+
+               uint32_t adr = fifo_dsc[f].base + FIFO_INDEX_IN;
+               uint8_t idx;
+
+               z80_request_bus();
+               idx = z80_read(adr);
+               z80_release_bus();
+               rc = idx == fifo_dsc[f].idx_out;
+       }
+
+       return rc;
+}
+
+int z80_memfifo_is_full(const fifo_t f)
+{
+       int rc = 1;
+       
+       if (fifo_dsc[f].base != 0) {
+               z80_request_bus();
+               rc = ((fifo_dsc[f].idx_in + 1) & fifo_dsc[f].mask)
+                       == z80_read(fifo_dsc[f].base+FIFO_INDEX_OUT);
+               z80_release_bus();
+       }
+       return rc;
+}
+
+uint8_t z80_memfifo_getc(const fifo_t f)
+{
+       uint8_t rc, idx;
+       
+       while (z80_memfifo_is_empty(f))
+               ;
+
+       z80_request_bus();
+       idx = fifo_dsc[f].idx_out;
+       rc = z80_read(fifo_dsc[f].base+idx);
+       fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
+       z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
+       z80_release_bus();
+       
+       return rc;
+}
+
+
+void z80_memfifo_putc(fifo_t f, uint8_t val)
+{
+       int idx;
+       
+       while (z80_memfifo_is_full(f))
+               ;
+
+       z80_request_bus();
+       idx = fifo_dsc[f].idx_in;
+       z80_write(fifo_dsc[f].base+idx, val);
+       fifo_dsc[f].idx_in = ++idx & fifo_dsc[f].mask;
+       z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in);
+       z80_release_bus();
+}
+
+/*--------------------------------------------------------------------------*/
+
+static struct {
+       uint32_t base;
+       //uint8_t  idx_out, idx_in;
+       uint16_t count;
+       uint8_t  buf[256];
+       } msg_fifo;
+
+/*--------------------------------------------------------------------------*/
+
+#if 0
+
+static void tim1_setup(void)
+{
+       RCC_APB2RSTR |= RCC_APB2RSTR_TIM1RST;
+       RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM1RST;
+
+       TIM1_CR1 = 0;
+
+       TIM1_SMCR = 0
+       /*      | TIM_SMCR_ETP                  */
+       /*      | TIM_SMCR_ETF_CK_INT_N_2       */
+               | TIM_SMCR_TS_ETRF
+               | TIM_SMCR_SMS_OFF
+               ;
+
+       TIM1_DIER = TIM_DIER_TDE;
+
+
+       TIM1_CCMR1 = 0
+               | TIM_CCMR1_OC1M_FORCE_LOW
+               | TIM_CCMR1_CC1S_OUT;
+
+       TIM1_SMCR |= TIM_SMCR_SMS_TM;
+}
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+static void tim1_ch4_setup(void)
+{
+       /* Reset Timer 1 */
+       RCC_APB2RSTR |= RCC_APB2RSTR_TIM1RST;
+       RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM1RST;
+
+       TIM1_CCMR2 = 0
+               | TIM_CCMR2_CC4S_IN_TI2
+               | TIM_CCMR2_IC4F_OFF
+               | TIM_CCMR2_IC4PSC_OFF;
+
+       TIM1_CCER = 0
+       /*      | TIM_CCER_CC4P */
+               | TIM_CCER_CC4E;
+
+       /* Enable DMA for channel 4 */
+       TIM1_DIER = TIM_DIER_CC4DE;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void dma1_ch4_setup(void)
+{
+       DMA1_CCR4 =
+               DMA_CCR_PL_VERY_HIGH
+               | DMA_CCR_MSIZE_8BIT
+               | DMA_CCR_PSIZE_8BIT
+               | DMA_CCR_MINC
+               | DMA_CCR_CIRC;
+
+       DMA1_CMAR4 = (uint32_t) msg_fifo.buf;
+
+#if (DB_SHIFT == 0) || (DB_SHIFT == 8)
+       DMA1_CPAR4 = DB_PORT + IDR + DB_SHIFT/8;
+#else
+       #error "Databus not byte aligned!"
+#endif
+
+       DMA1_CNDTR4 = NELEMS(msg_fifo.buf);
+//     msg_fifo.count = NELEMS(msg_fifo.buf);
+       msg_fifo.count = 0;
+       msg_fifo.base = 0;
+
+       DMA1_CCR4 |= DMA_CCR_EN;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void z80_setup_msg_fifo(void)
+{
+       gpio_set_mode(P_BUSACK, GPIO_MODE_INPUT,
+               GPIO_CNF_INPUT_FLOAT, GPIO_BUSACK | GPIO_IOCS1);
+
+       tim1_ch4_setup();
+       dma1_ch4_setup();
+}
+
+
+void z80_init_msg_fifo(uint32_t addr)
+{
+
+DBG_P(1, "z80_init_msg_fifo: %lx\n", addr);
+
+       z80_request_bus();
+       z80_write(addr+FIFO_INDEX_OUT, z80_read(addr+FIFO_INDEX_IN));
+       z80_release_bus();
+       msg_fifo.base = addr;
+}
+
+
+int z80_msg_fifo_getc(void)
+{
+       int c = -1;
+       
+       if (msg_fifo.count != (NELEMS(msg_fifo.buf) - DMA1_CNDTR4)) {
+               c = msg_fifo.buf[msg_fifo.count];
+               if (++msg_fifo.count == NELEMS(msg_fifo.buf))
+                       msg_fifo.count = 0;
+
+               if (msg_fifo.base != 0) {
+                       z80_request_bus();
+                       z80_write(msg_fifo.base+FIFO_INDEX_OUT, msg_fifo.count);
+                       z80_release_bus();
+               }
+       }
+
+       return c;
+}
diff --git a/stm32/z80-if.h b/stm32/z80-if.h
new file mode 100644 (file)
index 0000000..d7c030d
--- /dev/null
@@ -0,0 +1,32 @@
+
+typedef enum {LOW, HIGH} level_t;
+
+//static void z80_setup_adrbus_tristate(void);
+//static void z80_setup_adrbus_active(void);
+//static void z80_setup_dbus_in(void);
+//static void z80_setup_dbus_out(void);
+//static void z80_setaddress(uint32_t addr);
+void z80_setup_bus(void);
+void z80_write(uint32_t addr, uint8_t data);
+uint8_t z80_read(uint32_t addr);
+void z80_request_bus(void);
+void z80_release_bus(void);
+void z80_memset(uint32_t addr, uint8_t data, int length);
+void z80_reset(level_t level);
+void z80_reset_pulse(void);
+void z80_busreq(level_t level);
+void z80_write_block(uint8_t *src, uint32_t dest, uint32_t length);
+int z80_stat_halt(void);
+
+
+typedef enum fifo_t {fifo_in, fifo_out, NUM_FIFOS} fifo_t;
+
+void z80_memfifo_init(const fifo_t f, uint32_t adr);
+int z80_memfifo_is_empty(const fifo_t f);
+int z80_memfifo_is_full(const fifo_t f);
+uint8_t z80_memfifo_getc(const fifo_t f);
+void z80_memfifo_putc(fifo_t f, uint8_t val);
+
+void z80_setup_msg_fifo(void);
+void z80_init_msg_fifo(uint32_t addr);
+int z80_msg_fifo_getc(void);
diff --git a/z180/Makefile b/z180/Makefile
new file mode 100644 (file)
index 0000000..f676826
--- /dev/null
@@ -0,0 +1,126 @@
+
+
+SRC :=  r3init.180 ddtz.180
+SRC += fifoio.180 msgbuf.180 ser1-i.180 console.180
+SRC += romend.180
+
+INC := config.inc z180reg.inc z180.lib
+
+OBJ := $(SRC:.180=.rel)
+
+#CP/M emulator
+CPMEMU = zxcc
+
+#Location of CP/M binaries 
+CPMBIN = /usr/local/lib/cpm/bin80
+
+#AS = $(CPMEMU) $(CPMBIN)/m80.com
+AS = $(CPMEMU) slr180.com
+LN = $(CPMEMU) slrnk+.com
+#LN = $(CPMEMU) ccpline.com
+
+AS_OPT := MFS
+
+AS_QUIET = 1
+LN_QUIET = 1
+
+#LNKCMD = 
+LN_VERB = /V
+LN_PROG = 0
+LN_DATA = C000
+
+
+.suffixes:
+#.suffixes: .180 .rel
+
+.phony: all
+all: hdrom.c hdrom.h
+
+$(OBJ):  $(INC)
+
+hdrom.h: hdrom.c
+
+comma:= ,
+empty:=
+space:= $(empty) $(empty)
+
+ccpline = $(CPMEMU) $(1) -$(subst $(space),$(comma),$(strip $(2)))
+
+define cpm-asm =
+COMMAND="$(AS) -$(basename $<)/$(AS_OPT)"; \
+OUTPUT=$$(mktemp); echo $${COMMAND}; \
+$${COMMAND} > $${OUTPUT}; \
+grep -q '^ 0 Error(s) Detected' $${OUTPUT}; ERROR=$$? ; \
+if [ "$${ERROR}" != "0" ]; then cat $${OUTPUT}; rm -f $@; fi ; \
+exit $${ERROR}
+endef
+
+define cpm-link =
+  COMMAND="$(call ccpline, slrnk+, $(basename $@)/H/M /V \
+           /P:$(LN_PROG) /D:$(LN_DATA) $(basename $^) /E /Q)";\
+  OUTPUT=$$(mktemp); echo $${COMMAND};\
+  $${COMMAND} > $${OUTPUT};\
+  ERROR=0;\
+  cat $${OUTPUT};\
+  grep -q ' Duplicate Symbol ' $${OUTPUT} && ERROR=2; \
+  grep -q '\- Previously Defined' $${OUTPUT} && ERROR=2; \
+  [ "$${ERROR}" = "0" ] && grep -q '^ ** ' $${OUTPUT} && ERROR=1 ; \
+  [ "$${ERROR}" != "0" ] && rm -f $@; \
+  exit $${ERROR}
+endef
+
+#Use:   MAKESYM Filename[.ext][/PXXXX][/DXXXX][/CXXXX]
+#egrep '^[[:xdigit:]]{4}[[:space:]]+[[:xdigit:]]{4}[[:space:]]+D.*r3init\.rel' hdrom.map
+define cpm-mksym =
+COMMAND="$(CPMEMU) makesym -$^ -/P -D"; \
+OUTPUT=$$(mktemp); echo $${COMMAND}; \
+$${COMMAND} > $${OUTPUT}; \
+grep -q '^ 0 Error(s) Detected' $${OUTPUT}; ERROR=$$? ; \
+if [ "$${ERROR}" != "0" ]; then cat $${OUTPUT}; rm -f $@; fi ; \
+exit $${ERROR}
+endef
+
+hdrom.c: hdrom.hex     
+       srec_cat -o $@ -c_array $(basename $<) -C_COMpressed -include $< -Intel
+
+hdrom.hex : $(OBJ)
+       @#$(cpm-link)
+       ld80 -o $@ -ms $(@:.hex=.map) -P $(LN_PROG) -D $(LN_DATA) $^
+
+%.rel %lst: %.180
+       @$(cpm-asm)
+
+hdrom.map: hdrom.hex
+
+%.sym: hdrom.map %.lst 
+       @$(cpm-mksym)
+
+.phony: clean realclean
+clean:
+       rm -f $(OBJ) $(OBJ:.rel=.lst) $(OBJ:.rel=.sym) hdrom.hex
+
+realclean: clean
+       rm -f *.prn *~ hdrom.map
+
+
+#==================================================================
+
+%.REL: %.MAC
+       @COMMAND="$(AS) =$<"; \
+       OUTPUT=$$(mktemp); echo $${COMMAND}; \
+       $${COMMAND} > $${OUTPUT}; \
+       grep -q 'No Fatal error(s).$$' $${OUTPUT}; ERROR=$$? ; \
+       if [ "$${ERROR}" != "0" ]; then cat $${OUTPUT}; rm $@; fi ; \
+       rm $${OUTPUT}; \
+       exit $${ERROR}
+
+
+%.PRN: %.MAC
+       @COMMAND="$(AS) ,$@=$<"; \
+       OUTPUT=$$(mktemp); echo $${COMMAND}; \
+       $${COMMAND} > $${OUTPUT}; \
+       grep -q 'No Fatal error(s).$$' $${OUTPUT}; ERROR=$$? ; \
+       if [ "$${ERROR}" != "0" ]; then cat $${OUTPUT}; fi ; \
+       rm $${OUTPUT}; \
+       exit $${ERROR}
+
diff --git a/z180/Tupfile b/z180/Tupfile
new file mode 100644 (file)
index 0000000..ebdb1d1
--- /dev/null
@@ -0,0 +1,52 @@
+include_rules
+
+PROG   = hdrom
+
+SRC    = r3init.180 
+SRC    += ddtz.180
+#SRC   += fifoio.180 msgbuf.180 ser1-i.180 console.180
+SRC    += ser1-i.180 console.180
+SRC    += romend.180
+
+
+AS_OPT = MFS
+
+LN_PROG = 0
+LN_DATA = C000
+
+
+###############################################################################
+# Executables
+
+CPMEMU = zxcc
+
+#AS = $(CPMEMU) ccpline.com
+AS = $(CPMEMU) slr180.com
+
+
+###############################################################################
+
+!AS-plain = |> $(AS) -%B/$(AS_OPT) |> %B.rel | %B.lst 
+
+!AS = |> ^ $(AS) -%B/$(AS_OPT)^ set +e; OUTPUT=\$(mktemp);\
+$(AS) -%B/$(AS_OPT) > ${OUTPUT};\
+grep -q '^ 0 Error(s) Detected' ${OUTPUT}; ERROR=$?;\
+[ "${ERROR}" != "0" ] && cat ${OUTPUT};\
+[ "${ERROR}" != "0" ] && rm -f %B.rel;\
+rm -f ${OUTPUT}; exit ${ERROR} \
+|> %B.rel | %B.lst 
+
+!LINK = |> ld80 -o %o -ms %O.map -P $(LN_PROG) -D $(LN_DATA) %f |> | %O.map
+
+#ifndef DEBUG
+
+: foreach $(SRC) |> !AS |> {objs}
+: {objs} |> !LINK |> $(PROG).hex
+: $(PROG).hex |> srec_cat -o %o -c_array %B -C_COMpressed -include %f -Intel |> $(PROG).c | $(PROG).h
+
+
+#COMMAND="$(AS) -%B/$(AS_OPT)"; \
+
+
+#endif
+
diff --git a/z180/config.inc b/z180/config.inc
new file mode 100644 (file)
index 0000000..b03761c
--- /dev/null
@@ -0,0 +1,105 @@
+\r
+\r
+FOSC           equ     18432           ;Oscillator frequency [KHz]\r
+PHI            equ     FOSC/2          ;CPU frequency \r
+\r
+;-----------------------------------------------------\r
+; Programmable Reload Timer (PRT)\r
+\r
+PRT_PRE                equ     20              ;PRT prescaler\r
+\r
+; Reload value for 10 ms Int. (0.1KHz):\r
+; tc10ms = phi/prescale/0.1KHz  = phi / (prescale/10)\r
+\r
+PRT_TC10MS     equ     PHI / (PRT_PRE/10)\r
+\r
+;-----------------------------------------------------\r
+; MMU\r
+\r
+SYS$CBAR       equ     0C8h\r
+USR$CBAR       equ     0F0h\r
+\r
+\r
+BANKS          equ     18              ;max nr. of banks\r
+\r
+;-----------------------------------------------------\r
+\r
+CREFSH         equ     0               ;Refresh rate register (disable refresh)\r
+CWAITIO                equ     3 shl IWI0      ;Max I/O Wait States, 0 Memory Wait States\r
+\r
+\r
+ROMSYS         equ     0\r
+\r
+       if      ROMSYS\r
+c$rom          equ     0a5h\r
+ROM_EN         equ     0C0h\r
+ROM_DIS                equ     ROMEN+1\r
+CWAITROM       equ     2 shl MWI0\r
+       endif\r
+\r
+\r
+DRSTNUM        equ     30h             ;DDTZ Restart vector (breakpoints)\r
+\r
+\r
+msg_fb_len     equ     256\r
+rx.buf_len     equ     20h\r
+tx.buf_len     equ     80h\r
+rx.buf_len     equ     20h\r
+tx.buf_len     equ     80h\r
+\r
+\r
+s1.rx_len      equ     256             ;Serial 1 (ASCI1) buffers\r
+s1.tx_len      equ     256             ;\r
+\r
+PMSG           equ     80h\r
+\r
+;-----------------------------------------------------\r
+; Definition of (locical) top 2 memory pages \r
+\r
+sysram_start   equ     0FE00h\r
+stacksize      equ     80\r
+\r
+isvsw_loc      equ     0FEE0h\r
+\r
+ivtab          equ     0ffc0h          ;int vector table\r
+iv2tab         equ     ivtab + 2*9\r
+\r
+\r
+\r
+;-----------------------------------------------------\r
+\r
+\r
+o.mask         equ     -3\r
+o.in_idx       equ     -2\r
+o.out_idx      equ     -1\r
+       \r
+       .lall\r
+\r
+mkbuf  macro   name,size\r
+  if ((size & (size-1)) ne 0) or (size gt 256)\r
+    .printx Error: buffer ^size must be power of 2 and in range 0..256!\r
+    name&.mask equ ;wrong size error\r
+  else\r
+    ds 3       \r
+    name:: ds size\r
+    name&.mask equ low (size-1)\r
+    if size ne 0\r
+      name&.end equ $-1\r
+      name&.len equ size\r
+    endif\r
+  endif\r
+endm\r
+\r
+;-----------------------------------------------------\r
+\r
+inidat macro   \r
+       cseg\r
+??ps.a defl    $       \r
+       endm\r
+\r
+inidate        macro\r
+??ps.len defl  $ - ??ps.a\r
+       dseg\r
+       ds      ??ps.len\r
+       endm\r
+\r
diff --git a/z180/console.180 b/z180/console.180
new file mode 100644 (file)
index 0000000..d7b5ef6
--- /dev/null
@@ -0,0 +1,48 @@
+       ;page   255\r
+       .z80\r
+       \r
+\r
+       global  $coninit\r
+       global  $cists,$ci\r
+       global  $co\r
+\r
+\r
+       extrn   ser.init,ser.instat,ser.in,ser.out\r
+;      extrn   f.init,f.in,f.out,f.i.st\r
+;      extrn   msg.co\r
+       \r
+\r
+       include config.inc\r
+       include z180reg.inc\r
+\r
+       cseg\r
+;\r
+;\r
+\r
+$coninit:\r
+;      call    f.init\r
+       call    ser.init\r
+       ret\r
+       \r
+$cists:\r
+;      call    f.i.st\r
+;      ret     nz\r
+       call    ser.instat\r
+       ret\r
+       \r
+$ci:\r
+;      call    f.i.st\r
+;      jp      nz,f.in\r
+       call    ser.instat\r
+       jp      nz,ser.in\r
+       jr      $ci\r
+       \r
+;$costs:\r
+;      jp      f.o.st\r
+       \r
+$co:\r
+;      call    msg.co\r
+       jp      ser.out\r
+       \r
+       end\r
+\r
diff --git a/z180/ddtz.180 b/z180/ddtz.180
new file mode 100644 (file)
index 0000000..77da910
--- /dev/null
@@ -0,0 +1,6370 @@
+       page    255\r
+       .z80\r
+\r
+       external $ci, $co, $cists\r
+\r
+       global  ddtz,bpent\r
+       global  $stack\r
+\r
+\r
+       include config.inc\r
+       include z180reg.inc\r
+       include z180.lib\r
+\r
+BS     equ     08h\r
+TAB    equ     09h\r
+CR     equ     0dh\r
+LF     equ     0ah\r
+DEL    equ     7fh\r
+CNTRX  equ     'X'-'@'\r
+\r
+TPA    equ     100h\r
+TOPRAM equ     0f000h\r
+\r
+\r
+MEMDUMP_CNT    equ     16              ;mem dump bytes per line\r
+BP_CNT                 equ     12              ;number of breakbpoints\r
+\r
+\r
+;--------------------------------------------------\r
+; \r
+\r
+; copy code to common memory and execute it there\r
+comst  macro\r
+       call    ?excom\r
+       ds      1\r
+?lcs   defl    $\r
+       endm\r
+\r
+; mark end of common code snippet\r
+comend macro\r
+?lce   defl    $\r
+?lclen defl    ?lce-?lcs\r
+       org     ?lcs-1\r
+       db      ?lclen\r
+       org     ?lce\r
+       ifndef  ?lcmax\r
+?lcmax defl    0\r
+       endif\r
+       if      ?lclen gt ?lcmax\r
+?lcmax defl    ?lclen\r
+       endif\r
+       endm\r
+\r
+; repeat execution of last common code snippet\r
+comrep macro\r
+       call    ?exclst\r
+       endm\r
+\r
+\r
+\r
+       cseg\r
+\r
+;----------------------------------------------------------\r
+\r
+MSG:\r
+       DB      'DDT/Z - HD64180  (ROM)'\r
+       DB      CR,LF,0\r
+\r
+HLPMSG:\r
+       DB 'DDT/Z180 (ROM) Commands:',CR,LF\r
+       DB '> @                             examine/substitute the displacement register @',CR,LF\r
+       DB '> A [address]                   Assemble',CR,LF\r
+       DB '> B[X]                          display [or clear] all Breakpoints',CR,LF\r
+       DB '  B breakp [:count] [breakp..]  set Breakpoints',CR,LF\r
+       DB '  BX address [address..]        clear Breakpoints',CR,LF\r
+       DB '>>C[N][J] [count]               trace over Calls [No list] [Jumps only]',CR,LF\r
+       DB '  C[N][J] W|U expression        trace over Calls While|Until ...',CR,LF\r
+       DB '>>D [startadr] [endadr]         Display memory in hex and ascii',CR,LF\r
+       DB '> G [startadr] [;breakp..]      Go [to start] [temporary breakpoints]',CR,LF\r
+       DB '> H [expression [expression]]   compute expressions / show High/max load adr.',CR,LF\r
+       DB '>>I [port]                      Input a byte from port',CR,LF\r
+       DB '>>L [startadr] [endadr]         List disassembled code',CR,LF\r
+       DB '> M[V] startadr endadr destadr  Move memory [and verify]',CR,LF\r
+       DB '>>O [byte] [port]               Output a byte to port',CR,LF\r
+       DB '> Q[J] startadr endadr bytes    Qery memory for byte string [Justified]',CR,LF\r
+       DB '> R [displacement]              Read intel hex from console [add displacemt]',CR,LF\r
+       DB '> S address                     Substitute memory',CR,LF\r
+       DB '>>T[N][J] [count]               Trace [No list] [Jumps only] [count steps]',CR,LF\r
+       DB '  T[N][J] W|U expression        Trace While|Until expression',CR,LF\r
+       DB '> V startadr endadr destadr     Verify (compare) two memory areas',CR,LF\r
+       DB '> X[register]                   eXamine [and substitute] registers',CR,LF\r
+       DB '> Y[0..9]                       eXamine [and substitute] Y variables',CR,LF\r
+       DB '> Z startadr endadr bytes       Zap (fill) memory with a byte string',CR,LF\r
+       DB 0\r
+\r
+ddtz:\r
+       ld      sp,$stack\r
+       ld      a,(wstrtflg)            ;check warm start flag\r
+       or      a\r
+       jr      nz,ddtz_w\r
+\r
+       exx\r
+       ld      hl,sysramc\r
+       ld      de,topcodbeg\r
+       ld      bc,topcodend-topcodbeg\r
+       ldir                    \r
+       \r
+       ld      hl,vartab\r
+       ld      de,ddtram\r
+       ld      bc,vartabe-vartab\r
+       ldir            \r
+       exx\r
+\r
+       ld      a,e\r
+       ld      (ubbr),a\r
+       \r
+ddtz_w:\r
+       ld hl,MSG               ;073c\r
+       call PSTR               ;073f\r
+       call ddtei              ;0742\r
+\r
+; DDTZ main loop\r
+\r
+DDTZML:\r
+       ld sp,$stack            ;0761\r
+       ld hl,l07eah            ;0764\r
+       ld (CMD_ERR),hl         ;0767\r
+       ld hl,(REG.PC)          ;076a\r
+       ld (OFFS.pc),hl         ;076d\r
+       call sub_0e68h          ;0770\r
+       ld hl,(CMD_RPT)         ;0773\r
+       ld de,DDTZML            ;0776\r
+       call CP.HL.DE           ;0779\r
+       ld a,'>'                ;077c\r
+       call OUTCHAR            ;077e\r
+       call nz,OUTCHAR         ;0781\r
+       call z,OUTBL            ;0784\r
+       call INLINE             ;0787\r
+       call SKIPBL             ;078a\r
+       jr z,exe_hl             ;078d\r
+       ld hl,DDTZML            ;078f\r
+       ld (CMD_RPT),hl         ;0792\r
+       inc de                  ;0795\r
+       sub '?'                 ;0796\r
+       jr c,ERROR              ;0798\r
+       cp 'Z'+1-'?'            ;079a\r
+       jr nc,ERROR             ;079c\r
+       add a,a                 ;079e\r
+       ld hl,CMDTAB            ;079f\r
+       call ADD_HL_A           ;07a2\r
+       ld a,(hl)               ;07a5\r
+       inc hl                  ;07a6\r
+       ld h,(hl)               ;07a7\r
+       ld l,a                  ;07a8\r
+       jr exe_hl               ;07a9\r
+ERROR:\r
+       ld hl,(CMD_ERR)         ;07ab\r
+exe_hl:\r
+       call CALL.HL            ;07ae\r
+       jr DDTZML               ;07b1\r
+\r
+CALL.HL:\r
+       jp (hl)                 ;07b3\r
+\r
+\r
+CMDTAB:\r
+       defw CMD.?\r
+       defw CMD.@              ;07b4\r
+       defw CMD.A              ;07b6\r
+       defw CMD.B              ;07b8\r
+       defw CMD.C              ;07ba\r
+       defw CMD.D              ;07bc\r
+       defw ERROR              ;07be\r
+       defw ERROR              ;07c0\r
+       defw CMD.G              ;07c2\r
+       defw CMD.H              ;07c4\r
+       defw CMD.I              ;07c6\r
+       defw ERROR              ;07c8\r
+       defw ERROR              ;07ca\r
+       defw CMD.L              ;07cc\r
+       defw CMD.M              ;07ce\r
+       defw ERROR              ;07d0\r
+       defw CMD.O              ;07d2\r
+       defw ERROR              ;07d4\r
+       defw CMD.Q              ;07d6\r
+       defw CMD.R              ;07d8\r
+       defw CMD.S              ;07da\r
+       defw CMD.T              ;07dc\r
+       defw ERROR              ;07de\r
+       defw CMD.V              ;07e0\r
+       defw ERROR              ;07e2\r
+       defw CMD.X              ;07e4\r
+       defw CMD.Y              ;07e6\r
+       defw CMD.Z              ;07e8\r
+l07eah:\r
+       ld a,'?'                ;07ea\r
+       call OUTCHAR            ;07ec\r
+       jp CRLF                 ;07ef\r
+\r
+CMD.?:\r
+       call    assert_eol\r
+       ld      hl,HLPMSG\r
+       call    PSTR\r
+       ret\r
+\r
+DELC:\r
+       ld a,b                  ;07f2\r
+       or a                    ;07f3\r
+       ret z                   ;07f4\r
+       ld a,BS                 ;07f5\r
+       call $co                ;07f7\r
+       ld a,' '                ;07fa\r
+       call $co                ;07fc\r
+       ld a,BS                 ;07ff\r
+       call $co                ;0801\r
+       dec hl                  ;0804\r
+       dec b                   ;0805\r
+       inc c                   ;0806\r
+       ld a,(hl)               ;0807\r
+       cp ' '                  ;0808\r
+       ret nc                  ;080a\r
+       ld a,BS                 ;080b\r
+       call $co                ;080d\r
+       ld a,' '                ;0810\r
+       call $co                ;0812\r
+       ld a,BS                 ;0815\r
+       call $co                ;0817\r
+       ret                     ;081a\r
+DELL:\r
+       ld a,b                  ;081b\r
+       or a                    ;081c\r
+       ret z                   ;081d\r
+       call DELC               ;081e\r
+       jr DELL                 ;0821\r
+\r
+INLINE:\r
+       push hl                 ;0823\r
+       ld hl,CI.BUF            ;0824\r
+       ld c,(hl)               ;0827\r
+       inc hl                  ;0828\r
+       ld b,000h               ;0829\r
+       inc hl                  ;082b\r
+inlnxtch:\r
+       ld a,c                  ;082c\r
+       or a                    ;082d\r
+       jr z,inl_e              ;082e\r
+       call $ci                ;0830\r
+       cp CR                   ;0833\r
+       jr z,inl_e              ;0835\r
+       cp LF                   ;0837\r
+       jr z,inl_e              ;0839\r
+       cp BS                   ;083b\r
+       jr nz,l0844h            ;083d\r
+       call DELC               ;083f\r
+       jr inlnxtch             ;0842\r
+l0844h:\r
+       cp DEL                  ;0844\r
+       jr nz,l084dh            ;0846\r
+       call DELC               ;0848\r
+       jr inlnxtch             ;084b\r
+l084dh:\r
+       cp CNTRX                ;084d\r
+       jr nz,l0856h            ;084f\r
+       call DELL               ;0851\r
+       jr inlnxtch             ;0854\r
+l0856h:\r
+       cp TAB                  ;0856\r
+       jr nz,l085ch            ;0858\r
+       ld a,' '                ;085a\r
+l085ch:\r
+       ld (hl),a               ;085c\r
+       cp ' '                  ;085d\r
+       jr nc,l0869h            ;085f\r
+       ld a,'^'                ;0861\r
+       call $co                ;0863\r
+       ld a,(hl)               ;0866\r
+       add a,'@'               ;0867\r
+l0869h:\r
+       call $co                ;0869\r
+       inc hl                  ;086c\r
+       inc b                   ;086d\r
+       dec c                   ;086e\r
+       jr inlnxtch             ;086f\r
+\r
+inl_e:\r
+       ld hl,ci.buf+1          ;0871\r
+       ld (hl),b               ;0874\r
+       call CRLF               ;0875\r
+       ld de,ci.buf+1          ;0878\r
+       ld a,(de)               ;087b\r
+       ld b,a                  ;087c\r
+       ld c,000h               ;087d\r
+       inc b                   ;087f\r
+l0880h:\r
+       inc de                  ;0880\r
+       dec b                   ;0881\r
+       jr z,l08b2h             ;0882\r
+       ld a,(de)               ;0884\r
+       bit 0,c                 ;0885\r
+       call z,UPCASE           ;0887\r
+       ld (de),a               ;088a\r
+       cp ''''                 ;088b\r
+       jr nz,l0880h            ;088d\r
+       push de                 ;088f\r
+       dec de                  ;0890\r
+       ld a,(de)               ;0891\r
+       cp ''''                 ;0892\r
+       jr z,l08aeh             ;0894\r
+       dec de                  ;0896\r
+       ld a,(de)               ;0897\r
+       cp '^'                  ;0898\r
+       jr z,l08a2h             ;089a\r
+       dec de                  ;089c\r
+       ld a,(de)               ;089d\r
+       cp '^'                  ;089e\r
+       jr nz,l08aeh            ;08a0\r
+l08a2h:\r
+       inc de                  ;08a2\r
+       push bc                 ;08a3\r
+       call sub_0a0eh          ;08a4\r
+       pop bc                  ;08a7\r
+       dec de                  ;08a8\r
+       ld a,(de)               ;08a9\r
+       cp ''''                 ;08aa\r
+       jr z,l08afh             ;08ac\r
+l08aeh:\r
+       inc c                   ;08ae\r
+l08afh:\r
+       pop de                  ;08af\r
+       jr l0880h               ;08b0\r
+l08b2h:\r
+       xor a                   ;08b2\r
+       ld (de),a               ;08b3\r
+       ld de,ci.buf+2          ;08b4\r
+       pop hl                  ;08b7\r
+       ret                     ;08b8\r
+\r
+UPCASE:\r
+       cp 'a'                  ;08b9\r
+       ret c                   ;08bb\r
+       cp 'z'+1                ;08bc\r
+       ret nc                  ;08be\r
+       and 05fh                ;08bf\r
+       ret                     ;08c1\r
+\r
+out.hl.@:\r
+       call out.hl             ;08c2\r
+       push de                 ;08c5\r
+       push hl                 ;08c6\r
+       ld de,(offs.@)          ;08c7\r
+       ld a,d                  ;08cb\r
+       or e                    ;08cc\r
+       jr z,l08ddh             ;08cd\r
+       call OUTBL              ;08cf\r
+       ld a,'@'                ;08d2\r
+       call OUTCHAR            ;08d4\r
+       and a                   ;08d7\r
+       sbc hl,de               ;08d8\r
+       call out.hl             ;08da\r
+l08ddh:\r
+       pop hl                  ;08dd\r
+       pop de                  ;08de\r
+       ret                     ;08df\r
+\r
+out.bin.w:\r
+       ld a,h                  ;08e0\r
+       call out.bin.b          ;08e1\r
+       ld a,l                  ;08e4\r
+out.bin.b:\r
+       ld b,008h               ;08e5\r
+l08e7h:\r
+       add a,a                 ;08e7\r
+       push af                 ;08e8\r
+       ld a,0                  ;08e9\r
+       adc a,a                 ;08eb\r
+       call out.digit          ;08ec\r
+       pop af                  ;08ef\r
+       djnz l08e7h             ;08f0\r
+       ld a,'"'                ;08f2\r
+       jp OUTCHAR              ;08f4\r
+\r
+sub_08f7h:\r
+       ld a,'-'                ;08f7\r
+       call OUTCHAR            ;08f9\r
+       dec hl                  ;08fc\r
+       jp cpl.hl               ;08fd\r
+\r
+out.hl.decm:\r
+       push hl                 ;0900\r
+       call sub_08f7h          ;0901\r
+       db      3eh             ;0904  ld a,0E5h\r
+out.hl.dec:\r
+       push    hl\r
+       ld b,6                  ;0906\r
+       call sub_0917h          ;0908\r
+       pop hl                  ;090b\r
+       ld a,'.'                ;090c\r
+       call OUTCHAR            ;090e\r
+l0911h:\r
+       call OUTBL              ;0911\r
+       djnz l0911h             ;0914\r
+       ret                     ;0916\r
+\r
+\r
+sub_0917h:\r
+       dec b                   ;0917\r
+       push de                 ;0918\r
+       ld de,10                ;0919\r
+       call DIV_HL_DE          ;091c\r
+       ld a,h                  ;091f\r
+       or l                    ;0920\r
+       call nz,sub_0917h       ;0921\r
+       ld a,e                  ;0924\r
+       pop de                  ;0925\r
+       jr out.digit            ;0926\r
+\r
+sub_0928h:\r
+       push hl                 ;0928\r
+       call sub_08f7h          ;0929\r
+       call out.hl             ;092c\r
+       pop hl                  ;092f\r
+       ret                     ;0930\r
+out.hl:\r
+       ld a,h                  ;0931\r
+       call out.hex            ;0932\r
+       ld a,l                  ;0935\r
+out.hex:\r
+       push af                 ;0936\r
+       rra                     ;0937\r
+       rra                     ;0938\r
+       rra                     ;0939\r
+       rra                     ;093a\r
+       call out.digit          ;093b\r
+       pop af                  ;093e\r
+out.digit:\r
+       and 00fh                ;093f\r
+       cp 10                   ;0941\r
+       jr c,l0947h             ;0943\r
+       add a,007h              ;0945\r
+l0947h:\r
+       add a,'0'               ;0947\r
+       jr OUTCHAR              ;0949\r
+l094bh:\r
+       ld a,'-'                ;094b\r
+       call OUTCHAR            ;094d\r
+       ld a,040h               ;0950\r
+out.ascii:\r
+       ex af,af'               ;0952\r
+       call outquote           ;0953\r
+       ex af,af'               ;0956\r
+       push af                 ;0957\r
+       res 7,a                 ;0958\r
+       cp ' '                  ;095a\r
+       jr nc,l0960h            ;095c\r
+       sub 0c0h                ;095e\r
+l0960h:\r
+       call OUTCHAR            ;0960\r
+       push af                 ;0963\r
+       cp ''''                 ;0964\r
+       call z,OUTCHAR          ;0966\r
+       pop af                  ;0969\r
+       ex af,af'               ;096a\r
+       call outquote           ;096b\r
+       pop af                  ;096e\r
+       or a                    ;096f\r
+       ld a,'.'                ;0970\r
+       call m,OUTCHAR          ;0972\r
+       ex af,af'               ;0975\r
+       jr c,l094bh             ;0976\r
+       ret                     ;0978\r
+\r
+outquote:\r
+       ld a,''''               ;0979\r
+OUTCHAR:\r
+       push hl                 ;097b\r
+       push af                 ;097c\r
+       and 07fh                ;097d\r
+       call $co                ;097f\r
+       ld hl,CON.COL           ;0982\r
+       inc (hl)                ;0985\r
+       pop af                  ;0986\r
+       pop hl                  ;0987\r
+       ret                     ;0988\r
+\r
+inchar:\r
+       call $cists             ;0989\r
+       and a                   ;098c\r
+       ret z                   ;098d\r
+       call $ci                ;098e\r
+       scf                     ;0991\r
+       ret                     ;0992\r
+\r
+PSTR:\r
+       ld c,000h               ;0993\r
+l0995h:\r
+       ld a,(hl)               ;0995\r
+       and a                   ;0996\r
+       ret z                   ;0997\r
+       call OUTCHAR            ;0998\r
+       inc c                   ;099b\r
+       inc hl                  ;099c\r
+       and a                   ;099d\r
+       ret m                   ;099e\r
+       jr l0995h               ;099f\r
+\r
+outbl6:\r
+       call outbl2             ;09a1\r
+outbl4:\r
+       call outbl2             ;09a4\r
+outbl2:\r
+       call OUTBL              ;09a7\r
+OUTBL:\r
+       ld a,' '                ;09aa\r
+       jr OUTCHAR              ;09ac\r
+CRLF:\r
+       call inchar             ;09ae\r
+       ld a,CR                 ;09b1\r
+       call OUTCHAR            ;09b3\r
+       ld a,LF                 ;09b6\r
+       call OUTCHAR            ;09b8\r
+       ld a,000h               ;09bb\r
+       ld (CON.COL),a          ;09bd\r
+       jp c,DDTZML             ;09c0\r
+       ret                     ;09c3\r
+\r
+ADD_HL_A:\r
+       add a,l                 ;09c4\r
+       ld l,a                  ;09c5\r
+       ret nc                  ;09c6\r
+       inc h                   ;09c7\r
+       ret                     ;09c8\r
+\r
+SKIPBL0:\r
+       inc de                  ;09c9\r
+SKIPBL:\r
+       ld a,(de)               ;09ca\r
+       cp ' '                  ;09cb\r
+       jr z,SKIPBL0            ;09cd\r
+       cp 009h                 ;09cf\r
+       jr z,SKIPBL0            ;09d1\r
+       or a                    ;09d3\r
+       ret                     ;09d4\r
+\r
+skip_to_nextarg:\r
+       call SKIPBL             ;09d5\r
+       cp ','                  ;09d8\r
+       ret nz                  ;09da\r
+       inc de                  ;09db\r
+       call SKIPBL             ;09dc\r
+       cp a                    ;09df\r
+       ret                     ;09e0\r
+\r
+assert_eol:\r
+       call SKIPBL             ;09e1\r
+       ret z                   ;09e4\r
+l09e5h:\r
+       jp ERROR                ;09e5\r
+\r
+chk.sp:\r
+       push hl                 ;09e8\r
+       push de                 ;09e9\r
+       ld hl,0                 ;09ea\r
+       add hl,sp               ;09ed\r
+       ld de,$stack-50         ;09ee\r
+       call CP.HL.DE           ;09f1\r
+       pop de                  ;09f4\r
+       pop hl                  ;09f5\r
+       jr c,l09e5h             ;09f6\r
+       ret                     ;09f8\r
+\r
+CP.HL.DE:\r
+       and a                   ;09f9\r
+       sbc hl,de               ;09fa\r
+       add hl,de               ;09fc\r
+       ret                     ;09fd\r
+\r
+lookupch:\r
+       ld b,000h               ;09fe\r
+l0a00h:\r
+       ld a,(hl)               ;0a00\r
+       and a                   ;0a01\r
+       ret z                   ;0a02\r
+       ld a,(de)               ;0a03\r
+       cp (hl)                 ;0a04\r
+       jr z,l0a0bh             ;0a05\r
+       inc hl                  ;0a07\r
+       inc b                   ;0a08\r
+       jr l0a00h               ;0a09\r
+l0a0bh:\r
+       scf                     ;0a0b\r
+       inc de                  ;0a0c\r
+       ret                     ;0a0d\r
+\r
+sub_0a0eh:\r
+       ld hl,b_0x132A_start    ;0a0e\r
+       ld b,07fh               ;0a11\r
+       jr l0a17h               ;0a13\r
+\r
+sub_0a15h:\r
+       ld b,0ffh               ;0a15\r
+l0a17h:\r
+       inc b                   ;0a17\r
+       ld a,(hl)               ;0a18\r
+       and a                   ;0a19\r
+       ret z                   ;0a1a\r
+       call l0a27              ;0a1b\r
+       jr nc,l0a17h            ;0a1e\r
+       res 7,b                 ;0a20\r
+       ret                     ;0a22\r
+\r
+sub_0a23h:\r
+       push bc                 ;0a23\r
+       res 7,b                 ;0a24\r
+       db      3eh             ;0a26  ld a,0c5h\r
+l0a27:\r
+       push bc                 ;0a27\r
+       push de                 ;0a28\r
+l0a29h:\r
+       ld a,(de)               ;0a29\r
+       xor (hl)                ;0a2a\r
+       and 07fh                ;0a2b\r
+       jr nz,l0a41h            ;0a2d\r
+       bit 7,(hl)              ;0a2f\r
+       inc hl                  ;0a31\r
+       inc de                  ;0a32\r
+       jr z,l0a29h             ;0a33\r
+       scf                     ;0a35\r
+       bit 7,b                 ;0a36\r
+       call z,sub_0d20h        ;0a38\r
+       jr nc,l0a44h            ;0a3b\r
+       pop af                  ;0a3d\r
+       scf                     ;0a3e\r
+       pop bc                  ;0a3f\r
+       ret                     ;0a40\r
+\r
+l0a41h:\r
+       call sub_0a50h          ;0a41\r
+l0a44h:\r
+       pop de                  ;0a44\r
+       and a                   ;0a45\r
+       pop bc                  ;0a46\r
+       ret                     ;0a47\r
+\r
+sub_0a48h:\r
+       inc b                   ;0a48\r
+l0a49h:\r
+       dec b                   ;0a49\r
+       ret z                   ;0a4a\r
+       call sub_0a50h          ;0a4b\r
+       jr l0a49h               ;0a4e\r
+sub_0a50h:\r
+       ld a,(hl)               ;0a50\r
+       and a                   ;0a51\r
+       ret z                   ;0a52\r
+l0a53h:\r
+       ld a,(hl)               ;0a53\r
+       inc hl                  ;0a54\r
+       and a                   ;0a55\r
+       ret m                   ;0a56\r
+       jr l0a53h               ;0a57\r
+\r
+get_arg3:\r
+       call get_arg_range      ;0a59\r
+       push hl                 ;0a5c\r
+       push bc                 ;0a5d\r
+       call skip_to_nextarg    ;0a5e\r
+       call get_arg            ;0a61\r
+       ex de,hl                ;0a64\r
+       pop bc                  ;0a65\r
+       pop hl                  ;0a66\r
+       ret                     ;0a67\r
+\r
+sub_0a68h:\r
+       call EXPR               ;0a68\r
+       jr c,error0             ;0a6b\r
+       ret                     ;0a6d\r
+\r
+get_arg:\r
+       call sub_0a68h          ;0a6e\r
+l0a71h:\r
+       jp assert_eol           ;0a71\r
+\r
+get_lastarg_def:\r
+       call get_arg_def        ;0a74\r
+       jr l0a71h               ;0a77\r
+\r
+get_arg_def:\r
+       push hl                 ;0a79\r
+       call EXPR               ;0a7a\r
+       jr c,l0a80h             ;0a7d\r
+       ex (sp),hl              ;0a7f\r
+l0a80h:\r
+       pop hl                  ;0a80\r
+       ret                     ;0a81\r
+\r
+sub_0a82h:\r
+       call sub_0a87h          ;0a82\r
+       jr l0a71h               ;0a85\r
+\r
+sub_0a87h:\r
+       db      0e6h            ;0a87  and 037h (clear carry)\r
+get_arg_range:\r
+       scf\r
+       ex af,af'               ;0a89\r
+       push bc                 ;0a8a\r
+       push hl                 ;0a8b\r
+       call EXPR               ;0a8c\r
+       jr nc,l0a97h            ;0a8f\r
+       ex af,af'               ;0a91\r
+       jr c,error0             ;0a92\r
+       ex af,af'               ;0a94\r
+       pop hl                  ;0a95\r
+\r
+       defb 03eh               ;0a96\r
+l0a97h:\r
+       pop af                  ;0a97\r
+       call sub_0aa5h          ;0a98\r
+       jr nc,l0aa3h            ;0a9b\r
+       ex af,af'               ;0a9d\r
+       pop bc                  ;0a9e\r
+       ret nc                  ;0a9f\r
+error0:\r
+       jp ERROR                ;0aa0\r
+\r
+l0aa3h:\r
+       pop af                  ;0aa3\r
+       ret                     ;0aa4\r
+\r
+sub_0aa5h:\r
+       call skip_to_nextarg    ;0aa5\r
+       cp 'S'                  ;0aa8\r
+       jr nz,l0aadh            ;0aaa\r
+       inc de                  ;0aac\r
+l0aadh:\r
+       push hl                 ;0aad\r
+       push af                 ;0aae\r
+       call EXPR               ;0aaf\r
+       jr c,l0ac3h             ;0ab2\r
+       ld b,h                  ;0ab4\r
+       ld c,l                  ;0ab5\r
+       pop af                  ;0ab6\r
+       pop hl                  ;0ab7\r
+       jr z,l0ac1h             ;0ab8\r
+       ld a,c                  ;0aba\r
+       sub l                   ;0abb\r
+       ld c,a                  ;0abc\r
+       ld a,b                  ;0abd\r
+       sbc a,h                 ;0abe\r
+       ld b,a                  ;0abf\r
+       inc bc                  ;0ac0\r
+l0ac1h:\r
+       and a                   ;0ac1\r
+       ret                     ;0ac2\r
+\r
+l0ac3h:\r
+       pop af                  ;0ac3\r
+       pop hl                  ;0ac4\r
+       jr z,error0             ;0ac5\r
+       scf                     ;0ac7\r
+       ret                     ;0ac8\r
+\r
+EXPR:\r
+       call SKIPBL             ;0ac9\r
+EXPR1:\r
+       call do_subexpr         ;0acc\r
+       ret c                   ;0acf\r
+       call do_rel_op          ;0ad0\r
+       ret nc                  ;0ad3\r
+       push bc                 ;0ad4\r
+       push hl                 ;0ad5\r
+       call do_subexpr         ;0ad6\r
+       jr c,error0             ;0ad9\r
+       ex de,hl                ;0adb\r
+       ex (sp),hl              ;0adc\r
+       and a                   ;0add\r
+       sbc hl,de               ;0ade\r
+       ld hl,0ffffh            ;0ae0\r
+       pop de                  ;0ae3\r
+       ret                     ;0ae4\r
+\r
+do_op_eq:\r
+       jr z,l0af8h             ;0ae5\r
+       jr l0af7h               ;0ae7\r
+do_op_ne:\r
+       jr nz,l0af8h            ;0ae9\r
+       jr l0af7h               ;0aeb\r
+do_op_le:\r
+       jr z,l0af8h             ;0aed\r
+do_op_lt:\r
+       jr c,l0af8h             ;0aef\r
+       jr l0af7h               ;0af1\r
+do_op_gt:\r
+       jr z,l0af7h             ;0af3\r
+do_op_ge:\r
+       jr nc,l0af8h            ;0af5\r
+l0af7h:\r
+       inc hl                  ;0af7\r
+l0af8h:\r
+       and a                   ;0af8\r
+       ret                     ;0af9\r
+\r
+do_rel_op:\r
+       push hl                 ;0afa\r
+       ld hl,tab_eq_le_ge      ;0afb\r
+       call lookupch           ;0afe\r
+       jr nc,l0b28h            ;0b01\r
+       ld a,b                  ;0b03\r
+       or a                    ;0b04\r
+       jr z,l0b1ch             ;0b05\r
+       ld a,(de)               ;0b07\r
+       cp '='                  ;0b08\r
+       jr nz,l0b11h            ;0b0a\r
+       inc de                  ;0b0c\r
+       inc b                   ;0b0d\r
+       inc b                   ;0b0e\r
+       jr l0b1ch               ;0b0f\r
+\r
+l0b11h:\r
+       bit 0,b                 ;0b11\r
+       jr z,l0b1ch             ;0b13\r
+       cp '>'                  ;0b15\r
+       jr nz,l0b1ch            ;0b17\r
+       inc de                  ;0b19\r
+       ld b,005h               ;0b1a\r
+l0b1ch:\r
+       ld hl,tab_func_eqlege   ;0b1c\r
+       ld a,b                  ;0b1f\r
+       add a,a                 ;0b20\r
+       call ADD_HL_A           ;0b21\r
+       ld c,(hl)               ;0b24\r
+       inc hl                  ;0b25\r
+       ld b,(hl)               ;0b26\r
+       scf                     ;0b27\r
+l0b28h:\r
+       pop hl                  ;0b28\r
+       ret                     ;0b29\r
+\r
+tab_eq_le_ge:\r
+       db      '=<>',0\r
+\r
+tab_func_eqlege:\r
+       defw do_op_eq           ;0b2e\r
+       defw do_op_lt           ;0b30\r
+       defw do_op_gt           ;0b32\r
+       defw do_op_le           ;0b34\r
+       defw do_op_ge           ;0b36\r
+       defw do_op_ne           ;0b38\r
+\r
+do_subexpr:\r
+       call do_factor          ;0b3a\r
+       ret c                   ;0b3d\r
+l0b3eh:\r
+       call do_binary_op       ;0b3e\r
+       push hl                 ;0b41\r
+       push bc                 ;0b42\r
+       call do_factor          ;0b43\r
+       pop bc                  ;0b46\r
+       ex de,hl                ;0b47\r
+       ex (sp),hl              ;0b48\r
+       jr nc,l0b52h            ;0b49\r
+       pop de                  ;0b4b\r
+       ld a,b                  ;0b4c\r
+       or c                    ;0b4d\r
+       ret z                   ;0b4e\r
+       jp ERROR                ;0b4f\r
+\r
+l0b52h:\r
+       ld a,b                  ;0b52\r
+       or c                    ;0b53\r
+       push bc                 ;0b54\r
+       ret nz                  ;0b55\r
+       pop bc                  ;0b56\r
+do_op_add:\r
+       add hl,de               ;0b57\r
+l0b58h:\r
+       pop de                  ;0b58\r
+       jr l0b3eh               ;0b59\r
+\r
+do_op_sub:\r
+       and a                   ;0b5b\r
+       sbc hl,de               ;0b5c\r
+       jr l0b58h               ;0b5e\r
+\r
+do_op_mlt:\r
+       push bc                 ;0b60\r
+       ld      b,h\r
+       ld      c,e\r
+       ld      h,e\r
+       ld      e,l\r
+       mlt     bc\r
+       mlt     de\r
+       mlt     hl\r
+       ld      a,h\r
+       add     a,c\r
+       add     a,e\r
+       ld      h,a\r
+       pop bc                  ;0b72\r
+       jr l0b58h               ;0b73\r
+\r
+do_op_div:\r
+       call DIV_HL_DE          ;0b75\r
+       jr l0b58h               ;0b78\r
+\r
+do_op_mod:\r
+       call DIV_HL_DE          ;0b7a\r
+       ex de,hl                ;0b7d\r
+       jr l0b58h               ;0b7e\r
+\r
+DIV_HL_DE:\r
+       push bc                 ;0b80\r
+       ex de,hl                ;0b81\r
+       ld b,h                  ;0b82\r
+       ld c,l                  ;0b83\r
+       ld hl,0                 ;0b84\r
+       ld a,16                 ;0b87\r
+l0b89h:\r
+       push af                 ;0b89\r
+       add hl,hl               ;0b8a\r
+       ex de,hl                ;0b8b\r
+       xor a                   ;0b8c\r
+       add hl,hl               ;0b8d\r
+       ex de,hl                ;0b8e\r
+       adc a,l                 ;0b8f\r
+       sub c                   ;0b90\r
+       ld l,a                  ;0b91\r
+       ld a,h                  ;0b92\r
+       sbc a,b                 ;0b93\r
+       ld h,a                  ;0b94\r
+       inc de                  ;0b95\r
+       jr nc,l0b9ah            ;0b96\r
+       add hl,bc               ;0b98\r
+       dec de                  ;0b99\r
+l0b9ah:\r
+       pop af                  ;0b9a\r
+       dec a                   ;0b9b\r
+       jr nz,l0b89h            ;0b9c\r
+       ex de,hl                ;0b9e\r
+       pop bc                  ;0b9f\r
+       ret                     ;0ba0\r
+\r
+do_op_and:\r
+       ld a,h                  ;0ba1\r
+       and d                   ;0ba2\r
+       ld h,a                  ;0ba3\r
+       ld a,l                  ;0ba4\r
+       and e                   ;0ba5\r
+       ld l,a                  ;0ba6\r
+       jr l0b58h               ;0ba7\r
+\r
+do_op_or:\r
+       ld a,h                  ;0ba9\r
+       or d                    ;0baa\r
+       ld h,a                  ;0bab\r
+       ld a,l                  ;0bac\r
+       or e                    ;0bad\r
+       ld l,a                  ;0bae\r
+       jr l0b58h               ;0baf\r
+\r
+do_op_xor:\r
+       ld a,h                  ;0bb1\r
+       xor d                   ;0bb2\r
+       ld h,a                  ;0bb3\r
+       ld a,l                  ;0bb4\r
+       xor e                   ;0bb5\r
+       ld l,a                  ;0bb6\r
+       jr l0b58h               ;0bb7\r
+\r
+do_binary_op:\r
+       push hl                 ;0bb9\r
+       ld hl,tab_op_a          ;0bba\r
+       call lookupch           ;0bbd\r
+       ld a,b                  ;0bc0\r
+       ld hl,tab_func_opa      ;0bc1\r
+       add a,a                 ;0bc4\r
+       call ADD_HL_A           ;0bc5\r
+       ld c,(hl)               ;0bc8\r
+       inc hl                  ;0bc9\r
+       ld b,(hl)               ;0bca\r
+       pop hl                  ;0bcb\r
+       ret                     ;0bcc\r
+\r
+tab_op_a:\r
+       DB      '+-*/%&!#',0\r
+tab_func_opa:\r
+       defw do_op_add          ;0bd6\r
+       defw do_op_sub          ;0bd8\r
+       defw do_op_mlt          ;0bda\r
+       defw do_op_div          ;0bdc\r
+       defw do_op_mod          ;0bde\r
+       defw do_op_and          ;0be0\r
+       defw do_op_or           ;0be2\r
+       defw do_op_xor          ;0be4\r
+       defw 0                  ;0be6\r
+\r
+fact_factor:\r
+       call do_factor          ;0be8\r
+       ret nc                  ;0beb\r
+       jp ERROR                ;0bec\r
+\r
+do_factor:\r
+       call chk.sp             ;0bef\r
+       call get.number         ;0bf2\r
+       ret nc                  ;0bf5\r
+       inc de                  ;0bf6\r
+       ld hl,TOPRAM            ;0bf7\r
+       cp 'T'                  ;0bfa\r
+       ret z                   ;0bfc\r
+       ld hl,(HILOD)           ;0bfd\r
+       cp 'H'                  ;0c00\r
+       ret z                   ;0c02\r
+       ld hl,(MAXLOD)          ;0c03\r
+       cp 'M'                  ;0c06\r
+       ret z                   ;0c08\r
+       ld hl,TPA               ;0c09\r
+       cp 'L'                  ;0c0c\r
+       ret z                   ;0c0e\r
+       ld hl,(offs.@)          ;0c0f\r
+       cp '@'                  ;0c12\r
+       ret z                   ;0c14\r
+       ld hl,(OFFS.pc)         ;0c15\r
+       cp '$'                  ;0c18\r
+       ret z                   ;0c1a\r
+       cp '-'                  ;0c1b\r
+       jr z,fact_factneg       ;0c1d\r
+       cp '~'                  ;0c1f\r
+       jr z,fact_factinv               ;0c21\r
+       cp '+'                  ;0c23\r
+       jr z,fact_factor        ;0c25\r
+       cp '^'                  ;0c27\r
+       jr z,fact_reg.CPU       ;0c29\r
+       cp 'Y'                  ;0c2b\r
+       jr z,fact_reg.Y         ;0c2d\r
+       cp '('                  ;0c2f\r
+       jr z,fact_mem           ;0c31\r
+       cp '['                  ;0c33\r
+       jp z,EXPR_BRCKT         ;0c35   [ expression ]\r
+       cp ''''                 ;0c38\r
+       jr z,fact_factstring    ;0c3a\r
+       dec de                  ;0c3c\r
+       scf                     ;0c3d\r
+       ret                     ;0c3e\r
+\r
+fact_reg.Y:\r
+       call get.decdigit       ;0c3f\r
+       jp c,ERROR              ;0c42\r
+       inc de                  ;0c45\r
+       add a,a                 ;0c46\r
+       ld hl,reg.Y             ;0c47\r
+       call ADD_HL_A           ;0c4a\r
+       ld a,(hl)               ;0c4d\r
+       inc hl                  ;0c4e\r
+       ld h,(hl)               ;0c4f\r
+       ld l,a                  ;0c50\r
+       and a                   ;0c51\r
+       ret                     ;0c52\r
+fact_factstring:\r
+       ld hl,0                 ;0c53\r
+l0c56h:\r
+       ld a,(de)               ;0c56\r
+       cp ''''                 ;0c57\r
+       jr z,l0c62h             ;0c59\r
+       and a                   ;0c5b\r
+       ret z                   ;0c5c\r
+l0c5dh:\r
+       ld h,l                  ;0c5d\r
+       ld l,a                  ;0c5e\r
+       inc de                  ;0c5f\r
+       jr l0c56h               ;0c60\r
+\r
+l0c62h:\r
+       inc de                  ;0c62\r
+       ld a,(de)               ;0c63\r
+       cp ''''                 ;0c64\r
+       jr z,l0c5dh             ;0c66\r
+       sub '.'                 ;0c68\r
+       or a                    ;0c6a\r
+       ret nz                  ;0c6b\r
+       inc de                  ;0c6c\r
+       set 7,l                 ;0c6d\r
+       ret                     ;0c6f\r
+\r
+fact_reg.CPU:\r
+       call sub_1315h          ;0c70\r
+       jr nc,l0cbbh            ;0c73\r
+       ld a,(hl)               ;0c75\r
+       inc hl                  ;0c76\r
+       ld h,(hl)               ;0c77\r
+       ld l,a                  ;0c78\r
+       and a                   ;0c79\r
+       bit 0,c                 ;0c7a\r
+       ret nz                  ;0c7c\r
+       ld h,000h               ;0c7d\r
+       ret                     ;0c7f\r
+\r
+fact_factneg:\r
+       call fact_factor        ;0c80\r
+       dec hl                  ;0c83\r
+cpl.hl:\r
+       ld a,h                  ;0c84\r
+       cpl                     ;0c85\r
+       ld h,a                  ;0c86\r
+       ld a,l                  ;0c87\r
+       cpl                     ;0c88\r
+       ld l,a                  ;0c89\r
+       ret                     ;0c8a\r
+fact_factinv:\r
+       call fact_factor        ;0c8b\r
+       jr cpl.hl               ;0c8e\r
+\r
+fact_mem:\r
+       call EXPR1              ;0c90\r
+       jr c,l0cbbh             ;0c93\r
+       ld a,(de)               ;0c95\r
+       cp ')'                  ;0c96\r
+       jr nz,l0cbbh            ;0c98\r
+       inc de                  ;0c9a\r
+       comst\r
+        ld a,(hl)              ;0c9f\r
+        inc hl                 ;\r
+        ld h,(hl)              ;\r
+       comend\r
+       ld l,a                  ;0ca7\r
+       ld a,(de)               ;0ca8\r
+       inc de                  ;0ca9\r
+       cp '.'                  ;0caa\r
+       ret z                   ;0cac\r
+       dec de                  ;0cad\r
+       xor a                   ;0cae\r
+       ld h,a                  ;0caf\r
+       ret                     ;0cb0\r
+\r
+EXPR_BRCKT:\r
+       call EXPR1              ;0cb1\r
+       jr c,l0cbbh             ;0cb4\r
+       ld a,(de)               ;0cb6\r
+       cp ']'                  ;0cb7\r
+       inc de                  ;0cb9\r
+       ret z                   ;0cba\r
+l0cbbh:\r
+       jp ERROR                ;0cbb\r
+\r
+get.number:\r
+       call get.hexdigit       ;0cbe\r
+       ret c                   ;0cc1\r
+       push de                 ;0cc2\r
+l0cc3h:\r
+       inc de                  ;0cc3\r
+       call get.hexdigit       ;0cc4\r
+       jr nc,l0cc3h            ;0cc7\r
+       pop de                  ;0cc9\r
+       cp '.'                  ;0cca\r
+       jr z,l0d04h             ;0ccc\r
+       cp '"'                  ;0cce\r
+       jr z,l0ce9h             ;0cd0\r
+       ld hl,0                 ;0cd2\r
+l0cd5h:\r
+       call get.hexdigit       ;0cd5\r
+       jr c,l0ce4h             ;0cd8\r
+       add hl,hl               ;0cda\r
+       add hl,hl               ;0cdb\r
+       add hl,hl               ;0cdc\r
+       add hl,hl               ;0cdd\r
+       call ADD_HL_A           ;0cde\r
+       inc de                  ;0ce1\r
+       jr l0cd5h               ;0ce2\r
+l0ce4h:\r
+       xor 'H'                 ;0ce4\r
+       ret nz                  ;0ce6\r
+       inc de                  ;0ce7\r
+       ret                     ;0ce8\r
+\r
+l0ce9h:\r
+       ld hl,0                 ;0ce9\r
+l0cech:\r
+       call get.decdigit       ;0cec\r
+l0cefh:\r
+       inc de                  ;0cef\r
+       jr c,l0cf8h             ;0cf0\r
+       add hl,hl               ;0cf2\r
+       call ADD_HL_A           ;0cf3\r
+       jr l0cech               ;0cf6\r
+l0cf8h:\r
+       cp '"'                  ;0cf8\r
+       jp nz,ERROR             ;0cfa\r
+       call get.decdigit       ;0cfd\r
+       jr nc,l0cefh            ;0d00\r
+       or a                    ;0d02\r
+       ret                     ;0d03\r
+l0d04h:\r
+       ld hl,0                 ;0d04\r
+l0d07h:\r
+       call get.decdigit       ;0d07\r
+       inc de                  ;0d0a\r
+       jr c,l0d1ah             ;0d0b\r
+       push bc                 ;0d0d\r
+       add hl,hl               ;0d0e   hl *= 10\r
+       ld b,h                  ;0d0f\r
+       ld c,l                  ;0d10\r
+       add hl,hl               ;0d11\r
+       add hl,hl               ;0d12\r
+       add hl,bc               ;0d13\r
+       pop bc                  ;0d14\r
+       call ADD_HL_A           ;0d15\r
+       jr l0d07h               ;0d18\r
+l0d1ah:\r
+       cp '.'                  ;0d1a\r
+       ret z                   ;0d1c\r
+       jp ERROR                ;0d1d\r
+\r
+sub_0d20h:\r
+       ld a,(de)               ;0d20\r
+       cp 05bh                 ;0d21\r
+       jr l0d28h               ;0d23\r
+\r
+get.hexdigit:\r
+       ld a,(de)               ;0d25\r
+sub_0d26h:\r
+       cp 'F'+1                ;0d26\r
+l0d28h:\r
+       ccf                     ;0d28\r
+       ret c                   ;0d29\r
+       cp 'A'                  ;0d2a\r
+       jr c,l0d32h             ;0d2c\r
+       sub 'A'-10              ;0d2e\r
+       ret                     ;0d30\r
+\r
+get.decdigit:\r
+       ld a,(de)               ;0d31\r
+l0d32h:\r
+       cp '9'+1                ;0d32\r
+       jr l0d39h               ;0d34\r
+get.bindigit:\r
+       ld a,(de)               ;0d36\r
+       cp '1'+1                ;0d37\r
+l0d39h:\r
+       ccf                     ;0d39\r
+       ret c                   ;0d3a\r
+       cp '0'                  ;0d3b\r
+       ret c                   ;0d3d\r
+       sub '0'                 ;0d3e\r
+       ret                     ;0d40\r
+\r
+l0d41h:\r
+       call assert_eol         ;0d41\r
+\r
+prnt_cpustat:\r
+       call prnt_f             ;0d44\r
+       call outbl2             ;0d47\r
+       ld hl,b_0x0DFD_start    ;0d4a\r
+       ld de,b_0x0E1D_start    ;0d4d\r
+       ld b,006h               ;0d50\r
+l0d52h:\r
+       call prnt_regs          ;0d52\r
+       djnz l0d52h             ;0d55\r
+       push hl                 ;0d57\r
+       push de                 ;0d58\r
+       ld iy,(REG.PC)          ;0d59\r
+       call sub_1f77h          ;0d5d\r
+       exx                     ;0d60\r
+       ex af,af'               ;0d61\r
+       call CRLF               ;0d62\r
+       call prnt_f2            ;0d65\r
+       call outbl2             ;0d68\r
+       pop de                  ;0d6b\r
+       pop hl                  ;0d6c\r
+       ld b,007h               ;0d6d\r
+l0d6fh:\r
+       call prnt_regs          ;0d6f\r
+       djnz l0d6fh             ;0d72\r
+       exx                     ;0d74\r
+       ex af,af'               ;0d75\r
+       and a                   ;0d76\r
+       jr z,l0d7fh             ;0d77\r
+       call outbl6             ;0d79\r
+       call sub_1f5bh          ;0d7c\r
+l0d7fh:\r
+       jp crlf                 ;0d7f\r
+\r
+prnt_f:\r
+       ld a,(reg.f)            ;0d82\r
+       call prnt_flags         ;0d85\r
+       ld a,(reg.iff)          ;0d88\r
+       cp 0f3h                 ;0d8b\r
+       jp z,outbl              ;0d8d\r
+       ld a,'E'                ;0d90\r
+       jp outchar              ;0d92\r
+\r
+prnt_f2:\r
+       ld a,(reg.f2)           ;0d95\r
+       call prnt_flags         ;0d98\r
+       jp outbl                ;0d9b\r
+\r
+prnt_flags:\r
+       ld b,a                  ;0d9e\r
+       ld a,'S'                ;0d9f\r
+       call sub_0dbeh          ;0da1\r
+       ld a,'Z'                ;0da4\r
+       call sub_0dbeh          ;0da6\r
+       rl b                    ;0da9\r
+       ld a,'H'                ;0dab\r
+       call sub_0dbeh          ;0dad\r
+       rl b                    ;0db0\r
+       ld a,'V'                ;0db2\r
+       call sub_0dbeh          ;0db4\r
+       ld a,'N'                ;0db7\r
+       call sub_0dbeh          ;0db9\r
+       ld a,'C'                ;0dbc\r
+sub_0dbeh:\r
+       rl b                    ;0dbe\r
+       jp c,OUTCHAR            ;0dc0\r
+       jp OUTBL                ;0dc3\r
+\r
+prnt_regs:\r
+       push bc                 ;0dc6\r
+       push de                 ;0dc7\r
+       call PSTR               ;0dc8\r
+       ld a,'='                ;0dcb\r
+       call OUTCHAR            ;0dcd\r
+       ex (sp),hl              ;0dd0\r
+       ld e,(hl)               ;0dd1\r
+       inc hl                  ;0dd2\r
+       ld d,(hl)               ;0dd3\r
+       inc hl                  ;0dd4\r
+       ld a,(hl)               ;0dd5\r
+       inc hl                  ;0dd6\r
+       push hl                 ;0dd7\r
+       and a                   ;0dd8\r
+       jr z,l0df2h             ;0dd9\r
+       push af                 ;0ddb\r
+       ld a,(de)               ;0ddc\r
+       ld l,a                  ;0ddd\r
+       inc de                  ;0dde\r
+       ld a,(de)               ;0ddf\r
+       ld h,a                  ;0de0\r
+       pop af                  ;0de1\r
+       dec a                   ;0de2\r
+       jr z,l0dedh             ;0de3\r
+       call out.hl.@           ;0de5\r
+       call z,outbl6           ;0de8\r
+       jr l0df6h               ;0deb\r
+l0dedh:\r
+       call out.hl             ;0ded\r
+       jr l0df6h               ;0df0\r
+l0df2h:\r
+       ld a,(de)               ;0df2\r
+       call out.hex            ;0df3\r
+l0df6h:\r
+       call OUTBL              ;0df6\r
+       pop de                  ;0df9\r
+       pop hl                  ;0dfa\r
+       pop bc                  ;0dfb\r
+       ret                     ;0dfc\r
+\r
+b_0x0DFD_start:\r
+       DC      'A '\r
+       DC      'BC '\r
+       DC      'DE '\r
+       DC      'HL '\r
+       DC      'SP'\r
+       DC      'PC'\r
+       DC      'A'''\r
+       DC      'BC'''\r
+       DC      'DE'''\r
+       DC      'HL'''\r
+       DC      'IX'\r
+       DC      'IY'\r
+       DC      'I'\r
+       DB      0\r
+\r
+b_0x0E1D_start:\r
+       defw reg.a              ;0e1d\r
+       defb 000h               ;0e1f\r
+       defw reg.c              ;0e20\r
+       defb 001h               ;0e22\r
+       defw reg.e              ;0e23\r
+       defb 001h               ;0e25\r
+       defw reg.l              ;0e26\r
+       defb 001h               ;0e28\r
+       defw reg.sp             ;0e29\r
+       defb 001h               ;0e2b\r
+       defw reg.pc             ;0e2c\r
+       defb 002h               ;0e2e\r
+       defw reg.a2             ;0e2f\r
+       defb 000h               ;0e31\r
+       defw reg.c2             ;0e32\r
+       defb 001h               ;0e34\r
+       defw reg.e2             ;0e35\r
+       defb 001h               ;0e37\r
+       defw reg.l2             ;0e38\r
+       defb 001h               ;0e3a\r
+       defw reg.ix             ;0e3b\r
+       defb 001h               ;0e3d\r
+       defw reg.iy             ;0e3e\r
+       defb 001h               ;0e40\r
+       defw reg.i              ;0e41\r
+       dw      0               ;0e43\r
+\r
+CMD.G:\r
+       sub a                   ;0e45\r
+       ld (TCFLG),a            ;0e46\r
+       ld (XA747),a            ;0e49\r
+       call EXPR               ;0e4c\r
+       jr c,l0e54h             ;0e4f\r
+       ld (REG.PC),hl          ;0e51\r
+l0e54h:\r
+       call SKIPBL             ;0e54\r
+       jp z,l1183h             ;0e57\r
+       cp ';'                  ;0e5a\r
+       jp nz,ERROR             ;0e5c\r
+       inc de                  ;0e5f\r
+       ld a,002h               ;0e60\r
+       call sub_0f24h          ;0e62\r
+       jp l1183h               ;0e65\r
+\r
+sub_0e68h:\r
+       ld b,BP_CNT             ;0e68\r
+       ld ix,bp_tab            ;0e6a\r
+l0e6eh:\r
+       ld a,(ix+000h)          ;0e6e\r
+       and 0f1h                ;0e71\r
+       ld (ix+000h),a          ;0e73\r
+       call sub_11c5h          ;0e76\r
+       ld de,BP_SIZE           ;0e79\r
+       add ix,de               ;0e7c\r
+       djnz l0e6eh             ;0e7e\r
+       ret                     ;0e80\r
+\r
+CMD.B:\r
+       call SKIPBL             ;0e81\r
+       jr z,l0ecbh             ;0e84\r
+       inc de                  ;0e86\r
+       cp 'X'                  ;0e87\r
+       jr z,l0e91h             ;0e89\r
+       dec de                  ;0e8b\r
+       ld a,001h               ;0e8c\r
+       jp sub_0f24h            ;0e8e\r
+l0e91h:\r
+       call SKIPBL             ;0e91\r
+       jr z,l0ea6h             ;0e94\r
+l0e96h:\r
+       call EXPR               ;0e96\r
+       jp c,assert_eol         ;0e99\r
+       push de                 ;0e9c\r
+       call sub_0ea7h          ;0e9d\r
+       pop de                  ;0ea0\r
+       call skip_to_nextarg    ;0ea1\r
+       jr l0e96h               ;0ea4\r
+l0ea6h:\r
+       scf                     ;0ea6\r
+sub_0ea7h:\r
+       ld b,BP_CNT             ;0ea7\r
+       ld ix,bp_tab            ;0ea9\r
+l0eadh:\r
+       push af                 ;0ead\r
+       jr c,l0ebbh             ;0eae\r
+       ld e,(ix+002h)          ;0eb0\r
+       ld d,(ix+003h)          ;0eb3\r
+       call CP.HL.DE           ;0eb6\r
+       jr nz,l0ec2h            ;0eb9\r
+l0ebbh:\r
+       ld (ix+000h),000h       ;0ebb\r
+       call sub_11c5h          ;0ebf\r
+l0ec2h:\r
+       ld de,BP_SIZE           ;0ec2\r
+       add ix,de               ;0ec5\r
+       pop af                  ;0ec7\r
+       djnz l0eadh             ;0ec8\r
+       ret                     ;0eca\r
+l0ecbh:\r
+       ld b,BP_CNT             ;0ecb\r
+       ld ix,bp_tab            ;0ecd\r
+l0ed1h:\r
+       bit 0,(ix+000h)         ;0ed1\r
+       jr z,l0f1ch             ;0ed5\r
+       ld a,'R'                ;0ed7\r
+       bit 4,(ix+000h)         ;0ed9\r
+       jr nz,l0ee1h            ;0edd\r
+       ld a,' '                ;0edf\r
+l0ee1h:\r
+       call OUTCHAR            ;0ee1\r
+       call OUTBL              ;0ee4\r
+       ld l,(ix+002h)          ;0ee7\r
+       ld h,(ix+003h)          ;0eea\r
+       call out.hl.@           ;0eed\r
+       call outbl2             ;0ef0\r
+       ld a,':'                ;0ef3\r
+       call OUTCHAR            ;0ef5\r
+       ld l,(ix+004h)          ;0ef8\r
+       ld h,(ix+005h)          ;0efb\r
+       call out.hl             ;0efe\r
+       ld l,(ix+006h)          ;0f01\r
+       ld h,(ix+007h)          ;0f04\r
+       ld a,h                  ;0f07\r
+       or l                    ;0f08\r
+       jr z,l0f19h             ;0f09\r
+       call outbl4             ;0f0b\r
+       ld a,'I'                ;0f0e\r
+       call OUTCHAR            ;0f10\r
+       call outbl2             ;0f13\r
+       call PSTR               ;0f16\r
+l0f19h:\r
+       call CRLF               ;0f19\r
+l0f1ch:\r
+       ld de,BP_SIZE           ;0f1c\r
+       add ix,de               ;0f1f\r
+       djnz l0ed1h             ;0f21\r
+       ret                     ;0f23\r
+\r
+sub_0f24h:\r
+       ld b,a                  ;0f24\r
+       call SKIPBL             ;0f25\r
+       ret z                   ;0f28\r
+       cp 'R'                  ;0f29\r
+       jr nz,l0f30h            ;0f2b\r
+       inc de                  ;0f2d\r
+       set 4,b                 ;0f2e\r
+l0f30h:\r
+       push bc                 ;0f30\r
+       call EXPR               ;0f31\r
+       jp c,ERROR              ;0f34\r
+       pop bc                  ;0f37\r
+       bit 0,b                 ;0f38\r
+       push bc                 ;0f3a\r
+       push de                 ;0f3b\r
+       push hl                 ;0f3c\r
+       call nz,sub_0ea7h       ;0f3d\r
+       pop hl                  ;0f40\r
+       call sub_0f68h          ;0f41\r
+       pop de                  ;0f44\r
+       ld (ix+002h),l          ;0f45\r
+       ld (ix+003h),h          ;0f48\r
+       call sub_0f80h          ;0f4b\r
+       ld (ix+004h),l          ;0f4e\r
+       ld (ix+005h),h          ;0f51\r
+       call sub_0f91h          ;0f54\r
+       ld (ix+006h),l          ;0f57\r
+       ld (ix+007h),h          ;0f5a\r
+       call skip_to_nextarg    ;0f5d\r
+       pop af                  ;0f60\r
+       ld (ix+000h),a          ;0f61\r
+       and 00fh                ;0f64\r
+       jr sub_0f24h            ;0f66\r
+sub_0f68h:\r
+       ld b,BP_CNT             ;0f68\r
+       ld ix,bp_tab            ;0f6a\r
+l0f6eh:\r
+       ld a,(ix+000h)          ;0f6e\r
+       and 00fh                ;0f71\r
+       ret z                   ;0f73\r
+       push bc                 ;0f74\r
+       ld bc,BP_SIZE           ;0f75\r
+       add ix,bc               ;0f78\r
+       pop bc                  ;0f7a\r
+       djnz l0f6eh             ;0f7b\r
+       jp ERROR                ;0f7d\r
+\r
+sub_0f80h:\r
+       call SKIPBL             ;0f80\r
+       ld hl,1                 ;0f83\r
+       cp 03ah                 ;0f86\r
+       ret nz                  ;0f88\r
+       inc de                  ;0f89\r
+       call EXPR               ;0f8a\r
+       jp c,ERROR              ;0f8d\r
+       ret                     ;0f90\r
+sub_0f91h:\r
+       call SKIPBL             ;0f91\r
+       cp 049h                 ;0f94\r
+       ld hl,0                 ;0f96\r
+       ret nz                  ;0f99\r
+       inc de                  ;0f9a\r
+       call SKIPBL             ;0f9b\r
+       push de                 ;0f9e\r
+       call EXPR               ;0f9f\r
+       jp c,ERROR              ;0fa2\r
+       ex de,hl                ;0fa5\r
+       pop de                  ;0fa6\r
+       push de                 ;0fa7\r
+       sbc hl,de               ;0fa8\r
+       ld b,h                  ;0faa\r
+       ld c,l                  ;0fab\r
+       ld hl,(sexp1)           ;0fac\r
+       push hl                 ;0faf\r
+       add hl,bc               ;0fb0\r
+       ld de,sexpbufe          ;0fb1\r
+       call CP.HL.DE           ;0fb4\r
+       jp nc,ERROR             ;0fb7\r
+       pop hl                  ;0fba\r
+       ld (sexp2),hl           ;0fbb\r
+       pop de                  ;0fbe\r
+       ex de,hl                ;0fbf\r
+       ldir                    ;0fc0\r
+       xor a                   ;0fc2\r
+       ld (de),a               ;0fc3\r
+       inc de                  ;0fc4\r
+       ex de,hl                ;0fc5\r
+       ld (sexp1),hl           ;0fc6\r
+       ld hl,(sexp2)           ;0fc9\r
+       ret                     ;0fcc\r
+\r
+bpddtz:\r
+       if ROMSYS\r
+        ld h,ROMEN             ;0fcd\r
+        jr z,l0fd2h            ;0fcf\r
+        inc h                  ;0fd1\r
+l0fd2h:\r
+        push hl                ;0fd2   save rom enable stat\r
+       endif\r
+       push bc                 ;0fd3\r
+       push de                 ;0fd4\r
+       push ix                 ;0fd5\r
+       push iy                 ;0fd7\r
+       ld a,i                  ;0fd9\r
+       ld h,a                  ;0fdb\r
+       ld l,000h               ;0fdc\r
+       push hl                 ;0fde\r
+       ld a,0f3h               ;0fdf   DI\r
+       jp po,l0fe6h            ;0fe1\r
+       ld a,0fbh               ;0fe4   EI\r
+l0fe6h:\r
+       ld (reg.iff),a          ;0fe6\r
+       ld hl,ivtab             ;0fe9\r
+       ld a,h                  ;0fec\r
+       ld i,a                  ;0fed\r
+       call ddtei              ;0fef\r
+       ex af,af'               ;0ff2\r
+       push af                 ;0ff3\r
+       exx                     ;0ff4\r
+       push bc                 ;0ff5\r
+       push de                 ;0ff6\r
+       push hl                 ;0ff7\r
+       call bp.unset           ;0ff8\r
+       in0 a,(itc)             ;0ffb\r
+       jp p,l1017h             ;0ffe\r
+       res TRAP,a              ;1001\r
+       out0 (itc),a            ;1003\r
+       bit UFO,a               ;1006\r
+       jr z,l1011h             ;1008\r
+       ld hl,(REG.PC)          ;100a\r
+       dec hl                  ;100d\r
+       ld (REG.PC),hl          ;100e\r
+l1011h:\r
+       ld hl,MSG_trap          ;1011\r
+       call PSTR               ;1014\r
+l1017h:\r
+       ld a,(XBFE8)            ;1017\r
+       dec a                   ;101a\r
+       jr z,l1051h             ;101b\r
+       call inchar             ;101d\r
+       jr c,l102eh             ;1020\r
+       call sub_1059h          ;1022\r
+       and a                   ;1025\r
+       jp z,l1183h             ;1026\r
+       and 083h                ;1029\r
+       jp z,l284ah             ;102b\r
+l102eh:\r
+       call sub_0e68h          ;102e\r
+       call prnt_cpustat       ;1031\r
+       jp DDTZML               ;1034\r
+\r
+MSG_trap:\r
+       DB      CR,LF,'Undefined opcode trap'\r
+       DB      CR,LF,0\r
+\r
+l1051h:\r
+       ld (XBFE8),a            ;1051\r
+       ld c,007h               ;1054\r
+       jp l119fh               ;1056\r
+sub_1059h:\r
+       ld a,080h               ;1059\r
+       ex af,af'               ;105b\r
+       sub a                   ;105c\r
+       ld (XA747),a            ;105d\r
+       ld b,BP_CNT             ;1060\r
+       ld ix,bp_tab            ;1062\r
+l1066h:\r
+       ld a,(ix+000h)          ;1066\r
+       and 007h                ;1069\r
+       jr z,l107eh             ;106b\r
+       ld e,(ix+002h)          ;106d\r
+       ld d,(ix+003h)          ;1070\r
+       ld hl,(REG.PC)          ;1073\r
+       call CP.HL.DE           ;1076\r
+       push bc                 ;1079\r
+       call z,sub_1087h        ;107a\r
+       pop bc                  ;107d\r
+l107eh:\r
+       ld de,BP_SIZE           ;107e\r
+       add ix,de               ;1081\r
+       djnz l1066h             ;1083\r
+       ex af,af'               ;1085\r
+       ret                     ;1086\r
+sub_1087h:\r
+       ex af,af'               ;1087\r
+       res 7,a                 ;1088\r
+       ex af,af'               ;108a\r
+       ld e,(ix+006h)          ;108b\r
+       ld d,(ix+007h)          ;108e\r
+       ld a,d                  ;1091\r
+       or e                    ;1092\r
+       ld hl,0ffffh            ;1093\r
+       call nz,EXPR            ;1096\r
+       ld a,h                  ;1099\r
+       or l                    ;109a\r
+       jr z,l10aeh             ;109b\r
+       ld e,(ix+004h)          ;109d\r
+       ld d,(ix+005h)          ;10a0\r
+       dec de                  ;10a3\r
+       ld a,d                  ;10a4\r
+       or e                    ;10a5\r
+       jr z,l10b9h             ;10a6\r
+       ld (ix+004h),e          ;10a8\r
+       ld (ix+005h),d          ;10ab\r
+l10aeh:\r
+       bit 4,(ix+000h)         ;10ae\r
+       ret z                   ;10b2\r
+       ld a,001h               ;10b3\r
+       ld (XA747),a            ;10b5\r
+       ret                     ;10b8\r
+l10b9h:\r
+       ex af,af'               ;10b9\r
+       or (ix+000h)            ;10ba\r
+       ex af,af'               ;10bd\r
+       ret\r
+\r
+bp.unset:\r
+       ld b,BP_CNT             ;10bf\r
+       ld ix,bp_tab            ;10c1\r
+l10c5h:\r
+       bit 5,(ix+000h)         ;10c5\r
+       res 5,(ix+000h)         ;10c9\r
+       jr z,l10e7h             ;10cd\r
+       ld l,(ix+002h)          ;10cf\r
+       ld h,(ix+003h)          ;10d2\r
+       ld a,(ddtrst)           ;10d5\r
+       comst                   ;10e2\r
+       cp (hl)                 ;10dc\r
+       comend\r
+       jr nz,l10e7h            ;10dd\r
+       ld a,(ix+001h)          ;10df\r
+       comst                   ;10e2\r
+        ld (hl),a              ;10e6\r
+       comend\r
+l10e7h:\r
+       res 3,(ix+000h)         ;10e7\r
+       ld de,BP_SIZE           ;10eb\r
+       add ix,de               ;10ee\r
+       djnz l10c5h             ;10f0\r
+       ret                     ;10f2\r
+sub_10f3h:\r
+       ld b,BP_CNT             ;10f3\r
+       ld ix,bp_tab            ;10f5\r
+l10f9h:\r
+       ld a,(ix+000h)          ;10f9\r
+       and 003h                ;10fc\r
+       jr z,l110dh             ;10fe\r
+       ld e,(ix+002h)          ;1100\r
+       ld d,(ix+003h)          ;1103\r
+       ld hl,(REG.PC)          ;1106\r
+       call CP.HL.DE           ;1109\r
+       ret z                   ;110c\r
+l110dh:\r
+       ld de,BP_SIZE           ;110d\r
+       add ix,de               ;1110\r
+       djnz l10f9h             ;1112\r
+       sub a                   ;1114\r
+       inc a                   ;1115\r
+       ret                     ;1116\r
+sub_1117h:\r
+       call sub_0f68h          ;1117\r
+       ld (ix+004h),001h       ;111a\r
+       ld (ix+005h),000h       ;111e\r
+       ld (ix+002h),l          ;1122\r
+       ld (ix+003h),h          ;1125\r
+       ld (ix+006h),000h       ;1128\r
+       ld (ix+007h),000h       ;112c\r
+       ld a,(XBFE8)            ;1130\r
+       and a                   ;1133\r
+       ld a,008h               ;1134\r
+       jr nz,l113ah            ;1136\r
+       ld a,004h               ;1138\r
+l113ah:\r
+       ld (ix+000h),a          ;113a\r
+       ret                     ;113d\r
+\r
+bp.set:\r
+       ld b,BP_CNT             ;113e\r
+       ld ix,bp_tab            ;1140\r
+l1144h:\r
+       ld a,(ix+000h)          ;1144\r
+       and c                   ;1147\r
+       jr z,l117bh             ;1148\r
+       set 5,(ix+000h)         ;114a\r
+       ld l,(ix+002h)          ;114e\r
+       ld h,(ix+003h)          ;1151\r
+\r
+       if 0\r
+\r
+       comst                   ;1154\r
+        ld a,(hl)              ;1158\r
+       comend\r
+       ld (ix+001h),a          ;1159\r
+       ld a,(ddtrst)           ;115c\r
+       comst                   ;115f\r
+       ld (hl),a               ;1163\r
+       comend\r
+       and 038h                ;1164\r
+       ld h,000h               ;1166\r
+       ld l,a                  ;1168\r
+       ld a,0c3h               ;1169\r
+       comrep                  ;116b\r
+       inc hl                  ;116e\r
+       ld de,bpent             ;116f\r
+       ld a,e                  ;1172\r
+       comrep                  ;1173\r
+       inc hl                  ;1176\r
+       ld a,d                  ;1177\r
+       comrep                  ;1178\r
+       \r
+       else\r
+\r
+       ld a,(ddtrst)           ;115c\r
+       comst                   ;115f\r
+       ld e,(hl)               ;1158\r
+       ld (hl),a               ;1163\r
+       comend\r
+       ld (ix+001h),e          ;1159\r
+       and 038h                ;1164\r
+       ld h,0                  ;1166\r
+       ld l,a                  ;1168\r
+       ld de,bpent             ;116f\r
+       comst                   ;\r
+       ld (hl),0c3h            ;1169\r
+       inc hl                  ;116e\r
+       ld (hl),e               ;1172\r
+       inc hl                  ;1176\r
+       ld (hl),d               ;1177\r
+       comend\r
+\r
+       endif\r
+       \r
+l117bh:\r
+       ld de,BP_SIZE           ;117b\r
+       add ix,de               ;117e\r
+       djnz l1144h             ;1180\r
+       ret\r
+                               ;1182\r
+l1183h:\r
+       sub a                   ;1183\r
+       ld (XBFE8),a            ;1184\r
+       ld a,(XA747)            ;1187\r
+       and a                   ;118a\r
+       call nz,prnt_cpustat    ;118b\r
+       call sub_10f3h          ;118e\r
+       ld c,007h               ;1191\r
+       jr nz,l119fh            ;1193\r
+       ld a,001h               ;1195\r
+       ld (XBFE8),a            ;1197\r
+       call sub_26e7h          ;119a\r
+       ld c,008h               ;119d\r
+l119fh:\r
+       call bp.set             ;119f\r
+       ld sp,$stack            ;11a2   set/restore user cpu state\r
+       pop hl                  ;11a5\r
+       pop de                  ;11a6\r
+       pop bc                  ;11a7\r
+       pop af                  ;11a8\r
+       exx                     ;11a9\r
+       ex af,af'               ;11aa\r
+       pop af                  ;11ab\r
+       ld i,a                  ;11ac\r
+       pop iy                  ;11ae\r
+       pop ix                  ;11b0\r
+       pop de                  ;11b2\r
+       pop bc                  ;11b3\r
+       if ROMSYS\r
+        pop hl                 ;11b4\r
+        ld a,l                 ;11b5\r
+        and M_MWI              ;11b6\r
+        ld l,a                 ;11b8\r
+        di                     ;11b9\r
+        in0 a,(dcntl)          ;11ba\r
+        and ~M_MWI             ;11bd\r
+        or l                   ;11bf\r
+        ld l,a                 ;11c0\r
+        ld a,h                 ;11c1\r
+       else\r
+        pop hl\r
+        di\r
+       endif\r
+       jp $go                  ;11c2   common ram, switch banks and go to user prog\r
+\r
+sub_11c5h:\r
+       ld a,(ix+000h)          ;11c5\r
+       and 003h                ;11c8\r
+       ret nz                  ;11ca\r
+       ld e,(ix+006h)          ;11cb\r
+       ld d,(ix+007h)          ;11ce\r
+       ld a,d                  ;11d1\r
+       or e                    ;11d2\r
+       ret z                   ;11d3\r
+       push bc                 ;11d4\r
+       ld h,d                  ;11d5\r
+       ld l,e                  ;11d6\r
+       sub a                   ;11d7\r
+       ld (ix+006h),a          ;11d8\r
+       ld (ix+007h),a          ;11db\r
+       ld bc,0ffffh            ;11de\r
+       cpir                    ;11e1\r
+l11e3h:\r
+       push de                 ;11e3\r
+       ld de,(sexp1)           ;11e4\r
+       call CP.HL.DE           ;11e8\r
+       pop de                  ;11eb\r
+       jr nc,l11f9h            ;11ec\r
+       call sub_11ffh          ;11ee\r
+l11f1h:\r
+       ld a,(hl)               ;11f1\r
+       ldi                     ;11f2\r
+       and a                   ;11f4\r
+       jr nz,l11f1h            ;11f5\r
+       jr l11e3h               ;11f7\r
+l11f9h:\r
+       ld (sexp1),de           ;11f9\r
+       pop bc                  ;11fd\r
+       ret                     ;11fe\r
+sub_11ffh:\r
+       ld iy,bp_tab            ;11ff\r
+       push de                 ;1203\r
+l1204h:\r
+       ld e,(iy+006h)          ;1204\r
+       ld d,(iy+007h)          ;1207\r
+       call CP.HL.DE           ;120a\r
+       jr z,l1216h             ;120d\r
+       ld de,BP_SIZE           ;120f\r
+       add iy,de               ;1212\r
+       jr l1204h               ;1214\r
+l1216h:\r
+       pop de                  ;1216\r
+       ld (iy+006h),e          ;1217\r
+       ld (iy+007h),d          ;121a\r
+       ret                     ;121d\r
+\r
+CMD.Y:\r
+       call get.decdigit               ;121e\r
+       jr c,l122fh             ;1221\r
+       inc de                  ;1223\r
+       push af                 ;1224\r
+       call assert_eol         ;1225\r
+       pop af                  ;1228\r
+       call sub_1248h          ;1229\r
+       jp l127ch               ;122c\r
+l122fh:\r
+       call assert_eol         ;122f\r
+       xor a                   ;1232\r
+l1233h:\r
+       push af                 ;1233\r
+       call sub_1248h          ;1234\r
+       call outbl4             ;1237\r
+       pop af                  ;123a\r
+       inc a                   ;123b\r
+       bit 0,a                 ;123c\r
+       push af                 ;123e\r
+       call z,CRLF             ;123f\r
+       pop af                  ;1242\r
+       cp LF                   ;1243\r
+       jr c,l1233h             ;1245\r
+       ret                     ;1247\r
+\r
+sub_1248h:\r
+       ld c,a                  ;1248\r
+       ld b,0                  ;1249\r
+       add a,'0'+080h          ;124b\r
+       ld de,msg.Y+1           ;124d\r
+       ld (de),a               ;1250\r
+       dec de                  ;1251\r
+       ld hl,reg.Y             ;1252\r
+       add hl,bc               ;1255\r
+       add hl,bc               ;1256\r
+       ex de,hl                ;1257\r
+       ld c,003h               ;1258\r
+       jp l129ah               ;125a\r
+\r
+CMD.X:\r
+       call SKIPBL             ;125d\r
+       call sub_1315h          ;1260\r
+       jp nc,l0d41h            ;1263\r
+       call assert_eol         ;1266\r
+       ld a,b                  ;1269\r
+       cp 01fh                 ;126a\r
+       jr z,l12c6h             ;126c\r
+       cp 020h                 ;126e\r
+       jr z,l12b6h             ;1270\r
+       ex de,hl                ;1272\r
+       ld hl,b_0x132A_start    ;1273\r
+       call sub_0a48h          ;1276\r
+l1279h:\r
+       call l129ah             ;1279\r
+l127ch:\r
+       call OUTBL              ;127c\r
+       push de                 ;127f\r
+       push bc                 ;1280\r
+       call INLINE             ;1281\r
+       call SKIPBL             ;1284\r
+       jr z,l1297h             ;1287\r
+       call get_arg            ;1289\r
+       ld b,h                  ;128c\r
+       ld c,l                  ;128d\r
+       pop af                  ;128e\r
+       pop hl                  ;128f\r
+       ld (hl),c               ;1290\r
+       bit 0,a                 ;1291\r
+       ret z                   ;1293\r
+       inc hl                  ;1294\r
+       ld (hl),b               ;1295\r
+       ret                     ;1296\r
+l1297h:\r
+       pop af                  ;1297\r
+       pop hl                  ;1298\r
+       ret                     ;1299\r
+l129ah:\r
+       ld b,c                  ;129a\r
+       call PSTR               ;129b\r
+       ld a,'='                ;129e\r
+       call OUTCHAR            ;12a0\r
+       ld a,(de)               ;12a3\r
+       bit 0,b                 ;12a4\r
+       jp z,out.hex            ;12a6\r
+       ld l,a                  ;12a9\r
+       inc de                  ;12aa\r
+       ld a,(de)               ;12ab\r
+       dec de                  ;12ac\r
+       ld h,a                  ;12ad\r
+       bit 1,b                 ;12ae\r
+       jp z,out.hl             ;12b0\r
+       jp out.hl.@             ;12b3\r
+\r
+l12b6h:\r
+       call prnt_f             ;12b6\r
+       ld a,0f3h               ;12b9\r
+       ld (reg.iff),a          ;12bb\r
+       scf                     ;12be\r
+       call sub_12d1h          ;12bf\r
+       ld (reg.f),a            ;12c2\r
+       ret                     ;12c5\r
+\r
+l12c6h:\r
+       call prnt_f2            ;12c6\r
+       and a                   ;12c9\r
+       call sub_12d1h          ;12ca\r
+       ld (reg.f2),a           ;12cd\r
+       ret                     ;12d0\r
+\r
+sub_12d1h:\r
+       ex af,af'               ;12d1\r
+       ld b,000h               ;12d2\r
+       call outbl              ;12d4\r
+       call assert_eol         ;12d7\r
+       call inline             ;12da\r
+l12ddh:\r
+       call skipbl             ;12dd\r
+       ld a,b                  ;12e0\r
+       ret z                   ;12e1\r
+       push bc                 ;12e2\r
+       ld hl,tab_pr_flags      ;12e3\r
+       call lookupch           ;12e6\r
+       jp nc,error             ;12e9\r
+       ld a,b                  ;12ec\r
+       cp 008h                 ;12ed\r
+       jr z,l12feh             ;12ef\r
+       inc b                   ;12f1\r
+       ld a,001h               ;12f2\r
+       jr l12f7h               ;12f4\r
+l12f6h:\r
+       rlca                    ;12f6\r
+l12f7h:\r
+       djnz l12f6h             ;12f7\r
+       pop bc                  ;12f9\r
+       or b                    ;12fa\r
+       ld b,a                  ;12fb\r
+       jr l12ddh               ;12fc\r
+l12feh:\r
+       ex af,af'               ;12fe\r
+       jp nc,ERROR             ;12ff\r
+       ex af,af'               ;1302\r
+       ld a,0FBh               ;1303\r
+       ld (reg.iff),a          ;1305\r
+       pop bc                  ;1308\r
+       jr l12ddh               ;1309\r
+\r
+tab_pr_flags:\r
+       db      'CNV H ZSE'\r
+       db      0\r
+\r
+sub_1315h:\r
+       call sub_0a0eh          ;1315\r
+       ret nc                  ;1318\r
+       ld a,b                  ;1319\r
+       add a,b                 ;131a\r
+       add a,b                 ;131b\r
+       ld hl,b_0x136C_start    ;131c\r
+       call ADD_HL_A           ;131f\r
+       ld c,(hl)               ;1322\r
+       inc hl                  ;1323\r
+       ld a,(hl)               ;1324\r
+       inc hl                  ;1325\r
+       ld h,(hl)               ;1326\r
+       ld l,a                  ;1327\r
+       scf                     ;1328\r
+       ret                     ;1329\r
+\r
+b_0x132A_start:\r
+       DC      'CBAR'\r
+       DC      'BBR'\r
+       DC      'BC'''\r
+       DC      'DE'''\r
+       DC      'HL'''\r
+       DC      'BC'\r
+       DC      'DE'\r
+       DC      'HL'\r
+       DC      'A'''\r
+       DC      'B'''\r
+       DC      'C'''\r
+       DC      'D'''\r
+       DC      'E'''\r
+       DC      'H'''\r
+       DC      'L'''\r
+       DC      'A'\r
+       DC      'B'\r
+       DC      'C'\r
+       DC      'D'\r
+       DC      'E'\r
+       DC      'H'\r
+       DC      'L'\r
+       DC      'IX'\r
+       DC      'IY'\r
+       DC      'SP'\r
+       DC      'PC'\r
+       DC      'X'\r
+       DC      'Y'\r
+       DC      'S'\r
+       DC      'P'\r
+       DC      'I'\r
+       DC      'F'''\r
+       DC      'F'\r
+       if ROMSYS\r
+        DC     'ROMSEL'\r
+       endif\r
+       DB      0\r
+b_0x136C_start:\r
+       defb 000h               ;136c\r
+       defw ucbar              ;136d\r
+       defb 000h               ;136f\r
+       defw ubbr               ;1370\r
+       defb 003h               ;1372\r
+       defw reg.c2             ;1373\r
+       defb 003h               ;1375\r
+       defw reg.e2             ;1376\r
+       defb 003h               ;1378\r
+       defw reg.l2             ;1379\r
+       defb 003h               ;137b\r
+       defw reg.c              ;137c\r
+       defb 003h               ;137e\r
+       defw reg.e              ;137f\r
+       defb 003h               ;1381\r
+       defw reg.l              ;1382\r
+       defb 000h               ;1384\r
+       defw reg.a2             ;1385\r
+       defb 000h               ;1387\r
+       defw reg.b2             ;1388\r
+       defb 000h               ;138a\r
+       defw reg.c2             ;138b\r
+       defb 000h               ;138d\r
+       defw reg.d2             ;138e\r
+       defb 000h               ;1390\r
+       defw reg.e2             ;1391\r
+       defb 000h               ;1393\r
+       defw reg.h2             ;1394\r
+       defb 000h               ;1396\r
+       defw reg.l2             ;1397\r
+       defb 000h               ;1399\r
+       defw reg.a              ;139a\r
+       defb 000h               ;139c\r
+       defw reg.b              ;139d\r
+       defb 000h               ;139f\r
+       defw reg.c              ;13a0\r
+       defb 000h               ;13a2\r
+       defw reg.d              ;13a3\r
+       defb 000h               ;13a5\r
+       defw reg.e              ;13a6\r
+       defb 000h               ;13a8\r
+       defw reg.h              ;13a9\r
+       defb 000h               ;13ab\r
+       defw reg.l              ;13ac\r
+       defb 003h               ;13ae\r
+       defw reg.ix             ;13af\r
+       defb 003h               ;13b1\r
+       defw reg.iy             ;13b2\r
+       defb 003h               ;13b4\r
+       defw reg.sp             ;13b5\r
+       defb 003h               ;13b7\r
+       defw reg.pc             ;13b8\r
+       defb 003h               ;13ba\r
+       defw reg.ix             ;13bb\r
+       defb 003h               ;13bd\r
+       defw reg.iy             ;13be\r
+       defb 003h               ;13c0\r
+       defw reg.sp             ;13c1\r
+       defb 003h               ;13c3\r
+       defw reg.pc             ;13c4\r
+       defb 000h               ;13c6\r
+       defw reg.i              ;13c7\r
+       defb 000h               ;13c9\r
+       defw reg.f2             ;13ca\r
+       defb 000h               ;13cc\r
+       defw reg.f              ;13cd\r
+       if ROMSYS\r
+        defb 000h              ;13cf\r
+        defw uromen            ;13d0\r
+       endif\r
+CMD.S:\r
+       ld hl,(lst.S)           ;13d2\r
+       call get_lastarg_def    ;13d5\r
+l13d8h:\r
+       ld (lst.S),hl           ;13d8\r
+       call out.hl.@           ;13db\r
+       call OUTBL              ;13de\r
+       comst                   ;13e1\r
+       ld a,(hl)               ;13e5\r
+       comend\r
+       call out.hex            ;13e6\r
+       call outbl2             ;13e9\r
+       call INLINE             ;13ec\r
+       call SKIPBL             ;13ef\r
+       inc hl                  ;13f2\r
+       jr z,l13d8h             ;13f3\r
+       dec hl                  ;13f5\r
+       inc de                  ;13f6\r
+       cp '.'                  ;13f7\r
+       jp z,assert_eol         ;13f9\r
+       cp '-'                  ;13fc\r
+       jr nz,l1406h            ;13fe\r
+       ld a,(de)               ;1400\r
+       or a                    ;1401\r
+       dec hl                  ;1402\r
+       jr z,l13d8h             ;1403\r
+       inc hl                  ;1405\r
+l1406h:\r
+       dec de                  ;1406\r
+       call get_bytes_m        ;1407\r
+       jr l13d8h               ;140a\r
+\r
+CMD.@:\r
+       call assert_eol         ;140c\r
+       ld hl,MSG_at            ;140f\r
+       ld de,offs.@            ;1412\r
+       ld c,001h               ;1415\r
+       jp l1279h               ;1417\r
+MSG_at:\r
+       dc      '@'\r
+\r
+CMD.I:\r
+       ld hl,CMD.I             ;141b\r
+       ld (CMD_RPT),hl         ;141e\r
+       ld hl,(lst.IP)          ;1421\r
+       call get_lastarg_def    ;1424\r
+       ld (lst.IP),hl          ;1427\r
+       ld b,h                  ;142a\r
+       ld c,l                  ;142b\r
+       ld a,b                  ;142c\r
+       or a                    ;142d\r
+       jr nz,l1442h            ;142e\r
+       ld a,c                  ;1430\r
+       ld hl,ucbar             ;1431\r
+       cp cbar                 ;1434\r
+       jr z,l143fh             ;1436\r
+       ld hl,ubbr              ;1438\r
+       cp bbr                  ;143b\r
+       jr nz,l1442h            ;143d\r
+l143fh:\r
+       ld a,(hl)               ;143f\r
+       jr l1444h               ;1440\r
+l1442h:\r
+       in a,(c)                ;1442\r
+l1444h:\r
+       push af                 ;1444\r
+       call out.hex            ;1445\r
+       call outbl4             ;1448\r
+       pop af                  ;144b\r
+       call out.bin.b          ;144c\r
+       jp CRLF                 ;144f\r
+CMD.O:\r
+       ld hl,CMD.O             ;1452\r
+       ld (CMD_RPT),hl         ;1455\r
+       ld hl,(lst.OD)          ;1458\r
+       call get_arg_def        ;145b\r
+       ld a,l                  ;145e\r
+       ld (lst.OD),a           ;145f\r
+       push af                 ;1462\r
+       call skip_to_nextarg    ;1463\r
+       ld hl,(lst.OP)          ;1466\r
+       call get_lastarg_def    ;1469\r
+       ld (lst.OP),hl          ;146c\r
+       ld b,h                  ;146f\r
+       ld c,l                  ;1470\r
+       ld a,b                  ;1471\r
+       or a                    ;1472\r
+       jr nz,l1489h            ;1473\r
+       ld a,c                  ;1475\r
+       ld hl,ucbar             ;1476\r
+       cp cbar                 ;1479\r
+       jr z,l148dh             ;147b\r
+       ld hl,ubbr              ;147d\r
+       cp bbr                  ;1480\r
+       jr z,l148dh             ;1482\r
+       cp cbr                  ;1484\r
+       jp z,ERROR              ;1486\r
+l1489h:\r
+       pop af                  ;1489\r
+       out (c),a               ;148a\r
+       ret                     ;148c\r
+l148dh:\r
+       pop af                  ;148d\r
+       ld (hl),a               ;148e\r
+       ret                     ;148f\r
+\r
+CMD.V:\r
+       call get_arg3           ;1490   get from, size, to\r
+cmp_mem:\r
+       push bc                 ;1493\r
+       comst                   ;1494\r
+       ld a,(de)               ;1498\r
+       ld b,(hl)               ;1499\r
+       comend\r
+       cp b                    ;149a\r
+       jr z,l14bah             ;149b\r
+       ld c,a                  ;149d\r
+       call out.hl.@           ;149e\r
+       call OUTBL              ;14a1\r
+       ld a,b                  ;14a4\r
+       call out.hex            ;14a5\r
+       call outbl2             ;14a8\r
+       ld a,c                  ;14ab\r
+       call out.hex            ;14ac\r
+       call OUTBL              ;14af\r
+       ex de,hl                ;14b2\r
+       call out.hl.@           ;14b3\r
+       ex de,hl                ;14b6\r
+       call CRLF               ;14b7\r
+l14bah:\r
+       pop bc                  ;14ba\r
+       inc hl                  ;14bb\r
+       inc de                  ;14bc\r
+       dec bc                  ;14bd\r
+       ld a,b                  ;14be\r
+       or c                    ;14bf\r
+       jr nz,cmp_mem           ;14c0\r
+       ret                     ;14c2\r
+\r
+CMD.M:\r
+       ld a,(de)               ;14c3\r
+       cp 'V'                  ;14c4\r
+       jr nz,bm_nv             ;14c6\r
+       inc de                  ;14c8\r
+bm_nv:\r
+       push af                 ;14c9   save 'V' flag\r
+       call get_arg3           ;14ca\r
+       push hl                 ;14cd\r
+       push de                 ;14ce\r
+       push bc                 ;14cf\r
+       call CP.HL.DE           ;14d0\r
+       jr nc,bm_mvdown         ;14d3\r
+       add hl,bc               ;14d5\r
+       ex de,hl                ;14d6\r
+       add hl,bc               ;14d7\r
+       ex de,hl                ;14d8\r
+       dec hl                  ;14d9\r
+       dec de                  ;14da\r
+       comst                   ;14db\r
+       lddr                    ;14df\r
+       comend\r
+       jr bm_done              ;14e1\r
+bm_mvdown:\r
+       comst                   ;14e3\r
+       ldir                    ;14e7\r
+       comend\r
+bm_done:\r
+       pop bc                  ;14e9\r
+       pop de                  ;14ea\r
+       pop hl                  ;14eb\r
+       pop af                  ;14ec\r
+       jr z,cmp_mem            ;14ed   validate?\r
+       ret                     ;14ef\r
+CMD.H:\r
+       call EXPR               ;14f0\r
+       jp c,l173ch             ;14f3\r
+       call skip_to_nextarg    ;14f6\r
+       push hl                 ;14f9\r
+       call EXPR               ;14fa\r
+       push af                 ;14fd\r
+       call assert_eol         ;14fe\r
+       pop af                  ;1501\r
+       ex de,hl                        ;1502\r
+       pop hl                  ;1503\r
+       jr c,l1511h             ;1504\r
+       push hl                 ;1506\r
+       push de                 ;1507\r
+       add hl,de                       ;1508\r
+       call l1511h             ;1509\r
+       pop de                  ;150c\r
+       pop hl                  ;150d\r
+       and a                   ;150e\r
+       sbc hl,de               ;150f\r
+l1511h:\r
+       call out.hl             ;1511   val\r
+       call outbl2             ;1514\r
+       call sub_0928h          ;1517   -val\r
+       call outbl4             ;151a\r
+       call out.hl.dec         ;151d   dec\r
+       call outbl2             ;1520\r
+       call out.hl.decm        ;1523   -dec\r
+       call outbl4             ;1526\r
+       call out.bin.w          ;1529   bin\r
+       call outbl2             ;152c\r
+       ld a,l                  ;152f\r
+       call out.ascii          ;1530\r
+       jp CRLF                 ;1533\r
+\r
+CMD.Q:\r
+       ld a,(de)               ;1536\r
+       sub 'J'                 ;1537\r
+       ld (lst.Qj),a           ;1539\r
+       jr nz,l153fh            ;153c\r
+       inc de                  ;153e\r
+l153fh:\r
+       call get_arg_range      ;153f\r
+       push bc                 ;1542\r
+       push hl                 ;1543\r
+       call sub_15a7h          ;1544\r
+       pop hl                  ;1547\r
+l1548h:\r
+       call sub_1594h          ;1548\r
+       jr nz,l1562h            ;154b\r
+       push bc                 ;154d\r
+       push hl                 ;154e\r
+       ld a,(lst.Qj)           ;154f\r
+       or a                    ;1552\r
+       jr nz,l1559h            ;1553\r
+       ld bc,-8                ;1555\r
+       add hl,bc               ;1558\r
+l1559h:\r
+       ld bc,MEMDUMP_CNT       ;1559\r
+       and a                   ;155c\r
+       call memdump            ;155d\r
+       pop hl                  ;1560\r
+       pop bc                  ;1561\r
+l1562h:\r
+       inc hl                  ;1562\r
+       ex (sp),hl              ;1563\r
+       dec hl                  ;1564\r
+       ld a,h                  ;1565\r
+       or l                    ;1566\r
+       ex (sp),hl              ;1567\r
+       jr nz,l1548h            ;1568\r
+       pop bc                  ;156a\r
+       ret                     ;156b\r
+\r
+CMD.Z:\r
+       call get_arg_range      ;156c\r
+       push bc                 ;156f\r
+       push hl                 ;1570\r
+       call sub_15a7h          ;1571\r
+       ld a,b                  ;1574\r
+       pop hl                  ;1575\r
+       pop bc                  ;1576\r
+       push hl                 ;1577\r
+       ex de,hl                ;1578\r
+l1579h:\r
+       push af                 ;1579\r
+       ld a,(hl)               ;157a\r
+       comst                   ;157b\r
+       ld (de),a               ;157f\r
+       comend\r
+       pop af                  ;1580\r
+       inc de                  ;1581\r
+       cpi                     ;1582\r
+       jp po,l1592h            ;1584\r
+       dec a                   ;1587\r
+       jr nz,l1579h            ;1588\r
+       pop hl                  ;158a\r
+       comst                   ;158b\r
+       ldir                    ;158f\r
+       comend\r
+       ret                     ;1591\r
+l1592h:\r
+       pop hl                  ;1592\r
+       ret                     ;1593\r
+\r
+sub_1594h:\r
+       push hl                 ;1594\r
+       push de                 ;1595\r
+       push bc                 ;1596\r
+l1597h:\r
+       ld a,(de)               ;1597\r
+       comst                   ;1598\r
+       cp (hl)                 ;159c\r
+       comend\r
+       jr nz,l15a3h            ;159d\r
+       inc de                  ;159f\r
+       inc hl                  ;15a0\r
+       djnz l1597h             ;15a1\r
+l15a3h:\r
+       pop bc                  ;15a3\r
+       pop de                  ;15a4\r
+       pop hl                  ;15a5\r
+       ret                     ;15a6\r
+\r
+sub_15a7h:\r
+       ld hl,ci.buf+1          ;15a7\r
+       call get_bytes          ;15aa\r
+       ld de,ci.buf+1          ;15ad\r
+       and a                   ;15b0\r
+       sbc hl,de               ;15b1\r
+       ld b,l                  ;15b3\r
+       ret nz                  ;15b4\r
+       jp ERROR                ;15b5\r
+\r
+get_bytes:\r
+       db      0e6h            ;15b8  and 037h (clear carry, skip next opc)\r
+get_bytes_m:\r
+       scf\r
+l15bah:\r
+       push af                 ;15ba\r
+       call skip_to_nextarg    ;15bb\r
+       cp 'W'                  ;15be\r
+       jr nz,l15d9h            ;15c0\r
+       inc de                  ;15c2\r
+       push hl                 ;15c3\r
+       call sub_0a68h          ;15c4\r
+       ex de,hl                ;15c7\r
+       pop bc                  ;15c8\r
+       pop af                  ;15c9\r
+       push af                 ;15ca\r
+       push bc                 ;15cb\r
+       ex (sp),hl              ;15cc\r
+       jr nc,l15d3h            ;15cd\r
+       comst                   ;15cf\r
+l15d3h:\r
+       ld (hl),e               ;15d3\r
+       comend\r
+       inc hl                  ;15d4\r
+       ld c,d                  ;15d5\r
+       pop de                  ;15d6\r
+       jr l15e5h               ;15d7\r
+l15d9h:\r
+       cp ''''                 ;15d9\r
+       jr z,l15f1h             ;15db\r
+       push hl                 ;15dd\r
+       call EXPR               ;15de\r
+       ld c,l                  ;15e1\r
+       pop hl                  ;15e2\r
+       jr c,l1626h             ;15e3\r
+l15e5h:\r
+       pop af                  ;15e5\r
+       push af                 ;15e6\r
+       jr nc,l15edh            ;15e7\r
+       comst                   ;15e9\r
+l15edh:\r
+       ld (hl),c               ;15ed\r
+       comend\r
+       inc hl                  ;15ee\r
+       jr l161eh               ;15ef\r
+l15f1h:\r
+       inc de                  ;15f1\r
+       ld a,(de)               ;15f2\r
+       cp ''''                 ;15f3\r
+       jr z,l1607h             ;15f5\r
+       or a                    ;15f7\r
+       jr z,l1626h             ;15f8\r
+l15fah:\r
+       ld c,a                  ;15fa\r
+       pop af                  ;15fb\r
+       push af                 ;15fc\r
+       jr nc,l1603h            ;15fd\r
+       comst                   ;15ff\r
+l1603h:\r
+       ld (hl),c               ;1603\r
+       comend\r
+       inc hl                  ;1604\r
+       jr l15f1h               ;1605\r
+l1607h:\r
+       inc de                  ;1607\r
+       ld a,(de)               ;1608\r
+       cp ''''                 ;1609\r
+       jr z,l15fah             ;160b\r
+       cp '.'                  ;160d\r
+       jr nz,l161eh            ;160f\r
+       inc de                  ;1611\r
+       dec hl                  ;1612\r
+       pop af                  ;1613\r
+       push af                 ;1614\r
+       jr nc,l161bh            ;1615\r
+       comst                   ;1617\r
+l161bh:\r
+       set 7,(hl)              ;161b\r
+       comend\r
+       inc hl                  ;161d\r
+l161eh:\r
+       pop af                  ;161e\r
+       jr nc,l15bah            ;161f\r
+       ld (lst.S),hl           ;1621\r
+       jr l15bah               ;1624\r
+\r
+l1626h:\r
+       pop af                  ;1626\r
+       ret nc                  ;1627\r
+       ld (lst.S),hl           ;1628\r
+       ret                     ;162b\r
+\r
+CMD.D:\r
+       ld hl,CMD.D             ;162c\r
+       ld (CMD_RPT),hl         ;162f\r
+       ld hl,(lst.D)           ;1632\r
+       ld bc,00080h            ;1635\r
+       call sub_0a82h          ;1638\r
+       scf                     ;163b\r
+memdump:\r
+       push bc                 ;163c\r
+       push de                 ;163d\r
+       push hl                 ;163e\r
+       ex af,af'               ;163f\r
+l1640h:\r
+       call out.hl.@           ;1640\r
+       call z,outbl2           ;1643\r
+       call OUTBL              ;1646\r
+       ld de,0                 ;1649\r
+l164ch:\r
+       comst                   ;164c\r
+       ld a,(hl)               ;1650\r
+       comend\r
+       inc hl                  ;1651\r
+       call out.hex            ;1652\r
+       call OUTBL              ;1655\r
+       dec bc                  ;1658\r
+       inc e                   ;1659\r
+       ld a,e                  ;165a\r
+       cp 010h                 ;165b\r
+       jr z,l1668h             ;165d\r
+       and 003h                ;165f\r
+       call z,OUTBL            ;1661\r
+       ld a,b                  ;1664\r
+       or c                    ;1665\r
+       jr nz,l164ch            ;1666\r
+l1668h:\r
+       call OUTBL              ;1668\r
+       and a                   ;166b\r
+       sbc hl,de               ;166c\r
+l166eh:\r
+       comst                   ;166e\r
+       ld a,(hl)               ;1672\r
+       comend\r
+       call sub_168fh          ;1673\r
+       call OUTCHAR            ;1676\r
+       inc hl                  ;1679\r
+       dec e                   ;167a\r
+       jr nz,l166eh            ;167b\r
+       ex af,af'               ;167d\r
+       jr nc,l1683h            ;167e\r
+       ld (lst.D),hl           ;1680\r
+l1683h:\r
+       ex af,af'               ;1683\r
+       call CRLF               ;1684\r
+       ld a,b                  ;1687\r
+       or c                    ;1688\r
+       jr nz,l1640h            ;1689\r
+       pop hl                  ;168b\r
+       pop de                  ;168c\r
+       pop bc                  ;168d\r
+       ret                     ;168e\r
+sub_168fh:\r
+       and 07fh                ;168f\r
+       cp 07fh                 ;1691\r
+       jr z,l1698h             ;1693\r
+       cp 020h                 ;1695\r
+       ret nc                  ;1697\r
+l1698h:\r
+       ld a,02eh               ;1698\r
+       ret                     ;169a\r
+\r
+;      Read Intel Hex File from console.\r
+\r
+CMD.R:\r
+       ld hl,0                 ;169b\r
+       call get_lastarg_def    ;169e\r
+       push hl                 ;16a1\r
+       ld hl,0                 ;16a2\r
+       ld (HILOD),hl           ;16a5\r
+w_recstart:\r
+       call i.getchar          ;16a8\r
+       jr z,l16deh             ;16ab\r
+       cp ':'                  ;16ad\r
+       jr nz,w_recstart        ;16af\r
+       ld c,0                  ;16b1   init checksum\r
+       call i.gethexbyte       ;16b3   record len\r
+       ld b,a                  ;16b6\r
+       call i.gethexbyte       ;16b7   address high\r
+       ld h,a                  ;16ba\r
+       call i.gethexbyte       ;16bb   address low\r
+       ld l,a                  ;16be\r
+       call i.gethexbyte       ;16bf   record type (ignored)\r
+       ld a,b                  ;16c2\r
+       and a                   ;16c3   record len == 0?\r
+       jr z,l16deh             ;16c4\r
+l16c6h:\r
+       call i.gethexbyte       ;16c6\r
+       pop de                  ;16c9\r
+       push de                 ;16ca\r
+       push hl                 ;16cb\r
+       add hl,de               ;16cc\r
+       call i.storebyte        ;16cd\r
+       pop hl                  ;16d0\r
+       inc hl                  ;16d1\r
+       djnz l16c6h             ;16d2\r
+       call i.gethexbyte       ;16d4\r
+       ld a,c                  ;16d7\r
+       and a                   ;16d8\r
+       jp nz,ERROR             ;16d9   exit if checksum error\r
+       jr w_recstart           ;16dc   next record\r
+l16deh:\r
+       pop hl                  ;16de\r
+       call i.gethexbyte       ;16df\r
+       jp l173fh               ;16e2\r
+\r
+i.gethexbyte:\r
+       call sub_16f6h          ;16e5\r
+       rlca                    ;16e8\r
+       rlca                    ;16e9\r
+       rlca                    ;16ea\r
+       rlca                    ;16eb\r
+       ld d,a                  ;16ec\r
+       call sub_16f6h          ;16ed\r
+       add a,d                 ;16f0\r
+       ld d,a                  ;16f1\r
+       add a,c                 ;16f2\r
+       ld c,a                  ;16f3\r
+       ld a,d                  ;16f4\r
+       ret                     ;16f5\r
+\r
+sub_16f6h:\r
+       call i.getchar          ;16f6\r
+       jr z,l16ffh             ;16f9\r
+       call sub_0d26h          ;16fb\r
+       ret nc                  ;16fe\r
+l16ffh:\r
+       jp ERROR                ;16ff\r
+\r
+i.getchar:\r
+       call $ci                ;1702\r
+       cp 01ah                 ;1705\r
+       ret                     ;1707\r
+\r
+i.storebyte:\r
+       push af                 ;1708\r
+       push de                 ;1709\r
+       ld de,TPA               ;170a\r
+       call CP.HL.DE           ;170d\r
+       jp c,ERROR              ;1710\r
+       ld de,$stcka            ;1713\r
+       call CP.HL.DE           ;1716\r
+       jp nc,ERROR             ;1719\r
+       ld de,(HILOD)           ;171c\r
+       call CP.HL.DE           ;1720\r
+       jr c,l1728h             ;1723\r
+       ld (HILOD),hl           ;1725\r
+l1728h:\r
+       ld de,(MAXLOD)          ;1728\r
+       call CP.HL.DE           ;172c\r
+       jr c,l1734h             ;172f\r
+       ld (MAXLOD),hl          ;1731\r
+l1734h:\r
+       pop de                  ;1734\r
+       pop af                  ;1735\r
+       comst                   ;1736\r
+       ld (hl),a               ;173a\r
+       comend\r
+       ret                     ;173b\r
+\r
+l173ch:\r
+       call assert_eol         ;173c\r
+l173fh:\r
+       ld hl,MSG_high          ;173f\r
+       call PSTR               ;1742\r
+       ld hl,(HILOD)           ;1745\r
+       call out.hl             ;1748\r
+       ld hl,MSG_max           ;174b\r
+       call PSTR               ;174e\r
+       ld hl,(MAXLOD)          ;1751\r
+       call out.hl             ;1754\r
+       jp CRLF         ;1757\r
+\r
+MSG_high:\r
+       DC      'High = '\r
+MSG_max:\r
+       DC      '  Max = '\r
+\r
+CMD.A:\r
+       ld hl,(lst.A)           ;1769\r
+       call get_lastarg_def    ;176c\r
+       push hl                 ;176f\r
+       pop iy                  ;1770\r
+       ld hl,l17c4h            ;1772\r
+       ld (CMD_ERR),hl         ;1775\r
+       ld (XB068),sp           ;1778\r
+l177ch:\r
+       push iy                 ;177c\r
+       pop hl                  ;177e\r
+       ld (lst.A),hl           ;177f\r
+       ld (OFFS.pc),hl         ;1782\r
+       push hl                 ;1785\r
+       call sub_1f3fh          ;1786\r
+       pop iy                  ;1789\r
+       ld c,b                  ;178b\r
+       ld de,(offs.@)          ;178c\r
+       ld a,d                  ;1790\r
+       or e                    ;1791\r
+       ld b,011h               ;1792\r
+       jr z,l1798h             ;1794\r
+       ld b,019h               ;1796\r
+l1798h:\r
+       call OUTBL              ;1798\r
+       ld a,(CON.COL)          ;179b\r
+       cp b                    ;179e\r
+       jr c,l1798h             ;179f\r
+       push bc                 ;17a1\r
+       call INLINE             ;17a2\r
+       pop bc                  ;17a5\r
+       call SKIPBL             ;17a6\r
+       cp '.'                  ;17a9\r
+       ret z                   ;17ab\r
+       cp '-'                  ;17ac\r
+       jr nz,l17b6h            ;17ae\r
+       ld iy,(XB06C)           ;17b0\r
+       jr l177ch               ;17b4\r
+l17b6h:\r
+       and a                   ;17b6\r
+       call nz,sub_17cdh       ;17b7\r
+       ld (XB06C),iy           ;17ba\r
+       ld b,0                  ;17be\r
+       add iy,bc               ;17c0\r
+       jr l177ch               ;17c2\r
+l17c4h:\r
+       call l07eah             ;17c4\r
+       ld sp,(XB068)           ;17c7\r
+       jr l177ch               ;17cb\r
+\r
+sub_17cdh:\r
+       call SKIPBL             ;17cd\r
+       ld hl,t_MNEMONICS       ;17d0\r
+       call sub_0a15h          ;17d3\r
+       jp nc,ERROR             ;17d6\r
+       call SKIPBL             ;17d9\r
+       push de                 ;17dc\r
+       ld a,b                  ;17dd\r
+       add a,b                 ;17de\r
+       add a,b                 ;17df\r
+       ld hl,b_0x17EE_start            ;17e0\r
+       call ADD_HL_A           ;17e3\r
+       ld e,(hl)                       ;17e6\r
+       inc hl                  ;17e7\r
+       ld d,(hl)                       ;17e8\r
+       inc hl                  ;17e9\r
+       ld b,(hl)                       ;17ea\r
+       ex de,hl                        ;17eb\r
+       pop de                  ;17ec\r
+       jp (hl)                 ;17ed\r
+\r
+b_0x17EE_start:\r
+       defw l1b54h             ;17ee\r
+\r
+b_0x17F0_start:\r
+       defb 088h               ;17f0\r
+\r
+b_0x17F1_start:\r
+       defw l1b74h             ;17f1\r
+\r
+b_0x17F3_start:\r
+       defb 080h               ;17f3\r
+\r
+b_0x17F4_start:\r
+       defw l1babh             ;17f4\r
+\r
+b_0x17F6_start:\r
+       defb 0a0h               ;17f6\r
+\r
+b_0x17F7_start:\r
+       defw l1c14h             ;17f7\r
+\r
+b_0x17F9_start:\r
+       defb 040h               ;17f9\r
+\r
+b_0x17FA_start:\r
+       defw l1c38h             ;17fa\r
+\r
+b_0x17FC_start:\r
+       defb 0c4h               ;17fc\r
+\r
+b_0x17FD_start:\r
+       defw l1b36h             ;17fd\r
+\r
+b_0x17FF_start:\r
+       defb 03fh               ;17ff\r
+\r
+b_0x1800_start:\r
+       defw l1babh             ;1800\r
+\r
+b_0x1802_start:\r
+       defb 0b8h               ;1802\r
+\r
+b_0x1803_start:\r
+       defw gen.opc.ED2        ;1803\r
+\r
+b_0x1805_start:\r
+       defb 0a9h               ;1805\r
+\r
+b_0x1806_start:\r
+       defw gen.opc.ED2        ;1806\r
+\r
+b_0x1808_start:\r
+       defb 0b9h               ;1808\r
+\r
+b_0x1809_start:\r
+       defw gen.opc.ED2        ;1809\r
+\r
+b_0x180B_start:\r
+       defb 0a1h               ;180b\r
+\r
+b_0x180C_start:\r
+       defw gen.opc.ED2        ;180c\r
+\r
+b_0x180E_start:\r
+       defb 0b1h               ;180e\r
+\r
+b_0x180F_start:\r
+       defw l1b36h             ;180f\r
+\r
+b_0x1811_start:\r
+       defb 02fh               ;1811\r
+\r
+b_0x1812_start:\r
+       defw l1b36h             ;1812\r
+\r
+b_0x1814_start:\r
+       defb 027h               ;1814\r
+\r
+b_0x1815_start:\r
+       defw l1dabh             ;1815\r
+\r
+b_0x1817_start:\r
+       defb 005h               ;1817\r
+\r
+b_0x1818_start:\r
+       defw l1b36h             ;1818\r
+\r
+b_0x181A_start:\r
+       defb 0f3h               ;181a\r
+\r
+b_0x181B_start:\r
+       defw l1ca4h             ;181b\r
+\r
+b_0x181D_start:\r
+       defb 010h               ;181d\r
+\r
+b_0x181E_start:\r
+       defw l1b36h             ;181e\r
+\r
+b_0x1820_start:\r
+       defb 0fbh               ;1820\r
+\r
+b_0x1821_start:\r
+       defw l1d54h             ;1821\r
+\r
+b_0x1823_start:\r
+       defb 0e3h               ;1823\r
+\r
+b_0x1824_start:\r
+       defw l1b36h             ;1824\r
+\r
+b_0x1826_start:\r
+       defb 0d9h               ;1826\r
+\r
+b_0x1827_start:\r
+       defw l1b36h             ;1827\r
+\r
+b_0x1829_start:\r
+       defb 076h               ;1829\r
+\r
+b_0x182A_start:\r
+       defw l1cbfh             ;182a\r
+\r
+b_0x182C_start:\r
+       defb 046h               ;182c\r
+\r
+b_0x182D_start:\r
+       defw l1cf8h             ;182d\r
+\r
+b_0x182F_start:\r
+       defb 040h               ;182f\r
+\r
+b_0x1830_start:\r
+       defw l1dabh             ;1830\r
+\r
+b_0x1832_start:\r
+       defb 004h               ;1832\r
+\r
+b_0x1833_start:\r
+       defw gen.opc.ED2        ;1833\r
+\r
+b_0x1835_start:\r
+       defb 0aah               ;1835\r
+\r
+b_0x1836_start:\r
+       defw gen.opc.ED2        ;1836\r
+\r
+b_0x1838_start:\r
+       defb 0bah               ;1838\r
+\r
+b_0x1839_start:\r
+       defw gen.opc.ED2        ;1839\r
+\r
+b_0x183B_start:\r
+       defb 0a2h               ;183b\r
+\r
+b_0x183C_start:\r
+       defw gen.opc.ED2        ;183c\r
+\r
+b_0x183E_start:\r
+       defb 0b2h               ;183e\r
+\r
+b_0x183F_start:\r
+       defw l1c5eh             ;183f\r
+\r
+b_0x1841_start:\r
+       defb 0c2h               ;1841\r
+\r
+b_0x1842_start:\r
+       defw l1cabh             ;1842\r
+\r
+b_0x1844_start:\r
+       defb 020h               ;1844\r
+\r
+b_0x1845_start:\r
+       defw l1934h             ;1845\r
+\r
+b_0x1847_start:\r
+       defb 040h               ;1847\r
+\r
+b_0x1848_start:\r
+       defw gen.opc.ED2        ;1848\r
+\r
+b_0x184A_start:\r
+       defb 0a8h               ;184a\r
+\r
+b_0x184B_start:\r
+       defw gen.opc.ED2        ;184b\r
+\r
+b_0x184D_start:\r
+       defb 0b8h               ;184d\r
+\r
+b_0x184E_start:\r
+       defw gen.opc.ED2        ;184e\r
+\r
+b_0x1850_start:\r
+       defb 0a0h               ;1850\r
+\r
+b_0x1851_start:\r
+       defw gen.opc.ED2        ;1851\r
+\r
+b_0x1853_start:\r
+       defb 0b0h               ;1853\r
+\r
+b_0x1854_start:\r
+       defw gen.opc.ED2        ;1854\r
+\r
+b_0x1856_start:\r
+       defb 044h               ;1856\r
+\r
+b_0x1857_start:\r
+       defw l1b36h             ;1857\r
+\r
+b_0x1859_start:\r
+       defb 000h               ;1859\r
+\r
+b_0x185A_start:\r
+       defw l1babh             ;185a\r
+\r
+b_0x185C_start:\r
+       defb 0b0h               ;185c\r
+\r
+b_0x185D_start:\r
+       defw gen.opc.ED2        ;185d\r
+\r
+b_0x185F_start:\r
+       defb 0bbh               ;185f\r
+\r
+b_0x1860_start:\r
+       defw gen.opc.ED2        ;1860\r
+\r
+b_0x1862_start:\r
+       defb 0b3h               ;1862\r
+\r
+b_0x1863_start:\r
+       defw l1d2ch             ;1863\r
+\r
+b_0x1865_start:\r
+       defb 041h               ;1865\r
+\r
+b_0x1866_start:\r
+       defw gen.opc.ED2        ;1866\r
+\r
+b_0x1868_start:\r
+       defb 0abh               ;1868\r
+\r
+b_0x1869_start:\r
+       defw gen.opc.ED2        ;1869\r
+\r
+b_0x186B_start:\r
+       defb 0a3h               ;186b\r
+\r
+b_0x186C_start:\r
+       defw l1ce4h             ;186c\r
+\r
+b_0x186E_start:\r
+       defb 0c1h               ;186e\r
+\r
+b_0x186F_start:\r
+       defw l1ce4h             ;186f\r
+\r
+b_0x1871_start:\r
+       defb 0c5h               ;1871\r
+\r
+b_0x1872_start:\r
+       defw l1c14h             ;1872\r
+\r
+b_0x1874_start:\r
+       defb 080h               ;1874\r
+\r
+b_0x1875_start:\r
+       defw l1c50h             ;1875\r
+\r
+b_0x1877_start:\r
+       defb 0c0h               ;1877\r
+\r
+b_0x1878_start:\r
+       defw gen.opc.ED2        ;1878\r
+\r
+b_0x187A_start:\r
+       defb 04dh               ;187a\r
+\r
+b_0x187B_start:\r
+       defw gen.opc.ED2        ;187b\r
+\r
+b_0x187D_start:\r
+       defb 045h               ;187d\r
+\r
+b_0x187E_start:\r
+       defw l1bd8h             ;187e\r
+\r
+b_0x1880_start:\r
+       defb 010h               ;1880\r
+\r
+b_0x1881_start:\r
+       defw l1b36h             ;1881\r
+\r
+b_0x1883_start:\r
+       defb 017h               ;1883\r
+\r
+b_0x1884_start:\r
+       defw l1bd8h             ;1884\r
+\r
+b_0x1886_start:\r
+       defb 000h               ;1886\r
+\r
+b_0x1887_start:\r
+       defw l1b36h             ;1887\r
+\r
+b_0x1889_start:\r
+       defb 007h               ;1889\r
+\r
+b_0x188A_start:\r
+       defw gen.opc.ED2        ;188a\r
+\r
+b_0x188C_start:\r
+       defb 06fh               ;188c\r
+\r
+b_0x188D_start:\r
+       defw l1bd8h             ;188d\r
+\r
+b_0x188F_start:\r
+       defb 018h               ;188f\r
+\r
+b_0x1890_start:\r
+       defw l1b36h             ;1890\r
+\r
+b_0x1892_start:\r
+       defb 01fh               ;1892\r
+\r
+b_0x1893_start:\r
+       defw l1bd8h             ;1893\r
+\r
+b_0x1895_start:\r
+       defb 008h               ;1895\r
+\r
+b_0x1896_start:\r
+       defw l1b36h             ;1896\r
+\r
+b_0x1898_start:\r
+       defb 00fh               ;1898\r
+\r
+b_0x1899_start:\r
+       defw gen.opc.ED2        ;1899\r
+\r
+b_0x189B_start:\r
+       defb 067h               ;189b\r
+\r
+b_0x189C_start:\r
+       defw l1cd5h             ;189c\r
+\r
+b_0x189E_start:\r
+       defb 0c7h               ;189e\r
+\r
+b_0x189F_start:\r
+       defw l1b54h             ;189f\r
+\r
+b_0x18A1_start:\r
+       defb 098h               ;18a1\r
+\r
+b_0x18A2_start:\r
+       defw l1b36h             ;18a2\r
+\r
+b_0x18A4_start:\r
+       defb 037h               ;18a4\r
+\r
+b_0x18A5_start:\r
+       defw l1c14h             ;18a5\r
+\r
+b_0x18A7_start:\r
+       defb 0c0h               ;18a7\r
+\r
+b_0x18A8_start:\r
+       defw l1bd8h             ;18a8\r
+\r
+b_0x18AA_start:\r
+       defb 020h               ;18aa\r
+\r
+b_0x18AB_start:\r
+       defw l1bd8h             ;18ab\r
+\r
+b_0x18AD_start:\r
+       defb 028h               ;18ad\r
+\r
+b_0x18AE_start:\r
+       defw l1bd8h             ;18ae\r
+\r
+b_0x18B0_start:\r
+       defb 038h               ;18b0\r
+\r
+b_0x18B1_start:\r
+       defw l1babh             ;18b1\r
+\r
+b_0x18B3_start:\r
+       defb 090h               ;18b3\r
+\r
+b_0x18B4_start:\r
+       defw l1babh             ;18b4\r
+\r
+b_0x18B6_start:\r
+       defb 0a8h               ;18b6\r
+\r
+b_0x18B7_start:\r
+       defw A.IN0              ;18b7\r
+\r
+b_0x18B9_start:\r
+       defb 000h               ;18b9\r
+\r
+b_0x18BA_start:\r
+       defw A.MLT              ;18ba\r
+\r
+b_0x18BC_start:\r
+       defb 04ch               ;18bc\r
+       ld b,e                  ;18bd\r
+       dec de                  ;18be\r
+\r
+b_0x18BF_start:\r
+       defb 08bh               ;18bf\r
+\r
+b_0x18C0_start:\r
+       defw gen.opc.ED2        ;18c0\r
+\r
+b_0x18C2_start:\r
+       defb 09bh               ;18c2\r
+\r
+b_0x18C3_start:\r
+       defw gen.opc.ED2        ;18c3\r
+\r
+b_0x18C5_start:\r
+       defb 083h               ;18c5\r
+\r
+b_0x18C6_start:\r
+       defw gen.opc.ED2        ;18c6\r
+\r
+b_0x18C8_start:\r
+       defb 093h               ;18c8\r
+\r
+b_0x18C9_start:\r
+       defw l18fdh             ;18c9\r
+\r
+b_0x18CB_start:\r
+       defb 001h               ;18cb\r
+\r
+b_0x18CC_start:\r
+       defw gen.opc.ED2        ;18cc\r
+\r
+b_0x18CE_start:\r
+       defb 076h               ;18ce\r
+\r
+b_0x18CF_start:\r
+       defw l191dh             ;18cf\r
+\r
+b_0x18D1_start:\r
+       defb 004h               ;18d1\r
+\r
+b_0x18D2_start:\r
+       defw l192ch             ;18d2\r
+\r
+b_0x18D4_start:\r
+       defb 074h               ;18d4\r
+A.IN0:\r
+       call sub_1e41h          ;18d5\r
+       jr nc,l1931h            ;18d8\r
+       cp 006h         ;18da\r
+       jr z,l1931h             ;18dc\r
+       rlca                    ;18de\r
+       rlca                    ;18df\r
+       rlca                    ;18e0\r
+       add a,b                 ;18e1\r
+       ld b,a                  ;18e2\r
+       call sub_1ed1h          ;18e3\r
+       call sub_1e06h          ;18e6\r
+l18e9h:\r
+       call assert_eol         ;18e9\r
+       comst                   ;18ec\r
+       ld (iy+000h),0edh       ;18f0\r
+       ld (iy+001h),b          ;18f4\r
+       ld (iy+002h),l          ;18f7\r
+       comend\r
+       ld c,003h               ;18fa\r
+       ret                     ;18fc\r
+l18fdh:\r
+       call sub_1e06h          ;18fd\r
+       call sub_1ed1h          ;1900\r
+       call sub_1e41h          ;1903\r
+       jr nc,l1931h            ;1906\r
+       cp 006h                 ;1908\r
+       jr z,l1931h             ;190a\r
+       rlca                    ;190c\r
+       rlca                    ;190d\r
+       rlca                    ;190e\r
+       add a,b                 ;190f\r
+       ld b,a                  ;1910\r
+       jr l18e9h               ;1911\r
+A.MLT:\r
+       call sub_1e2eh          ;1913\r
+       jr nc,l1931h            ;1916\r
+       add a,b                 ;1918\r
+       ld b,a                  ;1919\r
+       jp gen.opc.ED2          ;191a\r
+l191dh:\r
+       call sub_1e41h          ;191d\r
+       jr nc,l192ah            ;1920\r
+       rlca                    ;1922\r
+       rlca                    ;1923\r
+       rlca                    ;1924\r
+       add a,b                 ;1925\r
+       ld b,a                  ;1926\r
+       jp gen.opc.ED2          ;1927\r
+l192ah:\r
+       ld b,064h               ;192a\r
+l192ch:\r
+       call sub_1e12h          ;192c\r
+       jr l18e9h               ;192f\r
+l1931h:\r
+       jp ERROR                ;1931\r
+l1934h:\r
+       call sub_1e41h          ;1934\r
+       jp c,l19bfh             ;1937\r
+       call sub_1e68h          ;193a\r
+       jp c,l1a64h             ;193d\r
+       call sub_1e2eh          ;1940\r
+       jp c,l1a93h             ;1943\r
+       call sub_1e50h          ;1946\r
+       jp c,l1af0h             ;1949\r
+       ld a,(de)               ;194c\r
+       cp 049h                 ;194d\r
+       jp z,l1b0ch             ;194f\r
+       cp 052h                 ;1952\r
+       jp z,l1b14h             ;1954\r
+       cp 028h                 ;1957\r
+       jp nz,ERROR             ;1959\r
+       inc de                  ;195c\r
+       call sub_1e2eh          ;195d\r
+       jp c,l1b23h             ;1960\r
+       call tst_EXPR           ;1963\r
+       call sub_1ed8h          ;1966\r
+       call sub_1ed1h          ;1969\r
+       call sub_1e2eh          ;196c\r
+       jr c,l19adh             ;196f\r
+       call sub_1e50h          ;1971\r
+       jr nc,l1991h            ;1974\r
+       ld b,022h               ;1976\r
+l1978h:\r
+       call assert_eol         ;1978\r
+       ld a,(pfx.IXY)          ;197b\r
+l197eh:\r
+       comst                   ;197e\r
+       ld (iy+000h),a          ;1982\r
+       ld (iy+001h),b          ;1985\r
+       ld (iy+002h),l          ;1988\r
+       ld (iy+003h),h          ;198b\r
+       comend\r
+       ld c,004h               ;198e\r
+       ret                     ;1990\r
+l1991h:\r
+       ld a,(de)                       ;1991\r
+       cp 041h         ;1992\r
+       jp nz,ERROR             ;1994\r
+       inc de                  ;1997\r
+       ld b,032h               ;1998\r
+l199ah:\r
+       call assert_eol         ;199a\r
+       comst                   ;199d\r
+       ld (iy+000h),b          ;19a1\r
+       ld (iy+001h),l          ;19a4\r
+       ld (iy+002h),h          ;19a7\r
+       comend\r
+       ld c,003h               ;19aa\r
+       ret                     ;19ac\r
+l19adh:\r
+       cp 020h         ;19ad\r
+       jr z,l19bbh             ;19af\r
+       add a,043h              ;19b1\r
+       ld b,a                  ;19b3\r
+l19b4h:\r
+       call assert_eol         ;19b4\r
+       ld a,0edh               ;19b7\r
+       jr l197eh               ;19b9\r
+l19bbh:\r
+       ld b,022h               ;19bb\r
+       jr l199ah               ;19bd\r
+l19bfh:\r
+       ld b,a                  ;19bf\r
+       call sub_1ed1h          ;19c0\r
+       call sub_1e41h          ;19c3\r
+       jr nc,l19dbh            ;19c6\r
+       push af                 ;19c8\r
+       ld a,b                  ;19c9\r
+       rlca                    ;19ca\r
+       rlca                    ;19cb\r
+       rlca                    ;19cc\r
+       ld b,a                  ;19cd\r
+       pop af                  ;19ce\r
+       add a,b                 ;19cf\r
+       add a,040h              ;19d0\r
+       cp 076h         ;19d2\r
+       jp z,ERROR              ;19d4\r
+l19d7h:\r
+       ld b,a                  ;19d7\r
+       jp l1b36h               ;19d8\r
+l19dbh:\r
+       call sub_1e68h          ;19db\r
+       jr nc,l1a02h            ;19de\r
+       ld a,b                  ;19e0\r
+       rlca                    ;19e1\r
+       rlca                    ;19e2\r
+       rlca                    ;19e3\r
+       add a,046h              ;19e4\r
+       cp 076h         ;19e6\r
+       jp z,ERROR              ;19e8\r
+l19ebh:\r
+       ld b,a                  ;19eb\r
+       call assert_eol         ;19ec\r
+       ld a,(pfx.IXY)          ;19ef\r
+       comst                   ;19f2\r
+       ld (iy+000h),a          ;19f6\r
+       ld (iy+001h),b          ;19f9\r
+       ld (iy+002h),c          ;19fc\r
+       comend\r
+       ld c,003h               ;19ff\r
+       ret                     ;1a01\r
+l1a02h:\r
+       ld a,(de)               ;1a02\r
+       cp 'I'                  ;1a03\r
+       jr z,l1a15h             ;1a05\r
+       cp 'R'                  ;1a07\r
+       jr nz,l1a21h            ;1a09\r
+       ld a,b                  ;1a0b\r
+       cp 007h                 ;1a0c\r
+       jp nz,ERROR             ;1a0e\r
+       ld b,05fh               ;1a11\r
+       jr l1a1dh               ;1a13\r
+l1a15h:\r
+       ld a,b                  ;1a15\r
+       cp 007h                 ;1a16\r
+       jp nz,ERROR             ;1a18\r
+       ld b,057h               ;1a1b\r
+l1a1dh:\r
+       inc de                  ;1a1d\r
+       jp gen.opc.ED2          ;1a1e\r
+l1a21h:\r
+       cp '('                  ;1a21\r
+       jr z,l1a3fh             ;1a23\r
+       call sub_1e12h          ;1a25\r
+       ld a,b                  ;1a28   ld r,nn\r
+       rlca                    ;1a29\r
+       rlca                    ;1a2a\r
+       rlca                    ;1a2b\r
+       add a,006h              ;1a2c\r
+l1a2eh:\r
+       ld b,a                  ;1a2e\r
+l1a2fh:\r
+       call assert_eol         ;1a2f\r
+       comst                   ;1a32\r
+       ld (iy+000h),b          ;1a36\r
+       ld (iy+001h),l          ;1a39\r
+       comend\r
+       ld c,002h               ;1a3c\r
+       ret                     ;1a3e\r
+l1a3fh:\r
+       inc de                  ;1a3f\r
+       ld a,b                  ;1a40\r
+       cp 007h         ;1a41\r
+       jp nz,ERROR             ;1a43\r
+       call sub_1e2eh          ;1a46\r
+       jr nc,l1a59h            ;1a49\r
+       cp 030h         ;1a4b\r
+       jp nc,ERROR             ;1a4d\r
+       add a,00ah              ;1a50\r
+       ld b,a                  ;1a52\r
+       call sub_1ed8h          ;1a53\r
+       jp l1b36h               ;1a56\r
+l1a59h:\r
+       call tst_EXPR           ;1a59\r
+       call sub_1ed8h          ;1a5c\r
+       ld b,03ah               ;1a5f\r
+       jp l199ah               ;1a61\r
+l1a64h:\r
+       call sub_1ed1h          ;1a64\r
+       call sub_1e41h          ;1a67\r
+       jr nc,l1a76h            ;1a6a\r
+       cp 006h                 ;1a6c\r
+       jp z,ERROR              ;1a6e\r
+       add a,070h              ;1a71\r
+       jp l19ebh               ;1a73\r
+l1a76h:\r
+       call sub_1e12h          ;1a76\r
+       call assert_eol         ;1a79\r
+       ld a,(pfx.IXY)          ;1a7c\r
+       comst                   ;1a7f\r
+       ld (iy+000h),a          ;1a83   dd/fd\r
+       ld (iy+001h),036h       ;1a86\r
+       ld (iy+002h),c          ;1a8a   displacement\r
+       ld (iy+003h),l          ;1a8d   nn\r
+       comend\r
+       ld c,4                  ;1a90\r
+       ret                     ;1a92\r
+l1a93h:\r
+       ld b,a                  ;1a93\r
+       call sub_1ed1h          ;1a94\r
+       ld hl,t_HL.AF           ;1a97\r
+       call sub_0a23h          ;1a9a\r
+       jr c,l1abeh             ;1a9d\r
+       call sub_1e50h          ;1a9f\r
+       jr nc,l1ac7h            ;1aa2\r
+       ld a,b                  ;1aa4\r
+       cp 030h         ;1aa5\r
+       jr nz,l1b20h            ;1aa7\r
+       ld b,0f9h               ;1aa9\r
+l1aabh:\r
+       call assert_eol         ;1aab\r
+       ld a,(pfx.IXY)          ;1aae\r
+       comst                   ;1ab1\r
+       ld (iy+000h),a          ;1ab5\r
+       ld (iy+001h),b          ;1ab8\r
+       comend\r
+       ld c,002h               ;1abb\r
+       ret                     ;1abd\r
+l1abeh:\r
+       ld a,b                  ;1abe\r
+       cp 030h                 ;1abf\r
+       jr nz,l1b20h            ;1ac1\r
+       ld b,0f9h               ;1ac3\r
+       jr l1b36h               ;1ac5\r
+l1ac7h:\r
+       ld a,(de)               ;1ac7\r
+       cp 028h                 ;1ac8\r
+       jr nz,l1ae3h            ;1aca\r
+       inc de                  ;1acc\r
+       call tst_EXPR           ;1acd\r
+       call sub_1ed8h          ;1ad0\r
+       ld a,b                  ;1ad3\r
+       cp 020h                 ;1ad4\r
+       jr z,l1adeh             ;1ad6\r
+       add a,04bh              ;1ad8\r
+       ld b,a                  ;1ada\r
+       jp l19b4h               ;1adb\r
+l1adeh:\r
+       ld b,02ah               ;1ade\r
+       jp l199ah               ;1ae0\r
+l1ae3h:\r
+       call tst_EXPR           ;1ae3\r
+       call assert_eol         ;1ae6\r
+       ld a,001h               ;1ae9\r
+       add a,b                 ;1aeb\r
+       ld b,a                  ;1aec\r
+       jp l199ah               ;1aed\r
+l1af0h:\r
+       call sub_1ed1h          ;1af0\r
+       ld a,(de)               ;1af3\r
+       cp 028h                 ;1af4\r
+       jr nz,l1b04h            ;1af6\r
+       inc de                  ;1af8\r
+       call tst_EXPR           ;1af9\r
+       call sub_1ed8h          ;1afc\r
+       ld b,02ah               ;1aff\r
+       jp l1978h               ;1b01\r
+l1b04h:\r
+       call tst_EXPR           ;1b04\r
+       ld b,021h               ;1b07\r
+       jp l1978h               ;1b09\r
+l1b0ch:\r
+       inc de                  ;1b0c\r
+       call sub_1ed1h          ;1b0d\r
+       ld b,047h               ;1b10\r
+       jr l1b1ah               ;1b12\r
+l1b14h:\r
+       inc de                  ;1b14\r
+       call sub_1ed1h          ;1b15\r
+       ld b,04fh               ;1b18\r
+l1b1ah:\r
+       ld a,(de)                       ;1b1a\r
+       inc de                  ;1b1b\r
+       cp 041h         ;1b1c\r
+       jr z,gen.opc.ED2        ;1b1e\r
+l1b20h:\r
+       jp ERROR                ;1b20\r
+l1b23h:\r
+       cp 020h         ;1b23\r
+       jr nc,l1b20h            ;1b25\r
+       add a,002h              ;1b27\r
+       ld b,a                  ;1b29\r
+       call sub_1ed8h          ;1b2a\r
+       call sub_1ed1h          ;1b2d\r
+       ld a,(de)                       ;1b30\r
+       cp 041h         ;1b31\r
+       jr nz,l1b20h            ;1b33\r
+       inc de                  ;1b35\r
+l1b36h:\r
+       call assert_eol         ;1b36\r
+       comst                   ;1b39\r
+       ld (iy+000h),b          ;1b3d\r
+       comend\r
+       ld c,001h               ;1b40\r
+       ret                     ;1b42\r
+gen.opc.ED2:\r
+       call assert_eol         ;1b43\r
+       comst                   ;1b46\r
+       ld (iy+000h),0edh               ;1b4a\r
+       ld (iy+001h),b          ;1b4e\r
+       comend\r
+       ld c,002h               ;1b51\r
+       ret                     ;1b53\r
+l1b54h:\r
+       ld hl,t_HL.AF           ;1b54\r
+       call sub_0a23h          ;1b57\r
+       jr nc,l1babh            ;1b5a\r
+       call sub_1ed1h          ;1b5c\r
+       call sub_1e2eh          ;1b5f\r
+       jp nc,ERROR             ;1b62\r
+       push af                 ;1b65\r
+       ld a,b                  ;1b66\r
+       cp 088h         ;1b67\r
+       ld b,04ah               ;1b69\r
+       jr z,l1b6fh             ;1b6b\r
+       ld b,042h               ;1b6d\r
+l1b6fh:\r
+       pop af                  ;1b6f\r
+       add a,b                 ;1b70\r
+l1b71h:\r
+       ld b,a                  ;1b71\r
+       jr gen.opc.ED2          ;1b72\r
+l1b74h:\r
+       ld hl,t_HL.AF           ;1b74\r
+       call sub_0a23h          ;1b77\r
+       jr c,l1b9dh             ;1b7a\r
+       call sub_1e50h          ;1b7c\r
+       jr nc,l1babh            ;1b7f\r
+       call sub_1ed1h          ;1b81\r
+       ld hl,t_BC.DE.IX.SP     ;1b84\r
+       ld a,(pfx.IXY)          ;1b87\r
+       cp 0fdh                 ;1b8a\r
+       jr nz,l1b91h            ;1b8c\r
+       ld hl,t_BC.DE.IY.SP     ;1b8e\r
+l1b91h:\r
+       call sub_1e2bh          ;1b91\r
+       jp nc,ERROR             ;1b94\r
+       add a,009h              ;1b97\r
+l1b99h:\r
+       ld b,a                  ;1b99\r
+       jp l1aabh               ;1b9a\r
+l1b9dh:\r
+       call sub_1ed1h          ;1b9d\r
+       call sub_1e2eh          ;1ba0\r
+       jp nc,ERROR             ;1ba3\r
+       add a,009h              ;1ba6\r
+       jp l19d7h               ;1ba8\r
+l1babh:\r
+       ld a,(de)               ;1bab\r
+       cp 041h                 ;1bac\r
+       jr nz,l1bbbh            ;1bae\r
+       push de                 ;1bb0\r
+       inc de                  ;1bb1\r
+       call skip_to_nextarg    ;1bb2\r
+       jr z,l1bbah             ;1bb5\r
+       pop de                  ;1bb7\r
+       jr l1bbbh               ;1bb8\r
+l1bbah:\r
+       pop af                  ;1bba\r
+l1bbbh:\r
+       call sub_1e41h          ;1bbb\r
+       jr c,l1bceh             ;1bbe\r
+       call sub_1e68h          ;1bc0\r
+       jr c,l1bd2h             ;1bc3\r
+       call sub_1e12h          ;1bc5\r
+       ld a,b                  ;1bc8\r
+       add a,046h              ;1bc9\r
+       jp l1a2eh               ;1bcb\r
+l1bceh:\r
+       add a,b                 ;1bce\r
+       jp l19d7h               ;1bcf\r
+l1bd2h:\r
+       ld a,b                  ;1bd2\r
+       add a,006h              ;1bd3\r
+       jp l19ebh               ;1bd5\r
+l1bd8h:\r
+       call sub_1e41h          ;1bd8\r
+       jr c,l1c01h             ;1bdb\r
+       call sub_1e68h          ;1bdd\r
+       jp nc,ERROR             ;1be0\r
+       ld a,b                  ;1be3\r
+       add a,006h              ;1be4\r
+       ld b,a                  ;1be6\r
+l1be7h:\r
+       call assert_eol         ;1be7\r
+       ld a,(pfx.IXY)          ;1bea\r
+       comst                   ;1bed\r
+       ld (iy+000h),a          ;1bf1\r
+       ld (iy+001h),0cbh               ;1bf4\r
+       ld (iy+002h),c          ;1bf8\r
+       ld (iy+003h),b          ;1bfb\r
+       comend\r
+       ld c,004h               ;1bfe\r
+       ret                     ;1c00\r
+l1c01h:\r
+       add a,b                 ;1c01\r
+l1c02h:\r
+       ld b,a                  ;1c02\r
+       call assert_eol         ;1c03\r
+       comst                   ;1c06\r
+       ld (iy+000h),0cbh               ;1c0a\r
+       ld (iy+001h),b          ;1c0e\r
+       comend\r
+       ld c,002h               ;1c11\r
+       ret                     ;1c13\r
+l1c14h:\r
+       call sub_1de6h          ;1c14\r
+       call sub_1ed1h          ;1c17\r
+       call sub_1e41h          ;1c1a\r
+       jr c,l1c2fh             ;1c1d\r
+       call sub_1e68h          ;1c1f\r
+       jp nc,ERROR             ;1c22\r
+       ld a,l                  ;1c25\r
+       rlca                    ;1c26\r
+       rlca                    ;1c27\r
+       rlca                    ;1c28\r
+       add a,006h              ;1c29\r
+       add a,b                 ;1c2b\r
+       ld b,a                  ;1c2c\r
+       jr l1be7h               ;1c2d\r
+l1c2fh:\r
+       add a,b                 ;1c2f\r
+       ld b,a                  ;1c30\r
+       ld a,l                  ;1c31\r
+       rlca                    ;1c32\r
+       rlca                    ;1c33\r
+       rlca                    ;1c34\r
+       add a,b                 ;1c35\r
+       jr l1c02h               ;1c36\r
+l1c38h:\r
+       push de                 ;1c38\r
+       call sub_1eb8h          ;1c39\r
+       jr nc,l1c47h            ;1c3c\r
+       add a,b                 ;1c3e\r
+       ld b,a                  ;1c3f\r
+       call skip_to_nextarg    ;1c40\r
+       jr z,l1c49h             ;1c43\r
+       pop de                  ;1c45\r
+       push de                 ;1c46\r
+l1c47h:\r
+       ld b,0cdh               ;1c47\r
+l1c49h:\r
+       pop af                  ;1c49\r
+       call tst_EXPR           ;1c4a\r
+       jp l199ah               ;1c4d\r
+l1c50h:\r
+       call sub_1eb8h          ;1c50\r
+       jr nc,l1c59h            ;1c53\r
+       add a,b                 ;1c55\r
+       ld b,a                  ;1c56\r
+       jr l1c5bh               ;1c57\r
+l1c59h:\r
+       ld b,0c9h               ;1c59\r
+l1c5bh:\r
+       jp l1b36h               ;1c5b\r
+l1c5eh:\r
+       push de                 ;1c5e\r
+       call sub_1eb8h          ;1c5f\r
+       jr c,l1c71h             ;1c62\r
+l1c64h:\r
+       pop de                  ;1c64\r
+       ld hl,b_0x1C97_start    ;1c65\r
+       call sub_0a15h          ;1c68\r
+       jr c,l1c7fh             ;1c6b\r
+       ld b,0c3h               ;1c6d\r
+       jr l1c79h               ;1c6f\r
+l1c71h:\r
+       add a,b                 ;1c71\r
+       ld b,a                  ;1c72\r
+       call skip_to_nextarg    ;1c73\r
+       jr nz,l1c64h            ;1c76\r
+       pop af                  ;1c78\r
+l1c79h:\r
+       call tst_EXPR           ;1c79\r
+       jp l199ah               ;1c7c\r
+l1c7fh:\r
+       call assert_eol         ;1c7f\r
+       ld a,b                  ;1c82\r
+       and a                   ;1c83\r
+       jr nz,l1c8bh            ;1c84\r
+       ld b,0e9h               ;1c86\r
+       jp l1b36h               ;1c88\r
+l1c8bh:\r
+       ld b,0ddh               ;1c8b\r
+       dec a                   ;1c8d\r
+       jr z,l1c92h             ;1c8e\r
+       ld b,0fdh               ;1c90\r
+l1c92h:\r
+       ld l,0e9h               ;1c92\r
+       jp l1a2fh               ;1c94\r
+\r
+b_0x1C97_start:\r
+       DC      '(HL)'\r
+       DC      '(IX)'\r
+       DC      '(IY)'\r
+       DB      0\r
+\r
+l1ca4h:\r
+       call skip_to_nextarg    ;1ca4\r
+       ld b,010h               ;1ca7\r
+       jr l1cb9h               ;1ca9\r
+l1cabh:\r
+       call sub_1ebfh          ;1cab\r
+       jr c,l1cb4h             ;1cae\r
+       ld b,018h               ;1cb0\r
+       jr l1cb9h               ;1cb2\r
+l1cb4h:\r
+       add a,b                 ;1cb4\r
+       ld b,a                  ;1cb5\r
+       call sub_1ed1h          ;1cb6\r
+l1cb9h:\r
+       call sub_1defh          ;1cb9\r
+       jp l1a2fh               ;1cbc\r
+l1cbfh:\r
+       call sub_1e12h          ;1cbf\r
+       ld a,l                  ;1cc2\r
+       cp 003h                 ;1cc3\r
+       jr nc,l1d23h            ;1cc5\r
+       and a                   ;1cc7\r
+       jr z,l1cd2h             ;1cc8\r
+       ld b,056h               ;1cca\r
+       cp 001h                 ;1ccc\r
+       jr z,l1cd2h             ;1cce\r
+       ld b,05eh               ;1cd0\r
+l1cd2h:\r
+       jp gen.opc.ED2          ;1cd2\r
+l1cd5h:\r
+       call sub_1e12h          ;1cd5\r
+       ld a,l                  ;1cd8\r
+       push af                 ;1cd9\r
+       add a,b                 ;1cda\r
+       ld b,a                  ;1cdb\r
+       pop af                  ;1cdc\r
+       and 0c7h                ;1cdd\r
+       jr nz,l1d23h            ;1cdf\r
+       jp l1b36h               ;1ce1\r
+l1ce4h:\r
+       call sub_1e50h          ;1ce4\r
+       jr c,l1cf2h             ;1ce7\r
+       call sub_1e25h          ;1ce9\r
+       jr nc,l1d23h            ;1cec\r
+       add a,b                 ;1cee\r
+       jp l19d7h               ;1cef\r
+l1cf2h:\r
+       ld a,b                  ;1cf2\r
+       add a,020h              ;1cf3\r
+       jp l1b99h               ;1cf5\r
+l1cf8h:\r
+       call sub_1e41h          ;1cf8\r
+       jr nc,l1d23h            ;1cfb\r
+       cp 006h         ;1cfd\r
+       jr z,l1d23h             ;1cff\r
+       rlca                    ;1d01\r
+       rlca                    ;1d02\r
+       rlca                    ;1d03\r
+       add a,b                 ;1d04\r
+       ld b,a                  ;1d05\r
+       cp 078h         ;1d06\r
+       jr nz,l1d1ah            ;1d08\r
+       call sub_1ed1h          ;1d0a\r
+       call sub_1d26h          ;1d0d\r
+       jr c,l1d20h             ;1d10\r
+       call sub_1e06h          ;1d12\r
+       ld b,0dbh               ;1d15\r
+       jp l1a2fh               ;1d17\r
+l1d1ah:\r
+       call sub_1ed1h          ;1d1a\r
+       call sub_1d26h          ;1d1d\r
+l1d20h:\r
+       jp c,gen.opc.ED2        ;1d20\r
+l1d23h:\r
+       jp ERROR                ;1d23\r
+sub_1d26h:\r
+       ld hl,t__C_             ;1d26\r
+       jp sub_0a23h            ;1d29\r
+l1d2ch:\r
+       call sub_1d26h          ;1d2c\r
+       jr nc,l1d44h            ;1d2f\r
+       call sub_1ed1h          ;1d31\r
+       call sub_1e41h          ;1d34\r
+       jr nc,l1d23h            ;1d37\r
+       cp 006h         ;1d39\r
+       jr z,l1d23h             ;1d3b\r
+       rlca                    ;1d3d\r
+       rlca                    ;1d3e\r
+       rlca                    ;1d3f\r
+       add a,b                 ;1d40\r
+       jp l1b71h               ;1d41\r
+l1d44h:\r
+       call sub_1e06h          ;1d44\r
+       call sub_1ed1h          ;1d47\r
+       cp 041h         ;1d4a\r
+       jr nz,l1d23h            ;1d4c\r
+       inc de                  ;1d4e\r
+       ld b,0d3h               ;1d4f\r
+       jp l1a2fh               ;1d51\r
+l1d54h:\r
+       ld hl,b_0x1D80_start    ;1d54\r
+       call sub_0a15h          ;1d57\r
+       jp nc,ERROR             ;1d5a\r
+       ld c,b                  ;1d5d\r
+       call assert_eol         ;1d5e\r
+       ld b,000h               ;1d61\r
+       ld hl,b_0x1DA1_start    ;1d63\r
+       add hl,bc               ;1d66\r
+       add hl,bc               ;1d67\r
+       ld a,(hl)               ;1d68\r
+       comst                   ;1d69\r
+       ld (iy+000h),a          ;1d6d\r
+       comend\r
+       ld c,001h               ;1d70\r
+       inc hl                  ;1d72\r
+       ld a,(hl)               ;1d73\r
+       and a                   ;1d74\r
+       ret z                   ;1d75\r
+       comst                   ;1d76\r
+       ld (iy+001h),a          ;1d7a\r
+       comend\r
+       ld c,002h               ;1d7d\r
+       ret                     ;1d7f\r
+\r
+b_0x1D80_start:\r
+       DC      'AF,AF'''\r
+l1d86h:\r
+       DC      'DE,HL'\r
+       DC      '(SP),HL'\r
+       DC      '(SP),IX'\r
+       DC      '(SP),IY'\r
+       db      000h            ;1da0\r
+\r
+b_0x1DA1_start:\r
+       db      008h            ;1da1\r
+       db      000h            ;1da2\r
+       db      0ebh            ;1da3\r
+       db      000h            ;1da4\r
+       db      0e3h            ;1da5\r
+       db      000h            ;1da6\r
+       db      0ddh            ;1da7\r
+       db      0e3h            ;1da8\r
+       db      0fdh            ;1da9\r
+       db      0e3h            ;1daa\r
+l1dabh:\r
+       call sub_1e50h          ;1dab\r
+       jr c,l1dc6h             ;1dae\r
+       call sub_1e2eh          ;1db0\r
+       jr c,l1dd2h             ;1db3\r
+       call sub_1e41h          ;1db5\r
+       jr c,l1ddfh             ;1db8\r
+       call sub_1e68h          ;1dba\r
+       jp nc,ERROR             ;1dbd\r
+       ld a,b                  ;1dc0\r
+       add a,030h              ;1dc1\r
+       jp l19ebh               ;1dc3\r
+l1dc6h:\r
+       ld a,b                  ;1dc6\r
+       ld b,023h               ;1dc7\r
+       cp 004h                 ;1dc9\r
+       jr z,l1dcfh             ;1dcb\r
+       ld b,02bh               ;1dcd\r
+l1dcfh:\r
+       jp l1aabh               ;1dcf\r
+l1dd2h:\r
+       push af                 ;1dd2\r
+       ld a,b                  ;1dd3\r
+       ld b,003h               ;1dd4\r
+       cp 004h                 ;1dd6\r
+       jr z,l1ddch             ;1dd8\r
+       ld b,00bh               ;1dda\r
+l1ddch:\r
+       pop af                  ;1ddc\r
+       jr l1de2h               ;1ddd\r
+l1ddfh:\r
+       rlca                    ;1ddf\r
+       rlca                    ;1de0\r
+       rlca                    ;1de1\r
+l1de2h:\r
+       add a,b                 ;1de2\r
+       jp l19d7h               ;1de3\r
+sub_1de6h:\r
+       call sub_1e12h          ;1de6\r
+       ld a,l                  ;1de9\r
+       cp 008h                 ;1dea\r
+       jr nc,error1            ;1dec\r
+       ret                     ;1dee\r
+sub_1defh:\r
+       call tst_EXPR           ;1def\r
+       push bc                 ;1df2\r
+       push iy                 ;1df3\r
+       pop bc                  ;1df5\r
+       and a                   ;1df6\r
+       sbc hl,bc               ;1df7\r
+       dec hl                  ;1df9\r
+       dec hl                  ;1dfa\r
+       pop bc                  ;1dfb\r
+       call sub_1e15h          ;1dfc\r
+       ld a,h                  ;1dff\r
+       xor l                   ;1e00\r
+       bit 7,a         ;1e01\r
+       jr nz,error1            ;1e03\r
+       ret                     ;1e05\r
+sub_1e06h:\r
+       ld a,(de)                       ;1e06\r
+       cp 028h         ;1e07\r
+       jr nz,sub_1e12h         ;1e09\r
+       inc de                  ;1e0b\r
+       call sub_1e12h          ;1e0c\r
+       jp sub_1ed8h            ;1e0f\r
+\r
+sub_1e12h:\r
+       call tst_EXPR           ;1e12\r
+sub_1e15h:\r
+       ld a,h                  ;1e15\r
+       and a                   ;1e16\r
+       ret z                   ;1e17\r
+       inc a                   ;1e18\r
+       ret z                   ;1e19\r
+       jr error1               ;1e1a\r
+\r
+tst_EXPR:\r
+       push bc                 ;1e1c\r
+       call EXPR               ;1e1d\r
+       pop bc                  ;1e20\r
+       ret nc                  ;1e21\r
+error1:\r
+       jp ERROR                ;1e22\r
+sub_1e25h:\r
+       push hl                 ;1e25\r
+       ld hl,t_BC.DE.HL.AF     ;1e26\r
+       jr l1e32h               ;1e29\r
+sub_1e2bh:\r
+       push hl                 ;1e2b\r
+       jr l1e32h               ;1e2c\r
+sub_1e2eh:\r
+       push hl                 ;1e2e\r
+       ld hl,t_BC.DE.HL.SP     ;1e2f\r
+l1e32h:\r
+       push bc                 ;1e32\r
+       call sub_0a15h          ;1e33\r
+       jr nc,l1e3eh            ;1e36\r
+       ld a,b                  ;1e38\r
+       rlca                    ;1e39\r
+       rlca                    ;1e3a\r
+       rlca                    ;1e3b\r
+       rlca                    ;1e3c\r
+       scf                     ;1e3d\r
+l1e3eh:\r
+       pop bc                  ;1e3e\r
+       pop hl                  ;1e3f\r
+       ret                     ;1e40\r
+sub_1e41h:\r
+       call SKIPBL             ;1e41\r
+       push bc                 ;1e44\r
+       push hl                 ;1e45\r
+       ld hl,t_BCDEHL_HL_A     ;1e46\r
+       call sub_0a15h          ;1e49\r
+       ld a,b                  ;1e4c\r
+       pop hl                  ;1e4d\r
+       pop bc                  ;1e4e\r
+       ret                     ;1e4f\r
+sub_1e50h:\r
+       push hl                 ;1e50\r
+       push bc                 ;1e51\r
+       ld hl,t_IX.IY           ;1e52\r
+       call sub_0a15h          ;1e55\r
+       jr nc,l1e65h            ;1e58\r
+       ld a,0ddh               ;1e5a\r
+       dec b                   ;1e5c\r
+       jr nz,l1e61h            ;1e5d\r
+       ld a,0fdh               ;1e5f\r
+l1e61h:\r
+       ld (pfx.IXY),a          ;1e61\r
+       scf                     ;1e64\r
+l1e65h:\r
+       pop bc                  ;1e65\r
+       pop hl                  ;1e66\r
+       ret                     ;1e67\r
+sub_1e68h:\r
+       push hl                 ;1e68\r
+       push bc                 ;1e69\r
+       ld a,(de)               ;1e6a\r
+       cp '('                  ;1e6b\r
+       jr nz,l1eb4h            ;1e6d\r
+       push de                 ;1e6f\r
+       inc de                  ;1e70\r
+       ld hl,t_IX.IY           ;1e71\r
+       call sub_0a15h          ;1e74\r
+       jr nc,l1eb3h            ;1e77\r
+       pop af                  ;1e79\r
+       ld a,0ddh               ;1e7a\r
+       dec b                   ;1e7c\r
+       jr nz,l1e81h            ;1e7d\r
+       ld a,0fdh               ;1e7f\r
+l1e81h:\r
+       ld (pfx.IXY),a          ;1e81\r
+       ld a,(de)               ;1e84\r
+       cp '+'                  ;1e85\r
+       jr z,l1e95h             ;1e87\r
+       cp ')'                  ;1e89\r
+       ld hl,0                 ;1e8b\r
+       jr z,l1eadh             ;1e8e\r
+       cp '-'                  ;1e90\r
+       jp nz,ERROR             ;1e92\r
+l1e95h:\r
+       push af                 ;1e95\r
+       inc de                  ;1e96\r
+       call sub_1e12h          ;1e97   get displacement\r
+       pop af                  ;1e9a\r
+       cp '+'                  ;1e9b\r
+       jr z,l1ea7h             ;1e9d\r
+       ld b,h                  ;1e9f\r
+       ld c,l                  ;1ea0\r
+       ld hl,0                 ;1ea1\r
+       and a                   ;1ea4\r
+       sbc hl,bc               ;1ea5\r
+l1ea7h:\r
+       ld a,(de)               ;1ea7\r
+       cp ')'                  ;1ea8\r
+       jp nz,ERROR             ;1eaa\r
+l1eadh:\r
+       inc de                  ;1ead\r
+       pop bc                  ;1eae\r
+       ld c,l                  ;1eaf\r
+       pop hl                  ;1eb0\r
+       scf                     ;1eb1\r
+       ret                     ;1eb2\r
+l1eb3h:\r
+       pop de                  ;1eb3\r
+l1eb4h:\r
+       pop bc                  ;1eb4\r
+       pop hl                  ;1eb5\r
+       and a                   ;1eb6\r
+       ret                     ;1eb7\r
+sub_1eb8h:\r
+       ld hl,t_tstfl_ZCPS      ;1eb8\r
+       ld c,007h               ;1ebb\r
+       jr l1ec4h               ;1ebd\r
+sub_1ebfh:\r
+       ld hl,t_tstfl_ZC        ;1ebf\r
+       ld c,003h               ;1ec2\r
+l1ec4h:\r
+       push bc                 ;1ec4\r
+       call sub_0a15h          ;1ec5\r
+       ld a,b                  ;1ec8\r
+       pop bc                  ;1ec9\r
+       ret nc                  ;1eca\r
+       and c                   ;1ecb\r
+       rlca                    ;1ecc\r
+       rlca                    ;1ecd\r
+       rlca                    ;1ece\r
+       scf                     ;1ecf\r
+       ret                     ;1ed0\r
+sub_1ed1h:\r
+       call skip_to_nextarg    ;1ed1\r
+       ret z                   ;1ed4\r
+l1ed5h:\r
+       jp ERROR                ;1ed5\r
+sub_1ed8h:\r
+       ld a,(de)                       ;1ed8\r
+       cp 029h         ;1ed9\r
+       jr nz,l1ed5h            ;1edb\r
+       inc de                  ;1edd\r
+       ret                     ;1ede\r
+CMD.L:\r
+       ld hl,CMD.L             ;1edf\r
+       ld (CMD_RPT),hl         ;1ee2\r
+       call EXPR               ;1ee5\r
+       jr nc,l1eedh            ;1ee8\r
+       ld hl,(lst.L)           ;1eea\r
+l1eedh:\r
+       push hl                 ;1eed\r
+       pop iy                  ;1eee\r
+       call skip_to_nextarg    ;1ef0\r
+       call sub_0aa5h          ;1ef3\r
+       jr nc,l1f17h            ;1ef6\r
+       call assert_eol         ;1ef8\r
+       ld b,010h               ;1efb\r
+l1efdh:\r
+       push bc                 ;1efd\r
+       push iy         ;1efe\r
+       pop hl                  ;1f00\r
+       push hl                 ;1f01\r
+       call sub_1f3fh          ;1f02\r
+       call CRLF               ;1f05\r
+       pop iy          ;1f08\r
+       ld c,b                  ;1f0a\r
+       ld b,000h               ;1f0b\r
+       add iy,bc               ;1f0d\r
+       ld (lst.L),iy           ;1f0f\r
+       pop bc                  ;1f13\r
+       djnz l1efdh             ;1f14\r
+       ret                     ;1f16\r
+l1f17h:\r
+       call assert_eol         ;1f17\r
+       ld h,b                  ;1f1a\r
+       ld l,c                  ;1f1b\r
+       ld a,b                  ;1f1c\r
+       or c                    ;1f1d\r
+       jr nz,l1f21h            ;1f1e\r
+       dec hl                  ;1f20\r
+l1f21h:\r
+       push hl                 ;1f21\r
+       push iy         ;1f22\r
+       pop hl                  ;1f24\r
+       push hl                 ;1f25\r
+       call sub_1f3fh          ;1f26\r
+       call CRLF               ;1f29\r
+       pop iy          ;1f2c\r
+       ld e,b                  ;1f2e\r
+       ld d,000h               ;1f2f\r
+       add iy,de               ;1f31\r
+       ld (lst.L),iy           ;1f33\r
+       pop hl                  ;1f37\r
+       and a                   ;1f38\r
+       sbc hl,de               ;1f39\r
+       ret z                   ;1f3b\r
+       ret c                   ;1f3c\r
+       jr l1f21h               ;1f3d\r
+sub_1f3fh:\r
+       call out.hl.@           ;1f3f\r
+       call z,OUTBL            ;1f42\r
+       call OUTBL              ;1f45\r
+       sub a                   ;1f48\r
+       ld (CON.COL),a          ;1f49\r
+       call sub_1f77h          ;1f4c\r
+       and a                   ;1f4f\r
+       ret z                   ;1f50\r
+l1f51h:\r
+       call OUTBL              ;1f51\r
+       ld a,(CON.COL)          ;1f54\r
+       cp 010h         ;1f57\r
+       jr c,l1f51h             ;1f59\r
+sub_1f5bh:\r
+       ld de,(offs.@)          ;1f5b\r
+       ld a,d                  ;1f5f\r
+       or e                    ;1f60\r
+       ret z                   ;1f61\r
+       ld a,'('                ;1f62\r
+       call OUTCHAR            ;1f64\r
+       ld a,'@'                ;1f67\r
+       call OUTCHAR            ;1f69\r
+       and a                   ;1f6c\r
+       sbc hl,de               ;1f6d\r
+       call out.hl             ;1f6f\r
+       ld a,')'                ;1f72\r
+       jp OUTCHAR              ;1f74\r
+sub_1f77h:\r
+       sub a                   ;1f77\r
+       ld (XBE03),a            ;1f78\r
+       call sub_1f9eh          ;1f7b\r
+       jr nc,l1f91h            ;1f7e\r
+       push bc                 ;1f80\r
+       call sub_2581h          ;1f81\r
+       ex de,hl                        ;1f84\r
+       call sub_1fdbh          ;1f85\r
+       pop bc                  ;1f88\r
+       ld a,(XBE03)            ;1f89\r
+       ld hl,(XBE01)           ;1f8c\r
+       scf                     ;1f8f\r
+       ret                     ;1f90\r
+l1f91h:\r
+       ld hl,b_0x1F9B_start            ;1f91\r
+       call PSTR               ;1f94\r
+       ld b,001h               ;1f97\r
+       sub a                   ;1f99\r
+       ret                     ;1f9a\r
+\r
+b_0x1F9B_start:\r
+       DC      '???'\r
+       \r
+sub_1f9eh:\r
+       sub a                   ;1f9e\r
+       ld (is.pfx.IXY),a       ;1f9f\r
+       comst                   ;1fa2\r
+       ld a,(iy+000h)          ;1fa6\r
+       comend\r
+       cp 0edh                 ;1fa9\r
+       jp z,disas_pfx.ED               ;1fab\r
+       cp 0ddh                 ;1fae\r
+       jr z,l1fc5h             ;1fb0\r
+       cp 0fdh                 ;1fb2\r
+       jr z,l1fc9h             ;1fb4\r
+sub_1fb6h:\r
+       comst                   ;1fb6\r
+       ld a,(iy+000h)          ;1fba\r
+       comend\r
+       cp 0cbh                 ;1fbd\r
+       jp z,l2061h             ;1fbf\r
+       jp l2078h               ;1fc2\r
+l1fc5h:\r
+       ld a,001h               ;1fc5\r
+       jr l1fcbh               ;1fc7\r
+l1fc9h:\r
+       ld a,002h               ;1fc9\r
+l1fcbh:\r
+       ld (is.pfx.IXY),a               ;1fcb\r
+       call sub_1fdch          ;1fce\r
+       ret nc                  ;1fd1\r
+       push bc                 ;1fd2\r
+       call sub_1fb6h          ;1fd3\r
+       pop af                  ;1fd6\r
+       add a,b                 ;1fd7\r
+       ld b,a                  ;1fd8\r
+       scf                     ;1fd9\r
+       ret                     ;1fda\r
+\r
+sub_1fdbh:\r
+       jp (hl)                 ;1fdb\r
+\r
+sub_1fdch:\r
+       inc iy                  ;1fdc\r
+       ld hl,b_0x2011_start    ;1fde\r
+       call sub_20bbh          ;1fe1\r
+       ld b,002h               ;1fe4\r
+       ret c                   ;1fe6\r
+       ld hl,l202ch            ;1fe7\r
+       call sub_20bbh          ;1fea\r
+       ld b,001h               ;1fed\r
+       ret c                   ;1fef\r
+       comst                   ;1ff0\r
+       ld a,(iy+000h)          ;1ff4\r
+       comend\r
+       cp 0cbh                 ;1ff7\r
+       jr nz,l200fh            ;1ff9\r
+       comst                   ;1ffb\r
+       ld a,(iy+002h)          ;1fff\r
+       comend\r
+       cp 036h                 ;2002\r
+       ret z                   ;2004\r
+       and 007h                ;2005\r
+       cp 006h                 ;2007\r
+       jr nz,l200fh            ;2009\r
+       ld b,002h               ;200b\r
+       scf                     ;200d\r
+       ret                     ;200e\r
+l200fh:\r
+       and a                   ;200f\r
+       ret                     ;2010\r
+\r
+b_0x2011_start:\r
+       db      034h            ;2011\r
+       db      035h            ;2012\r
+       db      036h            ;2013\r
+       db      046h            ;2014\r
+       db      04eh            ;2015\r
+       db      056h            ;2016\r
+       db      05eh            ;2017\r
+       db      066h            ;2018\r
+       db      06eh            ;2019\r
+       db      070h            ;201a\r
+       db      071h            ;201b\r
+       db      072h            ;201c\r
+       db      073h            ;201d\r
+       db      074h            ;201e\r
+       db      075h            ;201f\r
+       db      076h            ;2020\r
+       db      077h            ;2021\r
+       db      07eh            ;2022\r
+       db      086h            ;2023\r
+       db      08eh            ;2024\r
+       db      096h            ;2025\r
+       db      09eh            ;2026\r
+       db      0a6h            ;2027\r
+       db      0aeh            ;2028\r
+       db      0b6h            ;2029\r
+       db      0beh            ;202a\r
+       db      000h            ;202b\r
+l202ch:\r
+       db      009h            ;202c\r
+       db      019h            ;202d\r
+       db      021h            ;202e\r
+       db      022h            ;202f\r
+       db      023h            ;2030\r
+       db      029h            ;2031\r
+       db      02ah            ;2032\r
+       db      02bh            ;2033\r
+       db      039h            ;2034\r
+       db      0e1h            ;2035\r
+       db      0e3h            ;2036\r
+       db      0e5h            ;2037\r
+       db      0e9h            ;2038\r
+       db      0f9h            ;2039\r
+       db      000h            ;203a\r
+\r
+disas_pfx.ED:\r
+       inc iy                  ;203b\r
+       ld hl,b_0x2200_start    ;203d\r
+       call sub_209dh          ;2040\r
+       ld b,002h               ;2043\r
+       ret c                   ;2045\r
+       ld hl,l2235h            ;2046\r
+       call lookup_opc         ;2049\r
+       ld b,002h               ;204c\r
+       ret c                   ;204e\r
+       ld hl,l228bh            ;204f\r
+       call lookup_opc         ;2052\r
+       ld b,003h               ;2055\r
+       ret c                   ;2057\r
+       ld hl,l22b4h            ;2058\r
+       call lookup_opc         ;205b\r
+       ld b,004h               ;205e\r
+       ret                     ;2060\r
+l2061h:\r
+       push iy                 ;2061\r
+       inc iy                  ;2063\r
+       ld a,(is.pfx.IXY)       ;2065\r
+       and a                   ;2068\r
+       jr z,l206dh             ;2069\r
+       inc iy                  ;206b\r
+l206dh:\r
+       ld hl,l22c9h            ;206d\r
+       call lookup_opc         ;2070\r
+       pop iy                  ;2073\r
+       ld b,002h               ;2075\r
+       ret                     ;2077\r
+l2078h:\r
+       ld hl,b_0x218B_start    ;2078\r
+       call lookup_opc         ;207b\r
+       ld b,002h               ;207e\r
+       ret c                   ;2080\r
+       ld hl,b_0x20ED_start    ;2081\r
+       call sub_209dh          ;2084\r
+       ld b,001h               ;2087\r
+       ret c                   ;2089\r
+       ld hl,b_0x2108_start    ;208a\r
+       call lookup_opc         ;208d\r
+       ld b,001h               ;2090\r
+       ret c                   ;2092\r
+       ld hl,b_0x21D2_start    ;2093\r
+       call lookup_opc         ;2096\r
+       ret nc                  ;2099\r
+       ld b,003h               ;209a\r
+       ret                     ;209c\r
+\r
+sub_209dh:\r
+       ld a,(hl)               ;209d\r
+       cp 0ffh                 ;209e\r
+       ret z                   ;20a0\r
+       comst                   ;20a1\r
+       cp (iy+000h)            ;20a5\r
+       comend\r
+       jr z,l20aeh             ;20a8\r
+       inc hl                  ;20aa\r
+       inc hl                  ;20ab\r
+       jr sub_209dh            ;20ac\r
+l20aeh:\r
+       inc hl                  ;20ae\r
+       ld c,(hl)               ;20af\r
+       ld hl,t_MNEMONICS       ;20b0\r
+       ld b,000h               ;20b3\r
+       add hl,bc               ;20b5\r
+       ld de,l230bh            ;20b6\r
+       scf                     ;20b9\r
+       ret                     ;20ba\r
+sub_20bbh:\r
+       ld a,(hl)               ;20bb\r
+       and a                   ;20bc\r
+       ret z                   ;20bd\r
+       inc hl                  ;20be\r
+       comst                   ;20bf\r
+       cp (iy+000h)            ;20c3\r
+       comend\r
+       jr nz,sub_20bbh         ;20c6\r
+       scf                     ;20c8\r
+       ret                     ;20c9\r
+\r
+lookup_opc:\r
+       comst                   ;20ca\r
+       ld a,(iy+000h)          ;20ce\r
+       comend\r
+       and (hl)                        ;20d1\r
+       inc hl                  ;20d2\r
+       cp (hl)                 ;20d3\r
+       jr z,l20dfh             ;20d4\r
+       inc hl                  ;20d6\r
+       inc hl                  ;20d7\r
+       inc hl                  ;20d8\r
+       inc hl                  ;20d9\r
+       ld a,(hl)               ;20da\r
+       and a                   ;20db\r
+       jr nz,lookup_opc        ;20dc\r
+       ret                     ;20de\r
+l20dfh:\r
+       inc hl                  ;20df\r
+       ld c,(hl)               ;20e0\r
+       inc hl                  ;20e1\r
+       ld e,(hl)               ;20e2\r
+       inc hl                  ;20e3\r
+       ld d,(hl)               ;20e4\r
+       ld hl,t_MNEMONICS       ;20e5\r
+       ld b,000h               ;20e8\r
+       add hl,bc               ;20ea\r
+       scf                     ;20eb\r
+       ret                     ;20ec\r
+\r
+b_0x20ED_start:                        ;       1 byte opcodes (no parameters)\r
+       db      076h            ;20ed   halt\r
+       db      039h            ;20ee   \r
+       db      0d9h            ;20ef   exx\r
+       db      036h            ;20f0\r
+       db      0f3h            ;20f1   di\r
+       db      02ch            ;20f2\r
+       db      0fbh            ;20f3   ei\r
+       db      032h            ;20f4\r
+       db      000h            ;20f5   nop\r
+       db      069h            ;20f6\r
+       db      007h            ;20f7   rlca\r
+       db      09eh            ;20f8\r
+       db      00fh            ;20f9   rrca\r
+       db      0adh            ;20fa\r
+       db      017h            ;20fb   rla\r
+       db      098h            ;20fc\r
+       db      01fh            ;20fd   rra\r
+       db      0a7h            ;20fe\r
+       db      027h            ;20ff   daa\r
+       db      026h            ;2100\r
+       db      02fh            ;2101   cpl\r
+       db      023h            ;2102\r
+       db      037h            ;2103   scf\r
+       db      0bah            ;2104\r
+       db      03fh            ;2105   ccf\r
+       db      010h            ;2106\r
+       db      0ffh            ;2107   EOT\r
+\r
+b_0x2108_start:                        ;       1 byte opcodes\r
+       defb 0c0h               ;2108   ld r,r\r
+       defb 040h               ;2109\r
+       defb 056h               ;210a\r
+       defw l22fch             ;210b\r
+\r
+       defb 0f8h               ;210d   add a,r\r
+       defb 080h               ;210e\r
+       defb 003h               ;210f\r
+       defw l2305h             ;2110\r
+\r
+       defb 0f8h               ;2112   adc a,r\r
+       defb 088h               ;2113\r
+       defb 000h               ;2114\r
+       defw l2305h             ;2115\r
+\r
+       defb 0f8h               ;2117\r
+       defb 090h               ;2118\r
+       defb 0c9h               ;2119\r
+       defw l24ebh             ;211a\r
+\r
+       defb 0f8h               ;211c\r
+       defb 098h               ;211d\r
+       defb 0b7h               ;211e\r
+       defw l2305h             ;211f\r
+\r
+       defb 0f8h               ;2121\r
+       defb 0a0h               ;2122\r
+       defb 006h               ;2123\r
+       defw l24ebh             ;2124\r
+\r
+       defb 0f8h               ;2126\r
+       defb 0a8h               ;2127\r
+       defb 0cch               ;2128\r
+       defw l24ebh             ;2129\r
+\r
+       defb 0f8h               ;212b\r
+       defb 0b0h               ;212c\r
+       defb 06ch               ;212d\r
+       defw l24ebh             ;212e\r
+\r
+       defb 0f8h               ;2130\r
+       defb 0b8h               ;2131\r
+       defb 013h               ;2132\r
+       defw l24ebh             ;2133\r
+\r
+       defb 0c7h               ;2135\r
+       defb 0c0h               ;2136   ret cc\r
+       defb 08bh               ;2137\r
+       defw l2561h             ;2138\r
+\r
+       defb 0c7h               ;213a   rst \r
+       defb 0c7h               ;213b\r
+       defb 0b4h               ;213c\r
+       defw l231eh             ;213d\r
+\r
+       defb 0ffh               ;213f   ret\r
+       defb 0c9h               ;2140\r
+       defb 08bh               ;2141\r
+       defw l230bh             ;2142\r
+\r
+       defb 0cfh               ;2144   pop rr\r
+       defb 0c1h               ;2145\r
+       defb 081h               ;2146\r
+       defw l2546h             ;2147\r
+\r
+       defb 0cfh               ;2149   push rr\r
+       defb 0c5h               ;214a\r
+       defb 084h               ;214b\r
+       defw l2546h             ;214c\r
+\r
+       defb 0ffh               ;214e   ex (sp),hl\r
+       defb 0e3h               ;214f\r
+       defb 034h               ;2150\r
+       defw l232ah             ;2151\r
+\r
+       defb 0ffh               ;2153   jp (hl)\r
+       defb 0e9h               ;2154\r
+       defb 052h               ;2155\r
+       defw l2338h             ;2156\r
+\r
+       defb 0ffh               ;2158   ex de,hl\r
+       defb 0ebh               ;2159\r
+       defb 034h               ;215a\r
+       defw l2345h             ;215b\r
+\r
+       defb 0ffh               ;215d   ld sp,hl\r
+       defb 0f9h               ;215e\r
+       defb 056h               ;215f\r
+       defw l234bh             ;2160\r
+\r
+       defb 0cfh               ;2162   inc rr\r
+       defb 003h               ;2163\r
+       defb 041h               ;2164\r
+       defw l254bh             ;2165\r
+\r
+       defb 0cfh               ;2167   dec rr\r
+       defb 00bh               ;2168\r
+       defb 029h               ;2169\r
+       defw l254bh             ;216a\r
+\r
+       defb 0c7h               ;216c   inc r\r
+       defb 004h               ;216d\r
+       defb 041h               ;216e\r
+       defw l24dfh             ;216f\r
+\r
+       defb 0c7h               ;2171   dec r\r
+       defb 005h               ;2172\r
+       defb 029h               ;2173\r
+       defw l24dfh             ;2174\r
+\r
+       defb 0ffh               ;2176   ex af,af'\r
+       defb 008h               ;2177\r
+       defb 034h               ;2178\r
+       defw l2357h             ;2179\r
+\r
+       defb 0cfh               ;217b   add hl,rr\r
+       defb 009h               ;217c\r
+       defb 003h               ;217d\r
+       defw l235dh             ;217e\r
+\r
+       defb 0efh               ;2180   ld (rr),a ;rr=bc,de\r
+       defb 002h               ;2181\r
+       defb 056h               ;2182\r
+       defw l2366h             ;2183\r
+\r
+       defb 0efh               ;2185   ld a,(rr) ;rr=bc,de\r
+       defb 00ah               ;2186\r
+       defb 056h               ;2187\r
+       defw l236fh             ;2188\r
+\r
+       defb 000h               ;218a   EOT\r
+\r
+b_0x218B_start:                        ;       2 byte opdodes\r
+       defb 0c7h               ;218b   ld r,nn\r
+       defb 006h               ;218c\r
+       defb 056h               ;218d\r
+       defw l2384h             ;218e\r
+\r
+       defb 0ffh               ;2190   add a,nn\r
+       defb 0c6h               ;2191\r
+       defb 003h               ;2192\r
+       defw l237fh             ;2193\r
+\r
+       defb 0ffh               ;2195   adc a,nn\r
+       defb 0ceh               ;2196\r
+       defb 000h               ;2197\r
+       defw l237fh             ;2198\r
+\r
+       defb 0ffh               ;219a   sub a,nn\r
+       defb 0d6h               ;219b\r
+       defb 0c9h               ;219c\r
+       defw l2397h             ;219d\r
+\r
+       defb 0ffh               ;219f\r
+       defb 0deh               ;21a0\r
+       defb 0b7h               ;21a1\r
+       defw l237fh             ;21a2\r
+\r
+       defb 0ffh               ;21a4   and a,nn\r
+       defb 0e6h               ;21a5\r
+       defb 006h               ;21a6\r
+       defw l2397h             ;21a7\r
+\r
+       defb 0ffh               ;21a9\r
+       defb 0eeh               ;21aa\r
+       defb 0cch               ;21ab\r
+       defw l2397h             ;21ac\r
+\r
+       defb 0ffh               ;21ae\r
+       defb 0f6h               ;21af\r
+       defb 06ch               ;21b0\r
+       defw l2397h             ;21b1\r
+\r
+       defb 0ffh               ;21b3   cp a,nn\r
+       defb 0feh               ;21b4\r
+       defb 013h               ;21b5\r
+       defw l2397h             ;21b6\r
+\r
+       defb 0ffh               ;21b8   djnz\r
+       defb 010h               ;21b9\r
+       defb 02eh               ;21ba\r
+       defw l23b0h             ;21bb\r
+\r
+       defb 0ffh               ;21bd   jr\r
+       defb 018h               ;21be\r
+       defb 054h               ;21bf\r
+       defw l23b0h             ;21c0\r
+\r
+       defb 0e7h               ;21c2   jr,cc\r
+       defb 020h               ;21c3\r
+       defb 054h               ;21c4\r
+       defw l23a1h             ;21c5\r
+\r
+       defb 0ffh               ;21c7\r
+       defb 0d3h               ;21c8   out (nn),a\r
+       defb 076h               ;21c9\r
+       defw l23d5h             ;21ca\r
+\r
+       defb 0ffh               ;21cc   in a,(nn)\r
+       defb 0dbh               ;21cd\r
+       defb 03fh               ;21ce\r
+       defw l23c3h             ;21cf\r
+\r
+       defb 000h               ;21d1   EOT\r
+\r
+b_0x21D2_start:                        ;       3 byte opcodes\r
+       defb 0c7h               ;21d2\r
+       defb 0c2h               ;21d3\r
+       defb 052h               ;21d4\r
+       defw l23e0h             ;21d5\r
+\r
+       defb 0c7h               ;21d7\r
+       defb 0c4h               ;21d8\r
+       defb 00ch               ;21d9\r
+       defw l23e0h             ;21da\r
+\r
+       defb 0cfh               ;21dc\r
+       defb 001h               ;21dd\r
+       defb 056h               ;21de\r
+       defw l23fch             ;21df\r
+\r
+       defb 0ffh               ;21e1\r
+       defb 0c3h               ;21e2\r
+       defb 052h               ;21e3\r
+       defw l23e6h             ;21e4\r
+\r
+       defb 0ffh               ;21e6\r
+       defb 0cdh               ;21e7\r
+       defb 00ch               ;21e8\r
+       defw l23e6h             ;21e9\r
+\r
+       defb 0ffh               ;21eb\r
+       defb 022h               ;21ec\r
+       defb 056h               ;21ed\r
+       defw l2404h             ;21ee\r
+\r
+       defb 0ffh               ;21f0\r
+       defb 02ah               ;21f1\r
+       defb 056h               ;21f2\r
+       defw l240dh             ;21f3\r
+\r
+       defb 0ffh               ;21f5\r
+       defb 032h               ;21f6\r
+       defb 056h               ;21f7\r
+       defw l2416h             ;21f8\r
+\r
+       defb 0ffh               ;21fa\r
+       defb 03ah               ;21fb\r
+       defb 056h               ;21fc\r
+       defw l2421h             ;21fd\r
+\r
+       defb 000h               ;21ff\r
+\r
+b_0x2200_start:                        ;       prefix ED + 1 byte opcode\r
+       defb 044h               ;2200   neg\r
+       defb 066h               ;2201\r
+       defb 045h               ;2202   retn\r
+       defb 092h               ;2203\r
+       defb 04dh               ;2204   reti\r
+       defb 08eh               ;2205\r
+       defb 067h               ;2206   rrd\r
+       defb 0b1h               ;2207\r
+       defb 06fh               ;2208   rld\r
+       defb 0a2h               ;2209\r
+       defb 0a0h               ;220a   ldi\r
+       defb 05fh               ;220b\r
+       defb 0a1h               ;220c\r
+       defb 01ch               ;220d\r
+       defb 0a2h               ;220e\r
+       defb 04bh               ;220f\r
+       defb 0a3h               ;2210\r
+       defb 07dh               ;2211\r
+       defb 0a8h               ;2212   ldd\r
+       defb 058h               ;2213\r
+       defb 0a9h               ;2214\r
+       defb 015h               ;2215\r
+       defb 0aah               ;2216\r
+       defb 044h               ;2217\r
+       defb 0abh               ;2218\r
+       defb 079h               ;2219\r
+       defb 0b0h               ;221a   ldir\r
+       defb 062h               ;221b\r
+       defb 0b1h               ;221c\r
+       defb 01fh               ;221d\r
+       defb 0b2h               ;221e\r
+       defb 04eh               ;221f\r
+       defb 0b3h               ;2220\r
+       defb 072h               ;2221\r
+       defb 0b8h               ;2222   lddr\r
+       defb 05bh               ;2223\r
+       defb 0b9h               ;2224\r
+       defb 018h               ;2225\r
+       defb 0bah               ;2226\r
+       defb 047h               ;2227\r
+       defb 0bbh               ;2228\r
+       defb 06eh               ;2229\r
+       defb 08bh               ;222a   otdm\r
+       defb 0d5h               ;222b\r
+       defb 09bh               ;222c   otdmr\r
+       defb 0d9h               ;222d\r
+       defb 083h               ;222e   otim\r
+       defb 0deh               ;222f\r
+       defb 093h               ;2230   otimr\r
+       defb 0e2h               ;2231\r
+       defb 076h               ;2232   slp\r
+       defb 0ebh               ;2233\r
+       defb 0ffh               ;2234   EOT\r
+       \r
+l2235h:\r
+       defb 0e7h               ;2235   in r,(c) ;r=bcde\r
+       defb 040h               ;2236\r
+       defb 03fh               ;2237\r
+       defw l2455h             ;2238\r
+\r
+       defb 0f7h               ;223a   in r,(c) ;r=hl\r
+       defb 060h               ;223b\r
+       defb 03fh               ;223c\r
+       defw l2455h             ;223d\r
+\r
+       defb 0ffh               ;223f   in r,(c) ;r=a\r
+       defb 078h               ;2240\r
+       defb 03fh               ;2241\r
+       defw l2455h             ;2242\r
+\r
+       defb 0e7h               ;2244\r
+       defb 041h               ;2245\r
+       defb 076h               ;2246\r
+       defw l2461h             ;2247\r
+\r
+       defb 0f7h               ;2249\r
+       defb 061h               ;224a\r
+       defb 076h               ;224b\r
+       defw l2461h             ;224c\r
+\r
+       defb 0ffh               ;224e   out (c),r ;r=a\r
+       defb 079h               ;224f\r
+       defb 076h               ;2250\r
+       defw l2461h             ;2251\r
+\r
+       defb 0cfh               ;2253   sbc hl,rr\r
+       defb 042h               ;2254\r
+       defb 0b7h               ;2255\r
+       defw l246dh             ;2256\r
+\r
+       defb 0cfh               ;2258   adc hl,rr\r
+       defb 04ah               ;2259\r
+       defb 000h               ;225a\r
+       defw l246dh             ;225b\r
+\r
+       defb 0ffh               ;225d   im 0\r
+       defb 046h               ;225e\r
+       defb 03dh               ;225f\r
+       defw l2427h             ;2260\r
+\r
+       defb 0ffh               ;2262   im 1\r
+       defb 056h               ;2263\r
+       defb 03dh               ;2264\r
+       defw l242bh             ;2265\r
+\r
+       defb 0ffh               ;2267   im 2\r
+       defb 05eh               ;2268\r
+       defb 03dh               ;2269\r
+       defw l242fh             ;226a\r
+\r
+       defb 0ffh               ;226c   ld i,a\r
+       defb 047h               ;226d\r
+       defb 056h               ;226e\r
+       defw l2434h             ;226f\r
+\r
+       defb 0ffh               ;2271\r
+       defb 057h               ;2272\r
+       defb 056h               ;2273\r
+       defw l2439h             ;2274\r
+\r
+       defb 0ffh               ;2276\r
+       defb 04fh               ;2277\r
+       defb 056h               ;2278\r
+       defw l243eh             ;2279\r
+\r
+       defb 0ffh               ;227b\r
+       defb 05fh               ;227c\r
+       defb 056h               ;227d\r
+       defw l2443h             ;227e\r
+\r
+       defb 0cfh               ;2280   mlt rr\r
+       defb 04ch               ;2281\r
+       defb 0d2h               ;2282\r
+       defw l254bh             ;2283\r
+\r
+       defb 0c7h               ;2285   tst r\r
+       defb 004h               ;2286\r
+       defb 0eeh               ;2287\r
+       defw l24dfh             ;2288\r
+\r
+       defb 000h               ;228a\r
+\r
+l228bh:\r
+       defb 0e7h               ;228b\r
+       defb 000h               ;228c\r
+       defb 0cfh               ;228d\r
+\r
+b_0x228E_start:\r
+       defw l230ch             ;228e\r
+\r
+b_0x2290_start:\r
+       defb 0f7h               ;2290\r
+       defb 020h               ;2291\r
+       defb 0cfh               ;2292\r
+\r
+b_0x2293_start:\r
+       defw l230ch             ;2293\r
+\r
+b_0x2295_start:\r
+       defb 0ffh               ;2295\r
+       defb 038h               ;2296\r
+       defb 0cfh               ;2297\r
+\r
+b_0x2298_start:\r
+       defw l230ch             ;2298\r
+\r
+b_0x229A_start:\r
+       defb 0e7h               ;229a\r
+       defb 001h               ;229b\r
+       defb 0e7h               ;229c\r
+\r
+b_0x229D_start:\r
+       defw l2315h             ;229d\r
+\r
+b_0x229F_start:\r
+       defb 0f7h               ;229f\r
+       defb 021h               ;22a0\r
+       defb 0e7h               ;22a1\r
+\r
+b_0x22A2_start:\r
+       defw l2315h             ;22a2\r
+\r
+b_0x22A4_start:\r
+       defb 0ffh               ;22a4\r
+       defb 039h               ;22a5\r
+       defb 0e7h               ;22a6\r
+\r
+b_0x22A7_start:\r
+       defw l2315h             ;22a7\r
+\r
+b_0x22A9_start:\r
+       defb 0ffh               ;22a9\r
+       defb 064h               ;22aa\r
+       defb 0eeh               ;22ab\r
+\r
+b_0x22AC_start:\r
+       defw l2397h             ;22ac\r
+\r
+b_0x22AE_start:\r
+       defb 0ffh               ;22ae\r
+       defb 074h               ;22af\r
+       defb 0f1h               ;22b0\r
+\r
+b_0x22B1_start:\r
+       defw l2397h             ;22b1\r
+\r
+b_0x22B3_start:\r
+       defb 000h               ;22b3\r
+l22b4h:\r
+       defb 0efh               ;22b4\r
+       defb 043h               ;22b5\r
+       defb 056h               ;22b6\r
+\r
+b_0x22B7_start:\r
+       defw l2476h             ;22b7\r
+\r
+b_0x22B9_start:\r
+       defb 0ffh               ;22b9\r
+       defb 073h               ;22ba\r
+       defb 056h               ;22bb\r
+\r
+b_0x22BC_start:\r
+       defw l2476h             ;22bc\r
+\r
+b_0x22BE_start:\r
+       defb 0efh               ;22be\r
+       defb 04bh               ;22bf\r
+       defb 056h               ;22c0\r
+\r
+b_0x22C1_start:\r
+       defw l247fh             ;22c1\r
+\r
+b_0x22C3_start:\r
+       defb 0ffh               ;22c3\r
+       defb 07bh               ;22c4\r
+       defb 056h               ;22c5\r
+\r
+b_0x22C6_start:\r
+       defw l247fh             ;22c6\r
+\r
+b_0x22C8_start:\r
+       defb 000h               ;22c8\r
+l22c9h:\r
+       defb 0f8h               ;22c9\r
+       defb 000h               ;22ca\r
+       defb 09bh               ;22cb\r
+\r
+b_0x22CC_start:\r
+       defw l24aeh             ;22cc\r
+\r
+b_0x22CE_start:\r
+       defb 0f8h               ;22ce\r
+       defb 008h               ;22cf\r
+       defb 0aah               ;22d0\r
+\r
+b_0x22D1_start:\r
+       defw l24aeh             ;22d1\r
+\r
+b_0x22D3_start:\r
+       defb 0f8h               ;22d3\r
+       defb 010h               ;22d4\r
+       defb 096h               ;22d5\r
+\r
+b_0x22D6_start:\r
+       defw l24aeh             ;22d6\r
+\r
+b_0x22D8_start:\r
+       defb 0f8h               ;22d8\r
+       defb 018h               ;22d9\r
+       defb 0a5h               ;22da\r
+\r
+b_0x22DB_start:\r
+       defw l24aeh             ;22db\r
+\r
+b_0x22DD_start:\r
+       defb 0f8h               ;22dd\r
+       defb 020h               ;22de\r
+       defb 0c0h               ;22df\r
+\r
+b_0x22E0_start:\r
+       defw l24aeh             ;22e0\r
+\r
+b_0x22E2_start:\r
+       defb 0f8h               ;22e2\r
+       defb 028h               ;22e3\r
+       defb 0c3h               ;22e4\r
+\r
+b_0x22E5_start:\r
+       defw l24aeh             ;22e5\r
+\r
+b_0x22E7_start:\r
+       defb 0f8h               ;22e7\r
+       defb 038h               ;22e8\r
+       defb 0c6h               ;22e9\r
+\r
+b_0x22EA_start:\r
+       defw l24aeh             ;22ea\r
+\r
+b_0x22EC_start:\r
+       defb 0c0h               ;22ec\r
+       defb 040h               ;22ed\r
+       defb 009h               ;22ee\r
+\r
+b_0x22EF_start:\r
+       defw l2487h             ;22ef\r
+\r
+b_0x22F1_start:\r
+       defb 0c0h               ;22f1\r
+       defb 080h               ;22f2\r
+       defb 088h               ;22f3\r
+\r
+b_0x22F4_start:\r
+       defw l2487h             ;22f4\r
+\r
+b_0x22F6_start:\r
+       defb 0c0h               ;22f6\r
+       defb 0c0h               ;22f7\r
+       defb 0bdh               ;22f8\r
+\r
+b_0x22F9_start:\r
+       defw l2487h             ;22f9\r
+\r
+b_0x22FB_start:\r
+       defb 000h               ;22fb\r
+l22fch:\r
+       call l24dfh             ;22fc\r
+       call sub_257ch          ;22ff\r
+       jp l24ebh               ;2302\r
+l2305h:\r
+       call sub_2579h          ;2305\r
+       jp l24ebh               ;2308\r
+l230bh:\r
+       ret                     ;230b\r
+l230ch:\r
+       call l24dfh             ;230c\r
+       call sub_257ch          ;230f\r
+       jp l23c6h               ;2312\r
+l2315h:\r
+       call l23c6h             ;2315\r
+       call sub_257ch          ;2318\r
+       jp l24dfh               ;231b\r
+l231eh:\r
+       comst                   ;231e\r
+       ld a,(iy+000h)          ;2322\r
+       comend\r
+       and 038h                ;2325\r
+       jp out.hex              ;2327\r
+l232ah:\r
+       ld hl,b_0x2333_start    ;232a\r
+       call PSTR               ;232d\r
+       jp l253eh               ;2330\r
+\r
+b_0x2333_start:\r
+       DC      '(SP),'\r
+\r
+l2338h:\r
+       ld a,'('                ;2338\r
+       call OUTCHAR            ;233a\r
+       call l253eh             ;233d\r
+       ld a,')'                ;2340\r
+       jp OUTCHAR              ;2342\r
+l2345h:\r
+       ld hl,l1d86h            ;2345\r
+       jp PSTR                 ;2348\r
+l234bh:\r
+       ld hl,b_0x2354_start    ;234b\r
+       call PSTR               ;234e\r
+       jp l253eh               ;2351\r
+\r
+b_0x2354_start:\r
+       DC      'SP,'\r
+\r
+l2357h:\r
+       ld hl,b_0x1D80_start    ;2357\r
+       jp PSTR                 ;235a\r
+l235dh:\r
+       call l253eh             ;235d\r
+       call sub_257ch          ;2360\r
+       jp l254bh               ;2363\r
+l2366h:\r
+       call sub_2372h          ;2366\r
+       call sub_257ch          ;2369\r
+       jp l23dbh               ;236c\r
+l236fh:\r
+       call sub_2579h          ;236f\r
+sub_2372h:\r
+       ld a,'('                ;2372\r
+       call OUTCHAR            ;2374\r
+       call l254bh             ;2377\r
+       ld a,')'                ;237a\r
+       jp OUTCHAR              ;237c\r
+l237fh:\r
+       call sub_2579h          ;237f\r
+       jr l2397h               ;2382\r
+l2384h:\r
+       call l24dfh             ;2384\r
+       call sub_257ch          ;2387\r
+       ld a,(is.pfx.IXY)               ;238a\r
+       and a                   ;238d\r
+       comst                   ;238e\r
+       ld a,(iy+002h)          ;2392\r
+       comend\r
+       jr nz,l239eh            ;2395\r
+l2397h:\r
+       comst                   ;2397\r
+       ld a,(iy+001h)          ;239b\r
+       comend\r
+l239eh:\r
+       jp out.hex              ;239e\r
+l23a1h:\r
+       comst                   ;23a1\r
+       ld a,(iy+000h)          ;23a5\r
+       comend\r
+       and 018h                ;23a8\r
+       call sub_2568h          ;23aa\r
+       call sub_257ch          ;23ad\r
+l23b0h:\r
+       comst                   ;23b0\r
+       ld c,(iy+001h)          ;23b4\r
+       comend\r
+       ld a,c                  ;23b7\r
+       rla                     ;23b8\r
+       sbc a,a                 ;23b9\r
+       ld b,a                  ;23ba\r
+       push iy                 ;23bb\r
+       pop hl                  ;23bd\r
+       add hl,bc               ;23be\r
+       inc hl                  ;23bf\r
+       inc hl                  ;23c0\r
+       jr l23f0h               ;23c1\r
+l23c3h:\r
+       call sub_2579h          ;23c3\r
+l23c6h:\r
+       ld a,028h               ;23c6\r
+       call OUTCHAR            ;23c8\r
+       comst                   ;23cb\r
+       ld a,(iy+001h)          ;23cf\r
+       comend\r
+       jp l252bh               ;23d2\r
+l23d5h:\r
+       call l23c6h             ;23d5\r
+       call sub_257ch          ;23d8\r
+l23dbh:\r
+       ld a,041h               ;23db\r
+       jp OUTCHAR              ;23dd\r
+l23e0h:\r
+       call l2561h             ;23e0\r
+       call sub_257ch          ;23e3\r
+l23e6h:\r
+       comst                   ;23e6\r
+       ld l,(iy+001h)          ;23ea\r
+       ld h,(iy+002h)          ;23ed\r
+       comend\r
+l23f0h:\r
+       ld a,002h               ;23f0\r
+sub_23f2h:\r
+       ld (XBE03),a            ;23f2\r
+       ld (XBE01),hl           ;23f5\r
+       call out.hl             ;23f8\r
+       ret                     ;23fb\r
+l23fch:\r
+       call l254bh             ;23fc\r
+       call sub_257ch          ;23ff\r
+       jr l23e6h               ;2402\r
+l2404h:\r
+       call sub_24c6h          ;2404\r
+       call sub_257ch          ;2407\r
+       jp l253eh               ;240a\r
+l240dh:\r
+       call l253eh             ;240d\r
+       call sub_257ch          ;2410\r
+       jp sub_24c6h            ;2413\r
+l2416h:\r
+       call sub_24c6h          ;2416\r
+       call sub_257ch          ;2419\r
+       ld a,041h               ;241c\r
+       jp OUTCHAR              ;241e\r
+l2421h:\r
+       call sub_2579h          ;2421\r
+       jp sub_24c6h            ;2424\r
+l2427h:\r
+       ld a,030h               ;2427\r
+       jr l2431h               ;2429\r
+l242bh:\r
+       ld a,031h               ;242b\r
+       jr l2431h               ;242d\r
+l242fh:\r
+       ld a,032h               ;242f\r
+l2431h:\r
+       jp OUTCHAR              ;2431\r
+l2434h:\r
+       ld hl,b_0x2449_start    ;2434\r
+       jr l2446h               ;2437\r
+l2439h:\r
+       ld hl,l244ch            ;2439\r
+       jr l2446h               ;243c\r
+l243eh:\r
+       ld hl,l244fh            ;243e\r
+       jr l2446h               ;2441\r
+l2443h:\r
+       ld hl,l2452h            ;2443\r
+l2446h:\r
+       jp PSTR                 ;2446\r
+\r
+b_0x2449_start:\r
+       DC      'I,A'\r
+l244ch:\r
+       DC      'A,I'\r
+l244fh:\r
+       DC      'R,A'\r
+l2452h:\r
+       DC      'A,R'\r
+\r
+l2455h:\r
+       call l24dfh             ;2455\r
+       call sub_257ch          ;2458\r
+       ld hl,t__C_             ;245b\r
+       jp PSTR         ;245e\r
+l2461h:\r
+       ld hl,t__C_             ;2461\r
+       call PSTR               ;2464\r
+       call sub_257ch          ;2467\r
+       jp l24dfh               ;246a\r
+l246dh:\r
+       call l253eh             ;246d\r
+       call sub_257ch          ;2470\r
+       jp l254bh               ;2473\r
+l2476h:\r
+       call sub_24c6h          ;2476\r
+       call sub_257ch          ;2479\r
+       jp l254bh               ;247c\r
+l247fh:\r
+       call l254bh             ;247f\r
+       call sub_257ch          ;2482\r
+       jr sub_24c6h            ;2485\r
+l2487h:\r
+       ld a,(is.pfx.IXY)               ;2487\r
+       and a                   ;248a\r
+       jr nz,l2496h            ;248b\r
+       comst                   ;248d\r
+       ld a,(iy+001h)          ;2491\r
+       comend\r
+       jr l249dh               ;2494\r
+l2496h:\r
+       comst                   ;2496\r
+       ld a,(iy+002h)          ;249a\r
+       comend\r
+l249dh:\r
+       push af                 ;249d\r
+       rra                     ;249e\r
+       rra                     ;249f\r
+       rra                     ;24a0\r
+       and 007h                ;24a1\r
+       add a,'0'               ;24a3\r
+       call OUTCHAR            ;24a5\r
+       call sub_257ch          ;24a8\r
+       pop af                  ;24ab\r
+       jr l24f2h               ;24ac\r
+l24aeh:\r
+       ld a,(is.pfx.IXY)               ;24ae\r
+       and a                   ;24b1\r
+       jr nz,l24bdh            ;24b2\r
+       comst                   ;24b4\r
+       ld a,(iy+001h)          ;24b8\r
+       comend\r
+       jr l24c4h               ;24bb\r
+l24bdh:\r
+       comst                   ;24bd\r
+       ld a,(iy+002h)          ;24c1\r
+       comend\r
+l24c4h:\r
+       jr l24f2h               ;24c4\r
+sub_24c6h:\r
+       ld a,'('                ;24c6\r
+       call OUTCHAR            ;24c8\r
+       comst                   ;24cb\r
+       ld l,(iy+001h)          ;24cf\r
+       ld h,(iy+002h)          ;24d2\r
+       comend\r
+       ld a,001h               ;24d5\r
+       call sub_23f2h          ;24d7\r
+       ld a,')'                ;24da\r
+       jp OUTCHAR              ;24dc\r
+l24dfh:\r
+       comst                   ;24df\r
+       ld a,(iy+000h)          ;24e3\r
+       comend\r
+       rra                     ;24e6\r
+       rra                     ;24e7\r
+       rra                     ;24e8\r
+       jr l24f2h               ;24e9\r
+l24ebh:\r
+       comst                   ;24eb\r
+       ld a,(iy+000h)          ;24ef\r
+       comend\r
+l24f2h:\r
+       and 007h                ;24f2\r
+       cp 006h                 ;24f4\r
+       jr nz,l2533h            ;24f6\r
+       ld a,(is.pfx.IXY)               ;24f8\r
+       and a                   ;24fb\r
+       ld a,006h               ;24fc\r
+       jr z,l2533h             ;24fe\r
+       ld hl,b_0x2538_start    ;2500\r
+       ld a,(is.pfx.IXY)               ;2503\r
+       dec a                   ;2506\r
+       jr z,l250ch             ;2507\r
+       ld hl,b_0x253B_start    ;2509\r
+l250ch:\r
+       call PSTR               ;250c\r
+       comst                   ;250f\r
+       ld a,(iy+001h)          ;2513\r
+       comend\r
+       and a                   ;2516\r
+       push af                 ;2517\r
+       jp m,l2523h             ;2518\r
+       ld a,'+'                ;251b\r
+       call OUTCHAR            ;251d\r
+       pop af                  ;2520\r
+       jr l252bh               ;2521\r
+l2523h:\r
+       ld a,'-'                ;2523\r
+       call OUTCHAR            ;2525\r
+       pop af                  ;2528\r
+       neg                     ;2529\r
+l252bh:\r
+       call out.hex            ;252b\r
+       ld a,')'                ;252e\r
+       jp OUTCHAR              ;2530\r
+l2533h:\r
+       ld hl,t_BCDEHL_HL_A     ;2533\r
+       jr l2572h               ;2536\r
+\r
+b_0x2538_start:\r
+       DC      '(IX'\r
+b_0x253B_start:\r
+       DC      '(IY'\r
+\r
+l253eh:\r
+       ld a,(is.pfx.IXY)               ;253e\r
+       ld hl,t_HL.IX.IY        ;2541\r
+       jr l2572h               ;2544\r
+l2546h:\r
+       ld hl,t_BC.DE.HL.AF     ;2546\r
+       jr l254eh               ;2549\r
+l254bh:\r
+       ld hl,t_BC.DE.HL.SP     ;254b\r
+l254eh:\r
+       comst                   ;254e\r
+       ld a,(iy+000h)          ;2552\r
+       comend\r
+       rra                     ;2555\r
+       rra                     ;2556\r
+       rra                     ;2557\r
+       rra                     ;2558\r
+       and 003h                ;2559\r
+       cp 002h                 ;255b\r
+       jr z,l253eh             ;255d\r
+       jr l2572h               ;255f\r
+l2561h:\r
+       comst                   ;2561\r
+       ld a,(iy+000h)          ;2565\r
+       comend\r
+sub_2568h:\r
+       rra                     ;2568\r
+       rra                     ;2569\r
+       rra                     ;256a\r
+       and 007h                ;256b\r
+       ld hl,t_tstfl_ZCPS      ;256d\r
+       jr l2572h               ;2570\r
+l2572h:\r
+       ld b,a                  ;2572\r
+       call sub_0a48h          ;2573\r
+       jp PSTR                 ;2576\r
+sub_2579h:\r
+       call l23dbh             ;2579\r
+sub_257ch:\r
+       ld a,','                ;257c\r
+       jp OUTCHAR              ;257e\r
+sub_2581h:\r
+       call PSTR               ;2581\r
+l2584h:\r
+       call OUTBL              ;2584\r
+       inc c                   ;2587\r
+       ld a,c                  ;2588\r
+       cp 006h                 ;2589\r
+       jr nz,l2584h            ;258b\r
+       ret                     ;258d\r
+\r
+t_MNEMONICS:\r
+       DC      'ADC'\r
+       DC      'ADD'\r
+       DC      'AND'\r
+       DC      'BIT'\r
+       DC      'CALL'\r
+       DC      'CCF'\r
+       DC      'CP'\r
+       DC      'CPD'\r
+       DC      'CPDR'\r
+       DC      'CPI'\r
+       DC      'CPIR'\r
+       DC      'CPL'\r
+       DC      'DAA'\r
+       DC      'DEC'\r
+       DC      'DI'\r
+       DC      'DJNZ'\r
+       DC      'EI'\r
+       DC      'EX'\r
+       DC      'EXX'\r
+       DC      'HALT'\r
+       DC      'IM'\r
+       DC      'IN'\r
+       DC      'INC'\r
+       DC      'IND'\r
+       DC      'INDR'\r
+       DC      'INI'\r
+       DC      'INIR'\r
+       DC      'JP'\r
+       DC      'JR'\r
+       DC      'LD'\r
+       DC      'LDD'\r
+       DC      'LDDR'\r
+       DC      'LDI'\r
+       DC      'LDIR'\r
+       DC      'NEG'\r
+       DC      'NOP'\r
+       DC      'OR'\r
+       DC      'OTDR'\r
+       DC      'OTIR'\r
+       DC      'OUT'\r
+       DC      'OUTD'\r
+       DC      'OUTI'\r
+       DC      'POP'\r
+       DC      'PUSH'\r
+       DC      'RES'\r
+       DC      'RET'\r
+       DC      'RETI'\r
+       DC      'RETN'\r
+       DC      'RL'\r
+       DC      'RLA'\r
+       DC      'RLC'\r
+       DC      'RLCA'\r
+       DC      'RLD'\r
+       DC      'RR'\r
+       DC      'RRA'\r
+       DC      'RRC'\r
+       DC      'RRCA'\r
+       DC      'RRD'\r
+       DC      'RST'\r
+       DC      'SBC'\r
+       DC      'SCF'\r
+       DC      'SET'\r
+       DC      'SLA'\r
+       DC      'SRA'\r
+       DC      'SRL'\r
+       DC      'SUB'\r
+       DC      'XOR'\r
+       DC      'IN0'\r
+       DC      'MLT'\r
+       DC      'OTDM'\r
+       DC      'OTDMR'\r
+       DC      'OTIM'\r
+       DC      'OTIMR'\r
+       DC      'OUT0'\r
+       DC      'SLP'\r
+       DC      'TST'\r
+       DC      'TSTIO'\r
+       DB      0\r
+       \r
+t_BCDEHL_HL_A:\r
+       DC      'B'\r
+       DC      'C'\r
+       DC      'D'\r
+       DC      'E'\r
+       DC      'H'\r
+       DC      'L'\r
+       DC      '(HL)'\r
+       DC      'A'\r
+       DB      0\r
+t_BC.DE.HL.SP:\r
+       DC      'BC'\r
+       DC      'DE'\r
+       DC      'HL'\r
+       DC      'SP'\r
+       DB      0\r
+t_BC.DE.HL.AF:\r
+       DC      'BC'\r
+       DC      'DE'\r
+t_HL.AF:\r
+       DC      'HL'\r
+       DC      'AF'\r
+       DB      0\r
+t_BC.DE.IY.SP:\r
+       DC      'BC'\r
+       DC      'DE'\r
+       DC      'IY'\r
+       DC      'SP'\r
+       DB      0\r
+t_BC.DE.IX.SP:\r
+       DC      'BC'\r
+       DC      'DE'\r
+       DC      'IX'\r
+       DC      'SP'\r
+       DB      0\r
+t_HL.IX.IY:\r
+       DC      'HL'\r
+t_IX.IY:\r
+       DC      'IX'\r
+       DC      'IY'\r
+       DB      0\r
+t_tstfl_ZC:\r
+       DC      'NZ'\r
+       DC      'Z'\r
+       DC      'NC'\r
+       DC      'C'\r
+       DC      'NE'\r
+       DC      'EQ'\r
+       DC      'GE'\r
+       DC      'LT'\r
+       DB      0\r
+t_tstfl_ZCPS:\r
+       DC      'NZ'\r
+       DC      'Z'\r
+       DC      'NC'\r
+       DC      'C'\r
+       DC      'PO'\r
+       DC      'PE'\r
+       DC      'P'\r
+       DC      'M'\r
+       DC      'NE'\r
+       DC      'EQ'\r
+       DC      'GE'\r
+       DC      'LT'\r
+       DC      'NV'\r
+       DC      'V'\r
+       DB      0\r
+t__C_:\r
+       DC      '(C)'\r
+       DB      0\r
+\r
+sub_26e7h:\r
+       ld hl,(REG.PC)          ;26e7\r
+       ld a,h                  ;26ea\r
+       or l                    ;26eb\r
+       jr z,l2715h             ;26ec\r
+       ld iy,(REG.PC)          ;26ee\r
+       call sub_1f9eh          ;26f2\r
+       jp nc,ERROR             ;26f5\r
+       ld c,b                  ;26f8\r
+       ld b,000h               ;26f9\r
+       ld hl,(REG.PC)          ;26fb\r
+       add hl,bc               ;26fe\r
+       call sub_1117h          ;26ff\r
+       ld iy,(REG.PC)          ;2702\r
+       ld hl,b_0x2717_start    ;2706\r
+       call lookup_opc         ;2709\r
+       ccf                     ;270c\r
+       ret c                   ;270d\r
+       ex de,hl                ;270e\r
+       call CALL.HL            ;270f\r
+       call c,sub_1117h        ;2712\r
+l2715h:\r
+       scf                     ;2715\r
+       ret                     ;2716\r
+\r
+b_0x2717_start:\r
+       db      0ffh            ;2717\r
+       db      0ddh            ;2718\r
+       db      000h            ;2719\r
+       dw      x278d\r
+\r
+       db      0ffh            ;271c\r
+       db      0fdh            ;271d\r
+       db      000h            ;271e\r
+       dw      x2792\r
+\r
+       db      0ffh            ;2721\r
+       db      0edh            ;2722\r
+       db      000h            ;2723\r
+       dw      x27a2\r
+\r
+l2726h:\r
+       db      0ffh            ;2726\r
+       db      0cdh            ;2727\r
+       db      000h            ;2728\r
+       dw      x275e\r
+\r
+       db      0ffh            ;272b\r
+       db      0c3h            ;272c\r
+       db      000h            ;272d\r
+       dw      x2769\r
+\r
+       db      0ffh            ;2730\r
+       db      0e9h            ;2731\r
+       db      000h            ;2732\r
+       dw      x2788\r
+\r
+       db      0ffh            ;2735\r
+       db      0c9h            ;2736\r
+       db      000h            ;2737\r
+       dw      x27c9\r
+\r
+       db      0ffh            ;273a\r
+       db      0cfh            ;273b\r
+       db      000h            ;273c\r
+       dw      x280e\r
+\r
+       db      0c7h            ;273f\r
+       db      0c7h            ;2740\r
+       db      000h            ;2741\r
+       dw      x27ea\r
+\r
+       db      0c7h            ;2744\r
+       db      0c4h            ;2745\r
+       db      000h            ;2746\r
+       dw      x275e\r
+\r
+       db      0f7h            ;2749\r
+       db      010h            ;274a\r
+       db      000h            ;274b\r
+       dw      x2775\r
+\r
+       db      0e7h            ;274e\r
+       db      020h            ;274f\r
+       db      000h            ;2750\r
+       dw      x2775\r
+\r
+       db      0c7h            ;2753\r
+       db      0c2h            ;2754\r
+       db      000h            ;2755\r
+       dw      x2769\r
+\r
+       db      0c7h            ;2758\r
+       db      0c0h            ;2759\r
+       db      000h            ;275a\r
+       dw      x27b3\r
+\r
+       db      000h            ;275d\r
+\r
+x275e:\r
+       ld a,(XBFE8)            ;275e\r
+       and a                   ;2761\r
+       jr nz,x2769             ;2762\r
+       ld a,(TCFLG)            ;2764\r
+       and a                   ;2767\r
+       ret nz                  ;2768\r
+\r
+x2769:\r
+       comst                   ;2769\r
+       ld l,(iy+001h)          ;276d\r
+       ld h,(iy+002h)          ;2770\r
+       comend\r
+       scf                     ;2773\r
+       ret                     ;2774\r
+\r
+x2775:\r
+       comst                   ;2775\r
+       ld c,(iy+001h)          ;2779\r
+       comend\r
+       ld a,c                  ;277c\r
+       rla                     ;277d\r
+       sbc a,a                 ;277e\r
+       ld b,a                  ;277f\r
+       ld hl,(REG.PC)          ;2780\r
+       add hl,bc               ;2783\r
+       inc hl                  ;2784\r
+       inc hl                  ;2785\r
+       scf                     ;2786\r
+       ret                     ;2787\r
+\r
+x2788:\r
+       ld hl,(REG.L)           ;2788\r
+       scf                     ;278b\r
+       ret                     ;278c\r
+\r
+x278d:\r
+       ld hl,(reg.ix)          ;278d\r
+       jr l2795h               ;2790\r
+\r
+x2792:\r
+       ld hl,(reg.iy)          ;2792\r
+l2795h:\r
+       comst                   ;2795\r
+       ld a,(iy+001h)          ;2799\r
+       comend\r
+       cp 0e9h                 ;279c\r
+       scf                     ;279e\r
+       ret z                   ;279f\r
+       and a                   ;27a0\r
+       ret                     ;27a1\r
+\r
+x27a2:\r
+       comst                   ;27a2\r
+       ld a,(iy+001h)          ;27a6\r
+       comend\r
+       cp 04dh                 ;27a9\r
+       jr z,x27c9              ;27ab\r
+       cp 045h                 ;27ad\r
+       jr z,x27c9              ;27af\r
+       and a                   ;27b1\r
+       ret                     ;27b2\r
+\r
+x27b3:\r
+       comst                   ;27b3\r
+       ld a,(iy+000h)          ;27b7\r
+       comend\r
+       ld (XBEDD),a            ;27ba\r
+       ld hl,(REG.F)           ;27bd\r
+       push hl                 ;27c0\r
+       pop af                  ;27c1\r
+       call XBEDD              ;27c2\r
+       scf                     ;27c5\r
+       jr c,x27c9              ;27c6\r
+       ret                     ;27c8\r
+\r
+x27c9:\r
+       ld a,(XBFE8)            ;27c9\r
+       and a                   ;27cc\r
+       jr nz,l27dah            ;27cd\r
+       ld a,(TCFLG)            ;27cf\r
+       and a                   ;27d2\r
+       jr z,l27dah             ;27d3\r
+       call l27dah             ;27d5\r
+       pop hl                  ;27d8\r
+       ret                     ;27d9\r
+l27dah:\r
+       ld hl,(REG.SP)          ;27da\r
+       comst                   ;27dd\r
+       ld e,(hl)               ;27e1\r
+       inc hl                  ;27e2\r
+       ld d,(hl)               ;27e3\r
+       comend\r
+       ex de,hl                ;27e4\r
+       call sub_1117h          ;27e5\r
+       and a                   ;27e8\r
+       ret                     ;27e9\r
+\r
+x27ea:\r
+       ld a,(ddtrst)           ;27ea\r
+       comst                   ;27ed\r
+       cp (iy+000h)            ;27f1\r
+       comend\r
+       ret z                   ;27f4\r
+       comst                   ;27f5\r
+       ld a,(iy+000h)          ;27f9\r
+       comend\r
+       and 038h                ;27fc\r
+       ld l,a                  ;27fe\r
+       ld h,000h               ;27ff\r
+       ld a,(XBFE8)            ;2801\r
+       and a                   ;2804\r
+       jr nz,l280ch            ;2805\r
+       ld a,(TCFLG)            ;2807\r
+       and a                   ;280a\r
+       ret nz                  ;280b\r
+l280ch:\r
+       scf                     ;280c\r
+       ret                     ;280d\r
+\r
+x280e:\r
+       and a                   ;280e\r
+       ret                     ;280f\r
+\r
+CMD.C:\r
+       ld hl,CMD.C             ;2810\r
+       ld a,001h               ;2813\r
+       jr l281bh               ;2815\r
+\r
+CMD.T:\r
+       xor a                   ;2817\r
+       ld hl,CMD.T             ;2818\r
+l281bh:\r
+       ld (CMD_RPT),hl         ;281b\r
+       ld (TCFLG),a            ;281e\r
+       ld a,(de)               ;2821\r
+       sub 'N'                 ;2822\r
+       jr nz,l2827h            ;2824\r
+       inc de                  ;2826\r
+l2827h:\r
+       ld (TCNFLG),a           ;2827\r
+       ld a,(de)               ;282a\r
+       sub 'J'                 ;282b\r
+       jr nz,l2830h            ;282d\r
+       inc de                  ;282f\r
+l2830h:\r
+       ld (TRJFLG),a           ;2830\r
+       call sub_289fh          ;2833\r
+       jr z,l283eh             ;2836\r
+       ld hl,1                 ;2838\r
+       call get_lastarg_def    ;283b\r
+l283eh:\r
+       ld (TCCSTR),hl          ;283e\r
+       sub a                   ;2841\r
+       ld (XA747),a            ;2842\r
+l2845h:\r
+       call sub_26e7h          ;2845\r
+       jr l289ch               ;2848\r
+l284ah:\r
+       call sub_0e68h          ;284a\r
+       ld a,(TRJFLG)           ;284d\r
+       and a                   ;2850\r
+       jr nz,l2864h            ;2851\r
+       ld iy,(REG.PC)          ;2853\r
+       call sub_28c1h          ;2857\r
+       jr z,l2864h             ;285a\r
+       ld hl,l2726h            ;285c\r
+       call lookup_opc         ;285f\r
+       jr nc,l2845h            ;2862\r
+l2864h:\r
+       ld a,(XBFEA)            ;2864\r
+       and a                   ;2867\r
+       jr z,l2881h             ;2868\r
+       ld de,(TCCSTR)          ;286a\r
+       call EXPR               ;286e\r
+       ld a,h                  ;2871\r
+       or l                    ;2872\r
+       add a,0ffh              ;2873\r
+       sbc a,a                 ;2875\r
+       ld hl,XBFEA             ;2876\r
+       xor (hl)                ;2879\r
+       bit 1,a                 ;287a\r
+       jr z,l288ch             ;287c\r
+l287eh:\r
+       jp l102eh               ;287e\r
+l2881h:\r
+       ld hl,(TCCSTR)          ;2881\r
+       dec hl                  ;2884\r
+       ld (TCCSTR),hl          ;2885\r
+       ld a,h                  ;2888\r
+       or l                    ;2889\r
+       jr z,l287eh             ;288a\r
+l288ch:\r
+       call sub_26e7h          ;288c\r
+       jr nc,l287eh            ;288f\r
+       ld a,(TCNFLG)           ;2891\r
+       ld b,a                  ;2894\r
+       ld a,(XA747)            ;2895\r
+       or b                    ;2898\r
+       ld (XA747),a            ;2899\r
+l289ch:\r
+       jp l1183h               ;289c\r
+\r
+sub_289fh:\r
+       call SKIPBL             ;289f\r
+       xor a                   ;28a2\r
+       ld (XBFEA),a            ;28a3\r
+       ld a,(de)               ;28a6\r
+       cp 'U'                  ;28a7\r
+       jr z,l28aeh             ;28a9\r
+       cp 'W'                  ;28ab\r
+       ret nz                  ;28ad\r
+\r
+l28aeh:\r
+       inc de                  ;28ae\r
+       push af                 ;28af\r
+       push de                 ;28b0\r
+       call EXPR               ;28b1\r
+       jp c,ERROR              ;28b4\r
+       call assert_eol         ;28b7\r
+       pop hl                  ;28ba\r
+       pop af                  ;28bb\r
+       ld (XBFEA),a            ;28bc\r
+       sub a                   ;28bf\r
+       ret                     ;28c0\r
+\r
+sub_28c1h:\r
+       comst           \r
+       ld a,(iy+000h)  \r
+       ld b,(iy+0001)\r
+       comend\r
+       cp 0edh         \r
+       jr z,l28dbh     \r
+       and 0dfh        \r
+       cp 0ddh         \r
+       ret nz          \r
+       ld a,b\r
+       cp 0e9h         \r
+       ret             \r
+l28dbh:\r
+       ld a,b\r
+       and 0f7h        \r
+       cp 045h         \r
+       ret             \r
+\r
+?excom:\r
+       ex (sp),hl              ;28e7\r
+       push af                 ;28e8\r
+       push bc                 ;28e9\r
+       push de                 ;28ea\r
+       ld c,(hl)               ;28eb\r
+       ld b,000h               ;28ec\r
+       inc hl                  ;28ee\r
+       ld a,?lcmax\r
+       sub c\r
+       ld de,?exeit            ;28ef\r
+       ldir\r
+       ex de,hl\r
+       ld (hl),018h\r
+       inc hl\r
+       ld (hl),a\r
+       ex de,hl\r
+       pop de                  ;28f7\r
+       pop bc                  ;28f8\r
+       pop af                  ;28f9\r
+       ex (sp),hl              ;28fa\r
+?exclst:\r
+       push hl                 ;28fb\r
+       ld hl,(ubbr)            ;2900\r
+\r
+       if ROMSYS\r
+        push af                ;28fc\r
+        ld a,(uromen)          ;28fd\r
+       endif\r
+       jp ?comcod              ;2903\r
+       \r
+;------------------------------------------\r
+;      ddtram\r
+;------------------------------------------\r
+\r
+vartab:\r
+       dseg\r
+ddtram:                                \r
+;todo:\r
+; The following 2 params are changeable by user.\r
+; Should these moved to top ram?\r
+;\r
+ddtrst:        inidat                  ;\r
+       rst     DRSTNUM         ;rst used by ddtz\r
+       inidate                 ;\r
+ddtei: inidat                  ;\r
+       ei                      ;ints enabled/disabled while ddtz is running\r
+       ret                     ;\r
+       inidate                 ;\r
+offs.pc:\r
+       inidat  \r
+       dw      TPA     \r
+       inidate\r
+offs.@:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+CMD_ERR:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+CMD_RPT:\r
+       inidat\r
+       dw      DDTZML  \r
+       inidate\r
+ci.buf:\r
+       inidat\r
+       db      80      \r
+       rept    83\r
+       db      0\r
+       endm\r
+       inidate\r
+CON.COL:\r
+       inidat\r
+       db      0       \r
+       inidate\r
+XA747:\r
+       inidat\r
+       db      0       \r
+       inidate\r
+bp_tab:\r
+       inidat\r
+       rept    BP_CNT  \r
+       db      0,0\r
+       dw      0,0,0\r
+       endm\r
+BP_SIZE        equ     8\r
+       inidate\r
+sexp1:\r
+       inidat\r
+       dw      sexpbuf \r
+       inidate\r
+sexp2:\r
+       inidat\r
+       dw      sexpbuf \r
+       inidate\r
+sexpbuf:\r
+       inidat\r
+       rept    128     \r
+       db      0\r
+       endm\r
+       inidate\r
+sexpbufe:\r
+\r
+msg.Y:\r
+       inidat\r
+       dc      'Y0'    \r
+       inidate\r
+reg.Y:\r
+       inidat\r
+       rept    10      \r
+       dw      0\r
+       endm\r
+       inidate\r
+lst.S:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+lst.IP:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+lst.OP:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+lst.OD:\r
+       inidat\r
+       db      0\r
+       inidate\r
+lst.Qj:\r
+       inidat\r
+       db      0\r
+       inidate\r
+lst.D:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+HILOD:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+MAXLOD:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+XB068:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+lst.A:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+XB06C:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+pfx.IXY:\r
+       inidat\r
+       db      000h    \r
+       inidate\r
+is.pfx.IXY:\r
+       inidat\r
+       db      000h    \r
+       inidate\r
+lst.L:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+XBE01:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+XBE03:\r
+       inidat\r
+       db      000h    \r
+       inidate\r
+XBEDD:\r
+       inidat\r
+       ret             ;ret cc\r
+       and a           \r
+       pop hl          \r
+       inc hl          \r
+       jp (hl)         \r
+       inidate\r
+XBFE8:\r
+       inidat\r
+       db      0       \r
+       inidate\r
+TCFLG:\r
+       inidat\r
+       db      0       \r
+       inidate\r
+XBFEA:\r
+       inidat\r
+       db      0       \r
+       inidate\r
+TCCSTR:\r
+       inidat\r
+       dw      0       \r
+       inidate\r
+TCNFLG:\r
+       inidat\r
+       db      0       \r
+       inidate\r
+TRJFLG:\r
+       inidat\r
+       db      0       \r
+       inidate\r
+wstrtflg:\r
+       inidat\r
+       db      1\r
+       inidate\r
+\r
+       cseg\r
+vartabe:\r
+\r
+;------------------------------------------\r
+\r
+       .phase  sysram_start+stacksize\r
+$stack:\r
+$stcka equ     $ - stacksize\r
+\r
+curphse        defl    $\r
+       .dephase\r
+sysramc:\r
+       .phase curphse\r
+topcodbeg:\r
+\r
+reg.l2:        db      0               ; 0fe50h\r
+reg.h2:        db      0               ; 0fe51h\r
+reg.e2:        db      0               ; 0fe52h\r
+reg.d2:        db      0               ; 0fe53h\r
+reg.c2:        db      0               ; 0fe54h\r
+reg.b2:        db      0               ; 0fe55h\r
+reg.f2:        db      0               ; 0fe56h\r
+reg.a2:        db      0               ; 0fe57h\r
+       db      0\r
+reg.i: db      high ivtab\r
+reg.iy:        dw      0               ; 0fe5ah\r
+reg.ix:        dw      0               ; 0fe5ch\r
+reg.e: db      0               ; 0fe5eh\r
+reg.d: db      0               ; 0fe5fh\r
+reg.c: db      0               ; 0fe60h\r
+reg.b: db      0               ; 0fe61h\r
+       if      ROMSYS\r
+udcntl:         db     CWAITIO         ; 0fe62h        (mem-, io- wait)\r
+uromen:         db     ROM_DIS         ; 0fe63h\r
+       endif\r
+ubbr:  db      0               ; 0fe64h\r
+ucbar: db      USR$CBAR        ; 0fe65h\r
+reg.f: db      0               ; 0fe66h\r
+reg.a: db      0               ; 0fe67h\r
+reg.l: db      0               ; 0fe68h\r
+reg.h: db      0               ; 0fe69h\r
+reg.sp:        dw      TOPRAM          ; 0fe6ah\r
+\r
+$go:\r
+       if      ROMSYS\r
+        out (000h),a           ;064c fe6c\r
+        out0 (dcntl),l         ;064e\r
+        pop hl                 ;0651\r
+       endif\r
+       out0 (cbar),h           ;0652\r
+       out0 (bbr),l            ;0655\r
+       pop af                  ;0658\r
+       pop hl                  ;0659\r
+       ld sp,(reg.sp)          ;065a\r
+reg.iff:\r
+       ei                      ;065e\r
+       db      0C3h            ;jp TPA ;065f feff ($+1): reg.pc\r
+reg.pc:\r
+       dw      TPA\r
+                               \r
+bpent:\r
+       ld (reg.l),hl           ;0662 fe82: bpent:\r
+       pop hl                  ;0665\r
+       dec hl                  ;0666\r
+       ld (reg.pc),hl          ;0667\r
+       ld (reg.sp),sp          ;066a\r
+       ld sp,reg.l             ;066e\r
+       push af                 ;0671\r
+       in0 h,(cbar)            ;0672\r
+       in0 l,(bbr)             ;0675\r
+       push hl                 ;0678\r
+       ld a,SYS$CBAR           ;0679\r
+       out0 (cbar),a           ;067b\r
+\r
+       if ROMSYS\r
+        in0 l,(dcntl)          ;067e\r
+        ld a,CWAITROM+CWAITIO  ;0681\r
+        out0 (dcntl),a         ;0683\r
+        ld a,($crom)           ;0686\r
+        cp c$rom               ;0689\r
+        ld a,ROM_EN            ;068b\r
+        out (000h),a           ;068d\r
+       endif\r
+\r
+       jp bpddtz               ;068f\r
+\r
+?comcod:\r
+       if ROMSYS\r
+        out (000h),a           ;0692 feb2\r
+        pop af                 ;069a\r
+       endif\r
+\r
+       out0 (cbar),h           ;0694\r
+       out0 (bbr),l            ;0697\r
+       pop hl                  ;069b\r
+?exeit:\r
+       ds ?lcmax+2\r
+       push af                 ;069f\r
+       ld a,SYS$CBAR           ;06a0\r
+       out0 (cbar),a           ;06a2\r
+\r
+       if ROMSYS\r
+        ld a,ROM_EN            ;06a5\r
+        out (000h),a           ;06a7\r
+       endif\r
+       \r
+       pop af                  ;06a9\r
+       ret                     ;06aa\r
+\r
+topcodend:\r
+curph  defl    $\r
+       .dephase\r
+sysrame:\r
+\r
+       end\r
+\r
diff --git a/z180/fifoio.180 b/z180/fifoio.180
new file mode 100644 (file)
index 0000000..27745d4
--- /dev/null
@@ -0,0 +1,128 @@
+       page    255\r
+       .z80\r
+       \r
+       global  f.init,f.in,f.out,f.i.st\r
+\r
+       extrn   buf.init\r
+\r
+       include config.inc\r
+       include z180reg.inc\r
+\r
+\r
+;--------------------------------------------------------------\r
+\r
+       dseg\r
+       \r
+\r
+       mkbuf   rx.buf,rx.buf_len\r
+       mkbuf   tx.buf,tx.buf_len\r
+\r
+\r
+;--------------------------------------------------------------\r
+\r
+       cseg\r
+;\r
+; FIFO channels for communication with stm32\r
+;\r
+; Init Serial I/O for console input and output\r
+;\r
+       \r
+f.init:\r
+       ld      ix,rx.buf\r
+       ld      a,rx.buf.mask\r
+       call    buf.init\r
+       ld      ix,tx.buf\r
+       ld      a,tx.buf.mask\r
+       jp      buf.init\r
+\r
+\r
+f.i.st:\r
+       push    ix\r
+       ld      ix,rx.buf               ;\r
+\r
+buf.empty:\r
+       ld      a,(ix+o.in_idx)         ;\r
+       sub     (ix+o.out_idx)          ;\r
+       pop     ix\r
+       ret     z\r
+       or      0ffh\r
+       ret\r
+       \r
+\r
+f.in:\r
+       push    ix\r
+       ld      ix,rx.buf               ;\r
+\r
+buf.get:\r
+       ld      a,(ix+o.out_idx)        ;\r
+bg.wait:\r
+       cp      (ix+o.in_idx)           ;\r
+       jr      z,bg.wait\r
+\r
+       push    hl                      ;\r
+       push    ix\r
+       pop     hl\r
+       add     a,l\r
+       ld      l,a\r
+       jr      nc,bg.nc\r
+       inc     h\r
+bg.nc:\r
+       ld      l,(hl)\r
+       \r
+       ld      a,(ix+o.out_idx)        ;\r
+       inc     a\r
+       and     (ix+o.mask)\r
+       ld      (ix+o.out_idx),a\r
+       \r
+       ld      a,l\r
+       pop     hl\r
+       pop     ix\r
+       ret\r
+\r
+\r
+f.o.st:\r
+       push    ix\r
+       ld      ix,tx.buf               ;\r
+\r
+buf.full:\r
+       ld      a,(ix+o.in_idx)         ;\r
+       inc     a\r
+       and     (ix+o.mask)\r
+       sub     (ix+o.out_idx)          ;\r
+       pop     ix\r
+       ret     z\r
+       or      0ffh\r
+       ret\r
+\r
+\r
+f.out:\r
+       push    ix\r
+       ld      ix,tx.buf               ;\r
+\r
+buf.put:\r
+       push    hl                      ;\r
+       push    bc\r
+       push    ix\r
+       pop     hl\r
+       ld      c,(ix+o.in_idx)         ;\r
+       ld      b,0\r
+       add     hl,bc\r
+       ld      b,a\r
+\r
+       ld      a,c                     ;\r
+       inc     a\r
+       and     (ix+o.mask)\r
+bp.wait:\r
+       cp      (ix+o.out_idx)          ;\r
+       jr      z,bp.wait\r
+       ld      (hl),b\r
+       ld      (ix+o.in_idx),a\r
+       \r
+       ld      a,b\r
+       pop     bc\r
+       pop     hl\r
+       pop     ix\r
+       ret\r
+\r
+       end\r
+\r
diff --git a/z180/msgbuf.180 b/z180/msgbuf.180
new file mode 100644 (file)
index 0000000..2c67527
--- /dev/null
@@ -0,0 +1,129 @@
+       page    255\r
+       .z80\r
+       \r
+       global  msg_fifo\r
+       global  msginit\r
+       global  msg.out,msg.sout,msg.co\r
+       \r
+       extrn   buf.init\r
+\r
+       include config.inc\r
+       include z180reg.inc\r
+\r
+;--------------------------------------------------------------\r
+\r
+       dseg\r
+\r
+       mkbuf   msg_fifo, 0\r
+\r
+\r
+;--------------------------------------------------------------\r
+\r
+       cseg\r
+\r
+;\r
+; Init buffer\r
+;\r
+       \r
+msginit:\r
+       ld      ix,msg_fifo\r
+       ld      a,msg_fb_len-1\r
+       jp      buf.init\r
+\r
+\r
+;--------------------------------------------------------------\r
+\r
+msg.sts:\r
+       push    ix\r
+       ld      ix,msg_fifo             ;\r
+\r
+       ld      a,(ix+o.in_idx)         ;\r
+       inc     a\r
+       and     (ix+o.mask)\r
+       sub     (ix+o.out_idx)          ;\r
+       pop     ix\r
+       ret     z\r
+       or      0ffh\r
+       ret\r
+\r
+;--------------------------------------------------------------\r
+\r
+msg.out:\r
+       push    ix\r
+       ld      ix,msg_fifo             ;\r
+\r
+       push    bc\r
+       ld      b,a                     ;save char\r
+       ld      a,(ix+o.in_idx)         ;\r
+       inc     a\r
+       and     (ix+o.mask)\r
+bp.wait:\r
+       cp      (ix+o.out_idx)          ;\r
+       jr      z,bp.wait\r
+       ld      c,a\r
+       ld      a,b\r
+       out     (PMSG),a\r
+       ld      (ix+o.in_idx),c\r
+       \r
+       pop     bc\r
+       pop     ix\r
+       ret\r
+\r
+;--------------------------------------------------------------\r
+;\r
+; (hl): data\r
+  \r
+msg.sout:\r
+       push    ix\r
+       ld      ix,msg_fifo             ;\r
+       push    bc\r
+\r
+       ld      b,(hl)                  ;count\r
+       inc     hl\r
+obs_1:\r
+       ld      a,(ix+o.out_idx)        ;\r
+       sub     (ix+o.in_idx)           ;\r
+       dec     a\r
+       and     (ix+o.mask)\r
+       cp      b\r
+       jr      c,obs_1\r
+\r
+       ld      c,(hl)                  ;port address\r
+       inc     hl\r
+       ld      a,b\r
+       otir\r
+       add     (ix+o.in_idx)\r
+       and     (ix+o.mask)\r
+       ld      (ix+o.in_idx),a\r
+       pop     bc\r
+       pop     ix\r
+       ret\r
+\r
+;----------------------------------------------------------------------\r
+\r
+msg.co:\r
+       push    af\r
+       push    hl\r
+       ld      (buf_char),a\r
+       ld      hl,buf\r
+       call    msg.sout\r
+       pop     hl\r
+       pop     af\r
+       ret\r
+       \r
+       \r
+buf:\r
+       db      buf_end - $ - 2         ;output string length\r
+       db      PMSG                    ;output port\r
+       db      081h                    ; message start token\r
+       db      buf_end - $ - 1         ; message length\r
+       db      1                       ; command\r
+       db      1                       ; subcommand\r
+buf_char:\r
+       db      0                       ; pay load\r
+buf_end:\r
+\r
+;----------------------------------------------------------------------\r
+\r
+       end\r
+\r
diff --git a/z180/r3init.180 b/z180/r3init.180
new file mode 100644 (file)
index 0000000..7ba9a0c
--- /dev/null
@@ -0,0 +1,883 @@
+       page    255\r
+       .z80\r
+\r
+       extrn ddtz,bpent\r
+       extrn $stack\r
+       extrn $coninit,$cists,$ci\r
+\r
+       extrn romend\r
+\r
+\r
+       global  isv_sw\r
+\r
+       include config.inc\r
+       include z180reg.inc\r
+       include z180.lib\r
+       \r
+;CR    equ     0dh\r
+\r
+\r
+\r
+;----------------------------------------------------------------------\r
+\r
+       cseg\r
+\r
+       jp start                \r
+\r
+; restart vectors\r
+\r
+rsti   defl    1\r
+       rept    7\r
+        db 0, 0, 0, 0, 0\r
+        jp bpent\r
+rsti    defl rsti+1\r
+       endm\r
+\r
+;----------------------------------------------------------------------\r
+\r
+       if ROMSYS\r
+$crom:  defb c$rom             ;\r
+       else\r
+        db     0               ;\r
+       endif\r
+\r
+dmclrt:                                ;clear ram per dma\r
+       db      dmct_e-dmclrt-2 ;\r
+       db      sar0l           ;first port\r
+       dw      nullbyte        ;src (fixed) \r
+nullbyte:\r
+       db      000h            ;src\r
+       dw      romend          ;dst (inc), start after "rom" code\r
+       db      00h             ;dst\r
+       dw      0-romend        ;count (64k)\r
+dmct_e:\r
+\r
+INIWAITS defl  CWAITIO\r
+       if      ROMSYS\r
+INIWAITS defl  INIWAITS+CWAITROM\r
+       endif\r
+\r
+hwini0:\r
+       db      3               ;count\r
+       db      rcr,CREFSH      ;configure DRAM refresh\r
+       db      dcntl,INIWAITS  ;wait states\r
+       db      cbar,SYS$CBAR\r
+\r
+;----------------------------------------------------------------------\r
+\r
+start:\r
+       push af                 ;003c\r
+       in0 a,(itc)             ;003d   Illegal opcode trap?\r
+       jp p,??st01             ;0040\r
+       pop af                  ;0043\r
+       jp bpent                ;0044     yes, handle\r
+\r
+??st01:\r
+       ld a,i                  ;0047   I register == 0 ? \r
+       jr z,??st02             ;004b     yes, harware reset\r
+       pop af                  ;004d   \r
+       jp bpent                ;004e     no, allready set up\r
+\r
+??st02:\r
+       di                      ;0058\r
+       ld      a,CREFSH\r
+       out0    (rcr),a         ;       configure DRAM refresh\r
+       ld      a,CWAITIO\r
+       out0    (dcntl),a       ;       wait states\r
+\r
+; search warm start mark\r
+\r
+       ld ix,mark_55AA         ;00b8   ; top of common area\r
+       ld a,SYS$CBAR           ;\r
+       out0 (cbar),a           ;\r
+       ld a,071h               ;00bc\r
+       ex af,af'               ;00be   ;for cbr = 0x70 downto 0x40\r
+swsm_l:\r
+       ex af,af'               ;00bf   \r
+       dec a                   ;00c0\r
+       cp 03fh                 ;00c1\r
+       jr z,kstart             ;00c3   ;  break (mark not found)\r
+       out0 (cbr),a            ;00c5\r
+       ex af,af'               ;00c8\r
+       ld a,0aah               ;00c9\r
+       cp (ix+000h)            ;00cb\r
+       jr nz,swsm_l            ;00ce\r
+       cp (ix+002h)            ;00d0\r
+       jr nz,swsm_l            ;00d3\r
+       cpl                     ;00d5\r
+       cp (ix+001h)            ;00d6\r
+       jr nz,swsm_l            ;00d9\r
+       cp (ix+003h)            ;00db\r
+       jr nz,swsm_l            ;00de\r
+       ld sp,$stack            ;00e0   mark found, check\r
+       call checkcrc_alv       ;00e3\r
+       jp z,wstart             ;00e6   check ok,\r
+\r
+;\r
+; ram not ok, initialize    --  kstart --\r
+\r
+kstart:\r
+\r
+       ld      a,088h          ;00e9   0000-7fff: common 0\r
+       out0    (cbar),a        ;00eb   8000-ffff: common 1\r
+       ld      ix,08000h       ;00f3\r
+       ld      a,0             ;00f1   start at 008000 (2. phys. 32k block)\r
+??f_0:\r
+       out0    (cbr),a         ;00f9\r
+\r
+       ld      (ix+0),a        ;0103   \r
+       cpl\r
+       ld      (ix+1),a        ;0103   \r
+       cpl\r
+       add     a,8             ;010a   next 'bank'\r
+       cp      078h            ;010c   stop at 078000\r
+       jr      nz,??f_0        ;010e\r
+\r
+       ld      de,8000h        ;0114   first block not tested, but mark as ok\r
+       ld      a,0             ;00f1   start at 008000 (2. phys. 32k block)\r
+??cp_0:\r
+       out0    (cbr),a         ;011c\r
+       ld      c,a\r
+       xor     (ix+0)\r
+       ld      b,a\r
+       ld      a,c\r
+       cpl\r
+       xor     (ix+1)\r
+       or      b\r
+       jr      nz,??cp_1\r
+       scf\r
+??cp_1:\r
+       rr      d\r
+       rr      e\r
+       ld      a,c\r
+       add     a,8\r
+       cp      078h            ;       stop at 078000\r
+       jr      nz,??cp_0\r
+       \r
+;\r
+;  ram test found 1 or more error free blocks (32k)\r
+;\r
+\r
+ramok:\r
+       ld      a,SYS$CBAR      ;01c8\r
+       out0    (cbar),a        ;01ca\r
+       ld      h,d\r
+       ld      l,e\r
+       ld      c,070h          ;01ce   highest block\r
+       ld      b,15            ;01d0\r
+??sr_1:\r
+       add     hl,hl\r
+       jr      c,alloc         ;01d4   highest "error free" block\r
+       ld      a,c             ;01d6\r
+       sub     008h            ;01d7\r
+       ld      c,a             ;01d9\r
+       djnz    ??sr_1          ;01da\r
+\r
+       slp                     ;01dc   should never be reached\r
+\r
+alloc:\r
+       out0    (cbr),c         ;01de\r
+       ld      sp,$stack       ;01e1\r
+       \r
+; Clear RAM using DMA0\r
+\r
+       ld      hl,dmclrt       ;load DMA registers\r
+       call    io.ini.m\r
+       ld      a,0cbh          ;01ef   dst +1, src fixed, burst\r
+       out0    (dmode),a       ;01f1\r
+\r
+       ld      b,512/64\r
+       ld      a,062h          ;01f4   enable dma0, \r
+??cl_1:\r
+       out0    (dstat),a       ;01f9   clear (up to) 64k\r
+       djnz    ??cl_1          ;       end of RAM?\r
+       \r
+; Init bank manager\r
+       \r
+       ld      hl,banktabsys   ;020f\r
+       ld      (hl),c          ;       Common area\r
+       inc     hl              ;0213\r
+       ld      (hl),c          ;       System work area\r
+       inc     hl              ;0215   Point to bank 0 entry\r
+       ld      b,BANKS         ;0216\r
+l0218h:\r
+       ld      (hl),0ffh       ;0218   Mark all banks as unassigned\r
+       inc     hl              ;021a\r
+       djnz    l0218h          ;021b\r
+\r
+       ld      hl,memalv       ;\r
+       ld      b,8             ;       8*4k ie. first 32k\r
+??a_0:\r
+       ld      (hl),0e0h       ;       mark as sys ("rom"/monitor)\r
+       inc     hl\r
+       djnz    ??a_0\r
+       \r
+       rr      d               ;       shift out bit for block 0\r
+       rr      e               ;\r
+       ld      c,15            ;022c   15*32k remaining blocks\r
+l022eh:\r
+       ld      a,0feh          ;       0xfe == block with error(s)\r
+       rr      d               ;\r
+       rr      e\r
+       adc     a,0             ;       ==> 0xff : block ok\r
+       ld      b,32/4          ;       32k == 8 * 4k   \r
+l0236h:\r
+       ld      (hl),a          ;\r
+       inc     hl              ;\r
+       djnz    l0236h          ;\r
+       dec     c               ;\r
+       jr      nz,l022eh       ;next 32k block\r
+       \r
+       ld      hl,memalv+0ch   ;memalv+0ch\r
+       ld      a,(banktabsys)  ;\r
+       call    add_hl_a\r
+       ld      b,3             ;\r
+l024ah:\r
+       ld      (hl),0ech       ;alloc system ram\r
+       inc     hl              ;\r
+       djnz    l024ah          ;\r
+       ld      (hl),0efh       ;alloc common\r
+       call    gencrc_alv\r
+\r
+       ld      hl,0000h        ;bank # \r
+       ld      bc,0f0fh        ;  size (?) (4k blocks)\r
+       xor     a               ;\r
+       call    sub_0420h       ;alloc mem for bank 0\r
+       ld      c,l             ;\r
+       or      a               ;\r
+       call    z,sub_04b5h     ;\r
+\r
+       ld      hl,0101h        ;\r
+       ld      bc,0f0fh        ;\r
+       xor     a               ;\r
+       call    sub_0420h       ;\r
+       ld      c,l             ;\r
+       or      a               ;\r
+       call    z,sub_04b5h     ;\r
+\r
+       ld      hl,055AAh       ;set warm start mark\r
+       ld      (mark_55AA),hl  ;\r
+       ld      (mark_55AA+2),hl;\r
+\r
+;\r
+; crc ok       --  wstart  --\r
+;\r
+wstart:\r
+       call    sysram_init     ;027f\r
+       call    ivtab_init\r
+\r
+       call    prt0_init\r
+\r
+\r
+;;;    call    bufferinit\r
+\r
+\r
+       call    $coninit\r
+\r
+\r
+\r
+\r
+       im 2                    ;?030e\r
+       ei                      ;0282\r
+\r
+       call $cists             ;0284\r
+       call $cists             ;0287\r
+       or a                    ;028a\r
+       call nz,$ci             ;028d\r
+       \r
+       ld a,(banktab)          ;       \r
+       ld e,a                  ;       \r
+       jp ddtz                 ;0290\r
+       \r
+\r
+;\r
+;----------------------------------------------------------------------\r
+;\r
+\r
+;TODO: Make a ringbuffer module.\r
+\r
+       global  buf.init\r
+       \r
+buf.init:\r
+       ld      (ix+o.in_idx),0\r
+       ld      (ix+o.out_idx),0\r
+       ld      (ix+o.mask),a\r
+       ret\r
+\r
+;----------------------------------------------------------------------\r
+\r
+.comment *\r
+\r
+       extrn   msginit,msg.sout,msg_fifo\r
+       extrn   tx.buf,rx.buf\r
+\r
+\r
+bufferinit:\r
+       call     msginit\r
+       \r
+       ld      hl,buffers\r
+       ld      bc,0300h\r
+bfi_1:\r
+       ld      e,(hl)\r
+       inc     hl\r
+       ld      d,(hl)\r
+       inc     hl\r
+       push    hl\r
+       in0     a,cbr\r
+       call    log2phys\r
+       ld      (bufdat+1),hl\r
+       ld      (bufdat+3),a\r
+       ld      a,c\r
+       ld      (bufdat+0),a\r
+       ld      hl,inimsg\r
+       call    msg.sout\r
+       pop     hl\r
+       inc     c\r
+       djnz    bfi_1\r
+       ret\r
+\r
+       rept    20\r
+       db      0\r
+       endm\r
+       \r
+buffers:\r
+       dw      msg_fifo\r
+       dw      tx.buf\r
+       dw      rx.buf\r
+       \r
+inimsg:        \r
+       db      inimsg_e - $ -2\r
+       db      PMSG\r
+       db      81h\r
+       db      inimsg_e - $ -1\r
+       db      0\r
+bufdat:\r
+       db      0\r
+       dw      0\r
+       db      0\r
+inimsg_e:\r
+\r
+       *\r
+\r
+;\r
+;----------------------------------------------------------------------\r
+;\r
+\r
+sysram_init:\r
+       ld hl,sysramw\r
+       ld de,topcodsys\r
+       ld bc,sysrame-sysramw\r
+       ldir\r
+\r
+       ret\r
+\r
+;----------------------------------------------------------------------\r
+\r
+ivtab_init:\r
+       ld      hl,ivtab        ;\r
+       ld      a,h             ;\r
+       ld      i,a             ;\r
+       out0    (il),l          ;\r
+\r
+; Let all vectors point to spurious int routines.\r
+\r
+       ld      d,high sp.int0\r
+       ld      a,low  sp.int0\r
+       ld      b,9\r
+ivt_i1:        \r
+       ld      (hl),a\r
+       inc     l\r
+       ld      (hl),d\r
+       inc     l\r
+       add     a,sp.int.len\r
+       djnz    ivt_i1\r
+       ret\r
+\r
+;----------------------------------------------------------------------\r
+\r
+prt0_init:\r
+       ld      a,i\r
+       ld      h,a\r
+       in0     a,(il)\r
+       and     0E0h\r
+       or      IV$PRT0\r
+       ld      l,a\r
+       ld      (hl),low  iprt0\r
+       inc     hl\r
+       ld      (hl),high iprt0\r
+       ld      hl,prt0itab\r
+       call    io.ini.m\r
+       ret\r
+       \r
+prt0itab:\r
+       db      prt0it_e-prt0itab-2\r
+       db      tmdr0l\r
+       dw      PRT_TC10MS\r
+       dw      PRT_TC10MS\r
+       db      M_TIE0+M_TDE0   ;enable timer 0 interrupt and down count.\r
+prt0it_e:\r
+\r
+\r
+;\r
+;----------------------------------------------------------------------\r
+;\r
+\r
+io.ini:\r
+       push    bc\r
+       ld      b,0             ;high byte port adress\r
+       ld      a,(hl)          ;count\r
+       inc     hl\r
+ioi_1:\r
+       ld      c,(hl)          ;port address\r
+       inc     hl\r
+       outi\r
+       inc     b               ;outi decrements b\r
+       dec     a\r
+       jr      nz,ioi_1\r
+       pop     bc\r
+       ret\r
+\r
+io.ini.m:\r
+       push    bc\r
+       ld      b,(hl)\r
+       inc     hl\r
+       ld      c,(hl)\r
+       inc     hl\r
+       otimr   \r
+       pop     bc      \r
+       ret\r
+       \r
+io.ini.l:\r
+;\r
+\r
+;----------------------------------------------------------------------\r
+;\r
+\r
+; compute crc\r
+; hl: start adr\r
+; bc: len\r
+; bc returns crc val\r
+\r
+do_crc16:\r
+       ld      de,0FFFFh\r
+crc1:\r
+       ld      a,(hl)\r
+       xor     e\r
+       ld      e,a\r
+       rrca\r
+       rrca\r
+       rrca\r
+       rrca\r
+       and     0Fh\r
+       xor     e\r
+       ld      e,a\r
+       rrca\r
+       rrca\r
+       rrca\r
+       push    af\r
+       and     1Fh\r
+       xor     d\r
+       ld      d,a\r
+       pop     af\r
+       push    af\r
+       rrca\r
+       and     0F0h\r
+       xor     d\r
+       ld      d,a\r
+       pop     af\r
+       and     0E0h\r
+       xor     e\r
+       ld      e,d\r
+       ld      d,a\r
+       cpi\r
+       jp      pe,crc1\r
+       or      e               ;z-flag\r
+       ret\r
+\r
+\r
+gencrc_alv:\r
+       push hl                 ;03f6\r
+       push de                 ;03f7\r
+       push bc\r
+       push af                 ;03f8\r
+       ld hl,banktabsys        ;03f9\r
+       ld bc,crc_len           ;03fc\r
+       call do_crc16           ;03ff\r
+       ld (hl),e\r
+       inc hl\r
+       ld (hl),d\r
+       pop af                  ;0406\r
+       pop bc\r
+       pop de                  ;0407\r
+       pop hl                  ;0408\r
+       ret                     ;0409\r
+\r
+checkcrc_alv:\r
+       push hl                 ;040a\r
+       push de\r
+       push bc                 ;040b\r
+       ld hl,banktabsys        ;040d\r
+       ld bc,crc_len+2         ;0410\r
+       call do_crc16           ;0413\r
+       pop bc                  ;041d\r
+       pop de\r
+       pop hl                  ;041e\r
+       ret                     ;041f\r
+\r
+;----------------------------------------------------------------------\r
+\r
+;\r
+;  alloc\r
+;\r
+;      h:      max bank #\r
+;      l:      min bank #\r
+;      b:      max size\r
+;      c:      min size\r
+;\r
+;    ret:\r
+;      a:      0  == ok\r
+;              1  == \r
+;              2  == no bank # in requested range\r
+;              ff == crc error\r
+;\r
+\r
+sub_0420h:\r
+       call checkcrc_alv       ;0420\r
+       jr nz,l049ch            ;0424   crc error, tables corrupt\r
+       \r
+       call sub_049dh          ;0427   bank # in req. range available?\r
+       jr c,l0499h             ;042a\r
+       push ix                 ;042c\r
+       push iy                 ;042e\r
+       push de                 ;0430\r
+       push hl                 ;0431\r
+       push bc                 ;0432\r
+       ld c,b                  ;0433\r
+       ld b,alv_len+1          ;0434\r
+       ld d,0                  ;0436\r
+       ld hl,memalv-1          ;0438\r
+       jr l0441h               ;043b\r
+\r
+; find free blocks\r
+\r
+l043dh:\r
+       ld a,(hl)               ;043d\r
+       inc a                   ;043e   free blocks are marked 0ffh\r
+       jr z,l0446h             ;043f\r
+l0441h:\r
+       inc hl                  ;0441\r
+       djnz l043dh             ;0442\r
+       jr l0464h               ;0444\r
+l0446h:\r
+       push hl                 ;0446   \r
+       pop ix                  ;0447   free blocks start here\r
+       ld e,000h               ;0449\r
+       jr l0451h               ;044b\r
+l044dh:                                ;       count free blocks\r
+       ld a,(hl)               ;044d\r
+       inc a                   ;044e\r
+       jr nz,l0457h            ;044f\r
+l0451h:\r
+       inc e                   ;0451\r
+       inc hl                  ;0452\r
+       djnz l044dh             ;0453\r
+       jr l0464h               ;0455\r
+\r
+; end of free blocks run. \r
+\r
+l0457h:\r
+       ld a,d                  ;0457\r
+       cp e                    ;0458   nr of blocks >= requested ?\r
+       jr nc,l0441h            ;0459   \r
+\r
+       ld d,e                  ;045b\r
+       push ix                 ;045c\r
+       pop iy                  ;045e\r
+       ld a,d                  ;0460\r
+       cp c                    ;0461\r
+       jr c,l0441h             ;0462\r
+l0464h:\r
+       pop bc                  ;0464\r
+       ld a,d                  ;0465\r
+       cp b                    ;0466\r
+       jr c,l046ch             ;0467\r
+       ld d,b                  ;0469\r
+       jr l0471h               ;046a\r
+l046ch:\r
+       cp c                    ;046c\r
+       jr nc,l0471h            ;046d\r
+       ld d,000h               ;046f\r
+l0471h:\r
+       ld a,d                  ;0471\r
+       push iy                 ;0472\r
+       pop hl                  ;0474\r
+       ld de,memalv            ;0475\r
+       or a                    ;0478\r
+       sbc hl,de               ;0479\r
+       ld b,l                  ;047b\r
+       ld c,a                  ;047c\r
+       pop hl                  ;047d\r
+l047eh:\r
+       or a                    ;047e\r
+       jr z,l0489h             ;047f\r
+       ld (iy+0),l             ;0481\r
+       inc iy                  ;0484\r
+       dec a                   ;0486\r
+       jr l047eh               ;0487\r
+l0489h:\r
+       pop de                  ;0489\r
+       pop iy                  ;048a\r
+       pop ix                  ;048c\r
+       call gencrc_alv         ;048e\r
+       ld a,c                  ;0491\r
+       or a                    ;0492\r
+       ld a,000h               ;0493\r
+       ret nz                  ;0495\r
+       or 001h                 ;0496\r
+       ret                     ;0498\r
+\r
+l0499h:\r
+       ld a,2                  ;0499\r
+l049ch:\r
+       or a\r
+       ret                     ;049c\r
+\r
+\r
+; search a free bank number in range\r
+;      h: max #\r
+;      l: min #\r
+;    ret:\r
+;      l: bank number available\r
+;      nc, if found, bank nr. in l\r
+;      cy, if none found\r
+\r
+sub_049dh:\r
+       push de                 ;049d\r
+       push bc                 ;049e\r
+       ex de,hl                ;049f\r
+       dec e                   ;04a0\r
+l04a1h:\r
+       inc e                   ;04a1   test next #\r
+       ld a,d                  ;04a2\r
+       cp e                    ;04a3\r
+       jr c,l04b1h             ;04a4   \r
+       ld a,e                  ;04a6\r
+       ld hl,memalv            ;04a7\r
+       ld bc,alv_len           ;04aa\r
+       cpir                    ;04ad   bank# allready allocated?\r
+       jr z,l04a1h             ;04af   if yes, search for next\r
+l04b1h:\r
+       ex de,hl                ;04b1\r
+       pop bc                  ;04b2\r
+       pop de                  ;04b3\r
+       ret                     ;04b4\r
+\r
+\r
+sub_04b5h:\r
+       ld a,l                  ;04b5\r
+       cp 012h                 ;04b6\r
+       ccf                     ;04b8\r
+       ret c                   ;04b9\r
+       push hl                 ;04ba\r
+       ld hl,banktab           ;04bb\r
+       call add_hl_a\r
+       ld (hl),b               ;04c3\r
+       call gencrc_alv         ;04c4\r
+       pop hl                  ;04c7\r
+       or a                    ;04c8   clear carry\r
+       ret                     ;04c9\r
+\r
+\r
+;--------------------------------------------------------------\r
+;\r
+; de: Log. Address\r
+;  a: Bank number\r
+;\r
+;out ahl: Phys. (linear) Address\r
+\r
+\r
+bnk2phys:\r
+       push    hl\r
+       ld      hl,banktab\r
+       call    add_hl_a\r
+       ld      a,(hl)\r
+       pop     hl\r
+\r
+       ; fall thru\r
+;--------------------------------------------------------------\r
+;\r
+; de: Log. Address\r
+;  a: Bank (bbr)\r
+;\r
+; OP: ahl = (a<<12) + (d<<8) + e\r
+;\r
+;out ahl: Phys. (linear) Address\r
+\r
+\r
+log2phys:\r
+       push    bc              ;\r
+       ld      c,a             ;\r
+       ld      b,16            ;\r
+       mlt     bc              ;bc = a<<4\r
+       ld      l,d             ;\r
+       ld      h,0             ;\r
+       add     hl,bc           ;bc + d == a<<4 + d \r
+       ld      a,h             ;\r
+       ld      h,l             ;\r
+       ld      l,e             ;\r
+       pop     bc              ;\r
+       ret                     ;\r
+\r
+\r
+;--------------------------------------------------------------\r
+;\r
+;return:\r
+; hl = hl + a\r
+; Flags undefined\r
+;\r
+\r
+add_hl_a:\r
+       add a,l \r
+       ld l,a  \r
+       ret nc  \r
+       inc h   \r
+       ret     \r
+\r
+; ---------------------------------------------------------\r
+\r
+sysramw:\r
+\r
+       .phase isvsw_loc\r
+topcodsys:\r
+\r
+; Trampoline for interrupt routines in banked ram.\r
+; Switch stack pointer to "system" stack in top ram\r
+; Save cbar\r
+       \r
+isv_sw:                                ;\r
+       ex (sp),hl              ;       save hl, return adr in hl\r
+       push de                 ;\r
+       push af                 ;\r
+       ex de,hl                ;\r
+       ld hl,0                 ;\r
+       add hl,sp               ;\r
+       ld a,h                  ;\r
+       cp 0f8h                 ;\r
+       jr nc,isw_1             ;\r
+       ld sp,$stack            ;\r
+isw_1:\r
+       push hl                 ;\r
+       in0 h,(cbar)            ;\r
+       push hl                 ;\r
+       ld a,SYS$CBAR           ;\r
+       out0 (cbar),a           ;\r
+       ex de,hl                ;\r
+       ld e,(hl)               ;\r
+       inc hl                  ;\r
+       ld d,(hl)               ;\r
+       ex de,hl                ;\r
+       push bc                 ;\r
+       call jphl               ;\r
+\r
+       pop bc                  ;\r
+       pop hl                  ;\r
+       out0 (cbar),h           ;\r
+       pop hl                  ;\r
+       ld sp,hl                ;\r
+       pop af                  ;\r
+       pop de                  ;\r
+       pop hl                  ;\r
+       ei                      ;\r
+       ret                     ;\r
+jphl:\r
+       jp (hl)                 ;\r
+\r
+; ---------------------------------------------------------\r
+\r
+\r
+iprt0:\r
+       push    af\r
+       push    hl\r
+       in0     a,(tcr)\r
+       in0     a,(tmdr0l)\r
+       in0     a,(tmdr0h)\r
+       ld      a,(tim_ms)\r
+       inc     a\r
+       cp      100\r
+       jr      nz,iprt_1\r
+       xor     a\r
+       ld      hl,(tim_s)\r
+       inc     hl\r
+       ld      (tim_s),hl\r
+iprt_1:\r
+       ld      (tim_ms),a\r
+       pop     hl\r
+       pop     af\r
+       ei\r
+       ret\r
+\r
+; ---------------------------------------------------------\r
+\r
+sp.int0:\r
+       ld      a,0d0h\r
+       jr      sp.i.1\r
+sp.int.len equ $-sp.int0\r
+       ld      a,0d1h\r
+       jr      sp.i.1\r
+       ld      a,0d2h\r
+       jr      sp.i.1\r
+       ld      a,0d3h\r
+       jr      sp.i.1\r
+       ld      a,0d4h\r
+       jr      sp.i.1\r
+       ld      a,0d5h\r
+       jr      sp.i.1\r
+       ld      a,0d6h\r
+       jr      sp.i.1\r
+       ld      a,0d7h\r
+       jr      sp.i.1\r
+       ld      a,0d8h\r
+sp.i.1:\r
+;      out     (80h),a\r
+       halt\r
+\r
+curph  defl    $\r
+       .dephase\r
+sysrame:\r
+       .phase curph\r
+tim_ms:        db      0\r
+tim_s: dw      0\r
+       .dephase\r
+       \r
+;-----------------------------------------------------\r
+\r
+       dseg\r
+\r
+       ds      1\r
+banktabsys:\r
+       ds      1       ;0c001h\r
+       ds      1       ;0c002h\r
+banktab:\r
+       ds      BANKS   ;0c003h\r
+memalv:\r
+       ds      512/4           ;Number of 4k blocks\r
+alv_len        equ     $-memalv\r
+crc_len        equ     $-banktabsys\r
+\r
+crc_memalv:    \r
+       ds      2       ;\r
+\r
+       cseg\r
+\r
+       ;.phase 0ffc0h\r
+;ivtab equ     0ffc0h          ; 0ffc0h        ;int vector table\r
+       ;.dephase\r
+\r
+       ;.phase 0fffch\r
+mark_55AA equ 0fffch\r
+       ;ds     4               ; 0fffch\r
+       ;.dephase\r
+\r
+\r
+       end\r
+\r
diff --git a/z180/romend.180 b/z180/romend.180
new file mode 100644 (file)
index 0000000..2a63342
--- /dev/null
@@ -0,0 +1,9 @@
+\r
+       global  romend\r
+\r
+       cseg\r
+\r
+romend equ     $\r
+       \r
+       end\r
+\r
diff --git a/z180/ser1-i.180 b/z180/ser1-i.180
new file mode 100644 (file)
index 0000000..4074a9d
--- /dev/null
@@ -0,0 +1,257 @@
+       page    200\r
+\r
+\r
+       extrn   buf.init\r
+       extrn   isv_sw\r
+\r
+       \r
+       global  ser.init\r
+       global  ser.instat,ser.in\r
+       global  ser.out\r
+\r
+;TODO: define a trampoline area somewhere in top ram. \r
+rtxisvjmp      equ     0FF60h  ;momentan frei...\r
+\r
+       include config.inc\r
+       include z180reg.inc\r
+\r
+\r
+;-----------------------------------------------------\r
+\r
+       dseg\r
+       \r
+buf_start:\r
+       mkbuf   ser1.inbuf,s1.rx_len\r
+       mkbuf   ser1.outbuf,s1.tx_len\r
+buf_end:\r
+\r
+\r
+\r
+;-----------------------------------------------------\r
+\r
+       cseg\r
+;\r
+; Init Serial I/O for console input and output (ASCI1)\r
+;\r
+       \r
+\r
+ser.init:\r
+;      ld      a,i\r
+;      push    af              ;save IFF\r
+;      di\r
+\r
+       xor     a               ;\r
+       out0    (stat1),a       ;Disable rx/tx interrupts\r
+               \r
+       ld hl,rxtx_src          ;move rx and tx isv to common ram\r
+       ld de,rxtx_dst          ;\r
+       ld bc,rxtx_src_e-rxtx_src ;     \r
+       ldir                    ;\r
+\r
+       ld hl,rtxisvjmp         ;rx/tx int vector\r
+       ld (ivtab + IV$ASCI1),hl;\r
+       ld a,0cdh               ;\r
+       ld (rtxisvjmp),a        ;\r
+       ld hl,isv_sw            ;\r
+       ld (rtxisvjmp + 1),hl   ;\r
+       ld hl,rxtxisv           ;\r
+       ld (rtxisvjmp + 3),hl   ;\r
+\r
+; ASCI1: 8N1, highest baudrate (56700), CTS disabled\r
+\r
+       ld      a,M_MPBT \r
+       out0    (cntlb1),a\r
+       ld      a,M_RE + M_TE + M_MOD2\r
+       out0    (cntla1),a\r
+       ld      a,M_RIE\r
+       out0    (stat1),a       ;Enable rx interrupts\r
+\r
+       ld      ix,ser1.inbuf\r
+       ld      a,ser1.inbuf.mask\r
+       call    buf.init\r
+       ld      ix,ser1.outbuf\r
+       ld      a,ser1.outbuf.mask\r
+       call    buf.init\r
+\r
+;      pop     af\r
+;      ret     po\r
+;      ei\r
+       ret                     ;\r
+\r
+ser.instat:\r
+       push    ix\r
+       ld      ix,ser1.inbuf   ;\r
+\r
+buf.empty:\r
+       ld      a,(ix+o.in_idx) ;\r
+       sub     (ix+o.out_idx)  ;\r
+       pop     ix\r
+       ret     z\r
+       or      0ffh\r
+       ret\r
+       \r
+ser.in:\r
+       push    hl                      ;11     \r
+       push    de                      ;11\r
+       ld      hl,ser1.inbuf-1         ; 9     hl = &rx.out_idx        \r
+       ld      a,(hl)                  ; 6     a = rx.out_idx\r
+       dec     hl                      ; 4     hl = &rx.in_idx\r
+       jr      bg.w1\r
+bg.wait:\r
+       halt\r
+bg.w1:\r
+       cp      (hl)                    ; 6     while (out_idx==in_idx) \r
+       jr      z,bg.wait               ; 6 (/8)        ;\r
+\r
+       ld      e,a                     ; 4     \r
+       ld      d,0                     ; 6\r
+       inc     de\r
+       inc     de\r
+\r
+       ex      de,hl                   ; 3\r
+       add     hl,de                   ;10\r
+       ld      l,(hl)                  ; 6\r
+       ex      de,hl                   ; 3     \r
+\r
+       inc     a                       ; 4\r
+       dec     hl                      ; 4\r
+       and     (hl)                    ; 6     \r
+       inc     hl                      ; 4\r
+       inc     hl                      ; 4\r
+       ld      (hl),a                  ; 7\r
+       \r
+       ld      a,e                     ; 4\r
+       pop     de                      ; 9\r
+       pop     hl                      ; 9\r
+       ret                             ; 9\r
+                                       ;   153 \r
+\r
+ser.outstat:\r
+       push    ix\r
+       ld      ix,ser1.outbuf          ;\r
+buf.full:\r
+       ld      a,(ix+o.in_idx)         ;\r
+       inc     a\r
+       and     (ix+o.mask)\r
+       sub     (ix+o.out_idx)          ;\r
+       pop     ix\r
+       ret     z\r
+       or      0ffh\r
+       ret\r
+\r
+\r
+ser.out:\r
+       push    ix\r
+       ld      ix,ser1.outbuf          ;\r
+buf.put:\r
+       push    hl                      ;\r
+       push    bc\r
+       push    ix\r
+       pop     hl\r
+       ld      c,(ix+o.in_idx)         ;\r
+       ld      b,0\r
+       add     hl,bc\r
+       ld      (hl),a\r
+\r
+       ld      a,c                     ;\r
+       inc     a\r
+       and     (ix+o.mask)\r
+bp.wait:\r
+       cp      (ix+o.out_idx)          ;\r
+       jr      z,bp.wait\r
+       ld      (ix+o.in_idx),a\r
+\r
+       di                      ;036f\r
+       in0     a,(stat1)       ;0374\r
+       set     TIE,a           ;0377\r
+       out0    (stat1),a       ;0379\r
+       ei                      ;037c\r
+\r
+       ld      a,b\r
+       pop     bc\r
+       pop     hl\r
+       pop     ix\r
+       ret\r
+\r
+\r
+;------------------------------------------\r
+; ASCI 1 Transmit/Receive interupt routines\r
+; moved to common ram\r
+\r
+rxtx_src:\r
+       dseg\r
+rxtx_dst:                              ; (0c097h)  old\r
+\r
+rxtxisv:\r
+       inidat\r
+       in0 a,(stat1)                   ;receive flag set?\r
+       jp p,txisv                      ;\r
+\r
+       in0     d,(rdr1)                ;todo: break detection\r
+       bit     FE,a                    ;framing error?\r
+       jr      nz,??ri_1\r
+       \r
+       push    ix\r
+       ld      ix,ser1.inbuf           ;\r
+       ld      hl,ser1.inbuf           ;\r
+       ld      c,(ix+o.in_idx)         ;\r
+       ld      b,0\r
+       add     hl,bc\r
+\r
+       ld      a,c                     ;\r
+       inc     a\r
+       and     (ix+o.mask)\r
+       cp      (ix+o.out_idx)          ;\r
+       jr      z,??ri_0\r
+       ld      (hl),d\r
+       ld      (ix+o.in_idx),a\r
+??ri_0:\r
+       pop     ix\r
+??ri_1:\r
+       in0     a,(cntla1)              ;0705   c0c0\r
+       res     EFR,a                   ;0708\r
+       out0    (cntla1),a              ;070a\r
+       ret\r
+\r
+       inidate\r
+\r
+txisv:\r
+       inidat\r
+       push    ix\r
+       ld      ix,ser1.outbuf          ;\r
+\r
+       ld      a,(ix+o.out_idx)        ;\r
+       cp      (ix+o.in_idx)           ;\r
+       jr      z,??ti_2\r
+\r
+       ld      hl,ser1.outbuf          ;\r
+       add     a,l\r
+       ld      l,a\r
+       jr      nc,??ti_1\r
+       inc     h\r
+??ti_1:\r
+       ld      l,(hl)\r
+       out0    (tdr1),l                ;071b\r
+       \r
+       ld      a,(ix+o.out_idx)        ;\r
+       inc     a\r
+       and     (ix+o.mask)\r
+       ld      (ix+o.out_idx),a\r
+       jr      ??ti_3\r
+??ti_2:\r
+       in0     a,(stat1)               ;0730   disable tx-int\r
+       res     TIE,a                   ;0733\r
+       out0    (stat1),a               ;0735\r
+??ti_3:\r
+       pop     ix\r
+       ret\r
+\r
+       inidate\r
+\r
+       cseg\r
+rxtx_src_e:\r
+\r
+\r
+       end\r
+\r
+\r
diff --git a/z180/z180.lib b/z180/z180.lib
new file mode 100644 (file)
index 0000000..ffe0ab7
--- /dev/null
@@ -0,0 +1,120 @@
+       .xlist\r
+;;\r
+;; Z180 / HD64180 MACRO LIBRARY\r
+;;\r
+\r
+IFNDEF SLP\r
+\r
+;;\r
+;;\r
+;;     HD64180 instructions:\r
+;;\r
+;;     SLP                     ; Enter SLEEP mode\r
+;;     MLT     RR              ; 8 bit multiply with 16 bit result\r
+;;     IN0     R,P             ; Input from internal port\r
+;;     OUT0    P,R             ; Output to internal port\r
+;;     OTIM                    ; Block output, increment\r
+;;     OTIMR                   ; Block output, increment and repeat\r
+;;     OTDM                    ; Block output, decrement\r
+;;     OTDMR                   ; Block output, decrement and repeat\r
+;;     TSTIO   P               ; Non destructive AND, I/O port and A\r
+;;     TST     R               ; Non destructive AND, reg and A\r
+;;     TST     ID              ; Non destructive AND, immediate data and A\r
+;;     TST     (HL)            ; Non destructive AND, (HL) and A\r
+;;\r
+;;\r
+\r
+??BC   EQU     0       ; Double-register definitions\r
+??DE   EQU     1\r
+??HL   EQU     2\r
+??SP   EQU     3\r
+\r
+??A    EQU     7       ; Single-register defintions\r
+??B    EQU     0\r
+??C    EQU     1\r
+??D    EQU     2\r
+??E    EQU     3\r
+??H    EQU     4\r
+??L    EQU     5\r
+\r
+SLP    MACRO\r
+       DEFB    0EDH,76H\r
+       ENDM\r
+\r
+MLT    MACRO   ?R\r
+       DB      0EDH,4CH+(??&?R AND 3) SHL 4\r
+       ENDM\r
+\r
+IN0    MACRO   ?R,?P\r
+       DB      0EDH,(??&?R AND 7) SHL 3, ?P\r
+       ENDM\r
+\r
+OUT0   MACRO   ?P,?R\r
+       DB      0EDH,1+(??&?R AND 7) SHL 3,?P\r
+       ENDM\r
+\r
+OTIM   MACRO\r
+       DB      0EDH,83H\r
+       ENDM\r
+\r
+OTIMR  MACRO\r
+       DB      0EDH,93H\r
+       ENDM\r
+\r
+OTDM   MACRO\r
+       DB      0EDH,8BH\r
+       ENDM\r
+\r
+OTDMR  MACRO\r
+       DB      0EDH,9BH\r
+       ENDM\r
+\r
+TSTIO  MACRO   ?P\r
+       DB      0EDH,74H,?P\r
+       ENDM\r
+\r
+TSTR   MACRO   ?R\r
+       DB      0EDH,4+(??&?R AND 7) SHL 3\r
+       ENDM\r
+\r
+TSTD   MACRO   ?P\r
+       DB      0EDH,64H,?P\r
+       ENDM\r
+\r
+TSTP   MACRO\r
+       DB      0EDH,34H\r
+       ENDM\r
+\r
+TST    MACRO   ?R\r
+         ?D: SET 0\r
+         IRPC  ?X,?R\r
+         ?D: SET ?D+1          ; Count # chars in "?R"\r
+         ENDM\r
+           IF ?D EQ 1          ; IF # chars = 1\r
+            IRPC ?X,ABCDEHL    ; Look up the character\r
+              IF ??&?X EQ ??&?R\r
+              DB       0EDH,4+(??&?R AND 7) SHL 3\r
+              EXITM\r
+              ENDIF\r
+            ENDM\r
+            DB     0EDh,64h,?R\r
+            EXITM\r
+           ENDIF\r
+       IF      (?R = 2) & (?D = 4)\r
+          ?D: SET 0\r
+          IRPC ?X,?R\r
+               IFIDN <?X>,<(>\r
+                   DB 0EDh,34h\r
+                   EXITM\r
+               ENDIF\r
+          ?D: SET ?D + 1\r
+          ENDM\r
+       ENDIF\r
+       IF ?D NE 0\r
+          DB   0EDH,64H,?R\r
+       ENDIF\r
+       ENDM\r
+\r
+ENDIF ;/* IFNDEF SLP /\r
+       .list\r
+\r
diff --git a/z180/z180reg.inc b/z180/z180reg.inc
new file mode 100644 (file)
index 0000000..616138c
--- /dev/null
@@ -0,0 +1,190 @@
+       .xlist\r
+\r
+;;\r
+;; HD64180/Z180 Register Definitions\r
+;;\r
+\r
+\r
+b2m    macro   name,nr\r
+name   equ     nr\r
+M_&name        equ     1 shl nr\r
+       endm\r
+\r
+;      ifndef  IOBASE\r
+IOBASE equ     0\r
+;      endif\r
+\r
+cntla0 equ     IOBASE+00h      ;ASCI Control Register A Channel 0\r
+cntla1 equ     IOBASE+01h      ;ASCI Control Register A Channel 1\r
+       b2m MPE, 7              ;Multi-Processor Mode Enable\r
+       b2m RE, 6               ;Receiver Enable\r
+       b2m TE, 5               ;Transmitter Enable\r
+       b2m RTS0, 4             ;Request to Send Channel 0\r
+       b2m CKA1D, 4            ;\r
+       b2m MPBR, 3             ;Multiprocessor Bit Receive (Read)\r
+       b2m EFR, 3              ;Error Flag Reset (Write)\r
+       b2m MOD2, 2             ;Data Format Mode 1 = 8-Bit data\r
+       b2m NOD1, 1             ;1 = Parity enabled\r
+       b2m MOD0, 0             ;1 = 2 stop bits\r
+\r
+cntlb0 equ     IOBASE+02h      ;ASCI Control Register B Channel 0\r
+cntlb1 equ     IOBASE+03h      ;ASCI Control Register B Channel 1\r
+       b2m MPBT,7              ;Multiprocessor Bit Transmit\r
+       b2m MP,6                ;Multiprocessor Mode\r
+       b2m CTS,5               ;Clear to Send\r
+       b2m PS,5                ;Prescale\r
+       b2m PEO,4               ;Parity Even Odd\r
+       b2m DR,3                ;Divede Ratio\r
+       b2m SS2,2               ;Source/Speed Select 2,1,0\r
+       b2m SS1,1               ;\r
+       b2m SS0,0               ;\r
+\r
+stat0  equ     IOBASE+04h      ;ASCI Status Channel 0\r
+stat1  equ     IOBASE+05h      ;ASCI Status Channel 1\r
+       b2m RDRF,7              ;Receive Data Register Full\r
+       b2m OVRN,6              ;Overrun Error\r
+       b2m PERR,5              ;Parity Error   (M80: PE conflicts with JP/CALL cc)\r
+       b2m FE,4                ;Framing Error\r
+       b2m RIE,3               ;Receive Interrupt Enable\r
+       b2m DCD0,2              ;Data Carrier Detect (Ch 0)\r
+       b2m CTS1E,2             ;Clear To Send (Ch 1)\r
+       b2m TDRE,1              ;Transmit Data Register Empty\r
+       b2m TIE,0               ;Transmit Interrupt Enable\r
+\r
+tdr0   equ     IOBASE+06h      ;ASCI Transmit Data \r
+tdr1   equ     IOBASE+07h      ;ASCI Transmit Data \r
+rdr0   equ     IOBASE+08h      ;ASCI Receive Data \r
+rdr1   equ     IOBASE+09h      ;ASCI Receive Data \r
+\r
+cntr   equ     IOBASE+0Ah      ;CSI/O Control Register\r
+trdr   equ     IOBASE+0Bh      ;CSI/O Transmit/Receive Data Register\r
+\r
+tmdr0l equ     IOBASE+0Ch      ;Timer Data Register Channel 0\r
+tmdr0h equ     IOBASE+0Dh      ;\r
+rldr0l equ     IOBASE+0Eh      ;Timer Reload Register Channel 0\r
+rldr0h equ     IOBASE+0Fh      ;\r
+tcr    equ     IOBASE+10h      ;Timer Control Register\r
+       b2m TIF1,7              ;Timer Interrupt Flag\r
+       b2m TIF0,6              ;\r
+       b2m TIE1,5              ;Timer Interrupt Enable\r
+       b2m TIE0,4              ;\r
+       b2m TOC1,3              ;Timer Output Control\r
+       b2m TOC0,2              ;\r
+       b2m TDE1,1              ;Timer Down Count Enable\r
+       b2m TDE0,0              ;\r
+\r
+\r
+asext0 equ     IOBASE+12h      ;ASCI Extension Control Register\r
+asext1 equ     IOBASE+13h      ;ASCI Extension Control Register\r
+\r
+tmdr1l equ     IOBASE+14h      ;Timer Data Register Channel 1\r
+tmdr1h equ     IOBASE+15h      ;\r
+rldr1l equ     IOBASE+16h      ;Timer Reload Register Channel 1\r
+rldr1h equ     IOBASE+17h      ;\r
+\r
+frc    equ     IOBASE+18h      ;Free Running Counter\r
+\r
+astc0l equ     IOBASE+1Ah      ;ASCI Time Constant Register 0\r
+astc0h equ     IOBASE+1Bh      ;\r
+astc1l equ     IOBASE+1Ch      ;ASCI Time Constant Register 1\r
+astc1h equ     IOBASE+1Dh      ;\r
+\r
+cmr    equ     IOBASE+1Eh      ;Clock Mutiplier Register\r
+       b2m X2CM,7              ;X2 Clock Multiplier\r
+       b2m LNC,6               ;Low Noise Crystal\r
+\r
+ccr    equ     IOBASE+1Fh      ;CPU Control Register\r
+\r
+sar0l  equ     IOBASE+20h      ;DMA Src Adr Register Channel 0\r
+sar0h  equ     IOBASE+21h      ;\r
+sar0b  equ     IOBASE+22h      ;\r
+dar0l  equ     IOBASE+23h      ;DMA Dst Adr Register Channel 0\r
+dar0h  equ     IOBASE+24h      ;\r
+dar0b  equ     IOBASE+25h      ;\r
+bcr0l  equ     IOBASE+26h      ;DMA Byte Count Register Channel 0\r
+bcr0h  equ     IOBASE+27h      ;\r
+\r
+mar1l  equ     IOBASE+28h      ;DMA Memory Address Register Channel 1\r
+mar1h  equ     IOBASE+29h      ;\r
+mar1b  equ     IOBASE+2Ah      ;\r
+iar1l  equ     IOBASE+2Bh      ;DMA I/O Address Register Channel 1\r
+iar1h  equ     IOBASE+2Ch      ;\r
+iar1b  equ     IOBASE+2Dh      ;\r
+       b2m ALTE,7              ;Alternating Chnnels\r
+       b2m ALTC,6              ;Currently selected DMA Channel when Bit7=1\r
+       b2m REQ1SEL2,2          ;\r
+       b2m REQ1SEL1,1          ;\r
+       b2m REQ1SEL0,0          ;\r
+\r
+bcr1l  equ     IOBASE+2Eh      ;DMA Byte Count Register Channel 1\r
+bcr1h  equ     IOBASE+2Fh      ;\r
+\r
+dstat  equ     IOBASE+30h      ;DMA Status Register\r
+       b2m DE1,7               ;DMA enable ch 1,0\r
+       b2m DE0,6               ;\r
+       b2m DWE1,5              ;DMA Enable Bit Write Enable 1,0\r
+       b2m DWE0,4              ;\r
+       b2m DIE1,3              ;DMA Interrupt Enable 1,0\r
+       b2m DIE0,2              ;\r
+       b2m DME,0               ;DMA Master enable\r
+\r
+dmode  equ     IOBASE+31h      ;DMA Mode Register\r
+       b2m DM1,5               ;Ch 0 Destination Mode 1,0\r
+       b2m DM0,4               ;\r
+       b2m SM1,3               ;Ch 0 Source Mode 1,0\r
+       b2m SM0,2               ;\r
+       b2m MMOD,1              ;Memory MODE select (0=cycle steel/1=burst)\r
+\r
+dcntl  equ     IOBASE+32h      ;DMA/WAIT Control\r
+       b2m MWI1,7              ;Memory Wait Insertion\r
+       b2m MWI0,6              ;\r
+       b2m IWI1,5              ;I/O Wait Insertion\r
+       b2m IWI0,4              ;\r
+       b2m DMS1,3              ;DREQi Select (Edge/Level)\r
+       b2m DMS0,2              ;\r
+       b2m DIMA1,1             ;DMA Ch1 I/O Memory Mode Select\r
+       b2m DIMA0,0\r
+M_MWI  equ M_MWI1 + M_MWI0\r
+M_IWI  equ M_IWI1 + M_IWI0\r
+\r
+il     equ     IOBASE+33h      ;Interrupt Vector Low Register\r
+itc    equ     IOBASE+34h      ;INT/TRAP Control Register\r
+       b2m TRAP,7              ;Trap\r
+       b2m UFO,6               ;Unidentified Fetch Object\r
+       b2m ITE2,2              ;/INT Enable 2,1,0\r
+       b2m ITE1,1              ;\r
+       b2m ITE0,0              ;\r
+\r
+rcr    equ     IOBASE+36h      ;Refresh Control Register\r
+       b2m REFE,7              ;Refresh Enable\r
+       b2m REFW,6              ;Refresh Wait State\r
+       b2m CYC1,1              ;Cycle select\r
+       b2m CYC0,0              ;\r
+\r
+cbr    equ     IOBASE+38h      ;MMU Common Base Register\r
+bbr    equ     IOBASE+39h      ;MMU Bank Base Register\r
+cbar   equ     IOBASE+3Ah      ;MMU Common/Bank Register\r
+\r
+omcr   equ     IOBASE+3Eh      ;Operation Mode Control Register\r
+       b2m M1E,7               ;M1 Enable\r
+       b2m M1TE,6              ;M1 Temporary Enable\r
+       b2m IOC,5               ;I/O Compatibility\r
+\r
+icr    equ     IOBASE+3Fh      ;I/O Control Register\r
+       b2m IOSTP,5             ;I/O Stop\r
+;\r
+; Interrupt Vectors\r
+;\r
+\r
+IV$INT1         equ    0               ;/INT1         (highest priority)\r
+IV$INT2         equ    2               ;/INT2\r
+IV$PRT0         equ    4               ;PRT channel 0\r
+IV$PRT1         equ    6               ;PRT channel 1\r
+IV$DMA0         equ    8               ;DMA channel 0\r
+IV$DMA1         equ    10              ;DMA channel 1\r
+IV$CSIO         equ    12              ;CSI/O\r
+IV$ASCI0 equ   14              ;ASCI channel 0\r
+IV$ASCI1 equ   16              ;ASCI channel 1 (lowest priority)\r
+\r
+       .list\r
+\r