summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/kernel
diff options
context:
space:
mode:
authorYang Zhang <yang.z.zhang@intel.com>2015-08-28 09:58:54 +0800
committerYang Zhang <yang.z.zhang@intel.com>2015-09-01 12:44:00 +0800
commite44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch)
tree66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/openbios/kernel
parent9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff)
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5 Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/openbios/kernel')
-rw-r--r--qemu/roms/openbios/kernel/Kconfig88
-rw-r--r--qemu/roms/openbios/kernel/README93
-rw-r--r--qemu/roms/openbios/kernel/bootstrap.c1322
-rw-r--r--qemu/roms/openbios/kernel/build.xml16
-rw-r--r--qemu/roms/openbios/kernel/cross.h124
-rw-r--r--qemu/roms/openbios/kernel/dict.c320
-rw-r--r--qemu/roms/openbios/kernel/forth.c1966
-rw-r--r--qemu/roms/openbios/kernel/include/dict.h59
-rw-r--r--qemu/roms/openbios/kernel/stack.c46
9 files changed, 4034 insertions, 0 deletions
diff --git a/qemu/roms/openbios/kernel/Kconfig b/qemu/roms/openbios/kernel/Kconfig
new file mode 100644
index 000000000..32831f737
--- /dev/null
+++ b/qemu/roms/openbios/kernel/Kconfig
@@ -0,0 +1,88 @@
+menu "Kernel Debugging"
+
+config DEBUG
+ bool "Kernel Debugging"
+ default y
+ help
+ Kernel Debugging
+
+config DEBUG_BOOT
+ bool "Boot messages"
+ depends on DEBUG
+ default y
+ help
+ early boot code (multiboot parsing etc)
+
+config DEBUG_DSTACK
+ bool "dstack messages"
+ depends on DEBUG
+ default n
+ help
+ stack debugging. warning: heavy output!
+
+config DEBUG_RSTACK
+ bool "rstack messages"
+ depends on DEBUG
+ default n
+ help
+ stack debugging. warning: heavy output!
+
+config DEBUG_DICTIONARY
+ bool "Dictionary loading/dumping"
+ depends on DEBUG
+ default n
+ help
+ print few additional information on dictionary loading/dumping
+
+config DEBUG_INTERNAL
+ bool "Prime Words"
+ depends on DEBUG
+ default n
+ help
+ print additional information for some prime words, like branches
+
+config DEBUG_INTERPRETER
+ bool "Interpreter"
+ depends on DEBUG
+ default n
+ help
+ additional information about the unix.c builtin C interpreter
+ and some other places where it actually does not belong.
+
+config DEBUG_CONSOLE
+ bool "Console"
+ default y
+ help
+ use builtin C console code for user interaction. There is no
+ real alternative to this until someone writes a display/kbd or
+ serial driver in forth.
+
+config DEBUG_CONSOLE_SERIAL
+ bool "Serial Console"
+ depends on DEBUG_CONSOLE
+ default y
+ help
+ use serial console.
+
+config SERIAL_PORT
+ int "Serial Port"
+ depends on DEBUG_CONSOLE_SERIAL
+ default "1"
+ help
+ 0 for none, 1 for ttyS0, 2 for ttyS1
+
+config SERIAL_SPEED
+ int "Serial line speed"
+ depends on DEBUG_CONSOLE_SERIAL
+ default "115200"
+ help
+ supported speeds are: 115200, 57600, 38400, 19200, 9600
+
+config DEBUG_CONSOLE_VGA
+ bool "VGA Console"
+ depends on DEBUG_CONSOLE
+ default y
+ help
+ use vga textmode and keyboard console
+
+endmenu
diff --git a/qemu/roms/openbios/kernel/README b/qemu/roms/openbios/kernel/README
new file mode 100644
index 000000000..c84879b83
--- /dev/null
+++ b/qemu/roms/openbios/kernel/README
@@ -0,0 +1,93 @@
+
+Welcome to the OpenBIOS forth core "begin again".
+
+Find more information about OpenBIOS at http://www.openbios.org/
+
+This program was written by Patrick Mauritz and Stefan Reinauer in 2003
+For license details on this piece of software, check Documentation/COPYING.
+
+How OpenBIOS works
+------------------
+
+ The OpenBIOS forth core is split into a forth kernel written in C
+ and a forth dictionary which operated on by the kernel.
+
+ When building the forth core, you get different versions of
+ the forth kernel:
+
+ * a "hosted" unix binary. This binary can be used on a unix system
+
+ - to execute a forth dictionary from a file. This can be used for
+ testing openbios code in a development environment on a unix host.
+
+ - to create a dictionary file. Such a dictionary file sets up
+ all of the forth language. Primitives are indexed to save relocations.
+
+ The default is to create a forth dictionary forth.dict from
+ forth/start.fs. This file includes all of the basic forth language
+ constructs from forth/bootstrap.fs and starts the interpreter.
+
+ To achieve this, the hosted unix version contains a basic set of
+ forth words coded in C that allow creating a full dictionary.
+
+ * a varying number of target specific binaries. On x86 you can start
+ openbios for example from GRUB or LinuxBIOS. They are all based on
+ the same forth engine consisting of a dictionary scheduler, primitive
+ words needed to build the forth environment, 2 stacks and a simple
+ set of console functions. These binaries can not be started directly
+ in the unix host environment.
+
+Requirements
+------------
+ * gcc
+ * grub or any other multiboot loader to run the standalone
+ binary "openbios.multiboot"
+
+Building & Usage
+----------------
+
+ * make
+
+ this builds "openbios.multiboot", the standalone image and "unix",
+ the hosted image. Additionally it creates a forth dictionary
+ file from forth/start.fs. All generated files are written to
+ the absolute directory held by the variable BUILDDIR, which defaults
+ to obj-[platform]. Some compile time parameters can be tweaked in
+ include/config.h
+
+ * use "unix" to create a forth dictionary on your own:
+ $ ./unix -Iforth start.fs
+ creates the file forth.dict from forth source forth/start.fs.
+
+ * use "unix" to run a created dictionary:
+ $ ./unix forth.dict
+ This is useful for testing
+
+ * booting openbios
+ You can boot openbios i.e. in grub. Add the following lines to
+ your menu.lst:
+
+ title openbios
+ kernel (hd0,2)/boot/openbios.multiboot
+ module (hd0,2)/boot/openfirmware.dict
+
+ Note: change (hd0,2) to the partition you copied openbios and
+ forth.dict to.
+
+ To boot OpenBIOS from LinuxBIOS/etherboot, you can either use
+ "openbios" or "openbios.full":
+
+ - openbios is the pure kernel that loads the dictionary from a
+ hardcoded address in flash memory (0xfffe0000)
+
+ - openbios.full also includes the dictionary directly so that it
+ can be easily used from etherboot or the LinuxBIOS builtin ELF
+ loader without taking care of the dictionary
+
+
+Comments are welcome.
+
+ OpenBIOS team
+
+------------------------------------------------------------------------
+tag: README for openbios forth core
diff --git a/qemu/roms/openbios/kernel/bootstrap.c b/qemu/roms/openbios/kernel/bootstrap.c
new file mode 100644
index 000000000..520d7b48c
--- /dev/null
+++ b/qemu/roms/openbios/kernel/bootstrap.c
@@ -0,0 +1,1322 @@
+/* tag: forth bootstrap environment
+ *
+ * Copyright (C) 2003-2006 Stefan Reinauer, Patrick Mauritz
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "sysinclude.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <termios.h>
+#include <sys/stat.h>
+
+#ifdef __GLIBC__
+#define _GNU_SOURCE
+#include <getopt.h>
+#endif
+
+#include "config.h"
+#include "kernel/stack.h"
+#include "sysinclude.h"
+#include "kernel/kernel.h"
+#include "dict.h"
+#include "cross.h"
+#include "openbios-version.h"
+
+#define MAX_PATH_LEN 256
+
+#define MEMORY_SIZE (1024*1024) /* 1M ram for hosted system */
+#define DICTIONARY_SIZE (256*1024) /* 256k for the dictionary */
+#define TRAMPOLINE_SIZE (4*sizeof(cell)) /* 4 cells for the trampoline */
+
+/* state variables */
+static ucell *latest, *state, *base;
+static ucell *memory;
+ucell *trampoline;
+
+/* local variables */
+static int errors = 0;
+static int segfault = 0;
+static int verbose = 0;
+
+#define MAX_SRC_FILES 128
+
+static FILE *srcfiles[MAX_SRC_FILES];
+static char *srcfilenames[MAX_SRC_FILES];
+static int srclines[MAX_SRC_FILES];
+static unsigned int cursrc = 0;
+
+static char *srcbasedict;
+
+/* console variables */
+static FILE *console;
+
+#ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH
+unsigned long base_address;
+#endif
+
+/* include path handling */
+typedef struct include_path include;
+struct include_path {
+ const char *path;
+ include *next;
+};
+
+static include includes = { ".", NULL };
+static FILE *depfile;
+
+static ucell * relocation_address=NULL;
+static int relocation_length=0;
+
+/* the word names are used to generate the prim words in the
+ * dictionary. This is done by the C written interpreter.
+ */
+static const char *wordnames[] = {
+ "(semis)", "", "(lit)", "", "", "", "", "(do)", "(?do)", "(loop)",
+ "(+loop)", "", "", "", "dup", "2dup", "?dup", "over", "2over", "pick", "drop",
+ "2drop", "nip", "roll", "rot", "-rot", "swap", "2swap", ">r", "r>",
+ "r@", "depth", "depth!", "rdepth", "rdepth!", "+", "-", "*", "u*",
+ "mu/mod", "abs", "negate", "max", "min", "lshift", "rshift", ">>a",
+ "and", "or", "xor", "invert", "d+", "d-", "m*", "um*", "@", "c@",
+ "w@", "l@", "!", "+!", "c!", "w!", "l!", "=", ">", "<", "u>", "u<",
+ "sp@", "move", "fill", "(emit)", "(key?)", "(key)", "execute",
+ "here", "here!", "dobranch", "do?branch", "unaligned-w@",
+ "unaligned-w!", "unaligned-l@", "unaligned-l!", "ioc@", "iow@",
+ "iol@", "ioc!", "iow!", "iol!", "i", "j", "call", "sys-debug",
+ "$include", "$encode-file", "(debug", "(debug-off)"
+};
+
+/*
+ * dictionary related functions.
+ */
+
+/*
+ * Compare two dictionaries constructed at different addresses. When
+ * the cells don't match, a need for relocation is detected and the
+ * corresponding bit in reloc_table bitmap is set.
+ */
+static void relocation_table(unsigned char * dict_one, unsigned char *dict_two, int length)
+{
+ ucell *d1=(ucell *)dict_one, *d2=(ucell *)dict_two;
+ ucell *reloc_table;
+ int pos, bit;
+ int l=(length+(sizeof(cell)-1))/sizeof(ucell), i;
+
+ /* prepare relocation table */
+ relocation_length=(length+BITS-1)/BITS;
+ reloc_table = malloc(relocation_length*sizeof(cell));
+ memset(reloc_table,0,relocation_length*sizeof(cell));
+
+ for (i=0; i<l; i++) {
+
+ pos=i/BITS;
+ bit=i&~(-BITS);
+
+ if(d1[i]==d2[i]) {
+ reloc_table[pos] &= target_ucell(~((ucell)1ULL << bit));
+
+ // This check might bring false positives in data.
+ //if(d1[i] >= pointer2cell(dict_one) &&
+ // d1[i] <= pointer2cell(dict_one+length))
+ // printk("\nWARNING: inconsistent relocation (%x:%x)!\n", d1[i], d2[i]);
+ } else {
+ /* This is a pointer, it needs relocation, d2==dict */
+ reloc_table[pos] |= target_ucell((ucell)1ULL << bit);
+ d2[i] = target_ucell(target_ucell(d2[i]) - pointer2cell(d2));
+ }
+ }
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("dict1 %lx dict2 %lx dict %lx\n",dict_one, dict_two, dict);
+ for (i=0; i< relocation_length ; i++)
+ printk("reloc %d %lx\n",i+1, reloc_table[i]);
+#endif
+ relocation_address=reloc_table;
+}
+
+static void write_dictionary(const char *filename)
+{
+ FILE *f;
+ unsigned char *write_data, *walk_data;
+ int write_len;
+ dictionary_header_t *header;
+ u32 checksum=0;
+
+ /*
+ * get memory for dictionary
+ */
+
+ write_len = sizeof(dictionary_header_t)+dicthead+relocation_length*sizeof(cell);
+ write_data = malloc(write_len);
+ if(!write_data) {
+ printk("panic: can't allocate memory for output dictionary (%d"
+ " bytes\n", write_len);
+ exit(1);
+ }
+ memset(write_data, 0, write_len);
+
+ /*
+ * prepare dictionary header
+ */
+
+ header = (dictionary_header_t *)write_data;
+ *header = (dictionary_header_t){
+ .signature = DICTID,
+ .version = 2,
+ .cellsize = sizeof(ucell),
+#ifdef CONFIG_BIG_ENDIAN
+ .endianess = -1,
+#else
+ .endianess = 0,
+#endif
+ .checksum = 0,
+ .compression = 0,
+ .relocation = -1,
+ .length = target_ulong((uint32_t)dicthead),
+ .last = target_ucell((ucell)((unsigned long)last
+ - (unsigned long)dict)),
+ };
+
+ /*
+ * prepare dictionary data
+ */
+
+ walk_data=write_data+sizeof(dictionary_header_t);
+ memcpy (walk_data, dict, dicthead);
+
+ /*
+ * prepare relocation data.
+ * relocation_address is zero when writing a dictionary core.
+ */
+
+ if (relocation_address) {
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("writing %d reloc cells \n",relocation_length);
+#endif
+ walk_data += dicthead;
+ memcpy(walk_data, relocation_address,
+ relocation_length*sizeof(cell));
+ /* free relocation information */
+ free(relocation_address);
+ relocation_address=NULL;
+ } else {
+ header->relocation=0;
+ }
+
+ /*
+ * Calculate Checksum
+ */
+
+ walk_data=write_data;
+ while (walk_data<write_data+write_len) {
+ checksum+=read_long(walk_data);
+ walk_data+=sizeof(u32);
+ }
+ checksum=(u32)-checksum;
+
+ header->checksum=target_long(checksum);
+
+ if (verbose) {
+ dump_header(header);
+ }
+
+ f = fopen(filename, "w");
+ if (!f) {
+ printk("panic: can't write to dictionary '%s'.\n", filename);
+ exit(1);
+ }
+
+ fwrite(write_data, write_len, 1, f);
+
+ free(write_data);
+ fclose(f);
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("wrote dictionary to file %s.\n", filename);
+#endif
+}
+
+/*
+ * Write dictionary as a list of ucell hex values to filename. Array
+ * header and end lines are not generated.
+ *
+ * Cells with relocations are output using the expression
+ * DICTIONARY_BASE + value.
+ *
+ * Define some helpful constants.
+ */
+static void write_dictionary_hex(const char *filename)
+{
+ FILE *f;
+ ucell *walk;
+
+ f = fopen(filename, "w");
+ if (!f) {
+ printk("panic: can't write to dictionary '%s'.\n", filename);
+ exit(1);
+ }
+
+ for (walk = (ucell *)dict; walk < (ucell *)(dict + dicthead); walk++) {
+ int pos, bit, l;
+ ucell val;
+
+ l = (walk - (ucell *)dict);
+ pos = l / BITS;
+ bit = l & ~(-BITS);
+
+ val = read_ucell(walk);
+ if (relocation_address[pos] & target_ucell((ucell)1ULL << bit)) {
+ fprintf(f, "DICTIONARY_BASE + 0x%" FMT_CELL_x
+ ",\n", val);
+ } else {
+ fprintf(f, "0x%" FMT_CELL_x",\n", val);
+ }
+ }
+
+ fprintf(f, "#define FORTH_DICTIONARY_LAST 0x%" FMT_CELL_x"\n",
+ (ucell)((unsigned long)last - (unsigned long)dict));
+ fprintf(f, "#define FORTH_DICTIONARY_END 0x%" FMT_CELL_x"\n",
+ (ucell)dicthead);
+ fclose(f);
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("wrote dictionary to file %s.\n", filename);
+#endif
+}
+
+static ucell read_dictionary(char *fil)
+{
+ int ilen;
+ ucell ret;
+ char *mem;
+ FILE *f;
+ struct stat finfo;
+
+ if (stat(fil, &finfo))
+ return 0;
+
+ ilen = finfo.st_size;
+
+ if ((mem = malloc(ilen)) == NULL) {
+ printk("panic: not enough memory.\n");
+ exit(1);
+ }
+
+ f = fopen(fil, "r");
+ if (!f) {
+ printk("panic: can't open dictionary.\n");
+ exit(1);
+ }
+
+ if (fread(mem, ilen, 1, f) != 1) {
+ printk("panic: can't read dictionary.\n");
+ fclose(f);
+ exit(1);
+ }
+ fclose(f);
+
+ ret = load_dictionary(mem, ilen);
+
+ free(mem);
+ return ret;
+}
+
+
+/*
+ * C Parser related functions
+ */
+
+/*
+ * skipws skips all whitespaces (space, tab, newline) from the input file
+ */
+
+static void skipws(FILE * f)
+{
+ int c;
+ while (!feof(f)) {
+ c = getc(f);
+
+ if (c == ' ' || c == '\t')
+ continue;
+
+ if (c == '\n') {
+ srclines[cursrc - 1]++;
+ continue;
+ }
+
+ ungetc(c, f);
+ break;
+ }
+}
+
+/*
+ * parse gets the next word from the input stream, delimited by
+ * delim. If delim is 0, any word delimiter will end the stream
+ * word delimiters are space, tab and newline. The resulting word
+ * will be put zero delimited to the char array line.
+ */
+
+static int parse(FILE * f, char *line, char delim)
+{
+ int cnt = 0, c = 0;
+
+ while (!feof(f)) {
+ c = getc(f);
+
+ if (delim && c == delim)
+ break;
+
+ if ((!delim) && (c == ' ' || c == '\t' || c == '\n'))
+ break;
+
+ line[cnt++] = c;
+ }
+
+ /* Update current line number */
+ if (c == '\n') {
+ srclines[cursrc - 1]++;
+ }
+
+ line[cnt] = 0;
+
+ return cnt;
+}
+
+/*
+ * parse_word is a small helper that skips whitespaces before a word.
+ * it's behaviour is similar to the forth version parse-word.
+ */
+
+static void parse_word(FILE * f, char *line)
+{
+ skipws(f);
+ parse(f, line, 0);
+}
+
+
+static void writestring(const char *str)
+{
+ unsigned int i;
+ for (i = 0; i < strlen(str); i++) {
+ dict[dicthead + i] = str[i];
+ }
+ dicthead += i + 1;
+ dict[dicthead - 1] = (char) strlen(str) + 128;
+}
+
+#define writebyte(value) {write_byte(dict+dicthead,value); dicthead++;}
+#define writecell(value) {write_cell(dict+dicthead, value); dicthead+=sizeof(cell);}
+
+/*
+ * reveal a word, ie. make it visible.
+ */
+
+static void reveal(void)
+{
+ *last = *latest;
+}
+
+/*
+ * dictionary padding
+ */
+
+static void paddict(ucell align)
+{
+ while (dicthead % align != 0)
+ writebyte(0);
+}
+
+/*
+ * generic forth word creator function.
+ */
+
+static void fcreate(const char *word, ucell cfaval)
+{
+ if (strlen(word) == 0) {
+ printk("WARNING: tried to create unnamed word.\n");
+ return;
+ }
+
+ writestring(word);
+ /* get us at least 1 byte for flags */
+ writebyte(0);
+ paddict(sizeof(cell));
+ /* set flags high bit. */
+ dict[dicthead - 1] = 128;
+ /* lfa and cfa */
+ writecell(read_ucell(latest));
+ *latest = target_ucell(pointer2cell(dict) + dicthead - sizeof(cell));
+ writecell(cfaval);
+}
+
+
+static ucell *buildvariable(const char *name, cell defval)
+{
+ fcreate(name, DOVAR); /* see dict.h for DOVAR and other CFA ids */
+ writecell(defval);
+ return (ucell *) (dict + dicthead - sizeof(cell));
+}
+
+static void buildconstant(const char *name, cell defval)
+{
+ fcreate(name, DOCON); /* see dict.h for DOCON and other CFA ids */
+ writecell(defval);
+}
+
+static void builddefer(const char *name)
+{
+ fcreate(name, DODFR); /* see dict.h for DODFR and other CFA ids */
+ writecell((ucell)0);
+ writecell((ucell)findword("(semis)"));
+}
+
+/*
+ * Include file handling
+ */
+
+static void add_includepath(char *path)
+{
+ include *incl = &includes;
+ include *newpath;
+
+ while (incl->next)
+ incl = incl->next;
+
+ newpath = malloc(sizeof(include));
+ if (!newpath) {
+ printk("panic: not enough memory for include path.\n");
+ exit(1);
+ }
+
+ incl->next = newpath;
+ newpath->path = path;
+ newpath->next = NULL;
+}
+
+
+static FILE *fopen_include(const char *fil)
+{
+ char fullpath[MAX_PATH_LEN];
+ FILE *ret;
+ include *incl = &includes;
+
+ while (incl) {
+ snprintf(fullpath, sizeof(fullpath), "%s/%s", incl->path, fil);
+
+ ret = fopen(fullpath, "r");
+ if (ret != NULL) {
+
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("Including '%s'\n", fil);
+#endif
+ srcfilenames[cursrc] = strdup(fil);
+ srclines[cursrc] = 1;
+ srcfiles[cursrc++] = ret;
+
+ if (depfile) {
+ fprintf(depfile, " %s", fullpath);
+ }
+
+ return ret;
+ }
+
+ incl = incl->next;
+ }
+ return NULL;
+}
+
+
+/*
+ * Forth exception handler
+ */
+
+void exception(cell no)
+{
+ printk("%s:%d: ", srcfilenames[cursrc - 1], srclines[cursrc - 1]);
+
+ /* See also forth/bootstrap/interpreter.fs */
+ switch (no) {
+ case -1:
+ case -2:
+ printk("Aborted.\n");
+ break;
+ case -3:
+ printk("Stack Overflow.\n");
+ break;
+ case -4:
+ printk("Stack Underflow.\n");
+ break;
+ case -5:
+ printk("Return Stack Overflow.\n");
+ break;
+ case -6:
+ printk("Return Stack Underflow.\n");
+ break;
+ case -19:
+ printk("undefined word.\n");
+ break;
+ case -21:
+ printk("out of memory.\n");
+ break;
+ case -33:
+ printk("undefined method.\n");
+ break;
+ case -34:
+ printk("no such device.\n");
+ break;
+ default:
+ printk("error %" FMT_CELL_d " occured.\n", no);
+ }
+ exit(1);
+}
+
+
+/*
+ * This is the C version of the forth interpreter
+ */
+
+static int interpret_source(char *fil)
+{
+ FILE *f;
+ char tib[160];
+ cell num;
+ char *test;
+
+ const ucell SEMIS = (ucell)findword("(semis)");
+ const ucell LIT = (ucell)findword("(lit)");
+ const ucell DOBRANCH = (ucell)findword("dobranch");
+
+ if ((f = fopen_include(fil)) == NULL) {
+ printk("error while loading source file '%s'\n", fil);
+ errors++;
+ exit(1);
+ }
+
+ /* FIXME: We should read this file at
+ * once. No need to get it char by char
+ */
+
+ while (!feof(f)) {
+ xt_t res;
+ parse_word(f, tib);
+
+ /* if there is actually no word, we continue right away */
+ if (strlen(tib) == 0) {
+ continue;
+ }
+
+ /* Checking for builtin words that are needed to
+ * bootstrap the forth base dictionary.
+ */
+
+ if (!strcmp(tib, "(")) {
+ parse(f, tib, ')');
+ continue;
+ }
+
+ if (!strcmp(tib, "\\")) {
+ parse(f, tib, '\n');
+ continue;
+ }
+
+ if (!strcmp(tib, ":")) {
+ parse_word(f, tib);
+
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("create colon word %s\n\n", tib);
+#endif
+ fcreate(tib, DOCOL); /* see dict.h for DOCOL and other CFA ids */
+ *state = (ucell) (-1);
+ continue;
+ }
+
+ if (!strcmp(tib, ";")) {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("finish colon definition\n\n");
+#endif
+ writecell((cell)SEMIS);
+ *state = (ucell) 0;
+ reveal();
+ continue;
+ }
+
+ if (!strcasecmp(tib, "variable")) {
+ parse_word(f, tib);
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("defining variable %s\n\n", tib);
+#endif
+ buildvariable(tib, 0);
+ reveal();
+ continue;
+ }
+
+ if (!strcasecmp(tib, "constant")) {
+ parse_word(f, tib);
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("defining constant %s\n\n", tib);
+#endif
+ buildconstant(tib, POP());
+ reveal();
+ continue;
+ }
+
+ if (!strcasecmp(tib, "value")) {
+ parse_word(f, tib);
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("defining value %s\n\n", tib);
+#endif
+ buildconstant(tib, POP());
+ reveal();
+ continue;
+ }
+
+ if (!strcasecmp(tib, "defer")) {
+ parse_word(f, tib);
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("defining defer word %s\n\n", tib);
+#endif
+ builddefer(tib);
+ reveal();
+ continue;
+ }
+
+ if (!strcasecmp(tib, "include")) {
+ parse_word(f, tib);
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("including file %s\n\n", tib);
+#endif
+ interpret_source(tib);
+ continue;
+ }
+
+ if (!strcmp(tib, "[']")) {
+ xt_t xt;
+ parse_word(f, tib);
+ xt = findword(tib);
+ if (*state == 0) {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk
+ ("writing address of %s to stack\n\n",
+ tib);
+#endif
+ PUSH_xt(xt);
+ } else {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("writing lit, addr(%s) to dict\n\n",
+ tib);
+#endif
+ writecell(LIT); /* lit */
+ writecell((cell)xt);
+ }
+ continue;
+ /* we have no error detection here */
+ }
+
+ if (!strcasecmp(tib, "s\"")) {
+ int cnt;
+ cell loco;
+
+ cnt = parse(f, tib, '"');
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("compiling string %s\n", tib);
+#endif
+ loco = dicthead + (6 * sizeof(cell));
+ writecell(LIT);
+ writecell(pointer2cell(dict) + loco);
+ writecell(LIT);
+ writecell((ucell)cnt);
+ writecell(DOBRANCH);
+ loco = cnt + sizeof(cell) - 1;
+ loco &= ~(sizeof(cell) - 1);
+ writecell(loco);
+ memcpy(dict + dicthead, tib, cnt);
+ dicthead += cnt;
+ paddict(sizeof(cell));
+ continue;
+ }
+
+ /* look if tib is in dictionary. */
+ /* should the dictionary be searched before the builtins ? */
+ res = findword(tib);
+ if (res) {
+ u8 flags = read_byte((u8*)cell2pointer(res) -
+ sizeof(cell) - 1);
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("%s is 0x%" FMT_CELL_x "\n", tib, (ucell) res);
+#endif
+ if (!(*state) || (flags & 3)) {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("executing %s, %" FMT_CELL_d
+ " (flags: %s %s)\n",
+ tib, res,
+ (flags & 1) ? "immediate" : "",
+ (flags & 2) ? "compile-only" : "");
+#endif
+ PC = (ucell)res;
+ enterforth(res);
+ } else {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("writing %s to dict\n\n", tib);
+#endif
+ writecell((cell)res);
+ }
+ continue;
+ }
+
+ /* if not look if it's a number */
+ if (tib[0] == '-')
+ num = strtoll(tib, &test, read_ucell(base));
+ else
+ num = strtoull(tib, &test, read_ucell(base));
+
+
+ if (*test != 0) {
+ /* what is it?? */
+ printk("%s:%d: %s is not defined.\n\n", srcfilenames[cursrc - 1], srclines[cursrc - 1], tib);
+ errors++;
+#ifdef CONFIG_DEBUG_INTERPRETER
+ continue;
+#else
+ return -1;
+#endif
+ }
+
+ if (*state == 0) {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("pushed %" FMT_CELL_x " to stack\n\n", num);
+#endif
+ PUSH(num);
+ } else {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("writing lit, %" FMT_CELL_x " to dict\n\n", num);
+#endif
+ writecell(LIT); /* lit */
+ writecell(num);
+ }
+ }
+
+ fclose(f);
+ cursrc--;
+
+ return 0;
+}
+
+static int build_dictionary(void)
+{
+ ucell lfa = 0;
+ unsigned int i;
+
+ /* we need a temporary place for latest outside the dictionary */
+ latest = &lfa;
+
+ /* starting a new dictionary: clear dicthead */
+ dicthead = 0;
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("building dictionary, %d primitives.\nbuilt words:",
+ sizeof(wordnames) / sizeof(void *));
+#endif
+
+ for (i = 0; i < sizeof(wordnames) / sizeof(void *); i++) {
+ if (strlen(wordnames[i]) != 0) {
+ fcreate((char *) wordnames[i], i);
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk(" %s", wordnames[i]);
+#endif
+ }
+ }
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk(".\n");
+#endif
+
+ /* get last/latest and state */
+ state = buildvariable("state", 0);
+ last = buildvariable("forth-last", 0);
+ latest = buildvariable("latest", 0);
+
+ *latest = target_ucell(pointer2cell(latest)-2*sizeof(cell));
+
+ base=buildvariable("base", 10);
+
+ buildconstant("/c", sizeof(u8));
+ buildconstant("/w", sizeof(u16));
+ buildconstant("/l", sizeof(u32));
+ buildconstant("/n", sizeof(ucell));
+ buildconstant("/x", sizeof(u64));
+
+ reveal();
+ if (verbose) {
+ printk("Dictionary initialization finished.\n");
+ }
+ return 0;
+}
+
+/*
+ * functions used by primitives
+ */
+
+int availchar(void)
+{
+ int tmp;
+ if( cursrc < 1 ) {
+ interruptforth |= FORTH_INTSTAT_STOP;
+ /* return -1 in order to exit the loop in key() */
+ return -1;
+ }
+
+ tmp = getc( srcfiles[cursrc-1] );
+ if (tmp != EOF) {
+ ungetc(tmp, srcfiles[cursrc-1]);
+ return -1;
+ }
+
+ fclose(srcfiles[--cursrc]);
+
+ return availchar();
+}
+
+int get_inputbyte( void )
+{
+ int tmp;
+
+ if( cursrc < 1 ) {
+ interruptforth |= FORTH_INTSTAT_STOP;
+ return 0;
+ }
+
+ tmp = getc( srcfiles[cursrc-1] );
+
+ /* Update current line number */
+ if (tmp == '\n') {
+ srclines[cursrc - 1]++;
+ }
+
+ if (tmp != EOF) {
+ return tmp;
+ }
+
+ fclose(srcfiles[--cursrc]);
+
+ return get_inputbyte();
+}
+
+void put_outputbyte( int c )
+{
+ if (console)
+ fputc(c, console);
+}
+
+/*
+ * segmentation fault handler. linux specific?
+ */
+
+static void
+segv_handler(int signo __attribute__ ((unused)),
+ siginfo_t * si, void *context __attribute__ ((unused)))
+{
+ static int count = 0;
+ ucell addr = 0xdeadbeef;
+
+ if (count) {
+ printk("Died while dumping forth dictionary core.\n");
+ goto out;
+ }
+
+ count++;
+
+ if (PC >= pointer2cell(dict) && PC <= pointer2cell(dict) + dicthead)
+ addr = read_cell(cell2pointer(PC));
+
+ printk("panic: segmentation violation at %p\n", (char *)si->si_addr);
+ printk("dict=%p here=%p(dict+0x%" FMT_CELL_x ") pc=0x%" FMT_CELL_x "(dict+0x%" FMT_CELL_x ")\n",
+ dict, dict + dicthead, dicthead, PC, PC - pointer2cell(dict));
+ printk("dstackcnt=%d rstackcnt=%d instruction=%" FMT_CELL_x "\n",
+ dstackcnt, rstackcnt, addr);
+
+ printdstack();
+ printrstack();
+
+ printk("Writing dictionary core file\n");
+ write_dictionary("forth.dict.core");
+
+ out:
+ exit(1);
+}
+
+/*
+ * allocate memory and prepare engine for memory management.
+ */
+
+static void init_memory(void)
+{
+ memset(memory, 0, MEMORY_SIZE);
+
+ /* we push start and end of memory to the stack
+ * so that it can be used by the forth word QUIT
+ * to initialize the memory allocator.
+ * Add a cell to the start address so we don't end
+ * up with a start address of zero during bootstrap
+ */
+
+ PUSH(pointer2cell(memory)+sizeof(cell));
+ PUSH(pointer2cell(memory) + MEMORY_SIZE-1);
+}
+
+
+void
+include_file( const char *name )
+{
+ FILE *file;
+
+ if( cursrc >= sizeof(srcfiles)/sizeof(srcfiles[0]) ) {
+ printk("\npanic: Maximum include depth reached!\n");
+ exit(1);
+ }
+
+ file = fopen_include( name );
+ if( !file ) {
+ printk("\npanic: Failed opening file '%s'\n", name );
+ exit(1);
+ }
+}
+
+
+void
+encode_file( const char *name )
+{
+ FILE *file = fopen_include(name);
+ int size;
+
+ if( !file ) {
+ printk("\npanic: Can't open '%s'\n", name );
+ exit(1);
+ }
+ fseek( file, 0, SEEK_END );
+ size = ftell( file );
+ fseek( file, 0, SEEK_SET );
+
+ if (verbose) {
+ printk("\nEncoding %s [%d bytes]\n", name, size );
+ }
+ fread( dict + dicthead, size, 1, file );
+ PUSH( pointer2cell(dict + dicthead) );
+ PUSH( size );
+ dicthead += size;
+ paddict(sizeof(cell));
+}
+
+
+static void run_dictionary(char *basedict, char *confile)
+{
+ if(!basedict)
+ return;
+
+ read_dictionary(basedict);
+ PC = (ucell)findword("initialize");
+
+ if (!PC) {
+ if (verbose) {
+ printk("Unable to find initialize word in dictionary %s; ignoring\n", basedict);
+ }
+ return;
+ }
+
+ if(!srcfiles[0]) {
+ cursrc = 1;
+ srcfiles[cursrc-1] = stdin;
+ }
+
+ dstackcnt=0;
+ rstackcnt=0;
+
+ init_memory();
+ if (verbose)
+ printk("Jumping to dictionary %s...\n", basedict);
+
+ /* If a console file has been specified, open it */
+ if (confile)
+ console = fopen(confile, "w");
+
+ srcbasedict = basedict;
+
+ enterforth((xt_t)PC);
+
+ /* Close the console file */
+ if (console)
+ fclose(console);
+}
+
+static void new_dictionary(const char *source)
+{
+ build_dictionary();
+
+ interpret_source((char *)source);
+
+ if (verbose || errors > 0) {
+ printk("interpretion finished. %d errors occured.\n",
+ errors);
+ }
+}
+
+/*
+ * main loop
+ */
+
+#define BANNER "OpenBIOS bootstrap kernel. (C) 2003-2006 Patrick Mauritz, Stefan Reinauer\n"\
+ "This software comes with absolutely no warranty. "\
+ "All rights reserved.\n\n"
+
+#ifdef __GLIBC__
+#define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \
+ " -h|--help show this help\n" \
+ " -V|--version print version and exit\n" \
+ " -v|--verbose print debugging information\n" \
+ " -I|--include dir add dir to include path\n" \
+ " -d|--source-dictionary bootstrap.dict\n" \
+ " use this dictionary as base\n" \
+ " -D|--target-dictionary output.dict\n" \
+ " write to output.dict\n" \
+ " -c|--console output.log\n" \
+ " write kernel console output to log file\n" \
+ " -s|--segfault install segfault handler\n" \
+ " -M|--dependency-dump file\n" \
+ " dump dependencies in Makefile format\n\n" \
+ " -x|--hexdump output format is C language hex dump\n"
+#else
+#define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \
+ " -h show this help\n" \
+ " -V print version and exit\n" \
+ " -v print debugging information\n" \
+ " -I add dir to include path\n" \
+ " -d bootstrap.dict\n" \
+ " use this dictionary as base\n" \
+ " -D output.dict\n" \
+ " write to output.dict\n" \
+ " -c output.log\n" \
+ " write kernel console output to log file\n" \
+ " -s install segfault handler\n\n" \
+ " -M file dump dependencies in Makefile format\n\n" \
+ " -x output format is C language hex dump\n"
+#endif
+
+int main(int argc, char *argv[])
+{
+ struct sigaction sa;
+
+ unsigned char *ressources=NULL; /* All memory used by us */
+ const char *dictname = NULL;
+ char *basedict = NULL;
+ char *consolefile = NULL;
+ char *depfilename = NULL;
+
+ unsigned char *bootstrapdict[2];
+ int c, cnt, hexdump = 0;
+
+ const char *optstring = "VvhsI:d:D:c:M:x?";
+
+ while (1) {
+#ifdef __GLIBC__
+ int option_index = 0;
+ static struct option long_options[] = {
+ {"version", 0, NULL, 'V'},
+ {"verbose", 0, NULL, 'v'},
+ {"help", 0, NULL, 'h'},
+ {"segfault", 0, NULL, 's'},
+ {"include", 1, NULL, 'I'},
+ {"source-dictionary", 1, NULL, 'd'},
+ {"target-dictionary", 1, NULL, 'D'},
+ {"console", 1, NULL, 'c'},
+ {"dependency-dump", 1, NULL, 'M'},
+ {"hexdump", 0, NULL, 'x'},
+ };
+
+ /*
+ * option handling
+ */
+
+ c = getopt_long(argc, argv, optstring, long_options,
+ &option_index);
+#else
+ c = getopt(argc, argv, optstring);
+#endif
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'V':
+ printk("Version " OPENBIOS_VERSION_STR "\n");
+ return 0;
+ case 'h':
+ case '?':
+ printk("Version " OPENBIOS_VERSION_STR "\n" USAGE,
+ argv[0]);
+ return 0;
+ case 'v':
+ verbose = 1;
+ break;
+ case 's':
+ segfault = 1;
+ break;
+ case 'I':
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("adding '%s' to include path\n", optarg);
+#endif
+ add_includepath(optarg);
+ break;
+ case 'd':
+ if (!basedict) {
+ basedict = optarg;
+ }
+ break;
+ case 'D':
+ if(!dictname) {
+ dictname = optarg;
+ }
+ break;
+ case 'c':
+ if (!consolefile) {
+ consolefile = optarg;
+ }
+ break;
+ case 'M':
+ if (!depfilename) {
+ depfilename = optarg;
+ }
+ break;
+ case 'x':
+ hexdump = 1;
+ break;
+ default:
+ return 1;
+ }
+ }
+
+ if (!dictname) {
+ dictname = "bootstrap.dict";
+ }
+ if (verbose) {
+ printk(BANNER);
+ printk("Using source dictionary '%s'\n", basedict);
+ printk("Dumping final dictionary to '%s'\n", dictname);
+ printk("Dumping dependencies to '%s'\n", depfilename);
+ }
+
+ if (argc < optind) {
+ printk(USAGE, argv[0]);
+ return 1;
+ }
+
+ if (depfilename) {
+ depfile = fopen(depfilename, "w");
+ if (!depfile) {
+ printk("panic: can't write to dependency file '%s'.\n",
+ depfilename);
+ exit(1);
+ }
+ fprintf(depfile, "%s:", dictname);
+ }
+
+ /*
+ * Get all required resources
+ */
+
+
+ ressources = malloc(MEMORY_SIZE + (2 * DICTIONARY_SIZE) + TRAMPOLINE_SIZE);
+ if (!ressources) {
+ printk("panic: not enough memory on host system.\n");
+ return 1;
+ }
+
+#ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH
+ base_address=(unsigned long)ressources;
+#endif
+
+ memory = (ucell *)ressources;
+
+ bootstrapdict[0] = ressources + MEMORY_SIZE;
+ bootstrapdict[1] = ressources + MEMORY_SIZE + DICTIONARY_SIZE;
+ trampoline = (ucell *)(ressources + MEMORY_SIZE + DICTIONARY_SIZE + DICTIONARY_SIZE);
+
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printf("memory: %p\n",memory);
+ printf("dict1: %p\n",bootstrapdict[0]);
+ printf("dict2: %p\n",bootstrapdict[1]);
+ printf("trampoline: %p\n",trampoline);
+ printf("size=%d, trampoline_size=%d\n",MEMORY_SIZE + (2 *
+ DICTIONARY_SIZE) + TRAMPOLINE_SIZE,
+ TRAMPOLINE_SIZE);
+#endif
+
+ if (trampoline == NULL) {
+ /* We're using side effects which is to some extent nasty */
+ printf("WARNING: no trampoline!\n");
+ } else {
+ init_trampoline(trampoline);
+ }
+
+ if (!segfault) {
+ if (verbose)
+ printk("Installing SIGSEGV handler...");
+
+ sa.sa_sigaction = segv_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO | SA_NODEFER;
+ sigaction(SIGSEGV, &sa, NULL);
+
+ if (verbose)
+ printk("done.\n");
+ }
+
+ /*
+ * Now do the real work
+ */
+
+ for (cnt=0; cnt<2; cnt++) {
+ if (verbose) {
+ printk("Compiling dictionary %d/%d\n", cnt+1, 2);
+ }
+ dict=bootstrapdict[cnt];
+ if(!basedict) {
+ new_dictionary(argv[optind]);
+ } else {
+ for (c=argc-1; c>=optind; c--)
+ include_file(argv[c]);
+
+ run_dictionary(basedict, consolefile);
+ }
+ if (depfile) {
+ fprintf(depfile, "\n");
+ fclose(depfile);
+ depfile = NULL;
+ }
+ if(errors)
+ break;
+ }
+
+#ifndef CONFIG_DEBUG_INTERPRETER
+ if (errors)
+ printk("dictionary not dumped to file.\n");
+ else
+#endif
+ {
+ relocation_table( bootstrapdict[0], bootstrapdict[1], dicthead);
+ if (hexdump) {
+ write_dictionary_hex(dictname);
+ } else {
+ write_dictionary(dictname);
+ }
+ }
+
+ free(ressources);
+
+ if (errors)
+ return 1;
+ else
+ return 0;
+}
diff --git a/qemu/roms/openbios/kernel/build.xml b/qemu/roms/openbios/kernel/build.xml
new file mode 100644
index 000000000..1090cd62e
--- /dev/null
+++ b/qemu/roms/openbios/kernel/build.xml
@@ -0,0 +1,16 @@
+<build>
+
+ <executable name="forthstrap" target="host">
+ <object source="dict.c"/>
+ <object source="bootstrap.c"/>
+ <object source="forth.c"/>
+ <object source="stack.c"/>
+ </executable>
+
+ <library name="bootstrap" type="static" target="target">
+ <object source="dict.c"/>
+ <object source="forth.c"/>
+ <object source="stack.c"/>
+ </library>
+
+</build>
diff --git a/qemu/roms/openbios/kernel/cross.h b/qemu/roms/openbios/kernel/cross.h
new file mode 100644
index 000000000..9dd656f8e
--- /dev/null
+++ b/qemu/roms/openbios/kernel/cross.h
@@ -0,0 +1,124 @@
+/* memory access abstraction layer for forth kernel
+ *
+ * Copyright (C) 2005 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __CROSS_H
+#define __CROSS_H 1
+
+/* The forthstrap compiler has to abstract the underlying dictionary
+ * type: big/little endian, 32/64bit. All other binaries shall use
+ * unchanged memory access for performance.
+ */
+
+/* byte swapping */
+
+#ifndef SWAP_ENDIANNESS
+
+/* trivial case - we don't have to change anything */
+#define read_ucell(addr) (*(ucell *)(addr))
+#define read_cell(addr) (*(cell *)(addr))
+#define read_long(addr) (*(u32 *)(addr))
+#define read_word(addr) (*(u16 *)(addr))
+#define read_byte(addr) (*(u8 *)(addr))
+
+#define write_ucell(addr, value) {*(ucell *)(addr)=(value);}
+#define write_cell(addr, value) {*(cell *)(addr)=(value);}
+#define write_long(addr, value) {*(u32 *)(addr)=(value);}
+#define write_word(addr, value) {*(u16 *)(addr)=(value);}
+#define write_byte(addr, value) {*(u8 *)(addr)=(value);}
+
+#define target_ucell(x) (x)
+#define target_cell(x) (x)
+#define target_long(x) (x)
+#define target_ulong(x) (x)
+
+#else /* SWAP_ENDIANNESS */
+
+#define target_word(value) ( (((value)>>8)&0xff) | (((value)&0xff)<<8) )
+#define target_long(value) ( (((value)&0xff000000)>>24)|(((value)&0x00ff0000)>>8)|(((value)&0xff00)<<8)|(((value)&0xff)<<24) )
+#define target_ulong(value) (target_long(value))
+
+#if BITS==32
+#define target_ucell(value) ((ucell)target_long(value))
+#define target_cell(value) ((cell)target_long(value))
+#elif BITS==64
+#define target_ucell(value) \
+ ((((ucell)target_long((value) & 0xffffffff)) << 32) | \
+ ((ucell)target_long((value) >> 32)))
+#define target_cell(value) \
+ ((((cell)target_long((value) & 0xffffffff)) << 32) | \
+ ((cell)target_long((value) >> 32)))
+#else
+#error "Endianness not supported. Please report."
+#endif
+
+#define read_ucell(addr) target_ucell(*(ucell *)(addr))
+#define read_cell(addr) target_cell(*(cell *)(addr))
+#define read_long(addr) target_long(*(u32 *)(addr))
+#define read_word(addr) target_word(*(u16 *)(addr))
+#define read_byte(addr) (*(u8 *)(addr))
+
+#define write_ucell(addr, value) {*(ucell *)(addr)=target_ucell(value);}
+#define write_cell(addr, value) {*(cell *)(addr)=target_cell(value);}
+#define write_long(addr, value) {*(u32 *)(addr)=target_long(value);}
+#define write_word(addr, value) {*(u16 *)(addr)=target_word(value);}
+#define write_byte(addr, value) {*(u8 *)(addr)=(value);}
+#endif
+
+#ifdef CONFIG_LITTLE_ENDIAN
+#define unaligned_read_word(addr) \
+ (read_byte(addr)|(read_byte((u8 *)addr+1)<<8))
+
+#define unaligned_read_long(addr) \
+ (unaligned_read_word(addr)|(unaligned_read_word((u8 *)addr+2)<<16))
+
+#define unaligned_write_word(addr, value) \
+ write_byte(addr, (value & 0xff)); write_byte((u8 *)(addr+1), (value>>8))
+
+#define unaligned_write_long(addr, value) \
+ unaligned_write_word(addr, (value & 0xffff)); \
+ unaligned_write_word((addr + 2), (value >> 16))
+
+#endif
+
+#ifdef CONFIG_BIG_ENDIAN
+#define unaligned_read_word(addr) \
+ ((read_byte(addr)<<8)|read_byte((u8 *)addr+1))
+
+#define unaligned_read_long(addr) \
+ ((unaligned_read_word(addr)<<16)|unaligned_read_word((u8 *)addr+2))
+
+#define unaligned_write_word(addr, value) \
+ write_byte(addr, (value >> 8)); write_byte((u8 *)(addr+1), (value & 0xff))
+
+#define unaligned_write_long(addr, value) \
+ unaligned_write_word(addr, (value >> 16)); \
+ unaligned_write_word((addr + 2), (value & 0xffff))
+#endif
+
+/* bit width handling */
+
+#if BITS==32
+#define FMT_CELL_x PRIx32
+#define FMT_CELL_d PRId32
+#else
+#define FMT_CELL_x PRIx64
+#define FMT_CELL_d PRId64
+#endif
+
+#ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH
+extern unsigned long base_address;
+#define pointer2cell(x) ((ucell)(((unsigned long)(x))-base_address))
+#define cell2pointer(x) ((u8 *)(((unsigned long)(x))+base_address))
+#endif
+
+#ifdef NATIVE_BITWIDTH_LARGER_THAN_HOST_BITWIDTH
+#define pointer2cell(x) ((ucell)(unsigned long)(x))
+#define cell2pointer(x) ((u8 *)((unsigned long)(x)&0xFFFFFFFFUL))
+#endif
+
+#endif
diff --git a/qemu/roms/openbios/kernel/dict.c b/qemu/roms/openbios/kernel/dict.c
new file mode 100644
index 000000000..0986cb14f
--- /dev/null
+++ b/qemu/roms/openbios/kernel/dict.c
@@ -0,0 +1,320 @@
+/*
+ * tag: dict management
+ *
+ * Copyright (C) 2003-2005 Stefan Reinauer, Patrick Mauritz
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "dict.h"
+#ifdef BOOTSTRAP
+#include <string.h>
+#else
+#include "libc/string.h"
+#endif
+#include "cross.h"
+
+
+unsigned char *dict = NULL;
+ucell *last;
+cell dicthead = 0;
+cell dictlimit = 0;
+
+/* lfa2nfa
+ * converts a link field address to a name field address,
+ * i.e find pointer to a given words name
+ */
+
+ucell lfa2nfa(ucell ilfa)
+{
+ /* get offset from dictionary start */
+ ilfa = ilfa - (ucell)pointer2cell(dict);
+ ilfa--; /* skip status */
+ while (dict[--ilfa] == 0); /* skip all pad bytes */
+ ilfa -= (dict[ilfa] - 128);
+ return ilfa + (ucell)pointer2cell(dict);
+}
+
+/* lfa2cfa
+ * converts a link field address to a code field address.
+ * in this forth implementation this is just a fixed offset
+ */
+
+static xt_t lfa2cfa(ucell ilfa)
+{
+ return (xt_t)(ilfa + sizeof(cell));
+}
+
+
+/* fstrlen - returns length of a forth string. */
+
+ucell fstrlen(ucell fstr)
+{
+ fstr -= pointer2cell(dict)+1;
+ //fstr -= pointer2cell(dict); FIXME
+ while (dict[++fstr] < 128)
+ ;
+ return dict[fstr] - 128;
+}
+
+/* to_lower - convert a character to lowecase */
+
+static int to_lower(int c)
+{
+ return ((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a') : c;
+}
+
+/* fstrcmp - compare null terminated string with forth string. */
+
+static int fstrcmp(const char *s1, ucell fstr)
+{
+ char *s2 = (char*)cell2pointer(fstr);
+ while (*s1) {
+ if ( to_lower(*(s1++)) != to_lower(*(s2++)) )
+ return -1;
+ }
+ return 0;
+}
+
+/* fstrncpy - copy a forth string to a destination (with NULL termination) */
+
+void fstrncpy(char *dest, ucell src, unsigned int maxlen)
+{
+ int len = fstrlen(src);
+
+ if (fstrlen(src) >= maxlen) len = maxlen - 1;
+ memcpy(dest, cell2pointer(src), len);
+ *(dest + len) = '\0';
+}
+
+
+/* findword
+ * looks up a given word in the dictionary. This function
+ * is used by the c based interpreter and to find the "initialize"
+ * word.
+ */
+
+xt_t findword(const char *s1)
+{
+ ucell tmplfa, len;
+
+ if (!last)
+ return 0;
+
+ tmplfa = read_ucell(last);
+
+ len = strlen(s1);
+
+ while (tmplfa) {
+ ucell nfa = lfa2nfa(tmplfa);
+
+ if (len == fstrlen(nfa) && !fstrcmp(s1, nfa)) {
+ return lfa2cfa(tmplfa);
+ }
+
+ tmplfa = read_ucell(cell2pointer(tmplfa));
+ }
+
+ return 0;
+}
+
+
+/* findsemis_wordlist
+ * Given a DOCOL xt and a wordlist, find the address of the semis
+ * word at the end of the word definition. We do this by finding
+ * the word before this in the dictionary, then counting back one
+ * from the NFA.
+ */
+
+static ucell findsemis_wordlist(ucell xt, ucell wordlist)
+{
+ ucell tmplfa, nextlfa, nextcfa;
+
+ if (!wordlist)
+ return 0;
+
+ tmplfa = read_ucell(cell2pointer(wordlist));
+ nextcfa = lfa2cfa(tmplfa);
+
+ /* Catch the special case where the lfa of the word we
+ * want is the last word in the dictionary; in that case
+ * the end of the word is given by "here" - 1 */
+ if (nextcfa == xt)
+ return pointer2cell(dict) + dicthead - sizeof(cell);
+
+ while (tmplfa) {
+
+ /* Peek ahead and see if the next CFA in the list is the
+ * one we are searching for */
+ nextlfa = read_ucell(cell2pointer(tmplfa));
+ nextcfa = lfa2cfa(nextlfa);
+
+ /* If so, count back 1 cell from the current NFA */
+ if (nextcfa == xt)
+ return lfa2nfa(tmplfa) - sizeof(cell);
+
+ tmplfa = nextlfa;
+ }
+
+ return 0;
+}
+
+
+/* findsemis
+ * Given a DOCOL xt, find the address of the semis word at the end
+ * of the word definition by searching all vocabularies */
+
+ucell findsemis(ucell xt)
+{
+ ucell usesvocab = findword("vocabularies?") + sizeof(cell);
+ unsigned int i;
+
+ if (read_ucell(cell2pointer(usesvocab))) {
+ /* Vocabularies are in use, so search each one in turn */
+ ucell numvocabs = findword("#order") + sizeof(cell);
+
+ for (i = 0; i < read_ucell(cell2pointer(numvocabs)); i++) {
+ ucell vocabs = findword("vocabularies") + 2 * sizeof(cell);
+ ucell semis = findsemis_wordlist(xt, read_cell(cell2pointer(vocabs + (i * sizeof(cell)))));
+
+ /* If we get a non-zero result, we found the xt in this vocab */
+ if (semis)
+ return semis;
+ }
+ } else {
+ /* Vocabularies not in use */
+ return findsemis_wordlist(xt, read_ucell(last));
+ }
+
+ return 0;
+}
+
+
+/* findxtfromcell_wordlist
+ * Given a cell and a wordlist, determine the CFA of the word containing
+ * the cell or 0 if we are unable to return a suitable CFA
+ */
+
+ucell findxtfromcell_wordlist(ucell incell, ucell wordlist)
+{
+ ucell tmplfa;
+
+ if (!wordlist)
+ return 0;
+
+ tmplfa = read_ucell(cell2pointer(wordlist));
+ while (tmplfa) {
+ if (tmplfa < incell)
+ return lfa2cfa(tmplfa);
+
+ tmplfa = read_ucell(cell2pointer(tmplfa));
+ }
+
+ return 0;
+}
+
+
+/* findxtfromcell
+ * Given a cell, determine the CFA of the word containing
+ * the cell by searching all vocabularies
+ */
+
+ucell findxtfromcell(ucell incell)
+{
+ ucell usesvocab = findword("vocabularies?") + sizeof(cell);
+ unsigned int i;
+
+ if (read_ucell(cell2pointer(usesvocab))) {
+ /* Vocabularies are in use, so search each one in turn */
+ ucell numvocabs = findword("#order") + sizeof(cell);
+
+ for (i = 0; i < read_ucell(cell2pointer(numvocabs)); i++) {
+ ucell vocabs = findword("vocabularies") + 2 * sizeof(cell);
+ ucell semis = findxtfromcell_wordlist(incell, read_cell(cell2pointer(vocabs + (i * sizeof(cell)))));
+
+ /* If we get a non-zero result, we found the xt in this vocab */
+ if (semis)
+ return semis;
+ }
+ } else {
+ /* Vocabularies not in use */
+ return findxtfromcell_wordlist(incell, read_ucell(last));
+ }
+
+ return 0;
+}
+
+void dump_header(dictionary_header_t *header)
+{
+ printk("OpenBIOS dictionary:\n");
+ printk(" version: %d\n", header->version);
+ printk(" cellsize: %d\n", header->cellsize);
+ printk(" endianess: %s\n", header->endianess?"big":"little");
+ printk(" compression: %s\n", header->compression?"yes":"no");
+ printk(" relocation: %s\n", header->relocation?"yes":"no");
+ printk(" checksum: %08x\n", target_long(header->checksum));
+ printk(" length: %08x\n", target_long(header->length));
+ printk(" last: %0" FMT_CELL_x "\n", target_cell(header->last));
+}
+
+ucell load_dictionary(const char *data, ucell len)
+{
+ u32 checksum=0;
+ const char *checksum_walk;
+ ucell *walk, *reloc_table;
+ dictionary_header_t *header=(dictionary_header_t *)data;
+
+ /* assertions */
+ if (len <= (sizeof(dictionary_header_t)) || strncmp(DICTID, data, 8))
+ return 0;
+#ifdef CONFIG_DEBUG_DICTIONARY
+ dump_header(header);
+#endif
+
+ checksum_walk=data;
+ while (checksum_walk<data+len) {
+ checksum+=read_long(checksum_walk);
+ checksum_walk+=sizeof(u32);
+ }
+
+ if(checksum) {
+ printk("Checksum invalid (%08x)!\n", checksum);
+ return 0;
+ }
+
+ data += sizeof(dictionary_header_t);
+
+ dicthead = target_long(header->length);
+
+ memcpy(dict, data, dicthead);
+ reloc_table=(ucell *)(data+dicthead);
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("\nmoving dictionary (%x bytes) to %x\n",
+ (ucell)dicthead, (ucell)dict);
+ printk("\ndynamic relocation...");
+#endif
+
+ for (walk = (ucell *) dict; walk < (ucell *) (dict + dicthead);
+ walk++) {
+ int pos, bit, l;
+ l=(walk-(ucell *)dict);
+ pos=l/BITS;
+ bit=l&~(-BITS);
+ if (reloc_table[pos] & target_ucell((ucell)1ULL << bit)) {
+ // printk("%lx, pos %x, bit %d\n",*walk, pos, bit);
+ write_ucell(walk, read_ucell(walk)+pointer2cell(dict));
+ }
+ }
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk(" done.\n");
+#endif
+
+ last = (ucell *)(dict + target_ucell(header->last));
+
+ return -1;
+}
diff --git a/qemu/roms/openbios/kernel/forth.c b/qemu/roms/openbios/kernel/forth.c
new file mode 100644
index 000000000..61dd70d31
--- /dev/null
+++ b/qemu/roms/openbios/kernel/forth.c
@@ -0,0 +1,1966 @@
+/* tag: C implementation of all forth primitives,
+ * internal words, inner interpreter and such
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "sysinclude.h"
+#include "kernel/stack.h"
+#include "kernel/kernel.h"
+#include "dict.h"
+
+/*
+ * cross platform abstraction
+ */
+
+#include "cross.h"
+
+#ifndef FCOMPILER
+#include "libc/vsprintf.h"
+#else
+#include <stdarg.h>
+#endif
+
+/*
+ * execution works as follows:
+ * - PC is pushed on return stack
+ * - PC is set to new CFA
+ * - address pointed by CFA is executed by CPU
+ */
+
+typedef void forth_word(void);
+
+static forth_word * const words[];
+ucell PC;
+volatile int interruptforth = 0;
+
+#define DEBUG_MODE_NONE 0
+#define DEBUG_MODE_STEP 1
+#define DEBUG_MODE_TRACE 2
+#define DEBUG_MODE_STEPUP 3
+
+#define DEBUG_BANNER "\nStepper keys: <space>/<enter> Up Down Trace Rstack Forth\n"
+
+/* Empty linked list of debug xts */
+struct debug_xt {
+ ucell xt_docol;
+ ucell xt_semis;
+ int mode;
+ struct debug_xt *next;
+};
+
+static struct debug_xt debug_xt_eol = { (ucell)0, (ucell)0, 0, NULL};
+static struct debug_xt *debug_xt_list = &debug_xt_eol;
+
+/* Static buffer for xt name */
+char xtname[MAXNFALEN];
+
+#ifndef FCOMPILER
+/* instead of pointing to an explicit 0 variable we
+ * point behind the pointer.
+ */
+static ucell t[] = { 0, 0, 0, 0 };
+static ucell *trampoline = t;
+
+/*
+ * Code Field Address (CFA) definitions (DOCOL and the like)
+ */
+
+void forth_init(void)
+{
+ init_trampoline(trampoline);
+}
+#endif
+
+#ifndef CONFIG_DEBUG_INTERPRETER
+#define dbg_interp_printk( a... ) do { } while(0)
+#else
+#define dbg_interp_printk( a... ) printk( a )
+#endif
+
+#ifndef CONFIG_DEBUG_INTERNAL
+#define dbg_internal_printk( a... ) do { } while(0)
+#else
+#define dbg_internal_printk( a... ) printk( a )
+#endif
+
+
+void init_trampoline(ucell *tramp)
+{
+ tramp[0] = DOCOL;
+ tramp[1] = 0;
+ tramp[2] = target_ucell(pointer2cell(tramp) + 3 * sizeof(ucell));
+ tramp[3] = 0;
+}
+
+static inline void processxt(ucell xt)
+{
+ void (*tokenp) (void);
+
+ dbg_interp_printk("processxt: pc=%x, xt=%x\n", PC, xt);
+ tokenp = words[xt];
+ tokenp();
+}
+
+static void docol(void)
+{ /* DOCOL */
+ PUSHR(PC);
+ PC = read_ucell(cell2pointer(PC));
+
+ dbg_interp_printk("docol: %s\n", cell2pointer( lfa2nfa(PC - sizeof(cell)) ));
+}
+
+static void semis(void)
+{
+ PC = POPR();
+}
+
+static inline void next(void)
+{
+ PC += sizeof(ucell);
+
+ dbg_interp_printk("next: PC is now %x\n", PC);
+ processxt(read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))));
+}
+
+static inline void next_dbg(void);
+
+int enterforth(xt_t xt)
+{
+ ucell *_cfa = (ucell*)cell2pointer(xt);
+ cell tmp;
+
+ if (read_ucell(_cfa) != DOCOL) {
+ trampoline[1] = target_ucell(xt);
+ _cfa = trampoline;
+ }
+
+ if (rstackcnt < 0) {
+ rstackcnt = 0;
+ }
+
+ tmp = rstackcnt;
+ interruptforth = FORTH_INTSTAT_CLR;
+
+ PUSHR(PC);
+ PC = pointer2cell(_cfa);
+
+ while (rstackcnt > tmp && !(interruptforth & FORTH_INTSTAT_STOP)) {
+ if (debug_xt_list->next == NULL) {
+ while (rstackcnt > tmp && !interruptforth) {
+ dbg_interp_printk("enterforth: NEXT\n");
+ next();
+ }
+ } else {
+ while (rstackcnt > tmp && !interruptforth) {
+ dbg_interp_printk("enterforth: NEXT_DBG\n");
+ next_dbg();
+ }
+ }
+
+ /* Always clear the debug mode change flag */
+ interruptforth = interruptforth & (~FORTH_INTSTAT_DBG);
+ }
+
+#if 0
+ /* return true if we took an exception. The caller should normally
+ * handle exceptions by returning immediately since the throw
+ * is supposed to abort the execution of this C-code too.
+ */
+
+ if (rstackcnt != tmp) {
+ printk("EXCEPTION DETECTED!\n");
+ }
+#endif
+ return rstackcnt != tmp;
+}
+
+/* called inline thus a slightly different behaviour */
+static void lit(void)
+{ /* LIT */
+ PC += sizeof(cell);
+ PUSH(read_ucell(cell2pointer(PC)));
+ dbg_interp_printk("lit: %x\n", read_ucell(cell2pointer(PC)));
+}
+
+static void docon(void)
+{ /* DOCON */
+ ucell tmp = read_ucell(cell2pointer(read_ucell(cell2pointer(PC)) + sizeof(ucell)));
+ PUSH(tmp);
+ dbg_interp_printk("docon: PC=%x, value=%x\n", PC, tmp);
+}
+
+static void dovar(void)
+{ /* DOVAR */
+ ucell tmp = read_ucell(cell2pointer(PC)) + sizeof(ucell);
+ PUSH(tmp); /* returns address to variable */
+ dbg_interp_printk("dovar: PC: %x, %x\n", PC, tmp);
+}
+
+static void dobranch(void)
+{ /* unconditional branch */
+ PC += sizeof(cell);
+ PC += read_cell(cell2pointer(PC));
+}
+
+static void docbranch(void)
+{ /* conditional branch */
+ PC += sizeof(cell);
+ if (POP()) {
+ dbg_internal_printk(" ?branch: end loop\n");
+ } else {
+ dbg_internal_printk(" ?branch: follow branch\n");
+ PC += read_cell(cell2pointer(PC));
+ }
+}
+
+
+static void execute(void)
+{ /* EXECUTE */
+ ucell address = POP();
+ dbg_interp_printk("execute: %x\n", address);
+
+ PUSHR(PC);
+ trampoline[1] = target_ucell(address);
+ PC = pointer2cell(trampoline);
+}
+
+/*
+ * call ( ... function-ptr -- ??? )
+ */
+static void call(void)
+{
+#ifdef FCOMPILER
+ printk("Sorry. Usage of Forth2C binding is forbidden during bootstrap.\n");
+ exit(1);
+#else
+ void (*funcptr) (void);
+ funcptr=(void *)cell2pointer(POP());
+ dbg_interp_printk("call: %x", funcptr);
+ funcptr();
+#endif
+}
+
+/*
+ * sys-debug ( errno -- )
+ */
+
+static void sysdebug(void)
+{
+#ifdef FCOMPILER
+ cell errorno=POP();
+ exception(errorno);
+#else
+ (void) POP();
+#endif
+}
+
+static void dodoes(void)
+{ /* DODOES */
+ ucell data = read_ucell(cell2pointer(PC)) + (2 * sizeof(ucell));
+ ucell word = read_ucell(cell2pointer(read_ucell(cell2pointer(PC)) + sizeof(ucell)));
+
+ dbg_interp_printk("DODOES data=%x word=%x\n", data, word);
+
+ PUSH(data);
+ PUSH(word);
+
+ execute();
+}
+
+static void dodefer(void)
+{
+ docol();
+}
+
+static void dodo(void)
+{
+ cell startval, endval;
+ startval = POP();
+ endval = POP();
+
+ PUSHR(endval);
+ PUSHR(startval);
+}
+
+static void doisdo(void)
+{
+ cell startval, endval, offset;
+
+ startval = POP();
+ endval = POP();
+
+ PC += sizeof(cell);
+
+ if (startval == endval) {
+ offset = read_cell(cell2pointer(PC));
+ PC += offset;
+ } else {
+ PUSHR(endval);
+ PUSHR(startval);
+ }
+}
+
+static void doloop(void)
+{
+ cell offset, startval, endval;
+
+ startval = POPR() + 1;
+ endval = POPR();
+
+ PC += sizeof(cell);
+
+ if (startval < endval) {
+ offset = read_cell(cell2pointer(PC));
+ PC += offset;
+ PUSHR(endval);
+ PUSHR(startval);
+ }
+
+}
+
+static void doplusloop(void)
+{
+ ucell high, low;
+ cell increment, startval, endval, offset;
+
+ increment = POP();
+
+ startval = POPR();
+ endval = POPR();
+
+ low = (ucell) startval;
+ startval += increment;
+
+ PC += sizeof(cell);
+
+ if (increment >= 0) {
+ high = (ucell) startval;
+ } else {
+ high = low;
+ low = (ucell) startval;
+ }
+
+ if (endval - (low + 1) >= high - low) {
+ offset = read_cell(cell2pointer(PC));
+ PC += offset;
+
+ PUSHR(endval);
+ PUSHR(startval);
+ }
+}
+
+/*
+ * instance handling CFAs
+ */
+#ifndef FCOMPILER
+static ucell get_myself(void)
+{
+ static ucell *myselfptr = NULL;
+ if (myselfptr == NULL) {
+ myselfptr = (ucell*)cell2pointer(findword("my-self")) + 1;
+ }
+ ucell *myself = (ucell*)cell2pointer(*myselfptr);
+ return (myself != NULL) ? *myself : 0;
+}
+
+static void doivar(void)
+{
+ ucell r, *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell));
+ ucell ibase = get_myself();
+
+ dbg_interp_printk("ivar, offset: %d size: %d (ibase %d)\n", p[0], p[1], ibase );
+
+ r = ibase ? ibase + p[0] : pointer2cell(&p[2]);
+ PUSH( r );
+}
+
+static void doival(void)
+{
+ ucell r, *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell));
+ ucell ibase = get_myself();
+
+ dbg_interp_printk("ivar, offset: %d size: %d\n", p[0], p[1] );
+
+ r = ibase ? ibase + p[0] : pointer2cell(&p[2]);
+ PUSH( *(ucell *)cell2pointer(r) );
+}
+
+static void doidefer(void)
+{
+ ucell *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell));
+ ucell ibase = get_myself();
+
+ dbg_interp_printk("doidefer, offset: %d size: %d\n", p[0], p[1] );
+
+ PUSHR(PC);
+ PC = ibase ? ibase + p[0] : pointer2cell(&p[2]);
+ PC -= sizeof(ucell);
+}
+#else
+static void noinstances(void)
+{
+ printk("Opening devices is not supported during bootstrap. Sorry.\n");
+ exit(1);
+}
+#define doivar noinstances
+#define doival noinstances
+#define doidefer noinstances
+#endif
+
+/*
+ * $include / $encode-file
+ */
+#ifdef FCOMPILER
+static void
+string_relay(void (*func)(const char *))
+{
+ int len = POP();
+ char *name, *p = (char*)cell2pointer(POP());
+ name = malloc(len + 1);
+ memcpy(name, p, len);
+ name[len] = 0;
+ (*func)(name);
+ free(name);
+}
+#else
+#define string_relay(dummy) do { DROP(); DROP(); } while(0)
+#endif
+
+static void
+do_include(void)
+{
+ string_relay(&include_file);
+}
+
+static void
+do_encode_file( void )
+{
+ string_relay(&encode_file);
+}
+
+/*
+ * Debug support functions
+ */
+
+static
+int printf_console(const char *fmt, ...)
+{
+ cell tmp;
+
+ char buf[512];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ /* Push to the Forth interpreter for console output */
+ tmp = rstackcnt;
+
+ PUSH(pointer2cell(buf));
+ PUSH((int)strlen(buf));
+ trampoline[1] = findword("type");
+
+ PUSHR(PC);
+ PC = pointer2cell(trampoline);
+
+ while (rstackcnt > tmp) {
+ dbg_interp_printk("printf_console: NEXT\n");
+ next();
+ }
+
+ return i;
+}
+
+static
+int getchar_console(void)
+{
+ cell tmp;
+
+ /* Push to the Forth interpreter for console output */
+ tmp = rstackcnt;
+
+ trampoline[1] = findword("key");
+
+ PUSHR(PC);
+ PC = pointer2cell(trampoline);
+
+ while (rstackcnt > tmp) {
+ dbg_interp_printk("getchar_console: NEXT\n");
+ next();
+ }
+
+ return POP();
+}
+
+static void
+display_dbg_dstack(void)
+{
+ /* Display dstack contents between parentheses */
+ int i;
+
+ if (dstackcnt == 0) {
+ printf_console(" ( Empty ) ");
+ return;
+ } else {
+ printf_console(" ( ");
+ for (i = 1; i <= dstackcnt; i++) {
+ if (i != 1) {
+ printf_console(" ");
+ }
+ printf_console("%" FMT_CELL_x, dstack[i]);
+ }
+ printf_console(" ) ");
+ }
+}
+
+static void
+display_dbg_rstack(void)
+{
+ /* Display rstack contents between parentheses */
+ int i;
+
+ if (rstackcnt == 0) {
+ printf_console(" ( Empty ) ");
+ return;
+ } else {
+ printf_console("\nR: ( ");
+ for (i = 1; i <= rstackcnt; i++) {
+ if (i != 1) {
+ printf_console(" ");
+ }
+ printf_console("%" FMT_CELL_x, rstack[i]);
+ }
+ printf_console(" ) \n");
+ }
+}
+
+static int
+add_debug_xt(ucell xt)
+{
+ struct debug_xt *debug_xt_item;
+
+ /* If the xt CFA isn't DOCOL then issue a warning and do nothing */
+ if (read_ucell(cell2pointer(xt)) != DOCOL) {
+ printf_console("\nprimitive words cannot be debugged\n");
+ return 0;
+ }
+
+ /* If this xt is already in the list, do nothing but indicate success */
+ for (debug_xt_item = debug_xt_list; debug_xt_item->next != NULL;
+ debug_xt_item = debug_xt_item->next)
+ if (debug_xt_item->xt_docol == xt) {
+ return 1;
+ }
+
+ /* We already have the CFA (PC) indicating the starting cell of
+ the word, however we also need the ending cell too (we cannot
+ rely on the rstack as it can be arbitrarily changed by a forth
+ word). Hence the use of findsemis() */
+
+ /* Otherwise add to the head of the linked list */
+ debug_xt_item = malloc(sizeof(struct debug_xt));
+ debug_xt_item->xt_docol = xt;
+ debug_xt_item->xt_semis = findsemis(xt);
+ debug_xt_item->mode = DEBUG_MODE_NONE;
+ debug_xt_item->next = debug_xt_list;
+ debug_xt_list = debug_xt_item;
+
+ /* Indicate debug mode change */
+ interruptforth |= FORTH_INTSTAT_DBG;
+
+ /* Success */
+ return 1;
+}
+
+static void
+del_debug_xt(ucell xt)
+{
+ struct debug_xt *debug_xt_item, *tmp_xt_item;
+
+ /* Handle the case where the xt is at the head of the list */
+ if (debug_xt_list->xt_docol == xt) {
+ tmp_xt_item = debug_xt_list;
+ debug_xt_list = debug_xt_list->next;
+ free(tmp_xt_item);
+
+ return;
+ }
+
+ /* Otherwise find this xt in the linked list and remove it */
+ for (debug_xt_item = debug_xt_list; debug_xt_item->next != NULL;
+ debug_xt_item = debug_xt_item->next) {
+ if (debug_xt_item->next->xt_docol == xt) {
+ tmp_xt_item = debug_xt_item->next;
+ debug_xt_item->next = debug_xt_item->next->next;
+ free(tmp_xt_item);
+ }
+ }
+
+ /* If the list is now empty, indicate debug mode change */
+ if (debug_xt_list->next == NULL) {
+ interruptforth |= FORTH_INTSTAT_DBG;
+ }
+}
+
+static void
+do_source_dbg(struct debug_xt *debug_xt_item)
+{
+ /* Forth source debugger implementation */
+ char k, done = 0;
+
+ /* Display current dstack */
+ display_dbg_dstack();
+ printf_console("\n");
+
+ fstrncpy(xtname, lfa2nfa(read_ucell(cell2pointer(PC)) - sizeof(cell)), MAXNFALEN);
+ printf_console("%p: %s ", cell2pointer(PC), xtname);
+
+ /* If in trace mode, we just carry on */
+ if (debug_xt_item->mode == DEBUG_MODE_TRACE) {
+ return;
+ }
+
+ /* Otherwise in step mode, prompt for a keypress */
+ k = getchar_console();
+
+ /* Only proceed if done is true */
+ while (!done) {
+ switch (k) {
+
+ case ' ':
+ case '\n':
+ /* Perform a single step */
+ done = 1;
+ break;
+
+ case 'u':
+ case 'U':
+ /* Up - unmark current word for debug, mark its caller for
+ * debugging and finish executing current word */
+
+ /* Since this word could alter the rstack during its execution,
+ * we only know the caller when (semis) is called for this xt.
+ * Hence we mark the xt as a special DEBUG_MODE_STEPUP which
+ * means we run as normal, but schedule the xt for deletion
+ * at its corresponding (semis) word when we know the rstack
+ * will be set to its final parent value */
+ debug_xt_item->mode = DEBUG_MODE_STEPUP;
+ done = 1;
+ break;
+
+ case 'd':
+ case 'D':
+ /* Down - mark current word for debug and step into it */
+ done = add_debug_xt(read_ucell(cell2pointer(PC)));
+ if (!done) {
+ k = getchar_console();
+ }
+ break;
+
+ case 't':
+ case 'T':
+ /* Trace mode */
+ debug_xt_item->mode = DEBUG_MODE_TRACE;
+ done = 1;
+ break;
+
+ case 'r':
+ case 'R':
+ /* Display rstack */
+ display_dbg_rstack();
+ done = 0;
+ k = getchar_console();
+ break;
+
+ case 'f':
+ case 'F':
+ /* Start subordinate Forth interpreter */
+ PUSHR(PC - sizeof(cell));
+ PC = findword("outer-interpreter") + sizeof(ucell);
+
+ /* Save rstack position for when we return */
+ dbgrstackcnt = rstackcnt;
+ done = 1;
+ break;
+
+ default:
+ /* Display debug banner */
+ printf_console(DEBUG_BANNER);
+ k = getchar_console();
+ }
+ }
+}
+
+static void docol_dbg(void)
+{ /* DOCOL */
+ struct debug_xt *debug_xt_item;
+
+ PUSHR(PC);
+ PC = read_ucell(cell2pointer(PC));
+
+ /* If current xt is in our debug xt list, display word name */
+ debug_xt_item = debug_xt_list;
+ while (debug_xt_item->next) {
+ if (debug_xt_item->xt_docol == PC) {
+ fstrncpy(xtname, lfa2nfa(PC - sizeof(cell)), MAXNFALEN);
+ printf_console("\n: %s ", xtname);
+
+ /* Step mode is the default */
+ debug_xt_item->mode = DEBUG_MODE_STEP;
+ }
+
+ debug_xt_item = debug_xt_item->next;
+ }
+
+ dbg_interp_printk("docol_dbg: %s\n", cell2pointer(lfa2nfa(PC - sizeof(cell))));
+}
+
+static void semis_dbg(void)
+{
+ struct debug_xt *debug_xt_item, *debug_xt_up = NULL;
+
+ /* If current semis is in our debug xt list, disable debug mode */
+ debug_xt_item = debug_xt_list;
+ while (debug_xt_item->next) {
+ if (debug_xt_item->xt_semis == PC) {
+ if (debug_xt_item->mode != DEBUG_MODE_STEPUP) {
+ /* Handle the normal case */
+ fstrncpy(xtname, lfa2nfa(debug_xt_item->xt_docol - sizeof(cell)), MAXNFALEN);
+ printf_console("\n[ Finished %s ] ", xtname);
+
+ /* Reset to step mode in case we were in trace mode */
+ debug_xt_item->mode = DEBUG_MODE_STEP;
+ } else {
+ /* This word requires execution of the debugger "Up"
+ * semantics. However we can't do this here since we
+ * are iterating through the debug list, and we need
+ * to change it. So we do it afterwards.
+ */
+ debug_xt_up = debug_xt_item;
+ }
+ }
+
+ debug_xt_item = debug_xt_item->next;
+ }
+
+ /* Execute debugger "Up" semantics if required */
+ if (debug_xt_up) {
+ /* Only add the parent word if it is not within the trampoline */
+ if (rstack[rstackcnt] != (cell)pointer2cell(&trampoline[1])) {
+ del_debug_xt(debug_xt_up->xt_docol);
+ add_debug_xt(findxtfromcell(rstack[rstackcnt]));
+
+ fstrncpy(xtname, lfa2nfa(findxtfromcell(rstack[rstackcnt]) - sizeof(cell)), MAXNFALEN);
+ printf_console("\n[ Up to %s ] ", xtname);
+ } else {
+ fstrncpy(xtname, lfa2nfa(findxtfromcell(debug_xt_up->xt_docol) - sizeof(cell)), MAXNFALEN);
+ printf_console("\n[ Finished %s (Unable to go up, hit trampoline) ] ", xtname);
+
+ del_debug_xt(debug_xt_up->xt_docol);
+ }
+
+ debug_xt_up = NULL;
+ }
+
+ PC = POPR();
+}
+
+static inline void next_dbg(void)
+{
+ struct debug_xt *debug_xt_item;
+ void (*tokenp) (void);
+
+ PC += sizeof(ucell);
+
+ /* If the PC lies within a debug range, run the source debugger */
+ debug_xt_item = debug_xt_list;
+ while (debug_xt_item->next) {
+ if (PC >= debug_xt_item->xt_docol && PC <= debug_xt_item->xt_semis &&
+ debug_xt_item->mode != DEBUG_MODE_STEPUP) {
+ do_source_dbg(debug_xt_item);
+ }
+
+ debug_xt_item = debug_xt_item->next;
+ }
+
+ dbg_interp_printk("next_dbg: PC is now %x\n", PC);
+
+ /* Intercept DOCOL and SEMIS and redirect to debug versions */
+ if (read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))) == DOCOL) {
+ tokenp = docol_dbg;
+ tokenp();
+ } else if (read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))) == DOSEMIS) {
+ tokenp = semis_dbg;
+ tokenp();
+ } else {
+ /* Otherwise process as normal */
+ processxt(read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))));
+ }
+}
+
+static void
+do_debug_xt(void)
+{
+ ucell xt = POP();
+
+ /* Add to the debug list */
+ if (add_debug_xt(xt)) {
+ /* Display debug banner */
+ printf_console(DEBUG_BANNER);
+
+ /* Indicate change to debug mode */
+ interruptforth |= FORTH_INTSTAT_DBG;
+ }
+}
+
+static void
+do_debug_off(void)
+{
+ /* Empty the debug xt linked list */
+ while (debug_xt_list->next != NULL) {
+ del_debug_xt(debug_xt_list->xt_docol);
+ }
+}
+
+/*
+ * Forth primitives needed to set up
+ * all the words described in IEEE1275-1994.
+ */
+
+/*
+ * dup ( x -- x x )
+ */
+
+static void fdup(void)
+{
+ const cell tmp = GETTOS();
+ PUSH(tmp);
+}
+
+
+/*
+ * 2dup ( x1 x2 -- x1 x2 x1 x2 )
+ */
+
+static void twodup(void)
+{
+ cell tmp = GETITEM(1);
+ PUSH(tmp);
+ tmp = GETITEM(1);
+ PUSH(tmp);
+}
+
+
+/*
+ * ?dup ( x -- 0 | x x )
+ */
+
+static void isdup(void)
+{
+ const cell tmp = GETTOS();
+ if (tmp)
+ PUSH(tmp);
+}
+
+
+/*
+ * over ( x y -- x y x )
+ */
+
+static void over(void)
+{
+ const cell tmp = GETITEM(1);
+ PUSH(tmp);
+}
+
+
+/*
+ * 2over ( x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2 )
+ */
+
+static void twoover(void)
+{
+ const cell tmp = GETITEM(3);
+ const cell tmp2 = GETITEM(2);
+ PUSH(tmp);
+ PUSH(tmp2);
+}
+
+/*
+ * pick ( xu ... x1 x0 u -- xu ... x1 x0 xu )
+ */
+
+static void pick(void)
+{
+ const cell u = POP();
+ if (dstackcnt >= u) {
+ ucell tmp = dstack[dstackcnt - u];
+ PUSH(tmp);
+ } else {
+ /* underrun */
+ }
+}
+
+
+/*
+ * drop ( x -- )
+ */
+
+static void drop(void)
+{
+ POP();
+}
+
+/*
+ * 2drop ( x1 x2 -- )
+ */
+
+static void twodrop(void)
+{
+ POP();
+ POP();
+}
+
+
+/*
+ * nip ( x1 x2 -- x2 )
+ */
+
+static void nip(void)
+{
+ const cell tmp = POP();
+ POP();
+ PUSH(tmp);
+}
+
+
+/*
+ * roll ( xu ... x1 x0 u -- xu-1... x1 x0 xu )
+ */
+
+static void roll(void)
+{
+ const cell u = POP();
+ if (dstackcnt >= u) {
+ int i;
+ const cell xu = dstack[dstackcnt - u];
+ for (i = dstackcnt - u; i < dstackcnt; i++) {
+ dstack[i] = dstack[i + 1];
+ }
+ dstack[dstackcnt] = xu;
+ } else {
+ /* Stack underrun */
+ }
+}
+
+
+/*
+ * rot ( x1 x2 x3 -- x2 x3 x1 )
+ */
+
+static void rot(void)
+{
+ const cell tmp = POP();
+ const cell tmp2 = POP();
+ const cell tmp3 = POP();
+ PUSH(tmp2);
+ PUSH(tmp);
+ PUSH(tmp3);
+}
+
+
+/*
+ * -rot ( x1 x2 x3 -- x3 x1 x2 )
+ */
+
+static void minusrot(void)
+{
+ const cell tmp = POP();
+ const cell tmp2 = POP();
+ const cell tmp3 = POP();
+ PUSH(tmp);
+ PUSH(tmp3);
+ PUSH(tmp2);
+}
+
+
+/*
+ * swap ( x1 x2 -- x2 x1 )
+ */
+
+static void swap(void)
+{
+ const cell tmp = POP();
+ const cell tmp2 = POP();
+ PUSH(tmp);
+ PUSH(tmp2);
+}
+
+
+/*
+ * 2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
+ */
+
+static void twoswap(void)
+{
+ const cell tmp = POP();
+ const cell tmp2 = POP();
+ const cell tmp3 = POP();
+ const cell tmp4 = POP();
+ PUSH(tmp2);
+ PUSH(tmp);
+ PUSH(tmp4);
+ PUSH(tmp3);
+}
+
+
+/*
+ * >r ( x -- ) (R: -- x )
+ */
+
+static void tor(void)
+{
+ ucell tmp = POP();
+#ifdef CONFIG_DEBUG_RSTACK
+ printk(" >R: %x\n", tmp);
+#endif
+ PUSHR(tmp);
+}
+
+
+/*
+ * r> ( -- x ) (R: x -- )
+ */
+
+static void rto(void)
+{
+ ucell tmp = POPR();
+#ifdef CONFIG_DEBUG_RSTACK
+ printk(" R>: %x\n", tmp);
+#endif
+ PUSH(tmp);
+}
+
+
+/*
+ * r@ ( -- x ) (R: x -- x )
+ */
+
+static void rfetch(void)
+{
+ PUSH(GETTORS());
+}
+
+
+/*
+ * depth ( -- u )
+ */
+
+static void depth(void)
+{
+ const cell tmp = dstackcnt;
+ PUSH(tmp);
+}
+
+
+/*
+ * depth! ( ... u -- x1 x2 .. xu )
+ */
+
+static void depthwrite(void)
+{
+ ucell tmp = POP();
+ dstackcnt = tmp;
+}
+
+
+/*
+ * rdepth ( -- u )
+ */
+
+static void rdepth(void)
+{
+ const cell tmp = rstackcnt;
+ PUSH(tmp);
+}
+
+
+/*
+ * rdepth! ( u -- ) ( R: ... -- x1 x2 .. xu )
+ */
+
+static void rdepthwrite(void)
+{
+ ucell tmp = POP();
+ rstackcnt = tmp;
+}
+
+
+/*
+ * + ( nu1 nu2 -- sum )
+ */
+
+static void plus(void)
+{
+ cell tmp = POP() + POP();
+ PUSH(tmp);
+}
+
+
+/*
+ * - ( nu1 nu2 -- diff )
+ */
+
+static void minus(void)
+{
+ const cell nu2 = POP();
+ const cell nu1 = POP();
+ PUSH(nu1 - nu2);
+}
+
+
+/*
+ * * ( nu1 nu2 -- prod )
+ */
+
+static void mult(void)
+{
+ const cell nu2 = POP();
+ const cell nu1 = POP();
+ PUSH(nu1 * nu2);
+}
+
+
+/*
+ * u* ( u1 u2 -- prod )
+ */
+
+static void umult(void)
+{
+ const ucell tmp = (ucell) POP() * (ucell) POP();
+ PUSH(tmp);
+}
+
+
+/*
+ * mu/mod ( n1 n2 -- rem quot.l quot.h )
+ */
+
+static void mudivmod(void)
+{
+ const ucell b = POP();
+ const ducell a = DPOP();
+#ifdef NEED_FAKE_INT128_T
+ if (a.hi != 0) {
+ fprintf(stderr, "mudivmod called (0x%016llx %016llx / 0x%016llx)\n",
+ a.hi, a.lo, b);
+ exit(-1);
+ } else {
+ ducell c;
+
+ PUSH(a.lo % b);
+ c.hi = 0;
+ c.lo = a.lo / b;
+ DPUSH(c);
+ }
+#else
+ PUSH(a % b);
+ DPUSH(a / b);
+#endif
+}
+
+
+/*
+ * abs ( n -- u )
+ */
+
+static void forthabs(void)
+{
+ const cell tmp = GETTOS();
+ if (tmp < 0) {
+ POP();
+ PUSH(-tmp);
+ }
+}
+
+
+/*
+ * negate ( n1 -- n2 )
+ */
+
+static void negate(void)
+{
+ const cell tmp = POP();
+ PUSH(-tmp);
+}
+
+
+/*
+ * max ( n1 n2 -- n1|n2 )
+ */
+
+static void max(void)
+{
+ const cell tmp = POP();
+ const cell tmp2 = POP();
+ PUSH((tmp > tmp2) ? tmp : tmp2);
+}
+
+
+/*
+ * min ( n1 n2 -- n1|n2 )
+ */
+
+static void min(void)
+{
+ const cell tmp = POP();
+ const cell tmp2 = POP();
+ PUSH((tmp < tmp2) ? tmp : tmp2);
+}
+
+
+/*
+ * lshift ( x1 u -- x2 )
+ */
+
+static void lshift(void)
+{
+ const ucell u = POP();
+ const ucell x1 = POP();
+ PUSH(x1 << u);
+}
+
+
+/*
+ * rshift ( x1 u -- x2 )
+ */
+
+static void rshift(void)
+{
+ const ucell u = POP();
+ const ucell x1 = POP();
+ PUSH(x1 >> u);
+}
+
+
+/*
+ * >>a ( x1 u -- x2 ) ??
+ */
+
+static void rshifta(void)
+{
+ const cell u = POP();
+ const cell x1 = POP();
+ PUSH(x1 >> u);
+}
+
+
+/*
+ * and ( x1 x2 -- x3 )
+ */
+
+static void and(void)
+{
+ const cell x1 = POP();
+ const cell x2 = POP();
+ PUSH(x1 & x2);
+}
+
+
+/*
+ * or ( x1 x2 -- x3 )
+ */
+
+static void or(void)
+{
+ const cell x1 = POP();
+ const cell x2 = POP();
+ PUSH(x1 | x2);
+}
+
+
+/*
+ * xor ( x1 x2 -- x3 )
+ */
+
+static void xor(void)
+{
+ const cell x1 = POP();
+ const cell x2 = POP();
+ PUSH(x1 ^ x2);
+}
+
+
+/*
+ * invert ( x1 -- x2 )
+ */
+
+static void invert(void)
+{
+ const cell x1 = POP();
+ PUSH(x1 ^ -1);
+}
+
+
+/*
+ * d+ ( d1 d2 -- d.sum )
+ */
+
+static void dplus(void)
+{
+ const dcell d2 = DPOP();
+ const dcell d1 = DPOP();
+#ifdef NEED_FAKE_INT128_T
+ ducell c;
+
+ if (d1.hi != 0 || d2.hi != 0) {
+ fprintf(stderr, "dplus called (0x%016llx %016llx + 0x%016llx %016llx)\n",
+ d1.hi, d1.lo, d2.hi, d2.lo);
+ exit(-1);
+ }
+ c.hi = 0;
+ c.lo = d1.lo + d2.lo;
+ DPUSH(c);
+#else
+ DPUSH(d1 + d2);
+#endif
+}
+
+
+/*
+ * d- ( d1 d2 -- d.diff )
+ */
+
+static void dminus(void)
+{
+ const dcell d2 = DPOP();
+ const dcell d1 = DPOP();
+#ifdef NEED_FAKE_INT128_T
+ ducell c;
+
+ if (d1.hi != 0 || d2.hi != 0) {
+ fprintf(stderr, "dminus called (0x%016llx %016llx + 0x%016llx %016llx)\n",
+ d1.hi, d1.lo, d2.hi, d2.lo);
+ exit(-1);
+ }
+ c.hi = 0;
+ c.lo = d1.lo - d2.lo;
+ DPUSH(c);
+#else
+ DPUSH(d1 - d2);
+#endif
+}
+
+
+/*
+ * m* ( ?? -- )
+ */
+
+static void mmult(void)
+{
+ const cell u2 = POP();
+ const cell u1 = POP();
+#ifdef NEED_FAKE_INT128_T
+ ducell c;
+
+ if (0) { // XXX How to detect overflow?
+ fprintf(stderr, "mmult called (%016llx * 0x%016llx)\n", u1, u2);
+ exit(-1);
+ }
+ c.hi = 0;
+ c.lo = u1 * u2;
+ DPUSH(c);
+#else
+ DPUSH((dcell) u1 * u2);
+#endif
+}
+
+
+/*
+ * um* ( u1 u2 -- d.prod )
+ */
+
+static void ummult(void)
+{
+ const ucell u2 = POP();
+ const ucell u1 = POP();
+#ifdef NEED_FAKE_INT128_T
+ ducell c;
+
+ if (0) { // XXX How to detect overflow?
+ fprintf(stderr, "ummult called (%016llx * 0x%016llx)\n", u1, u2);
+ exit(-1);
+ }
+ c.hi = 0;
+ c.lo = u1 * u2;
+ DPUSH(c);
+#else
+ DPUSH((ducell) u1 * u2);
+#endif
+}
+
+
+/*
+ * @ ( a-addr -- x )
+ */
+
+static void fetch(void)
+{
+ const ucell *aaddr = (ucell *)cell2pointer(POP());
+ PUSH(read_ucell(aaddr));
+}
+
+
+/*
+ * c@ ( addr -- byte )
+ */
+
+static void cfetch(void)
+{
+ const u8 *aaddr = (u8 *)cell2pointer(POP());
+ PUSH(read_byte(aaddr));
+}
+
+
+/*
+ * w@ ( waddr -- w )
+ */
+
+static void wfetch(void)
+{
+ const u16 *aaddr = (u16 *)cell2pointer(POP());
+ PUSH(read_word(aaddr));
+}
+
+
+/*
+ * l@ ( qaddr -- quad )
+ */
+
+static void lfetch(void)
+{
+ const u32 *aaddr = (u32 *)cell2pointer(POP());
+ PUSH(read_long(aaddr));
+}
+
+
+/*
+ * ! ( x a-addr -- )
+ */
+
+static void store(void)
+{
+ const ucell *aaddr = (ucell *)cell2pointer(POP());
+ const ucell x = POP();
+#ifdef CONFIG_DEBUG_INTERNAL
+ printk("!: %lx : %lx -> %lx\n", aaddr, read_ucell(aaddr), x);
+#endif
+ write_ucell(aaddr,x);
+}
+
+
+/*
+ * +! ( nu a-addr -- )
+ */
+
+static void plusstore(void)
+{
+ const ucell *aaddr = (ucell *)cell2pointer(POP());
+ const cell nu = POP();
+ write_cell(aaddr,read_cell(aaddr)+nu);
+}
+
+
+/*
+ * c! ( byte addr -- )
+ */
+
+static void cstore(void)
+{
+ const u8 *aaddr = (u8 *)cell2pointer(POP());
+ const ucell byte = POP();
+#ifdef CONFIG_DEBUG_INTERNAL
+ printk("c!: %x = %x\n", aaddr, byte);
+#endif
+ write_byte(aaddr, byte);
+}
+
+
+/*
+ * w! ( w waddr -- )
+ */
+
+static void wstore(void)
+{
+ const u16 *aaddr = (u16 *)cell2pointer(POP());
+ const u16 word = POP();
+ write_word(aaddr, word);
+}
+
+
+/*
+ * l! ( quad qaddr -- )
+ */
+
+static void lstore(void)
+{
+ const u32 *aaddr = (u32 *)cell2pointer(POP());
+ const u32 longval = POP();
+ write_long(aaddr, longval);
+}
+
+
+/*
+ * = ( x1 x2 -- equal? )
+ */
+
+static void equals(void)
+{
+ cell tmp = (POP() == POP());
+ PUSH(-tmp);
+}
+
+
+/*
+ * > ( n1 n2 -- greater? )
+ */
+
+static void greater(void)
+{
+ cell tmp = ((cell) POP() < (cell) POP());
+ PUSH(-tmp);
+}
+
+
+/*
+ * < ( n1 n2 -- less? )
+ */
+
+static void less(void)
+{
+ cell tmp = ((cell) POP() > (cell) POP());
+ PUSH(-tmp);
+}
+
+
+/*
+ * u> ( u1 u2 -- unsigned-greater? )
+ */
+
+static void ugreater(void)
+{
+ cell tmp = ((ucell) POP() < (ucell) POP());
+ PUSH(-tmp);
+}
+
+
+/*
+ * u< ( u1 u2 -- unsigned-less? )
+ */
+
+static void uless(void)
+{
+ cell tmp = ((ucell) POP() > (ucell) POP());
+ PUSH(-tmp);
+}
+
+
+/*
+ * sp@ ( -- stack-pointer )
+ */
+
+static void spfetch(void)
+{
+ // FIXME this can only work if the stack pointer
+ // is within range.
+ ucell tmp = pointer2cell(&(dstack[dstackcnt]));
+ PUSH(tmp);
+}
+
+
+/*
+ * move ( src-addr dest-addr len -- )
+ */
+
+static void fmove(void)
+{
+ ucell count = POP();
+ void *dest = (void *)cell2pointer(POP());
+ const void *src = (const void *)cell2pointer(POP());
+ memmove(dest, src, count);
+}
+
+
+/*
+ * fill ( addr len byte -- )
+ */
+
+static void ffill(void)
+{
+ ucell value = POP();
+ ucell count = POP();
+ void *src = (void *)cell2pointer(POP());
+ memset(src, value, count);
+}
+
+
+/*
+ * unaligned-w@ ( addr -- w )
+ */
+
+static void unalignedwordread(void)
+{
+ const unsigned char *addr = (const unsigned char *) cell2pointer(POP());
+ PUSH(unaligned_read_word(addr));
+}
+
+
+/*
+ * unaligned-w! ( w addr -- )
+ */
+
+static void unalignedwordwrite(void)
+{
+ const unsigned char *addr = (const unsigned char *) cell2pointer(POP());
+ u16 w = POP();
+ unaligned_write_word(addr, w);
+}
+
+
+/*
+ * unaligned-l@ ( addr -- quad )
+ */
+
+static void unalignedlongread(void)
+{
+ const unsigned char *addr = (const unsigned char *) cell2pointer(POP());
+ PUSH(unaligned_read_long(addr));
+}
+
+
+/*
+ * unaligned-l! ( quad addr -- )
+ */
+
+static void unalignedlongwrite(void)
+{
+ unsigned char *addr = (unsigned char *) cell2pointer(POP());
+ u32 l = POP();
+ unaligned_write_long(addr, l);
+}
+
+/*
+ * here ( -- dictionary-pointer )
+ */
+
+static void here(void)
+{
+ PUSH(pointer2cell(dict) + dicthead);
+#ifdef CONFIG_DEBUG_INTERNAL
+ printk("here: %x\n", pointer2cell(dict) + dicthead);
+#endif
+}
+
+/*
+ * here! ( new-dict-pointer -- )
+ */
+
+static void herewrite(void)
+{
+ ucell tmp = POP(); /* converted pointer */
+ dicthead = tmp - pointer2cell(dict);
+#ifdef CONFIG_DEBUG_INTERNAL
+ printk("here!: new value: %x\n", tmp);
+#endif
+
+ if (dictlimit && dicthead >= dictlimit) {
+ printk("Dictionary space overflow:"
+ " dicthead=" FMT_ucellx
+ " dictlimit=" FMT_ucellx
+ "\n",
+ dicthead, dictlimit);
+ }
+}
+
+
+/*
+ * emit ( char -- )
+ */
+
+static void emit(void)
+{
+ cell tmp = POP();
+#ifndef FCOMPILER
+ putchar(tmp);
+#else
+ put_outputbyte(tmp);
+#endif
+}
+
+
+/*
+ * key? ( -- pressed? )
+ */
+
+static void iskey(void)
+{
+ PUSH((cell) availchar());
+}
+
+
+/*
+ * key ( -- char )
+ */
+
+static void key(void)
+{
+ while (!availchar());
+#ifdef FCOMPILER
+ PUSH(get_inputbyte());
+#else
+ PUSH(getchar());
+#endif
+}
+
+
+/*
+ * ioc@ ( reg -- val )
+ */
+
+static void iocfetch(void)
+{
+#ifndef FCOMPILER
+ cell reg = POP();
+ PUSH(inb(reg));
+#else
+ (void)POP();
+ PUSH(0);
+#endif
+}
+
+
+/*
+ * iow@ ( reg -- val )
+ */
+
+static void iowfetch(void)
+{
+#ifndef FCOMPILER
+ cell reg = POP();
+ PUSH(inw(reg));
+#else
+ (void)POP();
+ PUSH(0);
+#endif
+}
+
+/*
+ * iol@ ( reg -- val )
+ */
+
+static void iolfetch(void)
+{
+#ifndef FCOMPILER
+ cell reg = POP();
+ PUSH(inl(reg));
+#else
+ (void)POP();
+ PUSH(0);
+#endif
+}
+
+
+/*
+ * ioc! ( val reg -- )
+ */
+
+static void iocstore(void)
+{
+#ifndef FCOMPILER
+ cell reg = POP();
+ cell val = POP();
+
+ outb(val, reg);
+#else
+ (void)POP();
+ (void)POP();
+#endif
+}
+
+
+/*
+ * iow! ( val reg -- )
+ */
+
+static void iowstore(void)
+{
+#ifndef FCOMPILER
+ cell reg = POP();
+ cell val = POP();
+
+ outw(val, reg);
+#else
+ (void)POP();
+ (void)POP();
+#endif
+}
+
+
+/*
+ * iol! ( val reg -- )
+ */
+
+static void iolstore(void)
+{
+#ifndef FCOMPILER
+ ucell reg = POP();
+ ucell val = POP();
+
+ outl(val, reg);
+#else
+ (void)POP();
+ (void)POP();
+#endif
+}
+
+/*
+ * i ( -- i )
+ */
+
+static void loop_i(void)
+{
+ PUSH(rstack[rstackcnt]);
+}
+
+/*
+ * j ( -- i )
+ */
+
+static void loop_j(void)
+{
+ PUSH(rstack[rstackcnt - 2]);
+}
+
+/* words[] is a function array of all native code functions used by
+ * the dictionary, i.e. CFAs and primitives.
+ * Any change here needs a matching change in the primitive word's
+ * name list that is kept for bootstrapping in kernel/bootstrap.c
+ *
+ * NOTE: THIS LIST SHALL NOT CHANGE (EXCEPT MANDATORY ADDITIONS AT
+ * THE END). ANY OTHER CHANGE WILL BREAK COMPATIBILITY TO OLDER
+ * BINARY DICTIONARIES.
+ */
+static forth_word * const words[] = {
+ /*
+ * CFAs and special words
+ */
+ semis,
+ docol,
+ lit,
+ docon,
+ dovar,
+ dodefer,
+ dodoes,
+ dodo,
+ doisdo,
+ doloop,
+ doplusloop,
+ doival,
+ doivar,
+ doidefer,
+
+ /*
+ * primitives
+ */
+ fdup, /* dup */
+ twodup, /* 2dup */
+ isdup, /* ?dup */
+ over, /* over */
+ twoover, /* 2over */
+ pick, /* pick */
+ drop, /* drop */
+ twodrop, /* 2drop */
+ nip, /* nip */
+ roll, /* roll */
+ rot, /* rot */
+ minusrot, /* -rot */
+ swap, /* swap */
+ twoswap, /* 2swap */
+ tor, /* >r */
+ rto, /* r> */
+ rfetch, /* r@ */
+ depth, /* depth */
+ depthwrite, /* depth! */
+ rdepth, /* rdepth */
+ rdepthwrite, /* rdepth! */
+ plus, /* + */
+ minus, /* - */
+ mult, /* * */
+ umult, /* u* */
+ mudivmod, /* mu/mod */
+ forthabs, /* abs */
+ negate, /* negate */
+ max, /* max */
+ min, /* min */
+ lshift, /* lshift */
+ rshift, /* rshift */
+ rshifta, /* >>a */
+ and, /* and */
+ or, /* or */
+ xor, /* xor */
+ invert, /* invert */
+ dplus, /* d+ */
+ dminus, /* d- */
+ mmult, /* m* */
+ ummult, /* um* */
+ fetch, /* @ */
+ cfetch, /* c@ */
+ wfetch, /* w@ */
+ lfetch, /* l@ */
+ store, /* ! */
+ plusstore, /* +! */
+ cstore, /* c! */
+ wstore, /* w! */
+ lstore, /* l! */
+ equals, /* = */
+ greater, /* > */
+ less, /* < */
+ ugreater, /* u> */
+ uless, /* u< */
+ spfetch, /* sp@ */
+ fmove, /* move */
+ ffill, /* fill */
+ emit, /* emit */
+ iskey, /* key? */
+ key, /* key */
+ execute, /* execute */
+ here, /* here */
+ herewrite, /* here! */
+ dobranch, /* dobranch */
+ docbranch, /* do?branch */
+ unalignedwordread, /* unaligned-w@ */
+ unalignedwordwrite, /* unaligned-w! */
+ unalignedlongread, /* unaligned-l@ */
+ unalignedlongwrite, /* unaligned-l! */
+ iocfetch, /* ioc@ */
+ iowfetch, /* iow@ */
+ iolfetch, /* iol@ */
+ iocstore, /* ioc! */
+ iowstore, /* iow! */
+ iolstore, /* iol! */
+ loop_i, /* i */
+ loop_j, /* j */
+ call, /* call */
+ sysdebug, /* sys-debug */
+ do_include, /* $include */
+ do_encode_file, /* $encode-file */
+ do_debug_xt, /* (debug */
+ do_debug_off, /* (debug-off) */
+};
diff --git a/qemu/roms/openbios/kernel/include/dict.h b/qemu/roms/openbios/kernel/include/dict.h
new file mode 100644
index 000000000..749fd6fba
--- /dev/null
+++ b/qemu/roms/openbios/kernel/include/dict.h
@@ -0,0 +1,59 @@
+/* tag: dict management headers
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __DICT_H
+#define __DICT_H
+
+#define DICTID "OpenBIOS"
+
+#define DOSEMIS 0
+#define DOCOL 1
+#define DOLIT 2
+#define DOCON 3
+#define DOVAR 4
+#define DODFR 5
+#define DODOES 6
+
+#define MAXNFALEN 128
+
+/* The header is 28/32 bytes on 32/64bit platforms */
+
+typedef struct dictionary_header {
+ char signature[8];
+ u8 version;
+ u8 cellsize;
+ u8 endianess;
+ u8 compression;
+ u8 relocation;
+ u8 reserved[3];
+ u32 checksum;
+ u32 length;
+ ucell last;
+} __attribute__((packed)) dictionary_header_t;
+
+ucell lfa2nfa(ucell ilfa);
+ucell load_dictionary(const char *data, ucell len);
+void dump_header(dictionary_header_t *header);
+ucell fstrlen(ucell fstr);
+void fstrncpy(char *dest, ucell src, unsigned int maxlen);
+ucell findsemis(ucell xt);
+ucell findxtfromcell_wordlist(ucell incell, ucell wordlist);
+ucell findxtfromcell(ucell incell);
+
+/* program counter */
+extern ucell PC;
+
+extern unsigned char *dict;
+extern cell dicthead;
+extern cell dictlimit;
+extern ucell *last;
+#ifdef FCOMPILER
+extern ucell *trampoline;
+#endif
+
+#endif
diff --git a/qemu/roms/openbios/kernel/stack.c b/qemu/roms/openbios/kernel/stack.c
new file mode 100644
index 000000000..f6715d1c3
--- /dev/null
+++ b/qemu/roms/openbios/kernel/stack.c
@@ -0,0 +1,46 @@
+/* tag: defines the stacks, program counter and ways to access those
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+
+#include "config.h"
+#include "kernel/stack.h"
+#include "cross.h"
+
+#define dstacksize 512
+int dstackcnt = 0;
+cell dstack[dstacksize];
+
+#define rstacksize 512
+int rstackcnt = 0;
+cell rstack[rstacksize];
+
+/* Rstack value saved before entering forth interpreter in debugger */
+int dbgrstackcnt = 0;
+
+#if defined(CONFIG_DEBUG_DSTACK) || defined(FCOMPILER)
+void printdstack(void)
+{
+ int i;
+ printk("dstack:");
+ for (i = 0; i <= dstackcnt; i++) {
+ printk(" 0x%" FMT_CELL_x , dstack[i]);
+ }
+ printk("\n");
+}
+#endif
+#if defined(CONFIG_DEBUG_RSTACK) || defined(FCOMPILER)
+void printrstack(void)
+{
+ int i;
+ printk("rstack:");
+ for (i = 0; i <= rstackcnt; i++) {
+ printk(" 0x%" FMT_CELL_x , rstack[i]);
+ }
+ printk("\n");
+}
+#endif