summaryrefslogtreecommitdiff
path: root/usr/src/lib/efcode
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/efcode')
-rw-r--r--usr/src/lib/efcode/Makefile71
-rw-r--r--usr/src/lib/efcode/Makefile.efcode71
-rw-r--r--usr/src/lib/efcode/Makefile.subdirs50
-rw-r--r--usr/src/lib/efcode/efdaemon/Makefile69
-rw-r--r--usr/src/lib/efcode/efdaemon/efcode.sh33
-rw-r--r--usr/src/lib/efcode/efdaemon/efdaemon.c185
-rw-r--r--usr/src/lib/efcode/efdaemon/efdaemon.xml82
-rw-r--r--usr/src/lib/efcode/engine/Makefile29
-rw-r--r--usr/src/lib/efcode/engine/Makefile.com38
-rw-r--r--usr/src/lib/efcode/engine/actions.c399
-rw-r--r--usr/src/lib/efcode/engine/alarm.c101
-rw-r--r--usr/src/lib/efcode/engine/cleanup.c52
-rw-r--r--usr/src/lib/efcode/engine/debug.c1601
-rw-r--r--usr/src/lib/efcode/engine/env.c863
-rw-r--r--usr/src/lib/efcode/engine/extend.c147
-rw-r--r--usr/src/lib/efcode/engine/fb8.c54
-rw-r--r--usr/src/lib/efcode/engine/fcode.c1031
-rw-r--r--usr/src/lib/efcode/engine/font.c48
-rw-r--r--usr/src/lib/efcode/engine/forth.c2675
-rw-r--r--usr/src/lib/efcode/engine/framebuffer.c71
-rw-r--r--usr/src/lib/efcode/engine/init.c139
-rw-r--r--usr/src/lib/efcode/engine/instance.c117
-rw-r--r--usr/src/lib/efcode/engine/interactive.c808
-rw-r--r--usr/src/lib/efcode/engine/interface.c273
-rw-r--r--usr/src/lib/efcode/engine/interp.c121
-rw-r--r--usr/src/lib/efcode/engine/log.c361
-rw-r--r--usr/src/lib/efcode/engine/mcookie.c237
-rw-r--r--usr/src/lib/efcode/engine/package.c1077
-rw-r--r--usr/src/lib/efcode/engine/prims64.c464
-rw-r--r--usr/src/lib/efcode/engine/print.c265
-rw-r--r--usr/src/lib/efcode/engine/properties.c808
-rw-r--r--usr/src/lib/efcode/engine/resource.c134
-rw-r--r--usr/src/lib/efcode/engine/signal.c91
-rw-r--r--usr/src/lib/efcode/engine/sparcv9/Makefile34
-rw-r--r--usr/src/lib/efcode/engine/tracing.c223
-rw-r--r--usr/src/lib/efcode/extend/Makefile29
-rw-r--r--usr/src/lib/efcode/extend/Makefile.com38
-rw-r--r--usr/src/lib/efcode/extend/fthread.c96
-rw-r--r--usr/src/lib/efcode/extend/sparcv9/Makefile34
-rw-r--r--usr/src/lib/efcode/fcdriver/Makefile29
-rw-r--r--usr/src/lib/efcode/fcdriver/Makefile.com33
-rw-r--r--usr/src/lib/efcode/fcdriver/build_tree.c250
-rw-r--r--usr/src/lib/efcode/fcdriver/dma.c123
-rw-r--r--usr/src/lib/efcode/fcdriver/fcdebug.c116
-rw-r--r--usr/src/lib/efcode/fcdriver/get_req.c466
-rw-r--r--usr/src/lib/efcode/fcdriver/ioctl.c110
-rw-r--r--usr/src/lib/efcode/fcdriver/load_node.c289
-rw-r--r--usr/src/lib/efcode/fcdriver/misc.c659
-rw-r--r--usr/src/lib/efcode/fcdriver/phandle.c204
-rw-r--r--usr/src/lib/efcode/fcdriver/property.c180
-rw-r--r--usr/src/lib/efcode/fcdriver/sparcv9/Makefile34
-rw-r--r--usr/src/lib/efcode/fcdriver/upload.c178
-rw-r--r--usr/src/lib/efcode/fcode_test/Makefile56
-rw-r--r--usr/src/lib/efcode/fcode_test/access.fth70
-rw-r--r--usr/src/lib/efcode/fcode_test/arithmetic.fth174
-rw-r--r--usr/src/lib/efcode/fcode_test/bytemanipulate.fth56
-rw-r--r--usr/src/lib/efcode/fcode_test/calling.fth36
-rw-r--r--usr/src/lib/efcode/fcode_test/case.fth42
-rw-r--r--usr/src/lib/efcode/fcode_test/catch.fth33
-rw-r--r--usr/src/lib/efcode/fcode_test/create.fth40
-rw-r--r--usr/src/lib/efcode/fcode_test/find.fth35
-rw-r--r--usr/src/lib/efcode/fcode_test/iftest.fth118
-rw-r--r--usr/src/lib/efcode/fcode_test/instance.fth28
-rw-r--r--usr/src/lib/efcode/fcode_test/loop.fth97
-rw-r--r--usr/src/lib/efcode/fcode_test/misc.fth188
-rw-r--r--usr/src/lib/efcode/fcode_test/parse.fth56
-rw-r--r--usr/src/lib/efcode/fcode_test/stack.fth56
-rw-r--r--usr/src/lib/efcode/fcode_test/storage.fth46
-rw-r--r--usr/src/lib/efcode/fcode_test/test.fth70
-rw-r--r--usr/src/lib/efcode/fcode_test/test64.fth126
-rw-r--r--usr/src/lib/efcode/fcode_test/values.fth29
-rw-r--r--usr/src/lib/efcode/gp2/Makefile29
-rw-r--r--usr/src/lib/efcode/gp2/Makefile.com33
-rw-r--r--usr/src/lib/efcode/gp2/gp2.c341
-rw-r--r--usr/src/lib/efcode/gp2/sparcv9/Makefile34
-rw-r--r--usr/src/lib/efcode/include/fcdriver/fcdriver.h75
-rw-r--r--usr/src/lib/efcode/include/fcdriver/proto.h61
-rw-r--r--usr/src/lib/efcode/include/fcode/debug.h75
-rw-r--r--usr/src/lib/efcode/include/fcode/engine.h331
-rw-r--r--usr/src/lib/efcode/include/fcode/log.h60
-rw-r--r--usr/src/lib/efcode/include/fcode/private.h147
-rw-r--r--usr/src/lib/efcode/include/fcode/proto.h448
-rw-r--r--usr/src/lib/efcode/include/fcode/public.h59
-rw-r--r--usr/src/lib/efcode/interpreter/Makefile55
-rw-r--r--usr/src/lib/efcode/interpreter/interpreter.c198
-rw-r--r--usr/src/lib/efcode/interpreter/mapfile6432
-rw-r--r--usr/src/lib/efcode/packages/Makefile29
-rw-r--r--usr/src/lib/efcode/packages/Makefile.com39
-rw-r--r--usr/src/lib/efcode/packages/memalloc.c131
-rw-r--r--usr/src/lib/efcode/packages/parse.c135
-rw-r--r--usr/src/lib/efcode/packages/populate.c310
-rw-r--r--usr/src/lib/efcode/packages/sparcv9/Makefile34
-rw-r--r--usr/src/lib/efcode/pci/Makefile29
-rw-r--r--usr/src/lib/efcode/pci/Makefile.com34
-rw-r--r--usr/src/lib/efcode/pci/pci.c345
-rw-r--r--usr/src/lib/efcode/pci/sparcv9/Makefile34
-rw-r--r--usr/src/lib/efcode/upa/Makefile29
-rw-r--r--usr/src/lib/efcode/upa/Makefile.com32
-rw-r--r--usr/src/lib/efcode/upa/sparcv9/Makefile34
-rw-r--r--usr/src/lib/efcode/upa/upa.c74
100 files changed, 20313 insertions, 0 deletions
diff --git a/usr/src/lib/efcode/Makefile b/usr/src/lib/efcode/Makefile
new file mode 100644
index 0000000000..4806e7a9bc
--- /dev/null
+++ b/usr/src/lib/efcode/Makefile
@@ -0,0 +1,71 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.lib
+
+SUBDIRS = engine fcdriver extend packages pci gp2 upa interpreter efdaemon
+TESTDIRS = fcode_test
+
+EFCODEDIRS= $(ROOTLIBDIR)/efcode $(ROOTLIBDIR)/efcode/$(MACH64)
+
+all:= TARGET= all
+install:= TARGET= install
+clean:= TARGET= clean
+clobber:= TARGET= clobber
+lint:= TARGET= lint
+
+.PARALLEL: $(SUBDIRS)
+.KEEP_STATE:
+
+all clean clobber lint: $(SUBDIRS)
+
+$(EFCODEDIRS):
+ $(INS.dir)
+
+install: $(EFCODEDIRS) .WAIT $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+$(TESTDIRS): FRC
+ @cd $@; pwd; $(MAKE) all
+
+FRC:
+
+#
+# Interdependencies between shared objects follow.
+#
+
+extend fcdriver packages pci gp2 upa interpreter efdaemon: engine
+
+fcdriver: packages
+
+gp2 pci interpreter: fcdriver
+
+interpreter: packages extend
diff --git a/usr/src/lib/efcode/Makefile.efcode b/usr/src/lib/efcode/Makefile.efcode
new file mode 100644
index 0000000000..748c0294c2
--- /dev/null
+++ b/usr/src/lib/efcode/Makefile.efcode
@@ -0,0 +1,71 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Common build rules for efcode shared objects.
+#
+# For historical reasons, these shared objects aren't explicitly versioned, so
+# turn off VERS and LIBLINKS (VERS must be cleared before the inclusion of
+# Makefile.lib, and LIBLINKS must be cleared afterwards). Also, because of
+# the weird alternate naming scheme, we must define our own symlink macros.
+#
+
+VERS =
+
+include $(SRC)/lib/Makefile.lib
+
+LIBS = $(DYNLIB)
+LDLIBS += -lc
+LIBLINKS =
+
+CPPFLAGS += -DDEBUG -DFCODE_INTERNAL
+CPPFLAGS += -I $(SRC)/lib/efcode/include -I $(ROOT)/usr/platform/sun4u/include
+DYNFLAGS += -R\$$ORIGIN
+
+SRCDIR = ..
+EFCODE64DIR = /usr/lib/efcode/$(MACH64)
+ROOTLIBDIR = $(ROOT)/usr/lib/efcode
+ROOTLIBDIR64 = $(ROOT)/usr/lib/efcode/$(MACH64)
+ROOTSYMLINKS64 = $(SYMLINKS:%=$(ROOTLIBDIR64)/%)
+
+#
+# Since a number of efcode shared objects depend on fcode.so, fcdriver.so, and
+# fcpackage.so, provide macros that expand to their full paths.
+#
+FCODE64 = $(ROOTLIBDIR64)/fcode.so
+FCDRIVER64 = $(ROOTLIBDIR64)/fcdriver.so
+FCPACKAGE64 = $(ROOTLIBDIR64)/fcpackage.so
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+$(ROOTSYMLINKS64): $(ROOTLIBDIR64)/$(DYNLIB)
+ -$(RM) $@; $(SYMLINK) $(DYNLIB) $@
+
+include $(SRC)/lib/Makefile.targ
diff --git a/usr/src/lib/efcode/Makefile.subdirs b/usr/src/lib/efcode/Makefile.subdirs
new file mode 100644
index 0000000000..3dd1a71017
--- /dev/null
+++ b/usr/src/lib/efcode/Makefile.subdirs
@@ -0,0 +1,50 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include $(SRC)/lib/Makefile.lib
+
+#
+# No need for 32-bit versions of these shared objects.
+#
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+msg := TARGET= _msg
+
+.KEEP_STATE:
+
+all clean clobber install lint _msg: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/lib/efcode/efdaemon/Makefile b/usr/src/lib/efcode/efdaemon/Makefile
new file mode 100644
index 0000000000..30c27a7953
--- /dev/null
+++ b/usr/src/lib/efcode/efdaemon/Makefile
@@ -0,0 +1,69 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/efcode/efdaemon/Makefile
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/cmd/Makefile.cmd.64
+
+EFCODEDIR = $(ROOT)/usr/lib/efcode
+EFCODEDIR64 = $(EFCODEDIR)/$(MACH64)
+
+CPPFLAGS += -DDEBUG -DFCODE_INTERNAL
+CPPFLAGS += -I ../include -I $(ROOT)/usr/platform/sun4u/include
+
+PROG = efdaemon
+EFTARGETS += $(EFCODEDIR64)/$(PROG)
+EFTARGETS += $(EFCODEDIR)/efcode.sh
+
+MFSTDIR = $(ROOT)/var/svc/manifest/platform/sun4u
+MANIFEST = efdaemon.xml
+EFTARGETS += $(MFSTDIR)/$(MANIFEST)
+
+$(MFSTDIR)/$(MANIFEST) := FILEMODE = 0444
+
+all: $(PROG)
+
+clean:
+ -$(RM) $(PROG)
+
+$(EFCODEDIR64)/%: %
+ $(INS.file)
+
+$(EFCODEDIR)/%.sh: %.sh
+ $(INS.file)
+
+$(MFSTDIR)/%: %
+ $(INS.file)
+
+install: all .WAIT $(EFTARGETS)
+
+lint: lint_PROG
+
+.KEEP_STATE:
+
+include $(SRC)/cmd/Makefile.targ
diff --git a/usr/src/lib/efcode/efdaemon/efcode.sh b/usr/src/lib/efcode/efdaemon/efcode.sh
new file mode 100644
index 0000000000..914279b876
--- /dev/null
+++ b/usr/src/lib/efcode/efdaemon/efcode.sh
@@ -0,0 +1,33 @@
+#!/sbin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+#
+# The open /dev/fcode file descriptor is passed by efdaemon in file
+# descriptor 0, so redirecting stdin in this script is strongly discouraged.
+#
+/usr/lib/efcode/sparcv9/interpreter
diff --git a/usr/src/lib/efcode/efdaemon/efdaemon.c b/usr/src/lib/efcode/efdaemon/efdaemon.c
new file mode 100644
index 0000000000..7aba030848
--- /dev/null
+++ b/usr/src/lib/efcode/efdaemon/efdaemon.c
@@ -0,0 +1,185 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2000-2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * efdaemon - Emebbed Fcode Interpreter daemon.
+ *
+ * Opens /dev/fcode, detaches from tty and reads a request. Upon successful
+ * return, invokes the Fcode interpreter via the shell script:
+ * /usr/lib/efcode/efcode.sh Waits for completion of the interpreter.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <syslog.h>
+#include <errno.h>
+#include <sys/wait.h>
+
+char efcode_sh_file[] = "/usr/lib/efcode/efcode.sh";
+char dev_fcode_file[] = "/dev/fcode";
+
+int debug = 0;
+
+int
+main(int argc, char **argv)
+{
+ extern char *optarg;
+ extern int optind, opterr, optopt;
+ int c, fd, nbytes, status;
+ char tc;
+ pid_t pid, tpid;
+ long nerr = 0;
+
+ openlog("efdaemon", LOG_PID|LOG_CONS, LOG_DAEMON);
+
+ while ((c = getopt(argc, argv, "d")) != EOF) {
+ switch (c) {
+
+ case 'd':
+ debug++;
+ break;
+
+ case '?':
+ syslog(LOG_ERR, "Usage: efdaemon [ -d ]\n");
+ exit(1);
+ }
+ }
+
+ /*
+ * Ensure we can open /dev/fcode
+ */
+ if ((fd = open(dev_fcode_file, O_RDONLY)) < 0) {
+ /*
+ * Only output message if debug is on. On most systems,
+ * /dev/fcode will not exist, so this message would pollute the
+ * console.
+ */
+ if (debug)
+ syslog(LOG_ERR, "Can't open %s: %s\n", dev_fcode_file,
+ strerror(errno));
+ exit(1);
+ }
+ close(fd);
+
+ /*
+ * Ensure that /usr/lib/efcode/efcode.sh exists and is executable.
+ */
+ if (access(efcode_sh_file, X_OK | R_OK)) {
+ syslog(LOG_ERR, "%s: %s\n", efcode_sh_file, strerror(errno));
+ exit(1);
+ }
+
+ /*
+ * Fork a child then parent exits so we're a child of initd.
+ */
+ if ((pid = fork()) < 0) {
+ syslog(LOG_ERR, "Fork failed: %s\n", strerror(errno));
+ exit(1);
+ }
+ if (pid)
+ exit(0);
+
+
+ /*
+ * detach from tty here.
+ */
+ setpgrp();
+ close(0);
+ close(1);
+ close(2);
+ (void) open("/dev/null", O_RDWR);
+ (void) dup(0);
+ (void) dup(0);
+
+ for (;;) {
+ while ((fd = open(dev_fcode_file, O_RDONLY)) < 0) {
+ nerr++;
+ if (nerr == 1)
+ syslog(LOG_ERR, "Can't open %s: %s\n",
+ dev_fcode_file, strerror(errno));
+ sleep(1);
+ }
+ if (nerr > 1) {
+ syslog(LOG_ERR, "Open on %s failed %d times\n",
+ dev_fcode_file, nerr);
+ }
+ nerr = 0;
+ nbytes = read(fd, &tc, sizeof (tc));
+ if (nbytes < 0) {
+ syslog(LOG_ERR, "Read of %s: %s\n", dev_fcode_file,
+ strerror(errno));
+ close(fd);
+ continue;
+ }
+ if (debug)
+ syslog(LOG_DEBUG, "Got request\n");
+ while ((pid = fork()) < 0) {
+ nerr++;
+ if (nerr == 1)
+ syslog(LOG_ERR, "Fork failed: %s\n",
+ strerror(errno));
+ sleep(1);
+ }
+ if ((nerr > 1) && pid) {
+ syslog(LOG_ERR, "Fork failed %d times\n", nerr);
+ }
+ nerr = 0;
+ if (pid) {
+ tpid = wait(&status);
+ if (tpid < 0)
+ syslog(LOG_ERR, "Wait error: %s\n",
+ strerror(errno));
+ else if (pid != tpid)
+ syslog(LOG_ERR, "Wait error, expect pid: %d"
+ " got %d, status: %x\n", pid, tpid, status);
+ else if (status)
+ syslog(LOG_ERR, "Wait pid: %d status: %x\n",
+ pid, status);
+ else if (debug)
+ syslog(LOG_DEBUG, "Wait: pid: %d\n", pid);
+ close(fd);
+ continue;
+ }
+ if (debug)
+ syslog(LOG_DEBUG, "Child: %d processing request\n",
+ getpid());
+ fcntl(fd, F_DUP2FD, 0);
+ while (execl("/bin/sh", "sh", efcode_sh_file, NULL)) {
+ nerr++;
+ if (nerr == 1)
+ syslog(LOG_ERR, "execl(/bin/sh) failed: %s\n",
+ strerror(errno));
+ sleep(1);
+ }
+ }
+
+ return (0);
+}
diff --git a/usr/src/lib/efcode/efdaemon/efdaemon.xml b/usr/src/lib/efcode/efdaemon/efdaemon.xml
new file mode 100644
index 0000000000..415d692b88
--- /dev/null
+++ b/usr/src/lib/efcode/efdaemon/efdaemon.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+ Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License, Version 1.0 only
+ (the "License"). You may not use this file except in compliance
+ with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+ ident "%Z%%M% %I% %E% SMI"
+
+ NOTE: This service manifest is not editable; its contents will
+ be overwritten by package or patch operations, including
+ operating system upgrade. Make customizations in a different
+ file.
+-->
+
+<service_bundle type='manifest' name='SUNWefcr:efdaemon'>
+
+<service
+ name='platform/sun4u/efdaemon'
+ type='service'
+ version='1'>
+
+ <single_instance />
+
+ <dependency
+ name='single-user'
+ grouping='require_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri
+ value='svc:/milestone/single-user:default' />
+ </dependency>
+
+ <exec_method
+ type='method'
+ name='start'
+ exec='/usr/lib/efcode/sparcv9/efdaemon'
+ timeout_seconds='30' />
+
+ <exec_method
+ type='method'
+ name='stop'
+ exec=':kill'
+ timeout_seconds='30' />
+
+ <instance name='default' enabled='false' />
+
+ <stability value='Unstable' />
+
+ <template>
+ <common_name>
+ <loctext xml:lang='C'>
+ embedded FCode interpreter
+ </loctext>
+ </common_name>
+ <documentation>
+ <manpage title='efdaemon' section='1M' manpath='/usr/share/man' />
+ </documentation>
+ </template>
+
+</service>
+
+</service_bundle>
diff --git a/usr/src/lib/efcode/engine/Makefile b/usr/src/lib/efcode/engine/Makefile
new file mode 100644
index 0000000000..29132d88a1
--- /dev/null
+++ b/usr/src/lib/efcode/engine/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.subdirs
diff --git a/usr/src/lib/efcode/engine/Makefile.com b/usr/src/lib/efcode/engine/Makefile.com
new file mode 100644
index 0000000000..fc8c6135b5
--- /dev/null
+++ b/usr/src/lib/efcode/engine/Makefile.com
@@ -0,0 +1,38 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+OBJECTS = init.o interface.o signal.o forth.o fcode.o interp.o debug.o \
+ env.o print.o properties.o actions.o package.o instance.o \
+ alarm.o interactive.o framebuffer.o font.o fb8.o extend.o tracing.o \
+ resource.o prims64.o mcookie.o log.o cleanup.o
+
+LIBRARY = fcode.a
+
+include ../../Makefile.efcode
+
+LDLIBS += -lrt
diff --git a/usr/src/lib/efcode/engine/actions.c b/usr/src/lib/efcode/engine/actions.c
new file mode 100644
index 0000000000..11fb96c363
--- /dev/null
+++ b/usr/src/lib/efcode/engine/actions.c
@@ -0,0 +1,399 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#define NUM_DEFAULT_ACTIONS 7
+
+/*
+ * value_fetch and value_store are the same as "fetch" and "store", but
+ * we'll leave them implemented here for now.
+ */
+static void
+value_fetch(fcode_env_t *env)
+{
+ variable_t *addr;
+
+ CHECK_DEPTH(env, 1, "value_fetch");
+ addr = (variable_t *)POP(DS);
+ PUSH(DS, (variable_t)*addr);
+}
+
+static void
+value_store(fcode_env_t *env)
+{
+ variable_t *addr;
+
+ CHECK_DEPTH(env, 1, "value_store");
+ addr = (variable_t *)POP(DS);
+ *addr = (variable_t)POP(DS);
+}
+
+void *
+get_internal_address(fcode_env_t *env)
+{
+ int *ptr;
+
+ CHECK_DEPTH(env, 1, "get_internal_address");
+ ptr = (int *)POP(DS);
+ if (*ptr > 0)
+ return ((uchar_t *)env + *ptr);
+ return ((uchar_t *)MYSELF - *ptr);
+}
+
+void
+internal_env_fetch(fcode_env_t *env)
+{
+ instance_t **iptr;
+
+ CHECK_DEPTH(env, 1, "internal_env_fetch");
+ iptr = (instance_t **)get_internal_address(env);
+ PUSH(DS, (fstack_t)(*iptr));
+}
+
+void
+internal_env_store(fcode_env_t *env)
+{
+ instance_t **iptr;
+
+ CHECK_DEPTH(env, 2, "internal_env_store");
+ iptr = (instance_t **)get_internal_address(env);
+ *iptr = (instance_t *)POP(DS);
+}
+
+void
+internal_env_addr(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 1, "internal_env_addr");
+ d = (fstack_t)get_internal_address(env);
+ PUSH(DS, d);
+}
+
+void
+do_buffer_data(fcode_env_t *env, token_t *d, int instance)
+{
+ if (!*d) { /* check if buffer not alloc'ed yet */
+ token_t *buf;
+
+ if (instance) {
+ int n, off;
+
+ n = TOKEN_ROUNDUP(d[1]);
+ buf = alloc_instance_data(env, UINIT_DATA, n, &off);
+ memset(buf, 0, d[1]);
+ } else {
+ buf = (token_t *)HERE;
+ set_here(env, HERE + d[1], "do_buffer_data");
+ }
+ *d = (token_t)buf;
+ }
+ PUSH(DS, *d);
+}
+
+void
+ibuffer_init(fcode_env_t *env)
+{
+ token_t *d;
+
+ d = get_instance_address(env);
+ do_buffer_data(env, d, 1);
+}
+
+void
+buffer_init(fcode_env_t *env)
+{
+ token_t *d;
+
+ CHECK_DEPTH(env, 1, "buffer_init");
+ d = (token_t *)POP(DS);
+ do_buffer_data(env, d, 0);
+}
+
+void
+do_defer(fcode_env_t *env)
+{
+ fetch(env);
+ execute(env);
+}
+
+token_t *value_actions[NUM_DEFAULT_ACTIONS];
+token_t value_defines[NUM_DEFAULT_ACTIONS][3] = {
+ { (token_t)&value_fetch, (token_t)&value_store, (token_t)&noop },
+ { (token_t)&fetch_instance_data, (token_t)&set_instance_data,
+ (token_t)&address_instance_data },
+ { (token_t)&internal_env_fetch, (token_t)&internal_env_store,
+ (token_t)&internal_env_addr },
+ { (token_t)&do_defer, (token_t)&store, (token_t)&noop },
+ { (token_t)&idefer_exec, (token_t)&set_instance_data,
+ (token_t)&address_instance_data },
+ { (token_t)&buffer_init, (token_t)&two_drop, (token_t)&noop, },
+ { (token_t)&ibuffer_init, (token_t)&two_drop,
+ (token_t)&address_instance_data }
+};
+
+int
+run_action(fcode_env_t *env, acf_t acf, int action)
+{
+ token_t *p = (token_t *)acf;
+
+ if ((p[0] & 1) == 0) {
+ log_message(MSG_WARN, "run_action: acf: %p @acf: %p not"
+ " indirect\n", acf, p[0]);
+ return (1);
+ }
+
+ p = (token_t *)(p[0] & ~1);
+
+ if (action >= p[1] || action < 0) {
+ log_message(MSG_WARN, "run_action: acf: %p action: %d"
+ " out of range: 0-%d\n", acf, action, (int)p[1]);
+ return (1);
+ }
+
+ if (p[0] == (token_t)&do_default_action) {
+ fstack_t d;
+
+ d = (fstack_t)p[action+2];
+ PUSH(DS, d);
+ execute(env);
+ return (0);
+ }
+ log_message(MSG_WARN, "run_action: acf: %p/%p not default action\n",
+ acf, p[0]);
+ return (1);
+}
+
+void
+do_default_action(fcode_env_t *env)
+{
+ acf_t a;
+
+ CHECK_DEPTH(env, 1, "do_default_action");
+ a = (acf_t)TOS;
+ (void) run_action(env, (a-1), 0);
+}
+
+void
+do_set_action(fcode_env_t *env)
+{
+ acf_t a = (acf_t)TOS;
+
+ CHECK_DEPTH(env, 1, "do_set_action");
+ TOS += sizeof (acf_t);
+ (void) run_action(env, a, 1);
+}
+
+void
+action_colon(fcode_env_t *env)
+{
+ token_roundup(env, "action_colon");
+ env->action_ptr[env->action_count] = (token_t)HERE;
+ COMPILE_TOKEN(&do_colon);
+ env->action_count++;
+ env->state |= 1;
+}
+
+void
+actions(fcode_env_t *env)
+{
+ int n;
+ token_t *d;
+
+ token_roundup(env, "actions");
+ d = (token_t *)HERE;
+ *d++ = (token_t)&do_default_action;
+ n = (int)POP(DS);
+ *d++ = n;
+ env->num_actions = n;
+ env->action_count = 0;
+ env->action_ptr = d;
+ d += n;
+ set_here(env, (uchar_t *)d, "actions");
+}
+
+void
+install_actions(fcode_env_t *env, token_t *table)
+{
+ acf_t *dptr;
+ token_t p;
+
+ dptr = (acf_t *)LINK_TO_ACF(env->lastlink);
+ p = (token_t)table;
+ p -= (sizeof (token_t) + sizeof (acf_t));
+ *dptr = (acf_t)(p | 1);
+}
+
+void
+use_actions(fcode_env_t *env)
+{
+ if (env->state) {
+ TODO; /* use-actions in compile state. */
+ } else {
+ install_actions(env, env->action_ptr);
+ }
+}
+
+void
+perform_action(fcode_env_t *env)
+{
+ int n;
+ acf_t a;
+
+ CHECK_DEPTH(env, 2, "perform_action");
+ n = POP(DS);
+ a = (acf_t)POP(DS);
+ PUSH(DS, (fstack_t)ACF_TO_BODY(a));
+
+ if (run_action(env, a, n)) {
+ system_message(env, "Bad Object action");
+ }
+}
+
+void
+define_actions(fcode_env_t *env, int n, token_t *array)
+{
+ int a;
+
+ PUSH(DS, (fstack_t)n);
+ actions(env);
+
+ a = 0;
+ while (n--) {
+ action_colon(env);
+ COMPILE_TOKEN(&array[a]);
+ env->state |= 8;
+ semi(env);
+ a++;
+ }
+}
+
+/*
+ * This is for things like my-self which have meaning to the
+ * forth engine but I don't want to turn them into standard forth values
+ * that would make the 'C' variables hard to understand, instead these
+ * 'global' state variables will act directly upon the native 'C' structures.
+ */
+
+void
+set_internal_value_actions(fcode_env_t *env)
+{
+ ASSERT(value_actions[2]);
+ install_actions(env, value_actions[2]);
+}
+
+void
+set_value_actions(fcode_env_t *env, int which)
+{
+ ASSERT((which == 0) || (which == 1));
+ ASSERT(value_actions[which]);
+ install_actions(env, value_actions[which]);
+}
+
+void
+set_defer_actions(fcode_env_t *env, int which)
+{
+ ASSERT((which == 0) || (which == 1));
+ ASSERT(value_actions[which+3]);
+ install_actions(env, value_actions[which+3]);
+}
+
+void
+set_buffer_actions(fcode_env_t *env, int which)
+{
+ ASSERT((which == 0) || (which == 1));
+ ASSERT(value_actions[which+5]);
+ install_actions(env, value_actions[which+5]);
+}
+
+#if defined(DEBUG)
+
+void
+do_get(fcode_env_t *env)
+{
+ PUSH(DS, 0);
+ perform_action(env);
+}
+
+void
+do_set(fcode_env_t *env)
+{
+ PUSH(DS, 1);
+ perform_action(env);
+}
+
+void
+do_addr(fcode_env_t *env)
+{
+ PUSH(DS, 2);
+ perform_action(env);
+}
+
+void
+dump_actions(fcode_env_t *env)
+{
+ int i;
+ for (i = 0; i < NUM_DEFAULT_ACTIONS; i++) {
+ log_message(MSG_INFO, "Action Set: %d = %p\n", i,
+ value_actions[i]);
+ }
+}
+#endif /* DEBUG */
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+ int i;
+
+ ASSERT(env);
+ NOTICE;
+
+ for (i = 0; i < NUM_DEFAULT_ACTIONS; i++) {
+ define_actions(env, 3, value_defines[i]);
+ value_actions[i] = env->action_ptr;
+ }
+
+#if defined(DEBUG)
+ FORTH(0, "get", do_get);
+ FORTH(0, "set", do_set);
+ FORTH(0, "addr", do_addr);
+ FORTH(0, "dump-actions", dump_actions);
+ FORTH(IMMEDIATE, "actions", actions);
+ FORTH(IMMEDIATE, "use-actions", use_actions);
+ FORTH(IMMEDIATE, "action:", action_colon);
+ FORTH(0, "perform-action", perform_action);
+#endif /* DEBUG */
+}
diff --git a/usr/src/lib/efcode/engine/alarm.c b/usr/src/lib/efcode/engine/alarm.c
new file mode 100644
index 0000000000..c9d4550a9d
--- /dev/null
+++ b/usr/src/lib/efcode/engine/alarm.c
@@ -0,0 +1,101 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcode/private.h>
+
+/*
+ * 'user-abort' Fcode
+ */
+void
+user_abort(fcode_env_t *env)
+{
+ forth_abort(env, "user-abort called");
+}
+
+static fstack_t alarm_xt;
+static fstack_t alarm_ms;
+static fcode_env_t *alarm_env;
+
+static void
+catch_alarm(int signo)
+{
+ fcode_env_t *env = alarm_env;
+
+ if (env && alarm_xt && alarm_ms) {
+ PUSH(DS, alarm_xt);
+ execute(env);
+ signal(SIGALRM, catch_alarm);
+ alarm((alarm_ms + 999)/1000);
+ }
+}
+
+/*
+ * 'alarm' Fcode
+ */
+void
+do_alarm(fcode_env_t *env)
+{
+ fstack_t ms, xt;
+
+ CHECK_DEPTH(env, 2, "alarm");
+ ms = POP(DS);
+ xt = POP(DS);
+ if (ms == 0) {
+ alarm(0);
+ signal(SIGALRM, SIG_DFL);
+ alarm_xt = 0;
+ alarm_ms = 0;
+ alarm_env = 0;
+ } else {
+ signal(SIGALRM, catch_alarm);
+ alarm_xt = xt;
+ alarm_ms = ms;
+ alarm_env = env;
+ alarm((ms + 999)/1000);
+ }
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ P1275(0x213, 0, "alarm", do_alarm);
+
+ P1275(0x219, 0, "user-abort", user_abort);
+}
diff --git a/usr/src/lib/efcode/engine/cleanup.c b/usr/src/lib/efcode/engine/cleanup.c
new file mode 100644
index 0000000000..898924f33a
--- /dev/null
+++ b/usr/src/lib/efcode/engine/cleanup.c
@@ -0,0 +1,52 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#pragma fini(_fini)
+
+static void
+_fini(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+
+ debug_msg(DEBUG_EXIT_WORDS|DEBUG_TOKEN_USAGE,
+ "Dumping interpretter state\n");
+
+ DEBUGF(EXIT_WORDS, dump_words(env));
+ DEBUGF(TOKEN_USAGE, verify_usage(env));
+
+ destroy_environment(env);
+}
diff --git a/usr/src/lib/efcode/engine/debug.c b/usr/src/lib/efcode/engine/debug.c
new file mode 100644
index 0000000000..bcdd238b94
--- /dev/null
+++ b/usr/src/lib/efcode/engine/debug.c
@@ -0,0 +1,1601 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#ifndef DEBUG_LVL
+#define DEBUG_LVL 0
+#endif
+
+struct bitab {
+ token_t bi_ptr;
+ char *bi_name;
+ int bi_type;
+};
+
+struct bitab *lookup_builtin(token_t);
+
+static int debug_level = DEBUG_LVL;
+
+void
+set_interpreter_debug_level(long lvl)
+{
+ debug_level = lvl;
+}
+
+long
+get_interpreter_debug_level(void)
+{
+ return (debug_level);
+}
+
+void
+output_data_stack(fcode_env_t *env, int msglevel)
+{
+ int i;
+
+ log_message(msglevel, "( ");
+ if (DS > env->ds0) {
+ for (i = 0; i < (DS - env->ds0); i++)
+ log_message(msglevel, "%llx ",
+ (uint64_t)(env->ds0[i + 1]));
+ } else
+ log_message(msglevel, "<empty> ");
+ log_message(msglevel, ") ");
+}
+
+void
+output_return_stack(fcode_env_t *env, int show_wa, int msglevel)
+{
+ int i;
+ int anyout = 0;
+
+ log_message(msglevel, "R:( ");
+ if (show_wa) {
+ log_message(msglevel, "%s ",
+ acf_backup_search(env, (acf_t)WA));
+ anyout++;
+ }
+ if (IP) {
+ anyout++;
+ log_message(msglevel, "%s ", acf_backup_search(env, IP));
+ }
+ for (i = (RS - env->rs0) - 1; i > 0; i--) {
+ anyout++;
+ log_message(msglevel, "%s ",
+ acf_backup_search(env, (acf_t)env->rs0[i+1]));
+ }
+ if (!anyout)
+ log_message(msglevel, "<empty> ");
+ log_message(msglevel, ") ");
+}
+
+void
+dump_comma(fcode_env_t *env, char *type)
+{
+ xforth_t d;
+
+ if (strcmp(type, "x,") == 0)
+ d = peek_xforth(env);
+ else
+ d = TOS;
+ log_message(MSG_FC_DEBUG, "%s %p, %llx\n", type, HERE, (uint64_t)d);
+}
+
+static int ndebug_names;
+#define MAXDEBUG_NAMES 10
+static char *debug_names[MAXDEBUG_NAMES];
+
+static int ndebug_acfs;
+#define MAXDEBUG_ACFS 10
+static acf_t debug_acfs[MAXDEBUG_ACFS];
+
+void
+add_debug_acf(fcode_env_t *env, acf_t acf)
+{
+ int i;
+
+ for (i = 0; i < ndebug_acfs; i++)
+ if (acf == debug_acfs[i])
+ return;
+
+ if (!within_dictionary(env, acf))
+ log_message(MSG_ERROR, "Can't debug builtin\n");
+ else if (ndebug_acfs >= MAXDEBUG_ACFS)
+ log_message(MSG_ERROR, "Too many debug ACF's\n");
+ else {
+ debug_acfs[ndebug_acfs++] = acf;
+ *LINK_TO_FLAGS(ACF_TO_LINK(acf)) |= FLAG_DEBUG;
+ }
+}
+
+static void
+paren_debug(fcode_env_t *env)
+{
+ acf_t acf;
+
+ acf = (acf_t)POP(DS);
+ if (!within_dictionary(env, acf)) {
+ log_message(MSG_INFO, "acf: %llx not in dictionary\n",
+ (uint64_t)acf);
+ return;
+ }
+ if ((acf_t)_ALIGN(acf, token_t) != acf) {
+ log_message(MSG_INFO, "acf: %llx not aligned\n",
+ (uint64_t)acf);
+ return;
+ }
+ if (*acf != (token_t)(&do_colon)) {
+ log_message(MSG_INFO, "acf: %llx not a colon-def\n",
+ (uint64_t)acf);
+ return;
+ }
+ add_debug_acf(env, acf);
+}
+
+static void
+debug(fcode_env_t *env)
+{
+ fstack_t d;
+ char *word;
+ acf_t acf;
+
+ parse_word(env);
+ dollar_find(env);
+ d = POP(DS);
+ if (d) {
+ acf = (acf_t)POP(DS);
+ add_debug_acf(env, acf);
+ } else if (ndebug_names >= MAXDEBUG_NAMES) {
+ log_message(MSG_ERROR, "Too many forward debug words\n");
+ two_drop(env);
+ } else {
+ word = pop_a_duped_string(env, NULL);
+ log_message(MSG_INFO, "Forward defined word: %s\n", word);
+ debug_names[ndebug_names++] = word;
+ }
+}
+
+/*
+ * Eliminate dups and add vocabulary forth to end if not already on list.
+ */
+static void
+order_to_dict_list(fcode_env_t *env, token_t *order[])
+{
+ int i, j, norder = 0;
+
+ if (env->current)
+ order[norder++] = env->current;
+ for (i = env->order_depth; i >= 0; i--) {
+ for (j = 0; j < norder && order[j] != env->order[i]; j++)
+ ;
+ if (j == norder)
+ order[norder++] = env->order[i];
+ }
+ for (j = 0; j < norder && order[j] != (token_t *)&env->forth_voc_link;
+ j++)
+ ;
+ if (j == norder)
+ order[norder++] = (token_t *)&env->forth_voc_link;
+ order[norder] = NULL;
+}
+
+static acf_t
+search_all_dictionaries(fcode_env_t *env,
+ acf_t (*fn)(fcode_env_t *, acf_t, void *),
+ void *arg)
+{
+ token_t *order[MAX_ORDER+1];
+ int i;
+ token_t *dptr;
+ acf_t acf;
+
+ order_to_dict_list(env, order);
+ for (i = 0; (dptr = order[i]) != NULL; i++) {
+ for (dptr = (token_t *)(*dptr); dptr;
+ dptr = (token_t *)(*dptr))
+ if ((acf = (*fn)(env, LINK_TO_ACF(dptr), arg)) != NULL)
+ return (acf);
+ }
+ return (NULL);
+}
+
+char *
+acf_to_str(acf_t acf)
+{
+ static char msg[(sizeof (acf) * 2) + 3];
+
+ sprintf(msg, "(%08p)", acf);
+ return (msg);
+}
+
+char *
+get_name_or_acf(token_t *dptr)
+{
+ char *name;
+
+ if ((name = get_name(dptr)) != NULL)
+ return (name);
+ return (acf_to_str(LINK_TO_ACF(dptr)));
+}
+
+static void
+output_acf_name(acf_t acf)
+{
+ char *name;
+ token_t *dptr;
+ static int acf_count = 0;
+
+ if (acf == NULL) {
+ if (acf_count)
+ log_message(MSG_INFO, "\n");
+ acf_count = 0;
+ return;
+ }
+ dptr = ACF_TO_LINK(acf);
+ if ((name = get_name(dptr)) == NULL)
+ name = "<noname>";
+
+ log_message(MSG_INFO, "%24s (%08p)", name, acf);
+ if (++acf_count >= 2) {
+ log_message(MSG_INFO, "\n");
+ acf_count = 0;
+ } else
+ log_message(MSG_INFO, " ");
+}
+
+static void
+dot_debug(fcode_env_t *env)
+{
+ int i;
+ token_t *dptr;
+
+ if (ndebug_names == 0)
+ log_message(MSG_INFO, "No forward debug words\n");
+ else {
+ for (i = 0; i < ndebug_names; i++)
+ log_message(MSG_INFO, "%s Forward\n", debug_names[i]);
+ }
+ if (ndebug_acfs == 0)
+ log_message(MSG_INFO, "No debug words\n");
+ else {
+ for (i = 0; i < ndebug_acfs; i++)
+ log_message(MSG_INFO, "%s\n",
+ get_name_or_acf(ACF_TO_LINK(debug_acfs[i])));
+ }
+}
+
+static void
+do_undebug(fcode_env_t *env, char *name)
+{
+ int i;
+
+ for (i = 0; i < ndebug_names; i++) {
+ if (strcmp(debug_names[i], name) == 0) {
+ log_message(MSG_INFO, "Undebugging forward word %s\n",
+ name);
+ FREE(debug_names[i]);
+ for (i++; i < ndebug_names; i++)
+ debug_names[i - 1] = debug_names[i];
+ ndebug_names--;
+ break;
+ }
+ }
+}
+
+static void
+undebug(fcode_env_t *env)
+{
+ fstack_t d;
+ acf_t acf;
+ flag_t *flagp;
+ char *name;
+ int i, j;
+
+ parse_word(env);
+ two_dup(env);
+ dollar_find(env);
+ d = POP(DS);
+ if (d) {
+ acf = (acf_t)POP(DS);
+ flagp = LINK_TO_FLAGS(ACF_TO_LINK(acf));
+ if ((*flagp & FLAG_DEBUG) == 0)
+ log_message(MSG_WARN, "Word not debugged?\n");
+ else {
+ log_message(MSG_INFO, "Undebugging acf: %p\n", acf);
+ *flagp &= ~FLAG_DEBUG;
+ for (i = 0; i < ndebug_acfs; i++) {
+ if (debug_acfs[i] == acf) {
+ for (j = i + 1; j < ndebug_acfs; j++)
+ debug_acfs[j-1] = debug_acfs[j];
+ ndebug_acfs--;
+ break;
+ }
+ }
+ }
+ } else
+ two_drop(env);
+ name = pop_a_string(env, NULL);
+ do_undebug(env, name);
+}
+
+int
+name_is_debugged(fcode_env_t *env, char *name)
+{
+ int i;
+
+ if (ndebug_names <= 0)
+ return (0);
+ for (i = 0; i < ndebug_names; i++)
+ if (strcmp(debug_names[i], name) == 0)
+ return (1);
+ return (0);
+}
+
+/*
+ * This is complicated by being given ACF's to temporary compile words which
+ * don't have a header.
+ */
+int
+is_debug_word(fcode_env_t *env, acf_t acf)
+{
+ flag_t *flagp;
+ int i;
+
+ /* check to see if any words are being debugged */
+ if (ndebug_acfs == 0)
+ return (0);
+
+ /* only words in dictionary can be debugged */
+ if (!within_dictionary(env, acf))
+ return (0);
+
+ /* check that word has "FLAG_DEBUG" on */
+ flagp = LINK_TO_FLAGS(ACF_TO_LINK(acf));
+ if ((*flagp & FLAG_DEBUG) == 0)
+ return (0);
+
+ /* look in table of debug acf's */
+ for (i = 0; i < ndebug_acfs; i++)
+ if (debug_acfs[i] == acf)
+ return (1);
+ return (0);
+}
+
+#define MAX_DEBUG_STACK 100
+token_t debug_low[MAX_DEBUG_STACK], debug_high[MAX_DEBUG_STACK];
+int debug_prev_level[MAX_DEBUG_STACK];
+int debug_curr_level[MAX_DEBUG_STACK];
+int ndebug_stack = 0;
+
+void
+debug_set_level(fcode_env_t *env, int level)
+{
+ debug_curr_level[ndebug_stack - 1] = level;
+ set_interpreter_debug_level(level);
+}
+
+token_t
+find_semi_in_colon_def(fcode_env_t *env, acf_t acf)
+{
+ for (; within_dictionary(env, acf); acf++)
+ if (*acf == (token_t)(&semi_ptr))
+ return ((token_t)acf);
+ return (0);
+}
+
+void
+check_for_debug_entry(fcode_env_t *env)
+{
+ int top;
+
+ if (is_debug_word(env, WA) && ndebug_stack < MAX_DEBUG_STACK) {
+ top = ndebug_stack++;
+ debug_prev_level[top] = get_interpreter_debug_level();
+ debug_low[top] = (token_t)WA;
+ if (*WA == (token_t)(&do_colon)) {
+ debug_high[top] =
+ find_semi_in_colon_def(env, WA);
+ } else {
+ debug_high[top] = 0; /* marker... */
+ }
+ debug_set_level(env, DEBUG_STEPPING);
+ output_step_message(env);
+ }
+}
+
+void
+check_for_debug_exit(fcode_env_t *env)
+{
+ if (ndebug_stack) {
+ int top = ndebug_stack - 1;
+
+ if (debug_high[top] == 0) {
+ set_interpreter_debug_level(debug_prev_level[top]);
+ ndebug_stack--;
+ } else if ((token_t)IP >= debug_low[top] &&
+ (token_t)IP <= debug_high[top]) {
+ set_interpreter_debug_level(debug_curr_level[top]);
+ } else {
+ set_interpreter_debug_level(debug_prev_level[top]);
+ }
+ }
+}
+
+void
+check_semi_debug_exit(fcode_env_t *env)
+{
+ if (ndebug_stack) {
+ int top = ndebug_stack - 1;
+
+ if ((token_t)(IP - 1) == debug_high[top]) {
+ set_interpreter_debug_level(debug_prev_level[top]);
+ ndebug_stack--;
+ }
+ }
+}
+
+/*
+ * Really entering do_run, since this may be a recursive entry to do_run,
+ * we need to set the debug level to what it was previously.
+ */
+int
+current_debug_state(fcode_env_t *env)
+{
+ if (ndebug_stack) {
+ int top = ndebug_stack - 1;
+ set_interpreter_debug_level(debug_prev_level[top]);
+ }
+ return (ndebug_stack);
+}
+
+void
+clear_debug_state(fcode_env_t *env, int oldstate)
+{
+ if (ndebug_stack && oldstate <= ndebug_stack) {
+ set_interpreter_debug_level(debug_prev_level[oldstate]);
+ ndebug_stack = oldstate;
+ }
+}
+
+void
+unbug(fcode_env_t *env)
+{
+ int i;
+ token_t *link;
+ flag_t *flag;
+
+ for (i = ndebug_stack - 1; i >= 0; i--) {
+ link = ACF_TO_LINK(debug_low[i]);
+ flag = LINK_TO_FLAGS(link);
+ *flag &= ~FLAG_DEBUG;
+ }
+ clear_debug_state(env, 0);
+}
+
+void
+output_vitals(fcode_env_t *env)
+{
+ log_message(MSG_FC_DEBUG, "IP=%p, *IP=%p, WA=%p, *WA=%p ", IP,
+ (IP ? *IP : 0), WA, (WA ? *WA : 0));
+}
+
+int
+do_exec_debug(fcode_env_t *env, void *fn)
+{
+ int dl = debug_level;
+ int show_wa = 1;
+
+ if ((dl & (DEBUG_EXEC_DUMP_DS | DEBUG_EXEC_DUMP_RS |
+ DEBUG_EXEC_SHOW_VITALS | DEBUG_EXEC_TRACE | DEBUG_TRACING |
+ DEBUG_STEPPING)) == 0)
+ return (0);
+
+ if (dl & DEBUG_STEPPING) {
+ dl |= DEBUG_EXEC_DUMP_DS;
+ }
+ if (dl & (DEBUG_STEPPING | DEBUG_EXEC_TRACE)) {
+ log_message(MSG_FC_DEBUG, "%-15s ", acf_to_name(env, WA));
+ show_wa = 0;
+ }
+ if (dl & DEBUG_EXEC_DUMP_DS)
+ output_data_stack(env, MSG_FC_DEBUG);
+ if (dl & DEBUG_EXEC_DUMP_RS)
+ output_return_stack(env, show_wa, MSG_FC_DEBUG);
+ if (dl & DEBUG_EXEC_SHOW_VITALS)
+ output_vitals(env);
+ if (dl & DEBUG_TRACING)
+ do_fclib_trace(env, (void *) fn);
+ log_message(MSG_FC_DEBUG, "\n");
+ if (dl & DEBUG_STEPPING)
+ return (do_fclib_step(env));
+ return (0);
+}
+
+static void
+smatch(fcode_env_t *env)
+{
+ int len;
+ char *str, *p;
+
+ if ((str = parse_a_string(env, &len)) == NULL)
+ log_message(MSG_INFO, "smatch: no string\n");
+ else {
+ for (p = (char *)env->base; p < (char *)HERE; p++)
+ if (memcmp(p, str, len) == 0)
+ log_message(MSG_DEBUG, "%p\n", p);
+ }
+}
+
+void
+check_vitals(fcode_env_t *env)
+{
+ int i;
+ token_t *dptr;
+
+ dptr = env->current;
+ if (*dptr && !within_dictionary(env, (uchar_t *)*dptr))
+ log_message(MSG_ERROR, "Current: %p outside dictionary\n",
+ *dptr);
+ for (i = env->order_depth; i >= 0; i--) {
+ dptr = env->order[i];
+ if (!dptr)
+ continue;
+ if (*dptr && !within_dictionary(env, (uchar_t *)*dptr))
+ log_message(MSG_ERROR, "Order%d: %p outside"
+ " dictionary\n", i, *dptr);
+ }
+ if (HERE < env->base || HERE >= env->base + dict_size) {
+ log_message(MSG_ERROR, "HERE: %p outside range\n", HERE);
+ }
+ if (DS < env->ds0 || DS >= &env->ds0[stack_size]) {
+ forth_abort(env, "DS: %p outside range\n", DS);
+ }
+ if (RS < env->rs0 || RS >= &env->rs0[stack_size]) {
+ log_message(MSG_ERROR, "RS: %p outside range\n", RS);
+ RS = env->rs0;
+ }
+ if (IP && !within_dictionary(env, IP))
+ log_message(MSG_ERROR, "IP: %p outside dictionary\n", IP);
+ if (!within_dictionary(env, (void *)env->forth_voc_link))
+ log_message(MSG_ERROR, "forth_voc_link: %p outside"
+ " dictionary\n", env->forth_voc_link);
+}
+
+static void
+dump_table(fcode_env_t *env)
+{
+ int i;
+
+ for (i = 0; i < MAX_FCODE; i++) {
+ if (*(env->table[i].apf) != (token_t)(&f_error)) {
+ log_message(MSG_DEBUG, "Token: %4x %32s acf = %8p,"
+ " %8p\n", i, env->table[i].name, env->table[i].apf,
+ *(env->table[i].apf));
+ }
+ }
+ log_message(MSG_DEBUG, "%d FCODES implemented\n", fcode_impl_count);
+}
+
+void
+verify_usage(fcode_env_t *env)
+{
+ int i, untested = 0;
+
+ for (i = 0; i < MAX_FCODE; i++) {
+ int verify;
+
+ verify = env->table[i].flags & (ANSI_WORD|P1275_WORD);
+ if ((verify) &&
+#ifdef DEBUG
+ (env->table[i].usage == 0) &&
+#endif
+ (env->table[i].apf)) {
+ log_message(MSG_DEBUG,
+ "Untested: %4x %32s acf = %8p, %8p\n", i,
+ env->table[i].name, env->table[i].apf,
+ *(env->table[i].apf));
+ untested++;
+ }
+ }
+ if (untested)
+ log_message(MSG_DEBUG, "%d untested tokens\n", untested);
+}
+
+static void
+debugf(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)&debug_level);
+}
+
+static void
+control(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)&env->control);
+}
+
+struct bittab {
+ int b_bitval;
+ char *b_bitname;
+} bittab[] = {
+ DEBUG_CONTEXT, "context",
+ DEBUG_BYTELOAD_DS, "byteload-ds",
+ DEBUG_BYTELOAD_RS, "byteload-rs",
+ DEBUG_BYTELOAD_TOKENS, "byteload-tokens",
+ DEBUG_NEW_TOKEN, "new-token",
+ DEBUG_EXEC_TRACE, "exec-trace",
+ DEBUG_EXEC_SHOW_VITALS, "exec-show-vitals",
+ DEBUG_EXEC_DUMP_DS, "exec-dump-ds",
+ DEBUG_EXEC_DUMP_RS, "exec-dump-rs",
+ DEBUG_COMMA, "comma",
+ DEBUG_HEADER, "header",
+ DEBUG_EXIT_WORDS, "exit-words",
+ DEBUG_EXIT_DUMP, "exit-dump",
+ DEBUG_DUMP_TOKENS, "dump-tokens",
+ DEBUG_COLON, "colon",
+ DEBUG_NEXT_VITALS, "next-vitals",
+ DEBUG_VOC_FIND, "voc-find",
+ DEBUG_DUMP_DICT_TOKENS, "dump-dict-tokens",
+ DEBUG_TOKEN_USAGE, "token-usage",
+ DEBUG_DUMP_TOKEN_TABLE, "dump-token-table",
+ DEBUG_SHOW_STACK, "show-stack",
+ DEBUG_SHOW_RS, "show-rs",
+ DEBUG_TRACING, "tracing",
+ DEBUG_TRACE_STACK, "trace-stack",
+ DEBUG_CALL_METHOD, "call-method",
+ DEBUG_ACTIONS, "actions",
+ DEBUG_STEPPING, "stepping",
+ DEBUG_REG_ACCESS, "reg-access",
+ DEBUG_ADDR_ABUSE, "addr-abuse",
+ DEBUG_FIND_FCODE, "find-fcode",
+ DEBUG_UPLOAD, "upload",
+ 0
+};
+
+void
+debug_flags_to_output(fcode_env_t *env, int flags)
+{
+ int first = 1, i;
+
+ for (i = 0; bittab[i].b_bitval != 0; i++)
+ if (bittab[i].b_bitval & flags) {
+ if (!first)
+ log_message(MSG_INFO, ",");
+ first = 0;
+ log_message(MSG_INFO, bittab[i].b_bitname);
+ }
+ if (first)
+ log_message(MSG_INFO, "<empty>");
+ log_message(MSG_INFO, "\n");
+}
+
+static void
+dot_debugf(fcode_env_t *env)
+{
+ debug_flags_to_output(env, debug_level);
+}
+
+static void
+debugf_qmark(fcode_env_t *env)
+{
+ debug_flags_to_output(env, 0xffffffff);
+}
+
+int
+debug_flags_to_mask(char *str)
+{
+ int flags = 0;
+ char *p;
+ int i;
+
+ if (isdigit(*str)) {
+ if (*str == '0') {
+ str++;
+ if (*str == 'x' || *str == 'X') {
+ sscanf(str + 1, "%x", &flags);
+ } else
+ sscanf(str, "%o", &flags);
+ } else
+ sscanf(str, "%d", &flags);
+ return (flags);
+ }
+ if (strcmp(str, "clear") == 0)
+ return (0);
+ if (strcmp(str, "all") == 0)
+ return (0xffffffff & ~DEBUG_STEPPING);
+ if (*str) {
+ do {
+ if (p = strchr(str, ','))
+ *p++ = '\0';
+ for (i = 0; bittab[i].b_bitname != 0; i++)
+ if (strcmp(str, bittab[i].b_bitname) == 0) {
+ flags |= bittab[i].b_bitval;
+ break;
+ }
+ if (bittab[i].b_bitname == 0)
+ log_message(MSG_WARN,
+ "Unknown debug flag: '%s'\n", str);
+ str = p;
+ } while (p);
+ }
+ return (flags);
+}
+
+static void
+set_debugf(fcode_env_t *env)
+{
+ char *str;
+
+ str = parse_a_string(env, NULL);
+ debug_level = debug_flags_to_mask(str);
+}
+
+static acf_t
+show_a_word(fcode_env_t *env, acf_t acf, void *arg)
+{
+ static int nshow_words = 0;
+
+ if (acf == NULL) {
+ if (nshow_words > 0) {
+ log_message(MSG_DEBUG, "\n");
+ nshow_words = 0;
+ }
+ return (NULL);
+ }
+ log_message(MSG_DEBUG, "%15s ", get_name_or_acf(ACF_TO_LINK(acf)));
+ nshow_words++;
+ if (nshow_words >= 4) {
+ log_message(MSG_DEBUG, "\n");
+ nshow_words = 0;
+ }
+ return (NULL);
+}
+
+void
+words(fcode_env_t *env)
+{
+ (void) search_all_dictionaries(env, show_a_word, NULL);
+ (void) show_a_word(env, NULL, NULL);
+}
+
+static acf_t
+dump_a_word(fcode_env_t *env, acf_t acf, void *arg)
+{
+ output_acf_name(acf);
+ return (NULL);
+}
+
+void
+dump_words(fcode_env_t *env)
+{
+ (void) search_all_dictionaries(env, dump_a_word, NULL);
+ output_acf_name(NULL);
+}
+
+static void
+dump_line(uchar_t *ptr)
+{
+ uchar_t *byte;
+ int i;
+
+ log_message(MSG_INFO, "%p ", (uint32_t)ptr);
+ for (i = 0, byte = ptr; i < 16; i++) {
+ if (i == 8)
+ log_message(MSG_INFO, " ");
+ log_message(MSG_INFO, "%02.2x ", *byte++);
+ }
+ log_message(MSG_INFO, " ");
+ for (i = 0, byte = ptr; i < 16; i++, byte++) {
+ log_message(MSG_INFO, "%c",
+ ((*byte < 0x20) || (*byte > 0x7f)) ? '.' : *byte);
+ }
+ log_message(MSG_INFO, "\n");
+}
+
+void
+dump_dictionary(fcode_env_t *env)
+{
+ uchar_t *ptr;
+
+ log_message(MSG_INFO, "Dictionary dump: base: %p\n", env->base);
+ for (ptr = (uchar_t *)(((long)(env->base)) & ~0xf); ptr < HERE;
+ ptr += 16)
+ dump_line(ptr);
+}
+
+static char *
+acf_to_fcode_name(fcode_env_t *env, acf_t acf)
+{
+ int i;
+
+ for (i = 0; i < MAX_FCODE; i++)
+ if (env->table[i].apf == acf)
+ return (env->table[i].name);
+ return (NULL);
+}
+
+static acf_t
+acf_match(fcode_env_t *env, acf_t sacf, void *macf)
+{
+ if (sacf == (acf_t)macf)
+ return (sacf);
+ return (NULL);
+}
+
+/*
+ * Given an ACF, return ptr to name or "unknown" string.
+ */
+char *
+acf_to_name(fcode_env_t *env, acf_t acf)
+{
+ struct bitab *bip;
+ static char name_buf[256];
+ uchar_t *p, *np;
+ int i, n;
+
+ if (!within_dictionary(env, acf)) {
+ if ((bip = lookup_builtin((token_t)acf)) != NULL)
+ return (bip->bi_name);
+ return (NULL);
+ }
+ return (get_name_or_acf(ACF_TO_LINK(acf)));
+}
+
+int
+within_dictionary(fcode_env_t *env, void *addr)
+{
+ return ((uchar_t *)addr >= env->base &&
+ (uchar_t *)addr < env->base + dict_size);
+}
+
+static int
+within_word(fcode_env_t *env, acf_t acf, acf_t wacf)
+{
+ if (acf == wacf || acf + 1 == wacf)
+ return (1);
+ if (*acf == (token_t)(&do_colon)) {
+ do {
+ if (acf == wacf)
+ return (1);
+ } while (*acf++ != (token_t)(&semi_ptr));
+ }
+ return (0);
+}
+
+/*
+ * Given an ACF in the middle of a colon definition, search dictionary towards
+ * beginning for "colon" acf. If we find a "semi" acf first, we're not in
+ * the middle of a colon-def (temporary execute?).
+ */
+char *
+acf_backup_search(fcode_env_t *env, acf_t acf)
+{
+ acf_t nacf;
+ char *name;
+
+ if ((acf_t)_ALIGN(acf, token_t) == acf && within_dictionary(env, acf)) {
+ for (nacf = acf; nacf >= (acf_t)env->base; nacf--)
+ if (*nacf == (token_t)(&do_colon) ||
+ *nacf == (token_t)(&semi_ptr))
+ break;
+ if (nacf >= (acf_t)env->base && *nacf == (token_t)(&do_colon) &&
+ (name = get_name(ACF_TO_LINK(nacf))) != NULL)
+ return (name);
+ }
+ return (acf_to_str(acf));
+}
+
+/*
+ * Print out current process's C stack using /usr/proc/bin/pstack
+ */
+void
+ctrace(fcode_env_t *env)
+{
+ char buf[256];
+ FILE *fd;
+
+ log_message(MSG_DEBUG, "Interpreter C Stack:\n");
+ sprintf(buf, "/usr/proc/bin/pstack %d", getpid());
+ if ((fd = popen(buf, "r")) == NULL)
+ log_perror(MSG_ERROR, "Can't run: %s", buf);
+ else {
+ while (fgets(buf, sizeof (buf), fd))
+ log_message(MSG_DEBUG, buf);
+ fclose(fd);
+ }
+}
+
+/*
+ * Dump data, return stacks, try to unthread forth calling stack.
+ */
+void
+ftrace(fcode_env_t *env)
+{
+ log_message(MSG_DEBUG, "Forth Interpreter Stacks:\n");
+ output_data_stack(env, MSG_DEBUG);
+ output_return_stack(env, 1, MSG_DEBUG);
+ log_message(MSG_DEBUG, "\n");
+}
+
+int in_forth_abort;
+
+/*
+ * Handle fatal error, if interactive mode, return to ok prompt.
+ */
+void
+forth_abort(fcode_env_t *env, char *fmt, ...)
+{
+ va_list ap;
+ char msg[256];
+
+ if (in_forth_abort) {
+ log_message(MSG_FATAL, "ABORT: abort within forth_abort\n");
+ abort();
+ }
+ in_forth_abort++;
+
+ va_start(ap, fmt);
+ vsprintf(msg, fmt, ap);
+ log_message(MSG_ERROR, "ABORT: %s\n", msg);
+
+ if (env) {
+ ctrace(env);
+ ftrace(env);
+ }
+
+ return_to_interact(env);
+ /*
+ * If not in interactive mode, return_to_interact just returns.
+ */
+ exit(1);
+}
+
+/*
+ * Handle fatal system call error
+ */
+void
+forth_perror(fcode_env_t *env, char *fmt, ...)
+{
+ va_list ap;
+ char msg[256];
+ int save_errno = errno; /* just in case... */
+
+ va_start(ap, fmt);
+ vsprintf(msg, fmt, ap);
+
+ forth_abort(env, "%s: %s", msg, strerror(save_errno));
+}
+
+static void
+show_stack(fcode_env_t *env)
+{
+#ifdef DEBUG
+ debug_level ^= DEBUG_SHOW_STACK;
+#else
+ /*EMPTY*/
+#endif
+}
+
+static void
+print_bytes_header(int width, int offset)
+{
+ int i;
+
+ for (i = 0; i < width; i++)
+ log_message(MSG_INFO, " ");
+ log_message(MSG_INFO, " ");
+ for (i = 0; i < 16; i++) {
+ if (i == 8)
+ log_message(MSG_INFO, " ");
+ if (i == offset)
+ log_message(MSG_INFO, "\\/ ");
+ else
+ log_message(MSG_INFO, "%2x ", i);
+ }
+ log_message(MSG_INFO, " ");
+ for (i = 0; i < 16; i++) {
+ if (i == offset)
+ log_message(MSG_INFO, "v");
+ else
+ log_message(MSG_INFO, "%x", i);
+ }
+ log_message(MSG_INFO, "\n");
+}
+
+static void
+dump(fcode_env_t *env)
+{
+ uchar_t *data;
+ int len, offset;
+ char buf[20];
+
+ len = POP(DS);
+ data = (uchar_t *)POP(DS);
+ offset = ((long)data) & 0xf;
+ len += offset;
+ data = (uchar_t *)((long)data & ~0xf);
+ sprintf(buf, "%p", (uint32_t)data);
+ print_bytes_header(strlen(buf), offset);
+ for (len += offset; len > 0; len -= 16, data += 16)
+ dump_line(data);
+}
+
+static acf_t
+do_sifting(fcode_env_t *env, acf_t acf, void *pat)
+{
+ char *name;
+
+ if ((name = get_name(ACF_TO_LINK(acf))) != NULL && strstr(name, pat))
+ output_acf_name(acf);
+ return (NULL);
+}
+
+static void
+sifting(fcode_env_t *env)
+{
+ char *pat;
+
+ if ((pat = parse_a_string(env, NULL)) != NULL) {
+ (void) search_all_dictionaries(env, do_sifting, pat);
+ output_acf_name(NULL);
+ }
+}
+
+void
+print_level(int level, int *doprint)
+{
+ int i;
+
+ if (*doprint) {
+ log_message(MSG_DEBUG, "\n ");
+ for (i = 0; i < level; i++)
+ log_message(MSG_DEBUG, " ");
+ *doprint = 0;
+ }
+}
+
+#define BI_QUOTE 1
+#define BI_BLIT 2
+#define BI_BDO 3
+#define BI_QDO 4
+#define BI_BR 5
+#define BI_QBR 6
+#define BI_BOF 7
+#define BI_LOOP 8
+#define BI_PLOOP 9
+#define BI_TO 10
+#define BI_SEMI 11
+#define BI_COLON 12
+#define BI_NOOP 13
+#define BI_NOTYET 14 /* unimplented in "see" */
+
+struct bitab bitab[] = {
+ (token_t)(&quote_ptr), "\"", BI_QUOTE,
+ (token_t)(&blit_ptr), "blit", BI_BLIT,
+ (token_t)(&do_bdo_ptr), "do", BI_BDO,
+ (token_t)(&do_bqdo_ptr), "?do", BI_QDO,
+ (token_t)(&bbranch_ptrs[0]), "br", BI_BR,
+ (token_t)(&bbranch_ptrs[1]), "qbr", BI_QBR,
+ (token_t)(&bbranch_ptrs[2]), "bof", BI_BOF,
+ (token_t)(&do_loop_ptr), "loop", BI_LOOP,
+ (token_t)(&do_ploop_ptr), "+loop", BI_PLOOP,
+ (token_t)(&to_ptr), "to", BI_NOOP,
+ (token_t)(&semi_ptr), ";", BI_SEMI,
+ (token_t)(&do_colon), ":", BI_COLON,
+ (token_t)(&tlit_ptr), "[']", BI_NOOP,
+ (token_t)(&do_leave_ptr), "leave", BI_NOTYET,
+ (token_t)(&create_ptr), "create", BI_NOTYET,
+ (token_t)(&does_ptr), "does>", BI_NOTYET,
+ (token_t)(&value_defines[0][0]), "a.@", BI_NOTYET,
+ (token_t)(&value_defines[0][1]), "a.!", BI_NOTYET,
+ (token_t)(&value_defines[0][2]), "a.nop", BI_NOTYET,
+ (token_t)(&value_defines[1][0]), "a.i@", BI_NOTYET,
+ (token_t)(&value_defines[1][1]), "a.i!", BI_NOTYET,
+ (token_t)(&value_defines[1][2]), "a.iad", BI_NOTYET,
+ (token_t)(&value_defines[2][0]), "a.defer", BI_NOTYET,
+ (token_t)(&value_defines[2][1]), "a.@", BI_NOTYET,
+ (token_t)(&value_defines[2][2]), "a.nop", BI_NOTYET,
+ (token_t)(&value_defines[3][0]), "a.defexec", BI_NOTYET,
+ (token_t)(&value_defines[3][1]), "a.iset", BI_NOTYET,
+ (token_t)(&value_defines[3][2]), "a.iad", BI_NOTYET,
+ (token_t)(&value_defines[4][0]), "a.binit", BI_NOTYET,
+ (token_t)(&value_defines[4][1]), "a.2drop", BI_NOTYET,
+ (token_t)(&value_defines[4][2]), "a.nop", BI_NOTYET,
+ (token_t)(&value_defines[5][0]), "a.ibinit", BI_NOTYET,
+ (token_t)(&value_defines[5][1]), "a.2drop", BI_NOTYET,
+ (token_t)(&value_defines[5][2]), "a.iad", BI_NOTYET,
+ 0
+};
+
+struct bitab *
+lookup_builtin(token_t builtin)
+{
+ int i;
+
+ for (i = 0; bitab[i].bi_ptr; i++)
+ if (bitab[i].bi_ptr == builtin)
+ return (&bitab[i]);
+ return (NULL);
+}
+
+static void
+paren_see(fcode_env_t *env)
+{
+ acf_t save_acf = (acf_t)POP(DS);
+ acf_t acf = save_acf;
+ int i, n, pass;
+ token_t brtab[30], thentab[30], brstk[30];
+ int nbrtab = 0, nthentab = 0, nbrstk = 0;
+ uchar_t *p;
+ int level = 0, doprintlevel = 1, nthen;
+ struct bitab *bip;
+ token_t last_lit = 0, case_lit = 0, endof_loc = 0, endcase_loc = 0;
+
+ if ((bip = lookup_builtin(*acf)) == NULL ||
+ bip->bi_type != BI_COLON) {
+ if (bip = lookup_builtin((token_t)acf))
+ log_message(MSG_INFO, "%s: builtin\n", bip->bi_name);
+ else
+ log_message(MSG_INFO, "%s: builtin\n",
+ acf_to_name(env, acf));
+ return;
+ }
+ log_message(MSG_INFO, ": %s", acf_to_name(env, acf));
+ for (pass = 0; pass < 2; pass++) {
+ acf = save_acf;
+ for (acf++; ; acf++) {
+ if (pass) {
+ print_level(level, &doprintlevel);
+ for (nthen = 0; nthentab > 0 &&
+ thentab[nthentab-1] == (token_t)acf;
+ nthentab--)
+ nthen++;
+ if (nthen) {
+ level -= nthen;
+ doprintlevel = 1;
+ print_level(level, &doprintlevel);
+ for (i = 0; i < nthen; i++)
+ log_message(MSG_INFO, "then ");
+ }
+ print_level(level, &doprintlevel);
+ for (i = 0; i < nbrtab; i += 2)
+ if ((token_t)acf == brtab[i]) {
+ log_message(MSG_INFO, "begin ");
+ brstk[nbrstk++] = brtab[i+1];
+ level++;
+ doprintlevel = 1;
+ }
+ print_level(level, &doprintlevel);
+ if (case_lit == (token_t)acf) {
+ log_message(MSG_INFO, "case ");
+ doprintlevel = 1;
+ print_level(level, &doprintlevel);
+ }
+ if (endof_loc == (token_t)acf) {
+ log_message(MSG_INFO, "endof ");
+ doprintlevel = 1;
+ print_level(level, &doprintlevel);
+ }
+ if (endcase_loc == (token_t)acf) {
+ doprintlevel = 1;
+ print_level(level, &doprintlevel);
+ log_message(MSG_INFO, "endcase ");
+ }
+ }
+ if ((bip = lookup_builtin((token_t)*acf)) == 0) {
+ last_lit = (token_t)acf;
+ if (pass)
+ log_message(MSG_INFO, "%s ",
+ acf_to_name(env, (acf_t)*acf));
+ continue;
+ }
+ if (bip->bi_type == BI_SEMI) {
+ if (pass) {
+ log_message(MSG_INFO, "\n");
+ log_message(MSG_INFO, "%s\n",
+ bip->bi_name);
+ }
+ break;
+ }
+ switch (bip->bi_type) {
+
+ case BI_NOOP:
+ case BI_NOTYET:
+ if (pass)
+ log_message(MSG_INFO, "%s ",
+ bip->bi_name);
+ break;
+
+ case BI_QUOTE:
+ if (pass)
+ log_message(MSG_INFO, "\" ");
+ acf++;
+ p = (uchar_t *)acf;
+ n = *p++;
+ if (pass)
+ log_message(MSG_INFO, "%s\" ", p);
+ p += n + 1;
+ for (; ((token_t)(p)) & (sizeof (token_t) - 1);
+ p++)
+ ;
+ acf = (acf_t)p;
+ acf--;
+ break;
+
+ case BI_BLIT:
+ acf++;
+ if (pass)
+ log_message(MSG_INFO, "%x ", *acf);
+ break;
+
+ case BI_BDO:
+ case BI_QDO:
+ if (pass) {
+ log_message(MSG_INFO, "%s ",
+ bip->bi_name);
+ doprintlevel = 1;
+ level++;
+ }
+ acf++;
+ break;
+
+ case BI_BR:
+ acf++;
+ if (pass) {
+ if (*acf < (token_t)acf) {
+ if (nbrstk) {
+ doprintlevel = 1;
+ level--;
+ print_level(level,
+ &doprintlevel);
+ log_message(MSG_INFO,
+ "repeat ");
+ nbrstk--;
+ } else
+ log_message(MSG_INFO,
+ "[br back?]");
+ } else if (nthentab) {
+ doprintlevel = 1;
+ print_level(level - 1,
+ &doprintlevel);
+ log_message(MSG_INFO, "else ");
+ doprintlevel = 1;
+ thentab[nthentab - 1] = *acf;
+ }
+ } else {
+ if (*acf < (token_t)acf) {
+ brtab[nbrtab++] = *acf;
+ brtab[nbrtab++] = (token_t)acf;
+ }
+ if (endcase_loc == 0 &&
+ case_lit) {
+ endcase_loc = *acf;
+ }
+ }
+ break;
+
+ case BI_QBR:
+ acf++;
+ if (pass) {
+ if (*acf < (token_t)acf) {
+ if (nbrstk) {
+ doprintlevel = 1;
+ level--;
+ print_level(level,
+ &doprintlevel);
+ log_message(MSG_INFO,
+ "until ");
+ nbrstk--;
+ } else
+ log_message(MSG_INFO,
+ "[br back?]");
+ } else if (nbrstk > 0 &&
+ *acf >= brstk[nbrstk - 1]) {
+ doprintlevel = 1;
+ print_level(level - 1,
+ &doprintlevel);
+ log_message(MSG_INFO,
+ "while ");
+ doprintlevel = 1;
+ } else {
+ log_message(MSG_INFO, "if ");
+ doprintlevel = 1;
+ level++;
+ thentab[nthentab++] = *acf;
+ }
+ } else if (*acf < (token_t)acf) {
+ brtab[nbrtab++] = *acf;
+ brtab[nbrtab++] = (token_t)acf;
+ }
+ break;
+
+ case BI_BOF:
+ acf++;
+ if (pass) {
+ log_message(MSG_INFO, "of ");
+ endof_loc = *acf;
+ } else if (case_lit == 0) {
+ case_lit = last_lit;
+ }
+ break;
+
+ case BI_LOOP:
+ case BI_PLOOP:
+ if (pass) {
+ level--;
+ doprintlevel = 1;
+ print_level(level, &doprintlevel);
+ log_message(MSG_INFO, "%s ",
+ bip->bi_name);
+ }
+ acf++;
+ break;
+
+ default:
+ log_message(MSG_ERROR, "Invalid builtin %s\n",
+ bip->bi_name);
+ }
+ }
+ }
+}
+
+static void
+see(fcode_env_t *env)
+{
+ fstack_t d;
+
+ parse_word(env);
+ dollar_find(env);
+ d = POP(DS);
+ if (d)
+ paren_see(env);
+ else {
+ log_message(MSG_WARN, "?");
+ two_drop(env);
+ }
+}
+
+static acf_t
+do_dot_calls(fcode_env_t *env, acf_t acf, void *cacf)
+{
+ token_t *dptr = ACF_TO_LINK(acf);
+ token_t *wptr = acf;
+
+ if (*wptr == (token_t)(&do_colon)) {
+ do {
+ if ((acf_t)(*wptr) == (acf_t)cacf)
+ output_acf_name(acf);
+ } while (*wptr++ != (token_t)(&semi_ptr));
+ } else if ((acf_t)(*wptr) == cacf)
+ output_acf_name(acf);
+ else if (wptr == (token_t *)cacf)
+ output_acf_name(acf);
+ return (NULL);
+}
+
+static void
+dot_calls(fcode_env_t *env)
+{
+ acf_t acf = (acf_t)POP(DS);
+
+ search_all_dictionaries(env, do_dot_calls, acf);
+ output_acf_name(NULL);
+}
+
+static void
+dot_pci_space(fcode_env_t *env)
+{
+ fstack_t d = POP(DS);
+
+ switch ((d >> 24) & 0x3) {
+ case 0: log_message(MSG_INFO, "Config,"); break;
+ case 1: log_message(MSG_INFO, "IO,"); break;
+ case 2: log_message(MSG_INFO, "Memory32,"); break;
+ case 3: log_message(MSG_INFO, "Memory64,"); break;
+ }
+ if (d & 0x80000000)
+ log_message(MSG_INFO, "Not_reloc,");
+ if (d & 0x400000000)
+ log_message(MSG_INFO, "Prefetch,");
+ if (d & 0x200000000)
+ log_message(MSG_INFO, "Alias,");
+ log_message(MSG_INFO, "Bus%d,", (d >> 16) & 0xff);
+ log_message(MSG_INFO, "Dev%d,", (d >> 11) & 0x1f);
+ log_message(MSG_INFO, "Func%d,", (d >> 8) & 0x7);
+ log_message(MSG_INFO, "Reg%x", d & 0xff);
+ log_message(MSG_INFO, "\n");
+}
+
+void
+fcode_debug(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)(&env->fcode_debug));
+}
+
+static void
+base_addr(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)env->base);
+}
+
+static int mw_valid;
+static int mw_size;
+static void *mw_addr;
+static fstack_t mw_value;
+static fstack_t mw_lastvalue;
+
+static fstack_t
+mw_fetch(void)
+{
+ switch (mw_size) {
+ case 1: return (*((uint8_t *)mw_addr));
+ case 2: return (*((uint16_t *)mw_addr));
+ case 4: return (*((uint32_t *)mw_addr));
+ case 8: return (*((uint64_t *)mw_addr));
+ }
+ return (0);
+}
+
+void
+do_memory_watch(fcode_env_t *env)
+{
+ fstack_t value;
+
+ if (!mw_valid)
+ return;
+ value = mw_fetch();
+ if (value != mw_lastvalue) {
+ if (mw_valid == 1 || mw_value == value) {
+ log_message(MSG_INFO,
+ "memory-watch: %p/%d: %llx -> %llx\n",
+ mw_addr, mw_size, (uint64_t)mw_lastvalue,
+ (uint64_t)value);
+ do_fclib_step(env);
+ }
+ mw_lastvalue = value;
+ }
+}
+
+static void
+set_memory_watch(fcode_env_t *env, int type, int size, void *addr,
+ fstack_t value)
+{
+ switch (size) {
+ case 1: case 2: case 4: case 8:
+ break;
+ default:
+ log_message(MSG_ERROR, "set_memory_watch: invalid size: %d\n",
+ size);
+ return;
+ }
+ mw_valid = type;
+ mw_size = size;
+ mw_addr = addr;
+ mw_value = value;
+ mw_lastvalue = mw_fetch();
+}
+
+static void
+memory_watch(fcode_env_t *env)
+{
+ int size = POP(DS);
+ void *addr = (void *)POP(DS);
+
+ set_memory_watch(env, 1, size, addr, 0);
+}
+
+static void
+memory_watch_value(fcode_env_t *env)
+{
+ int size = POP(DS);
+ void *addr = (void *)POP(DS);
+ fstack_t value = POP(DS);
+
+ set_memory_watch(env, 2, size, addr, value);
+}
+
+static void
+memory_watch_clear(fcode_env_t *env)
+{
+ mw_valid = 0;
+}
+
+static void
+vsearch(fcode_env_t *env)
+{
+ fstack_t value;
+ int size = POP(DS);
+ fstack_t match_value = POP(DS);
+ uchar_t *toaddr = (uchar_t *)POP(DS);
+ uchar_t *fromaddr = (uchar_t *)POP(DS);
+
+ log_message(MSG_INFO, "%p to %p by %d looking for %llx\n", fromaddr,
+ toaddr, size, (uint64_t)match_value);
+ for (; fromaddr < toaddr; fromaddr += size) {
+ switch (size) {
+ case 1: value = *((uint8_t *)fromaddr); break;
+ case 2: value = *((uint16_t *)fromaddr); break;
+ case 4: value = *((uint32_t *)fromaddr); break;
+ case 8: value = *((uint64_t *)fromaddr); break;
+ default:
+ log_message(MSG_INFO, "Invalid size: %d\n", size);
+ return;
+ }
+ if (value == match_value)
+ log_message(MSG_INFO, "%p\n", fromaddr);
+ }
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ FORTH(IMMEDIATE, "words", words);
+ FORTH(IMMEDIATE, "dump-words", dump_words);
+ FORTH(IMMEDIATE, "dump-dict", dump_dictionary);
+ FORTH(IMMEDIATE, "dump-table", dump_table);
+ FORTH(0, "debugf", debugf);
+ FORTH(0, ".debugf", dot_debugf);
+ FORTH(0, "set-debugf", set_debugf);
+ FORTH(0, "debugf?", debugf_qmark);
+ FORTH(0, "control", control);
+ FORTH(0, "dump", dump);
+ FORTH(IMMEDIATE, "showstack", show_stack);
+ FORTH(IMMEDIATE, "sifting", sifting);
+ FORTH(IMMEDIATE, "ctrace", ctrace);
+ FORTH(IMMEDIATE, "ftrace", ftrace);
+ FORTH(0, "see", see);
+ FORTH(0, "(see)", paren_see);
+ FORTH(0, "base-addr", base_addr);
+ FORTH(0, "smatch", smatch);
+ FORTH(0, ".calls", dot_calls);
+ FORTH(0, ".pci-space", dot_pci_space);
+ FORTH(0, "(debug)", paren_debug);
+ FORTH(0, "debug", debug);
+ FORTH(0, ".debug", dot_debug);
+ FORTH(0, "undebug", undebug);
+ FORTH(0, "memory-watch", memory_watch);
+ FORTH(0, "memory-watch-value", memory_watch_value);
+ FORTH(0, "memory-watch-clear", memory_watch_clear);
+ FORTH(0, "vsearch", vsearch);
+}
diff --git a/usr/src/lib/efcode/engine/env.c b/usr/src/lib/efcode/engine/env.c
new file mode 100644
index 0000000000..e5d20ec882
--- /dev/null
+++ b/usr/src/lib/efcode/engine/env.c
@@ -0,0 +1,863 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+
+static variable_t verbose_emit;
+
+void
+do_verbose_emit(fcode_env_t *env)
+{
+ verbose_emit ^= 1;
+}
+
+/*
+ * Internal "emit".
+ * Note log_emit gathers up characters and issues a syslog or write to
+ * error log file if enabled.
+ */
+void
+do_emit(fcode_env_t *env, uchar_t c)
+{
+ if (verbose_emit)
+ log_message(MSG_ERROR, "emit(%x)\n", c);
+
+ if (c == '\n') {
+ env->output_column = 0;
+ env->output_line++;
+ } else if (c == '\r')
+ env->output_column = 0;
+ else
+ env->output_column++;
+ if (isatty(fileno(stdout))) {
+ if ((c >= 0x20 && c <= 0x7f) || c == '\n' || c == '\r' ||
+ c == '\b')
+ putchar(c);
+ else if (c >= 0 && c < 0x20)
+ printf("@%c", c + '@');
+ else
+ printf("\\%x", c);
+ fflush(stdout);
+ }
+ log_emit(c);
+}
+
+void
+system_message(fcode_env_t *env, char *msg)
+{
+ throw_from_fclib(env, 1, msg);
+}
+
+void
+emit(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 1, "emit");
+ d = POP(DS);
+ do_emit(env, d);
+}
+
+#include <sys/time.h>
+
+/*
+ * 'key?' - abort if stdin is not a tty.
+ */
+void
+keyquestion(fcode_env_t *env)
+{
+ struct timeval timeval;
+ fd_set readfds;
+ int ret;
+
+ if (isatty(fileno(stdin))) {
+ FD_ZERO(&readfds);
+ FD_SET(fileno(stdin), &readfds);
+ timeval.tv_sec = 0;
+ timeval.tv_usec = 1000;
+ ret = select(fileno(stdin) + 1, &readfds, NULL, NULL, &timeval);
+ if (FD_ISSET(fileno(stdin), &readfds))
+ PUSH(DS, TRUE);
+ else
+ PUSH(DS, FALSE);
+ } else
+ forth_abort(env, "'key?' called in non-interactive mode");
+}
+
+/*
+ * 'key' - abort if stdin is not a tty, will block on read if char not avail.
+ */
+void
+key(fcode_env_t *env)
+{
+ uchar_t c;
+
+ if (isatty(fileno(stdin))) {
+ read(fileno(stdin), &c, 1);
+ PUSH(DS, c);
+ } else
+ forth_abort(env, "'key' called in non-interactive mode");
+}
+
+void
+type(fcode_env_t *env)
+{
+ int len;
+ char *ptr;
+
+ CHECK_DEPTH(env, 2, "type");
+ ptr = pop_a_string(env, &len);
+ while (len--)
+ do_emit(env, *ptr++);
+}
+
+void
+paren_cr(fcode_env_t *env)
+{
+ do_emit(env, '\r');
+}
+
+void
+fc_crlf(fcode_env_t *env)
+{
+ do_emit(env, '\n');
+}
+
+void
+fc_num_out(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)(&env->output_column));
+}
+
+void
+fc_num_line(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)(&env->output_line));
+}
+
+void
+expect(fcode_env_t *env)
+{
+ char *buf, *rbuf;
+ int len;
+
+ CHECK_DEPTH(env, 2, "expect");
+ buf = pop_a_string(env, &len);
+ read_line(env);
+ rbuf = pop_a_string(env, NULL);
+ if (rbuf) {
+ strcpy(buf, rbuf);
+ env->span = strlen(buf);
+ } else
+ env->span = 0;
+}
+
+void
+span(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)&env->span);
+}
+
+void
+do_ms(fcode_env_t *env)
+{
+ fstack_t d;
+ timespec_t rqtp;
+
+ CHECK_DEPTH(env, 1, "ms");
+ d = POP(DS);
+ if (d) {
+ rqtp.tv_sec = 0;
+ rqtp.tv_nsec = d*1000*1000;
+ nanosleep(&rqtp, 0);
+ }
+}
+
+void
+do_get_msecs(fcode_env_t *env)
+{
+ struct timeval tp;
+ long ms;
+ timespec_t rqtp;
+
+ gettimeofday(&tp, NULL);
+ ms = (tp.tv_usec/1000) + (tp.tv_sec * 1000);
+ PUSH(DS, (fstack_t)ms);
+ rqtp.tv_sec = 0;
+ rqtp.tv_nsec = 1000*1000;
+ nanosleep(&rqtp, 0);
+}
+
+#define CMN_MSG_SIZE 256
+#define CMN_MAX_DIGITS 3
+
+typedef struct CMN_MSG_T cmn_msg_t;
+
+struct CMN_MSG_T {
+ char buf[CMN_MSG_SIZE];
+ int level;
+ int len;
+ cmn_msg_t *prev;
+ cmn_msg_t *next;
+};
+
+typedef struct CMN_FMT_T cmn_fmt_t;
+
+struct CMN_FMT_T {
+ int fwidth; /* format field width */
+ int cwidth; /* column width specified in format */
+ char format; /* format type */
+};
+
+static cmn_msg_t *root = NULL;
+static int cmn_msg_level = 0;
+
+/*
+ * validfmt()
+ *
+ * Called by fmt_str() function to validate and extract formatting
+ * information from the supplied input buffer.
+ *
+ * Supported formats are:
+ * %c - character
+ * %d - signed decimal
+ * %x - unsigned hex
+ * %s - string
+ * %ld - signed 64 bit data
+ * %lx - unsigned 64 bit data
+ * %p - unsigned 64 bit data(pointer)
+ * %% - print as single "%" character
+ *
+ * Return values are:
+ * 0 - valid formatting
+ * 1 - invalid formatting found in the input buffer
+ * -1 - NULL pointer passed in for caller's receptacle
+ *
+ *
+ * For valid formatting, caller's supplied cmn_fmt_t elements are
+ * filled in:
+ * fwidth:
+ * > 0 - returned value is the field width
+ * < 0 - returned value is negation of field width for
+ * 64 bit data formats
+ * cwidth:
+ * formatted column width(if specified), otherwise 0
+ *
+ * format:
+ * contains the formatting(single) character
+ */
+static int
+validfmt(char *fmt, cmn_fmt_t *cfstr)
+{
+ int isll = 0;
+ int *fwidth, *cwidth;
+ char *format;
+ char *dig1, *dig2;
+ char cdigs[CMN_MAX_DIGITS+1];
+
+ if (cfstr == NULL)
+ return (-1);
+
+ fwidth = &cfstr->fwidth;
+ cwidth = &cfstr->cwidth;
+ format = &cfstr->format;
+ *fwidth = *cwidth = 0;
+ *format = NULL;
+ dig1 = dig2 = NULL;
+
+ /* check for left justification character */
+ if (*fmt == '-') {
+ fmt++;
+ (*fwidth)++;
+
+ /* check for column width specification */
+ if (isdigit(*fmt))
+ dig1 = fmt; /* save ptr to first digit */
+ while (isdigit(*fmt)) {
+ fmt++;
+ (*fwidth)++;
+ }
+ /* if ljust specified w/o size, return format error */
+ if (*fwidth == 1) {
+ return (1);
+ }
+ dig2 = fmt; /* save ptr to last digit + 1 */
+ } else {
+ /* check for column width specification */
+ if (isdigit(*fmt)) {
+ dig1 = fmt; /* save ptr to first digit */
+ while (isdigit(*fmt)) {
+ fmt++;
+ (*fwidth)++;
+ }
+ dig2 = fmt; /* save ptr to last digit + 1 */
+ }
+ }
+
+ /* if a column width was specified, save it in caller's struct */
+ if (dig1) {
+ int nbytes;
+
+ nbytes = dig2 - dig1;
+ /* if too many digits in the width return error */
+ if (nbytes > CMN_MAX_DIGITS)
+ return (1);
+ strncpy(cdigs, dig1, nbytes);
+ cdigs[nbytes] = 0;
+ *cwidth = atoi(cdigs);
+ }
+
+ /* check for long format specifier */
+ if (*fmt == 'l') {
+ fmt++;
+ (*fwidth)++;
+ isll = 1;
+ }
+
+ /* process by specific format type */
+ switch (*fmt) {
+ case 'c':
+ case 's':
+ case '%':
+ if (isll)
+ return (1);
+ case 'd':
+ case 'x':
+ *format = *fmt;
+ (*fwidth)++;
+ break;
+ case 'p':
+ isll = 1; /* uses 64 bit format */
+ *format = *fmt;
+ (*fwidth)++;
+ break;
+ default:
+ return (1); /* unknown format type */
+ }
+ if (isll) {
+ *fwidth *= -1;
+ }
+ return (0);
+}
+
+/*
+ * fmt_args()
+ *
+ * Called by fmt_str() to setup arguments for subsequent snprintf()
+ * calls. For cases not involving column width limitations, processing
+ * simply POPs the data stack as required to setup caller's arg(or
+ * llarg, as appropriate). When a column width is specified for output,
+ * a temporary buffer is constructed to contain snprintf() generated
+ * output for the argument. Testing is then performed to determine if
+ * the specified column width will require truncation of the output.
+ * If so, truncation of least significant digits is performed as
+ * necessary, and caller's arg(or llarg) is adjusted to obtain the
+ * specified column width.
+ *
+ */
+
+static void
+fmt_args(fcode_env_t *env, int cw, int fw, char format, long *arg,
+ long long *llarg)
+{
+ char *cbuf;
+ char snf[3];
+ int cbsize;
+ int cnv = 10, ndigits = 0;
+
+ if (fw > 0) { /* check for normal (not long) formats */
+
+ /* initialize format string for snprintf call */
+ snf[0] = '%';
+ snf[1] = format;
+ snf[2] = 0;
+
+ /* process by format type */
+ switch (format) {
+ case 'x':
+ cnv = 16;
+ case 'd':
+ case 'c':
+ case 'p':
+ *arg = POP(DS);
+ break;
+ case 's':
+ POP(DS);
+ *arg = POP(DS);
+ break;
+ case '%':
+ return;
+ default:
+ log_message(MSG_ERROR,
+ "fmt_args:invalid format type! (%s)\n",
+ &format);
+ return;
+ }
+
+ /* check if a column width was specified */
+ if (cw) {
+ /* allocate a scratch buffer */
+ cbsize = 2*(sizeof (long long)) + 1;
+ cbuf = MALLOC(cbsize);
+
+ if (snprintf(cbuf, cbsize, snf, *arg) < 0)
+ log_message(MSG_ERROR,
+ "fmt_args: snprintf output error\n");
+ while ((cbuf[ndigits] != NULL) &&
+ (ndigits < cbsize))
+ ndigits++;
+
+ /* if truncation is necessary, do it */
+ if (ndigits > cw) {
+ cbuf[cw] = 0;
+ if (format == 's') {
+ char *str;
+ str = (char *)*arg;
+ str[cw] = 0;
+ } else
+ *arg = strtol(cbuf,
+ (char **)NULL, cnv);
+ }
+ free(cbuf);
+ }
+
+ } else { /* process long formats */
+
+ *llarg = POP(DS);
+
+ /* check if a column width was specified */
+ if (cw) {
+ /* allocate a scratch buffer */
+ cbsize = 2*(sizeof (long long)) + 1;
+ cbuf = MALLOC(cbsize);
+
+ switch (format) {
+ case 'p':
+ cnv = 16;
+ if (snprintf(cbuf, cbsize, "%p", *llarg) < 0)
+ log_message(MSG_ERROR,
+ "fmt_args: snprintf error\n");
+ break;
+ case 'x':
+ cnv = 16;
+ if (snprintf(cbuf, cbsize, "%lx", *llarg) < 0)
+ log_message(MSG_ERROR,
+ "fmt_args: snprintf error\n");
+ break;
+ case 'd':
+ if (snprintf(cbuf, cbsize, "%ld", *llarg) < 0)
+ log_message(MSG_ERROR,
+ "fmt_args: snprintf error\n");
+ break;
+ default:
+ log_message(MSG_ERROR,
+ "invalid long format type! (l%s)\n",
+ &format);
+ free(cbuf);
+ return;
+ }
+ while ((cbuf[ndigits] != NULL) &&
+ (ndigits < cbsize)) {
+ ndigits++;
+ }
+ /* if truncation is necessary, do it */
+ if (ndigits > cw) {
+ cbuf[cw] = 0;
+ *llarg = strtoll(cbuf, (char **)NULL, cnv);
+ }
+ free(cbuf);
+ }
+ }
+}
+
+/*
+ * fmt_str()
+ *
+ * Extracts text from caller's input buffer, processes explicit
+ * formatting as necessary, and outputs formatted text to caller's
+ * receptacle.
+ *
+ * env - pointer to caller's fcode environment
+ * fmt - pointer to caller's input buffr
+ * fmtbuf - ponter to caller's receptacle buffer
+ * bsize - size of caller's fmtbuf buffer
+ *
+ * This function performs an initial test to determine if caller's
+ * input buffer contains formatting(specified by presence of "%")
+ * in the buffer. If so, validfmt() function is called to verify
+ * the formatting, after which the buffer is processed according
+ * to the field width specified by validfmt() output. Special
+ * processing is required when caller's buffer contains a double
+ * "%" ("%%"), in which case the second "%" is accepted as normal
+ * text.
+ */
+
+static void
+fmt_str(fcode_env_t *env, char *fmt, char *fmtbuf, int bsize)
+{
+ char tbuf[CMN_MSG_SIZE];
+ char *fmptr, *pct;
+ int l, cw, fw, bytes;
+ long arg;
+ long long llarg;
+
+ *fmtbuf = 0;
+ if ((pct = strchr(fmt, '%')) != 0) {
+ cmn_fmt_t cfstr;
+ int vferr;
+
+ l = strlen(pct++);
+ vferr = validfmt(pct, &cfstr);
+ if (!vferr) {
+ fw = cfstr.fwidth;
+ cw = cfstr.cwidth;
+ fmptr = &cfstr.format;
+ } else {
+ if (vferr < 0) {
+ log_message(MSG_ERROR,
+ "fmt_str: NULL ptr supplied to validfmt()\n");
+ return;
+ }
+
+ bytes = pct - fmt;
+ strncpy(tbuf, fmt, bytes);
+ strncpy(tbuf+bytes, "%", 1);
+ strncpy(tbuf+bytes+1, fmt+bytes, 1);
+ bytes += 2;
+ tbuf[bytes] = 0;
+
+ log_message(MSG_ERROR,
+ "fmt_str: invalid format type! (%s)\n",
+ tbuf+bytes-3);
+
+ strncpy(fmtbuf, tbuf, bsize);
+ return;
+ }
+
+ if (fw > 0) { /* process normal (not long) formats */
+ bytes = pct - fmt + fw;
+ strncpy(tbuf, fmt, bytes);
+ tbuf[bytes] = 0;
+ } else {
+ /* if here, fw must be a long format */
+ if (*fmptr == 'p') {
+ bytes = pct - fmt - fw;
+ strncpy(tbuf, fmt, bytes);
+ tbuf[bytes] = 0;
+ } else {
+ bytes = pct - fmt - fw - 2;
+ strncpy(tbuf, fmt, bytes);
+ tbuf[bytes] = 'l';
+ strncpy(tbuf+bytes+1, fmt+bytes, 2);
+ tbuf[bytes+1+2] = 0;
+ }
+ }
+
+ /* if more input buffer to process, recurse */
+ if ((l - abs(fw)) != 0) {
+ fmt_str(env, pct+abs(fw), (tbuf + strlen(tbuf)),
+ CMN_MSG_SIZE - strlen(tbuf));
+ }
+
+ /* call to extract args for snprintf() calls below */
+ fmt_args(env, cw, fw, *fmptr, &arg, &llarg);
+
+ if (fw > 0) { /* process normal (not long) formats */
+ switch (*fmptr) {
+ case 'd':
+ case 'x':
+ case 'c':
+ case 's':
+ case 'p':
+ (void) snprintf(fmtbuf, bsize, tbuf, arg);
+ break;
+ case '%':
+ (void) snprintf(fmtbuf, bsize, tbuf);
+ break;
+ default:
+ log_message(MSG_ERROR,
+ "fmt_str: invalid format (%s)\n",
+ fmptr);
+ return;
+ }
+
+ } else /* process long formats */
+ (void) snprintf(fmtbuf, bsize, tbuf, llarg);
+
+ } else
+ strncpy(fmtbuf, fmt, bsize);
+}
+
+/*
+ * fc_cmn_append()
+ *
+ * Pops data stack to obtain message text, and calls fmt_str()
+ * function to perform any message formatting necessary.
+ *
+ * This function is called from fc_cmn_end() or directly in
+ * processing a cmn-append token. Since a pre-existing message
+ * context is assumed, initial checking is performed to verify
+ * its existence.
+ */
+
+void
+fc_cmn_append(fcode_env_t *env)
+{
+ int len;
+ char *str;
+
+ if (root == NULL) {
+ log_message(MSG_ERROR,
+ "fc_cmn_append: no message context for append\n");
+ return;
+ }
+
+ len = POP(DS);
+ str = (char *)POP(DS);
+
+ if ((root->len + len) < CMN_MSG_SIZE) {
+ fmt_str(env, str, root->buf+root->len, CMN_MSG_SIZE -
+ root->len);
+ root->len += len;
+ } else
+ log_message(MSG_ERROR,
+ "fc_cmn_append: append exceeds max msg size\n");
+}
+
+/*
+ * fc_cmn_end()
+ *
+ * Process ]cmn-end token to log the message initiated by a preceeding
+ * fc_cmn_start() call.
+ *
+ * Since nested cmn-xxx[ calls are supported, a test is made to determine
+ * if this is the final cmn-end of a nested sequence. If so, or if
+ * there was no nesting, log_message() is called with the appropriate
+ * text buffer. Otherwise, the root variable is adjusted to point to
+ * the preceeding message in the sequence and links in the list are
+ * updated. No logging is performed until the final ]cmn-end of the
+ * sequence is processed; then, messages are logged in FIFO order.
+ */
+void
+fc_cmn_end(fcode_env_t *env)
+{
+ cmn_msg_t *old;
+
+ if (root == 0) {
+ log_message(MSG_ERROR, "]cmn-end call w/o buffer\n");
+ return;
+ }
+
+ fc_cmn_append(env);
+
+ if (root->prev == 0) {
+ cmn_msg_t *next;
+ do {
+ log_message(root->level, "%s\n", root->buf);
+ next = root->next;
+ free(root);
+ root = next;
+ } while (root);
+ } else {
+ old = root->prev;
+ old->next = root;
+ root = old;
+ }
+}
+
+/*
+ * fc_cmn_start()
+ *
+ * Generic function to begin a common message.
+ *
+ * Allocates a new cmn_msg_t to associate with the message, and sets
+ * up initial text as specified by callers' inputs:
+ *
+ * env - pointer to caller's fcode environment
+ * head - pointer to initial text portion of the message
+ * path - flag to indicate if a device path is to be generated
+ */
+static void
+fc_cmn_start(fcode_env_t *env, char *head, int path)
+{
+ cmn_msg_t *new;
+ char *dpath;
+
+ new = MALLOC(sizeof (cmn_msg_t));
+ new->prev = root;
+ if (root != 0)
+ root->next = new;
+ strcpy(new->buf, head);
+ new->len = strlen(head);
+ if (path && env->current_device) {
+ dpath = get_path(env, env->current_device);
+ strcpy(new->buf+new->len, dpath);
+ new->len += strlen(dpath);
+ strncpy(new->buf+new->len++, ": ", 2);
+ ++new->len;
+ free(dpath);
+ }
+ new->level = cmn_msg_level;
+ new->next = NULL;
+ root = new;
+}
+
+/*
+ * fc_cmn_type()
+ *
+ * Process cmn-type[ token.
+ *
+ * Invokes fc_cmn_start() to create a message containing blank
+ * header and no device path information.
+ */
+void
+fc_cmn_type(fcode_env_t *env)
+{
+ cmn_msg_level = MSG_INFO;
+ fc_cmn_start(env, "", 0);
+}
+
+/*
+ * fc_cmn_msg()
+ *
+ * Process cmn-msg[ token.
+ *
+ * Invokes fc_cmn_start() to create a message containing blank
+ * header but specifying device path information.
+ */
+void
+fc_cmn_msg(fcode_env_t *env)
+{
+
+ cmn_msg_level = MSG_INFO;
+ fc_cmn_start(env, "", 1);
+}
+
+/*
+ * fc_cmn_note()
+ *
+ * Process cmn-note[ token.
+ *
+ * Invokes fc_cmn_start() to create a message with NOTICE stamping in
+ * the header and specification of device path information.
+ */
+void
+fc_cmn_note(fcode_env_t *env)
+{
+ cmn_msg_level = MSG_NOTE;
+ fc_cmn_start(env, "NOTICE: ", 1);
+}
+
+/*
+ * fc_cmn_warn()
+ *
+ * Process cmn-warn[ token.
+ *
+ * Invokes fc_cmn_start() to create a message with WARNING stamping in
+ * the header and specification of device path information.
+ */
+void
+fc_cmn_warn(fcode_env_t *env)
+{
+ cmn_msg_level = MSG_WARN;
+ fc_cmn_start(env, "WARNING: ", 1);
+}
+
+/*
+ * fc_cmn_error()
+ *
+ * Process cmn-error[ token.
+ *
+ * Invokes fc_cmn_start() to create a message with ERROR stamping in
+ * the header and specification of device path information.
+ */
+void
+fc_cmn_error(fcode_env_t *env)
+{
+ cmn_msg_level = MSG_ERROR;
+ fc_cmn_start(env, "ERROR: ", 1);
+}
+
+/*
+ * fc_cmn_fatal()
+ *
+ * Process cmn-fatal[ token.
+ *
+ * Invokes fc_cmn_start() to create a message with FATAL stamping in
+ * the header and specification of device path information.
+ */
+void
+fc_cmn_fatal(fcode_env_t *env)
+{
+ cmn_msg_level = MSG_FATAL;
+ fc_cmn_start(env, "FATAL: ", 1);
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+ ASSERT(env);
+ NOTICE;
+
+ ANSI(0x088, 0, "span", span);
+ ANSI(0x08a, 0, "expect", expect);
+
+ ANSI(0x08d, 0, "key?", keyquestion);
+ ANSI(0x08e, 0, "key", key);
+ ANSI(0x08f, 0, "emit", emit);
+ ANSI(0x090, 0, "type", type);
+ ANSI(0x091, 0, "(cr", paren_cr);
+ ANSI(0x092, 0, "cr", fc_crlf);
+ ANSI(0x093, 0, "#out", fc_num_out);
+ ANSI(0x094, 0, "#line", fc_num_line);
+
+ FCODE(0x125, 0, "get-msecs", do_get_msecs);
+ FCODE(0x126, 0, "ms", do_ms);
+
+ FORTH(0, "verbose-emit", do_verbose_emit);
+ FCODE(0x7e9, 0, "cmn-fatal[", fc_cmn_fatal);
+ FCODE(0x7ea, 0, "cmn-error[", fc_cmn_error);
+ FCODE(0x7eb, 0, "cmn-warn[", fc_cmn_warn);
+ FCODE(0x7ec, 0, "cmn-note[", fc_cmn_note);
+ FCODE(0x7ed, 0, "cmn-type[", fc_cmn_type);
+ FCODE(0x7ee, 0, "cmn-append", fc_cmn_append);
+ FCODE(0x7ef, 0, "]cmn-end", fc_cmn_end);
+ FCODE(0x7f0, 0, "cmn-msg[", fc_cmn_msg);
+}
diff --git a/usr/src/lib/efcode/engine/extend.c b/usr/src/lib/efcode/engine/extend.c
new file mode 100644
index 0000000000..9e631012b2
--- /dev/null
+++ b/usr/src/lib/efcode/engine/extend.c
@@ -0,0 +1,147 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <sys/shm.h>
+#include <dlfcn.h>
+#include <fcode/private.h>
+
+static void
+do_dlopen(fcode_env_t *env)
+{
+ char *name;
+ int mode;
+ void *pl;
+
+ mode = POP(DS);
+ name = pop_a_string(env, NULL);
+ pl = dlopen(name, mode);
+ PUSH(DS, (fstack_t)pl);
+}
+
+static void
+do_extend(fcode_env_t *env)
+{
+ parse_word(env);
+ PUSH(DS, (fstack_t)RTLD_NOW);
+ do_dlopen(env);
+ drop(env);
+}
+
+static void
+do_dlclose(fcode_env_t *env)
+{
+ void *pl = (void *)POP(DS);
+ dlclose(pl);
+}
+
+static void
+do_dlsym(fcode_env_t *env)
+{
+ char *name;
+ fstack_t d;
+
+ name = pop_a_string(env, NULL);
+ d = POP(DS);
+ d = (fstack_t)dlsym((void *) d, name);
+ PUSH(DS, d);
+}
+
+static void
+do_dlexec(fcode_env_t *env)
+{
+ int args;
+ fstack_t a, b, c, d;
+ fstack_t (*fn0)(void);
+ fstack_t (*fn1)(fstack_t);
+ fstack_t (*fn2)(fstack_t, fstack_t);
+ fstack_t (*fn3)(fstack_t, fstack_t, fstack_t);
+ fstack_t (*fn4)(fstack_t, fstack_t, fstack_t, fstack_t);
+
+ args = POP(DS);
+ a = POP(DS);
+ switch (args) {
+
+ case 0:
+ fn0 = (fstack_t (*)(void)) a;
+ a = fn0();
+ PUSH(DS, a);
+ break;
+
+ case 1:
+ fn1 = (fstack_t (*)(fstack_t)) a;
+ a = POP(DS);
+ a = fn1(a);
+ PUSH(DS, a);
+ break;
+
+ case 2:
+ fn2 = (fstack_t (*)(fstack_t, fstack_t))a;
+ a = POP(DS);
+ b = POP(DS);
+ a = fn2(a, b);
+ PUSH(DS, a);
+ break;
+
+ case 3:
+ fn3 = (fstack_t (*)(fstack_t, fstack_t, fstack_t))a;
+ a = POP(DS);
+ b = POP(DS);
+ c = POP(DS);
+ a = fn3(a, b, c);
+ PUSH(DS, a);
+ break;
+
+ case 4:
+ fn4 = (fstack_t (*)(fstack_t, fstack_t, fstack_t, fstack_t))a;
+ a = POP(DS);
+ b = POP(DS);
+ c = POP(DS);
+ d = POP(DS);
+ a = fn4(a, b, c, d);
+ PUSH(DS, a);
+ break;
+ }
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ FORTH(0, "dl-open", do_dlopen);
+ FORTH(0, "dl-close", do_dlclose);
+ FORTH(0, "dl-sym", do_dlsym);
+ FORTH(0, "dl-exec", do_dlexec);
+ FORTH(IMMEDIATE, "extend-from", do_extend);
+}
diff --git a/usr/src/lib/efcode/engine/fb8.c b/usr/src/lib/efcode/engine/fb8.c
new file mode 100644
index 0000000000..777b9d0713
--- /dev/null
+++ b/usr/src/lib/efcode/engine/fb8.c
@@ -0,0 +1,54 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <fcode/private.h>
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ FCODE(0x180, 0, "fb8-draw-character", fc_unimplemented);
+ FCODE(0x181, 0, "fb8-reset-screen", fc_unimplemented);
+ FCODE(0x182, 0, "fb8-toggle-cursor", fc_unimplemented);
+ FCODE(0x183, 0, "fb8-erase-screen", fc_unimplemented);
+ FCODE(0x184, 0, "fb8-blink-screen", fc_unimplemented);
+ FCODE(0x185, 0, "fb8-invert-screen", fc_unimplemented);
+ FCODE(0x186, 0, "fb8-insert-characters", fc_unimplemented);
+ FCODE(0x187, 0, "fb8-delete-characters", fc_unimplemented);
+ FCODE(0x188, 0, "fb8-insert-lines", fc_unimplemented);
+ FCODE(0x189, 0, "fb8-delete-lines", fc_unimplemented);
+ FCODE(0x18a, 0, "fb8-draw-logo", fc_unimplemented);
+ FCODE(0x18b, 0, "fb8-install", fc_unimplemented);
+}
diff --git a/usr/src/lib/efcode/engine/fcode.c b/usr/src/lib/efcode/engine/fcode.c
new file mode 100644
index 0000000000..e8cedb3816
--- /dev/null
+++ b/usr/src/lib/efcode/engine/fcode.c
@@ -0,0 +1,1031 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+int fcode_impl_count = 0;
+
+void (*crash_ptr)(fcode_env_t *env) = do_crash;
+
+uchar_t
+next_bytecode(fcode_env_t *env)
+{
+ uchar_t byte;
+
+ byte = *env->fcode_ptr;
+ env->fcode_ptr += env->fcode_incr;
+ return (byte);
+}
+
+ushort_t
+get_next_token(fcode_env_t *env)
+{
+ ushort_t token = next_bytecode(env);
+ if ((token) && (token < 0x10)) {
+ token = (token << 8) | next_bytecode(env);
+ }
+ env->last_fcode = token;
+ return (token);
+}
+
+ushort_t
+get_short(fcode_env_t *env)
+{
+ ushort_t u;
+
+ /*
+ * Logical or DOES NOT guarantee left to right evaluation...
+ */
+ u = next_bytecode(env) << 8;
+ return (u | next_bytecode(env));
+}
+
+uint_t
+get_int(fcode_env_t *env)
+{
+ uint_t u;
+
+ /*
+ * Logical or DOES NOT guarantee left to right evaluation...
+ */
+ u = get_short(env) << 16;
+ return (u | get_short(env));
+}
+
+void
+expose_acf(fcode_env_t *env, char *name)
+{
+ if (name == NULL)
+ name = "<unknown>";
+ EXPOSE_ACF;
+ debug_msg(DEBUG_CONTEXT, "CONTEXT:expose_acf: acf: %p/'%s' %p\n",
+ LINK_TO_ACF(env->lastlink), name, env->current);
+}
+
+void
+do_code(fcode_env_t *env, int token, char *name, void (*fn)(fcode_env_t *))
+{
+ env->table[token].name = name;
+ if (fn == NULL) {
+ env->table[token].apf = NULL;
+ env->table[token].name = name;
+ } else {
+ header(env, name, strlen(name), 0);
+ env->table[token].apf = (acf_t)HERE;
+ COMPILE_TOKEN(fn);
+ expose_acf(env, name);
+ }
+}
+
+void
+define_word(fcode_env_t *env, int flag, char *name, void (*fn)(fcode_env_t *))
+{
+ header(env, name, strlen(name), flag);
+ COMPILE_TOKEN(fn);
+ expose_acf(env, name);
+}
+
+void
+end0(fcode_env_t *env)
+{
+ env->interpretting = 0;
+}
+
+static void
+end1(fcode_env_t *env)
+{
+ env->interpretting = 0;
+}
+
+void
+blit(fcode_env_t *env)
+{
+ fstack_t d = (int)get_int(env);
+ PUSH(DS, d);
+ literal(env);
+}
+
+void (*bbranch_ptrs[3])(fcode_env_t *env) = {
+ do_bbranch,
+ do_bqbranch,
+ do_bofbranch
+};
+
+void
+branch_common(fcode_env_t *env, short direction, fstack_t which, int doswap)
+{
+ fstack_t *sp;
+ token_t *branch_loc;
+
+ ASSERT((which < 3) && (which >= 0));
+ which = (fstack_t)&bbranch_ptrs[which];
+ set_temporary_compile(env);
+ COMPILE_TOKEN(which);
+ if (direction >= 0) {
+ bmark(env);
+ if (doswap)
+ swap(env);
+ PUSH(DS, 0);
+ compile_comma(env);
+ } else {
+
+ /*
+ * We look down the stack for a branch location
+ * that isn't pointing to zero (i.e. a forward branch label).
+ * We move the first one we find to the top of the stack,
+ * which is what gets compiled in with 'compile_comma'.
+ * Not finding a valid branch label is bad.
+ */
+ for (sp = env->ds; sp >= env->ds0; sp--) {
+ branch_loc = (token_t *)*sp;
+ if (branch_loc && *branch_loc) {
+ break;
+ }
+ }
+ if (sp < env->ds0)
+ log_message(MSG_ERROR, "branch_common: back: "
+ "no branch loc on stack\n");
+ else {
+ /* Move branch_loc to top of data stack */
+ for (; sp < env->ds; sp++)
+ *sp = sp[1];
+ *sp = (fstack_t)branch_loc;
+ }
+ env->level--;
+ compile_comma(env);
+ temporary_execute(env);
+ }
+}
+
+void
+bbranch(fcode_env_t *env)
+{
+ short offset = (short)get_short(env);
+
+ branch_common(env, offset, 0, 1);
+}
+
+void
+bqbranch(fcode_env_t *env)
+{
+ short offset = (short)get_short(env);
+
+ branch_common(env, offset, 1, 0);
+}
+
+void
+do_quote(fcode_env_t *env)
+{
+ int len;
+ uchar_t *strptr;
+
+ strptr = (uchar_t *)IP;
+ len = *strptr;
+ PUSH(DS, (fstack_t)strptr+1);
+ PUSH(DS, len);
+ strptr += TOKEN_ROUNDUP(len+2);
+ IP = (token_t *)strptr;
+}
+
+void
+bquote(fcode_env_t *env)
+{
+ char stringbuff[256];
+ int len, count;
+ char *strptr;
+
+ count = len = next_bytecode(env);
+ if (env->state) {
+ COMPILE_TOKEN(&quote_ptr);
+ strptr = (char *)HERE;
+ *strptr++ = len;
+ while (count--)
+ *strptr++ = next_bytecode(env);
+ *strptr++ = 0;
+ set_here(env, (uchar_t *)strptr, "bquote");
+ token_roundup(env, "bquote");
+ } else {
+ strptr = stringbuff;
+ while (count--)
+ *strptr++ = next_bytecode(env);
+ *strptr = 0;
+ push_string(env, stringbuff, len);
+ }
+}
+
+char *
+get_name(token_t *linkp)
+{
+ char *name, *p;
+ flag_t *fptr = LINK_TO_FLAGS(linkp);
+ int len;
+ char *cptr;
+
+ if (*fptr & FLAG_NONAME)
+ return (NULL);
+
+ cptr = (char *)fptr;
+ len = cptr[-1];
+ if (len <= 0 || len > 64 || cptr[-2] != '\0')
+ return (NULL);
+
+ name = cptr - (len+2);
+
+ for (p = name; *p != '\0'; p++)
+ if (!isprint(*p))
+ return (NULL);
+
+ if ((p - name) != len)
+ return (NULL);
+
+ return (name);
+}
+
+void
+header(fcode_env_t *env, char *name, int len, flag_t flag)
+{
+ char *strptr;
+ flag_t *fptr;
+ acf_t dptr;
+ extern void add_debug_acf(fcode_env_t *, acf_t);
+
+ /* Now form the entry in the dictionary */
+ token_roundup(env, "header");
+ dptr = (acf_t)HERE;
+ if (len) {
+ int bytes = len+2+sizeof (flag_t);
+ dptr = (acf_t)(TOKEN_ROUNDUP(HERE+bytes));
+ fptr = LINK_TO_FLAGS(dptr);
+ strptr = (char *)fptr - 1;
+ *strptr-- = len;
+ *strptr-- = 0;
+ while (len)
+ *strptr-- = name[--len];
+ } else {
+ dptr++;
+ fptr = LINK_TO_FLAGS(dptr);
+ flag |= FLAG_NONAME;
+ }
+ *fptr = flag;
+ *dptr = *((acf_t)env->current);
+ env->lastlink = dptr++;
+ set_here(env, (uchar_t *)dptr, "header");
+
+ if (name_is_debugged(env, name)) {
+ log_message(MSG_INFO, "Turning debug on for %s\n", name);
+ add_debug_acf(env, LINK_TO_ACF(env->lastlink));
+ }
+ debug_msg(DEBUG_HEADER, "Define: '%s' @ %p\n", name, HERE);
+}
+
+void
+token_common(fcode_env_t *env, int headered, int visible)
+{
+ char namebuff[32];
+ int len, count, token;
+ char *strptr, c;
+
+ strptr = namebuff;
+ if (headered) {
+ len = next_bytecode(env);
+ for (count = 0; count < len; count++) {
+ c = next_bytecode(env);
+ if (count < sizeof (namebuff))
+ *strptr++ = c;
+ }
+ }
+
+ if (!visible)
+ len = 0;
+ *strptr = 0;
+ token = get_short(env);
+ env->last_token = token;
+
+ debug_msg(DEBUG_NEW_TOKEN, "Define %s token: '%s' (%x)\n",
+ (visible ? "named" : "headerless"), namebuff, token);
+
+ header(env, namebuff, len, 0);
+ env->table[token].flags = 0;
+ if (len) {
+ env->table[token].name = MALLOC(len+1);
+ strncpy(env->table[token].name, namebuff, len);
+ } else {
+ env->table[token].name = NULL;
+ }
+ env->last_token = token;
+}
+
+void
+named_token(fcode_env_t *env)
+{
+ token_common(env, 1, env->fcode_debug);
+}
+
+void
+external_token(fcode_env_t *env)
+{
+ token_common(env, 1, 1);
+}
+
+void
+new_token(fcode_env_t *env)
+{
+ token_common(env, 0, 0);
+}
+
+void
+offset16(fcode_env_t *env)
+{
+ env->offset_incr = 2;
+}
+
+void
+minus_one(fcode_env_t *env)
+{
+ PUSH(DS, -1);
+}
+
+void
+zero(fcode_env_t *env)
+{
+ PUSH(DS, 0);
+}
+
+void
+one(fcode_env_t *env)
+{
+ PUSH(DS, 1);
+}
+
+void
+two(fcode_env_t *env)
+{
+ PUSH(DS, 2);
+}
+
+void
+three(fcode_env_t *env)
+{
+ PUSH(DS, 3);
+}
+
+void
+version1(fcode_env_t *env)
+{
+ env->fcode_incr = 1;
+}
+
+static void
+start0(fcode_env_t *env)
+{
+ env->fcode_incr = 1;
+}
+
+static void
+start1(fcode_env_t *env)
+{
+ env->fcode_incr = 1;
+}
+
+void
+start2(fcode_env_t *env)
+{
+ env->fcode_incr = 2;
+}
+
+static void
+start4(fcode_env_t *env)
+{
+ env->fcode_incr = 4;
+}
+
+int
+check_fcode_header(char *fname, uchar_t *header, int len)
+{
+ uint32_t length;
+ static char func_name[] = "check_fcode_header";
+
+ if (len <= 8) {
+ log_message(MSG_ERROR, "%s: '%s' fcode size (%d) <= 8\n",
+ func_name, fname, len);
+ return (0);
+ }
+ if (header[0] != 0xf1 && header[0] != 0xfd) {
+ log_message(MSG_ERROR, "%s: '%s' header[0] is 0x%02x not"
+ " 0xf1/0xfd\n", func_name, fname, header[0]);
+ return (0);
+ }
+ length = (header[4] << 24) | (header[5] << 16) | (header[6] << 8) |
+ header[7];
+ if (length > len) {
+ log_message(MSG_ERROR, "%s: '%s' length (%d) >"
+ " fcode size (%d)\n", func_name, fname, length, len);
+ return (0);
+ }
+ if (length < len) {
+ log_message(MSG_WARN, "%s: '%s' length (%d) <"
+ " fcode size (%d)\n", func_name, fname, length, len);
+ }
+ return (1);
+}
+
+void
+byte_load(fcode_env_t *env)
+{
+ uchar_t *fcode_buffer;
+ uchar_t *fcode_ptr;
+ int fcode_incr;
+ int offset_incr;
+ int fcode_xt;
+ int interpretting;
+ int depth;
+ int length;
+ int past_eob = 0;
+ int db;
+
+ /* save any existing interpret state */
+ fcode_buffer = env->fcode_buffer;
+ fcode_ptr = env->fcode_ptr;
+ fcode_incr = env->fcode_incr;
+ offset_incr = env->offset_incr;
+ interpretting = env->interpretting;
+ depth = DEPTH-2;
+
+ /* Now init them */
+ CHECK_DEPTH(env, 2, "byte-load");
+ fcode_xt = POP(DS);
+ env->fcode_ptr = env->fcode_buffer = (uchar_t *)POP(DS);
+ if (fcode_xt != 1) {
+ log_message(MSG_WARN, "byte-load: ignoring xt\n");
+ }
+
+ length = (env->fcode_buffer[4] << 24) | (env->fcode_buffer[5] << 16) |
+ (env->fcode_buffer[6] << 8) | env->fcode_buffer[7];
+ if (!check_fcode_header("byte-load", env->fcode_ptr, length))
+ log_message(MSG_WARN, "byte-load: header NOT OK\n");
+
+ env->fcode_incr = 1;
+ env->offset_incr = 1;
+ env->interpretting = 1;
+ env->level = 0;
+
+ db = get_interpreter_debug_level() &
+ (DEBUG_BYTELOAD_DS|DEBUG_BYTELOAD_RS|DEBUG_BYTELOAD_TOKENS);
+ debug_msg(db, "byte_load: %p, %d\n", env->fcode_buffer, fcode_xt);
+ debug_msg(db, " header: %x, %x\n",
+ env->fcode_buffer[0], env->fcode_buffer[1]);
+ debug_msg(db, " crc: %x\n",
+ (env->fcode_buffer[2]<<8)|(env->fcode_buffer[3]));
+ debug_msg(db, " length: %x\n", length);
+ env->fcode_ptr += 8;
+
+ debug_msg(db, "Interpretting: %d\n", env->interpretting);
+
+ while (env->interpretting) {
+ int token;
+ fcode_token *entry;
+ acf_t apf;
+
+ if (!past_eob && env->fcode_ptr >= env->fcode_buffer + length) {
+ log_message(MSG_WARN, "byte-load: past EOB\n");
+ past_eob = 1;
+ }
+
+ env->last_fcode_ptr = env->fcode_ptr;
+ token = get_next_token(env);
+
+ entry = &env->table[token];
+ apf = entry->apf;
+
+ DEBUGF(BYTELOAD_DS, output_data_stack(env, MSG_FC_DEBUG));
+ DEBUGF(BYTELOAD_RS, output_return_stack(env, 1, MSG_FC_DEBUG));
+ DEBUGF(BYTELOAD_TOKENS, log_message(MSG_FC_DEBUG,
+ "%s: %04x %03x %s (%x)",
+ ((env->state && (entry->flags & IMMEDIATE) == 0)) ?
+ "Compile" : "Execute",
+ env->last_fcode_ptr - env->fcode_buffer, token,
+ entry->name ? entry->name : "???", entry->flags));
+ if (db)
+ log_message(MSG_FC_DEBUG, "\n");
+ if (apf) {
+ DEBUGF(TOKEN_USAGE, entry->usage++);
+ PUSH(DS, (fstack_t)apf);
+ if ((env->state) &&
+ ((entry->flags & IMMEDIATE) == 0)) {
+ /* Compile in references */
+ compile_comma(env);
+ } else {
+ execute(env);
+ }
+ }
+ }
+ if (DEPTH != depth) {
+ log_message(MSG_ERROR, "FCODE has net stack change of %d\n",
+ DEPTH-depth);
+ }
+ /* restore old state */
+ env->fcode_ptr = fcode_ptr;
+ env->fcode_buffer = fcode_buffer;
+ env->fcode_incr = fcode_incr;
+ env->offset_incr = offset_incr;
+ env->interpretting = interpretting;
+}
+
+void
+btick(fcode_env_t *env)
+{
+ int token = get_next_token(env);
+
+ PUSH(DS, (fstack_t)env->table[token].apf);
+ tick_literal(env);
+}
+
+static void
+show_fcode_def(fcode_env_t *env, char *type)
+{
+ int i = env->last_token;
+
+ if (get_interpreter_debug_level() & DEBUG_DUMP_TOKENS) {
+ if (env->table[i].name)
+ log_message(MSG_INFO, "%s: %s %03x %p\n", type,
+ env->table[i].name, i, env->table[i].apf);
+ else
+ log_message(MSG_INFO, "%s: <noname> %03x %p\n", type, i,
+ env->table[i].apf);
+ }
+}
+
+void
+bcolon(fcode_env_t *env)
+{
+ if (env->state == 0) {
+ env->table[env->last_token].apf = (acf_t)HERE;
+ env->table[env->last_token].flags = 0;
+ show_fcode_def(env, "bcolon");
+ }
+ env->state |= 1;
+ COMPILE_TOKEN(&do_colon);
+}
+
+void
+bcreate(fcode_env_t *env)
+{
+ env->table[env->last_token].apf = (acf_t)HERE;
+ show_fcode_def(env, "bcreate");
+ COMPILE_TOKEN(&do_create);
+ expose_acf(env, "<bcreate>");
+}
+
+void
+get_token_name(fcode_env_t *env, int token, char **name, int *len)
+{
+ *name = env->table[token].name;
+ if (*name) {
+ *len = strlen(*name);
+ } else
+ *len = 0;
+}
+
+void
+bvalue(fcode_env_t *env)
+{
+ env->table[env->last_token].apf = (acf_t)HERE;
+ show_fcode_def(env, "bvalue");
+ make_common_access(env, 0, 0, 1,
+ env->instance_mode, &noop, &noop, &set_value_actions);
+}
+
+void
+bvariable(fcode_env_t *env)
+{
+ env->table[env->last_token].apf = (acf_t)HERE;
+ show_fcode_def(env, "bvariable");
+ PUSH(DS, 0);
+ make_common_access(env, 0, 0, 1,
+ env->instance_mode, &instance_variable, &do_create, NULL);
+}
+
+void
+bconstant(fcode_env_t *env)
+{
+ env->table[env->last_token].apf = (acf_t)HERE;
+ show_fcode_def(env, "bconstant");
+ make_common_access(env, 0, 0, 1,
+ env->instance_mode, &do_constant, &do_constant, NULL);
+}
+
+void
+bdefer(fcode_env_t *env)
+{
+ env->table[env->last_token].apf = (acf_t)HERE;
+ show_fcode_def(env, "bdefer");
+
+ PUSH(DS, (fstack_t)&crash_ptr);
+ make_common_access(env, 0, 0, 1, env->instance_mode,
+ &noop, &noop, &set_defer_actions);
+}
+
+void
+bbuffer_colon(fcode_env_t *env)
+{
+ env->table[env->last_token].apf = (acf_t)HERE;
+ show_fcode_def(env, "buffer:");
+ PUSH(DS, 0);
+ make_common_access(env, 0, 0, 2, env->instance_mode,
+ &noop, &noop, &set_buffer_actions);
+}
+
+void
+do_field(fcode_env_t *env)
+{
+ fstack_t *d;
+
+ d = (fstack_t *)WA;
+ TOS += *d;
+}
+
+void
+bfield(fcode_env_t *env)
+{
+ env->table[env->last_token].apf = (acf_t)HERE;
+ show_fcode_def(env, "bfield");
+ COMPILE_TOKEN(&do_field);
+ over(env);
+ compile_comma(env);
+ add(env);
+ expose_acf(env, "<bfield>");
+}
+
+void
+bto(fcode_env_t *env)
+{
+ btick(env);
+
+ if (env->state) {
+ COMPILE_TOKEN(&to_ptr);
+ } else {
+ do_set_action(env);
+ }
+}
+
+void
+get_token(fcode_env_t *env)
+{
+ fstack_t tok;
+ fstack_t immediate = 0;
+
+ CHECK_DEPTH(env, 1, "get-token");
+ tok = POP(DS);
+ tok &= MAX_FCODE;
+ PUSH(DS, (fstack_t)env->table[tok].apf);
+ if (env->table[tok].flags & IMMEDIATE) immediate = 1;
+ PUSH(DS, immediate);
+}
+
+void
+set_token(fcode_env_t *env)
+{
+ fstack_t tok;
+ fstack_t immediate;
+ acf_t acf;
+
+ CHECK_DEPTH(env, 3, "set-token");
+ tok = POP(DS);
+ tok &= MAX_FCODE;
+ immediate = POP(DS);
+ acf = (acf_t)POP(DS);
+ if (immediate)
+ env->table[tok].flags |= IMMEDIATE;
+ else
+ env->table[tok].flags &= ~IMMEDIATE;
+ env->table[tok].apf = acf;
+ immediate = env->last_token;
+ env->last_token = tok;
+ show_fcode_def(env, "set_token");
+ env->last_token = immediate;
+}
+
+void
+bof(fcode_env_t *env)
+{
+ short offset = get_short(env);
+ branch_common(env, offset, 2, 0);
+}
+
+void
+bcase(fcode_env_t *env)
+{
+ env->level++;
+ set_temporary_compile(env);
+ PUSH(DS, 0);
+}
+
+void
+bendcase(fcode_env_t *env)
+{
+ COMPILE_TOKEN(env->table[0x46].apf); /* Hack for now... */
+ while (TOS) {
+ bresolve(env);
+ }
+ (void) POP(DS);
+ env->level--;
+ temporary_execute(env);
+}
+
+void
+bendof(fcode_env_t *env)
+{
+ short offset = get_short(env);
+ branch_common(env, offset, 0, 1);
+ bresolve(env);
+}
+
+void
+fcode_revision(fcode_env_t *env)
+{
+ /* We are Version 3.0 */
+ PUSH(DS, 0x30000);
+}
+
+void
+alloc_mem(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "alloc-mem");
+ TOS = (fstack_t)MALLOC((size_t)TOS);
+ if (!TOS) {
+ throw_from_fclib(env, 1, "alloc-mem failed");
+ }
+}
+
+void
+free_mem(fcode_env_t *env)
+{
+ void *p;
+
+ CHECK_DEPTH(env, 2, "free-mem");
+ (void) POP(DS);
+ p = (void *) POP(DS);
+ FREE(p);
+}
+
+void
+parse_two_int(fcode_env_t *env)
+{
+ uint_t lo, hi;
+ char *str;
+ int len;
+
+ CHECK_DEPTH(env, 2, "parse-2int");
+ lo = 0;
+ hi = 0;
+ str = pop_a_string(env, &len);
+ if (len) {
+ if (sscanf(str, "%x,%x", &hi, &lo) != 2) {
+ throw_from_fclib(env, 1, "parse_2int");
+ }
+ }
+ PUSH(DS, lo);
+ PUSH(DS, hi);
+}
+
+void
+left_parse_string(fcode_env_t *env)
+{
+ char sep, *cptr, *lstr, *rstr;
+ int len, llen, rlen;
+
+ CHECK_DEPTH(env, 3, "left-parse-string");
+ sep = (char)POP(DS);
+ if (TOS == 0) {
+ two_dup(env);
+ return;
+ }
+ lstr = pop_a_string(env, &llen);
+ len = 0;
+ cptr = NULL;
+ while (len < llen) {
+ if (lstr[len] == sep) {
+ cptr = lstr+len;
+ break;
+ }
+ len++;
+ }
+ if (cptr != NULL) {
+ rstr = cptr+1;
+ rlen = lstr + llen - rstr;
+ llen = len;
+ } else {
+ rlen = 0;
+ rstr = lstr;
+ }
+ PUSH(DS, (fstack_t)rstr);
+ PUSH(DS, rlen);
+ PUSH(DS, (fstack_t)lstr);
+ PUSH(DS, llen);
+}
+
+/*
+ * (is-user-word) ( name-str name-len xt -- )
+ */
+void
+is_user_word(fcode_env_t *env)
+{
+ fstack_t xt;
+ char *name;
+ int len;
+
+ CHECK_DEPTH(env, 3, "(is-user-word)");
+ xt = POP(DS);
+ name = pop_a_string(env, &len);
+ header(env, name, len, 0);
+ COMPILE_TOKEN(&do_alias);
+ COMPILE_TOKEN(xt);
+ expose_acf(env, name);
+}
+
+void
+f_error(fcode_env_t *env)
+{
+#if 0
+ env->interpretting = 0;
+ log_message(MSG_ERROR, "Uniplemented FCODE token encountered %x\n",
+ env->last_fcode);
+#else
+ forth_abort(env, "Unimplemented FCODE token: 0x%x\n", env->last_fcode);
+#endif
+}
+
+static void
+fcode_buffer_addr(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)(env->fcode_buffer));
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ P1275(0x000, DEFINER, "end0", end0);
+ P1275(0x010, DEFINER, "b(lit)", blit);
+ P1275(0x011, DEFINER, "b(')", btick);
+ P1275(0x012, DEFINER, "b(\")", bquote);
+ P1275(0x013, DEFINER, "bbranch", bbranch);
+ P1275(0x014, DEFINER, "b?branch", bqbranch);
+ P1275(0x015, DEFINER, "b(loop)", bloop);
+ P1275(0x016, DEFINER, "b(+loop)", bplusloop);
+ P1275(0x017, DEFINER, "b(do)", bdo);
+ P1275(0x018, DEFINER, "b(?do)", bqdo);
+ P1275(0x01b, DEFINER, "b(leave)", bleave);
+ P1275(0x01c, DEFINER, "b(of)", bof);
+
+ P1275(0x087, 0, "fcode-revision", fcode_revision);
+
+ P1275(0x08b, 0, "alloc-mem", alloc_mem);
+ P1275(0x08c, 0, "free-mem", free_mem);
+
+ P1275(0x0a4, 0, "-1", minus_one);
+ P1275(0x0a5, 0, "0", zero);
+ P1275(0x0a6, 0, "1", one);
+ P1275(0x0a7, 0, "2", two);
+ P1275(0x0a8, 0, "3", three);
+
+ P1275(0x0ae, 0, "aligned", aligned);
+ P1275(0x0b1, DEFINER, "b(<mark)", bmark);
+ P1275(0x0b2, DEFINER, "b(>resolve)", bresolve);
+ FCODE(0x0b3, 0, "set-token-table", fc_historical);
+ FCODE(0x0b4, 0, "set-table", fc_historical);
+ P1275(0x0b5, 0, "new-token", new_token);
+ P1275(0x0b6, 0, "named-token", named_token);
+ P1275(0x0b7, DEFINER, "b(:)", bcolon);
+ P1275(0x0b8, DEFINER, "b(value)", bvalue);
+ P1275(0x0b9, DEFINER, "b(variable)", bvariable);
+ P1275(0x0ba, DEFINER, "b(constant)", bconstant);
+ P1275(0x0bb, DEFINER, "b(create)", bcreate);
+ P1275(0x0bc, DEFINER, "b(defer)", bdefer);
+ P1275(0x0bd, 0, "b(buffer:)", bbuffer_colon);
+ P1275(0x0be, 0, "b(field)", bfield);
+ FCODE(0x0bf, 0, "b(code)", fc_historical);
+ P1275(0x0c0, IMMEDIATE, "instance", instance);
+
+ P1275(0x0c2, DEFINER, "b(;)", semi);
+ P1275(0x0c3, DEFINER, "b(to)", bto);
+ P1275(0x0c4, DEFINER, "b(case)", bcase);
+ P1275(0x0c5, DEFINER, "b(endcase)", bendcase);
+ P1275(0x0c6, DEFINER, "b(endof)", bendof);
+
+ P1275(0x0ca, 0, "external-token", external_token);
+ P1275(0x0cc, 0, "offset16", offset16);
+ P1275(0x0cd, 0, "evaluate", evaluate);
+
+ P1275(0x0da, 0, "get-token", get_token);
+ P1275(0x0db, 0, "set-token", set_token);
+
+ P1275(0x0f0, 0, "start0", start0);
+ P1275(0x0f1, 0, "start1", start1);
+ P1275(0x0f2, 0, "start2", start2);
+ P1275(0x0f3, 0, "start4", start4);
+
+ P1275(0x0fd, 0, "version1", version1);
+ FCODE(0x0fe, 0, "4-byte-id", fc_historical);
+
+ P1275(0x0ff, 0, "end1", end1);
+
+ /* Call it "old-dma-alloc" so no one gets confused */
+ FCODE(0x101, 0, "old-dma-alloc", fc_historical);
+
+ FCODE(0x104, 0, "memmap", fc_historical);
+ FCODE(0x105, 0, "free-virtual", fc_unimplemented);
+
+ FCODE(0x106, 0, ">physical", fc_historical);
+
+ FCODE(0x10f, 0, "my-params", fc_historical);
+
+ P1275(0x11b, 0, "parse-2int", parse_two_int);
+
+ FCODE(0x122, 0, "memory-test-suite", fc_unimplemented);
+ FCODE(0x123, 0, "group-code", fc_historical);
+ FCODE(0x124, 0, "mask", fc_unimplemented);
+
+ FCODE(0x130, 0, "map-low", fc_unimplemented);
+ FCODE(0x131, 0, "sbus-intr>cpu", fc_unimplemented);
+
+ FCODE(0x170, 0, "fb1-draw-character", fc_historical);
+ FCODE(0x171, 0, "fb1-reset-screen", fc_historical);
+ FCODE(0x172, 0, "fb1-toggle-cursor", fc_historical);
+ FCODE(0x173, 0, "fb1-erase-screen", fc_historical);
+ FCODE(0x174, 0, "fb1-blink-screen", fc_historical);
+ FCODE(0x175, 0, "fb1-invert-screen", fc_historical);
+ FCODE(0x176, 0, "fb1-insert-characters", fc_historical);
+ FCODE(0x177, 0, "fb1-delete-characters", fc_historical);
+ FCODE(0x178, 0, "fb1-insert-lines", fc_historical);
+ FCODE(0x179, 0, "fb1-delete-lines", fc_historical);
+ FCODE(0x17a, 0, "fb1-draw-logo", fc_historical);
+ FCODE(0x17b, 0, "fb1-install", fc_historical);
+ FCODE(0x17c, 0, "fb1-slide-up", fc_historical);
+
+ FCODE(0x190, 0, "VME-bus Support", fc_obsolete);
+ FCODE(0x191, 0, "VME-bus Support", fc_obsolete);
+ FCODE(0x192, 0, "VME-bus Support", fc_obsolete);
+ FCODE(0x193, 0, "VME-bus Support", fc_obsolete);
+ FCODE(0x194, 0, "VME-bus Support", fc_obsolete);
+ FCODE(0x195, 0, "VME-bus Support", fc_obsolete);
+ FCODE(0x196, 0, "VME-bus Support", fc_obsolete);
+
+ FCODE(0x1a0, 0, "return-buffer", fc_historical);
+ FCODE(0x1a1, 0, "xmit-packet", fc_historical);
+ FCODE(0x1a2, 0, "poll-packet", fc_historical);
+
+ FCODE(0x210, 0, "processor-type", fc_historical);
+ FCODE(0x211, 0, "firmware-version", fc_historical);
+ FCODE(0x212, 0, "fcode-version", fc_historical);
+
+ FCODE(0x214, 0, "(is-user-word)", is_user_word);
+ FCODE(0x215, 0, "suspend-fcode", fc_unimplemented);
+
+ FCODE(0x229, 0, "adr-mask", fc_historical);
+
+ FCODE(0x238, 0, "probe", fc_historical);
+ FCODE(0x239, 0, "probe-virtual", fc_historical);
+
+ P1275(0x23e, 0, "byte-load", byte_load);
+
+ P1275(0x240, 0, "left-parse-string", left_parse_string);
+ FORTH(0, "fcode-buffer", fcode_buffer_addr);
+}
diff --git a/usr/src/lib/efcode/engine/font.c b/usr/src/lib/efcode/engine/font.c
new file mode 100644
index 0000000000..a38307480f
--- /dev/null
+++ b/usr/src/lib/efcode/engine/font.c
@@ -0,0 +1,48 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <fcode/private.h>
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ P1275(0x16a, 0, "default-font", fc_unimplemented);
+ P1275(0x16b, 0, "set-font", fc_unimplemented);
+ P1275(0x16c, 0, "char-height", fc_unimplemented);
+ P1275(0x16d, 0, "char-width", fc_unimplemented);
+ P1275(0x16e, 0, ">font", fc_unimplemented);
+ P1275(0x16f, 0, "fontbytes", fc_unimplemented);
+}
diff --git a/usr/src/lib/efcode/engine/forth.c b/usr/src/lib/efcode/engine/forth.c
new file mode 100644
index 0000000000..b0b8005342
--- /dev/null
+++ b/usr/src/lib/efcode/engine/forth.c
@@ -0,0 +1,2675 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+void (*semi_ptr)(fcode_env_t *env) = do_semi;
+void (*does_ptr)(fcode_env_t *env) = install_does;
+void (*quote_ptr)(fcode_env_t *env) = do_quote;
+void (*blit_ptr)(fcode_env_t *env) = do_literal;
+void (*tlit_ptr)(fcode_env_t *env) = do_literal;
+void (*do_bdo_ptr)(fcode_env_t *env) = do_bdo;
+void (*do_bqdo_ptr)(fcode_env_t *env) = do_bqdo;
+void (*create_ptr)(fcode_env_t *env) = do_creator;
+void (*do_leave_ptr)(fcode_env_t *env) = do_bleave;
+void (*do_loop_ptr)(fcode_env_t *env) = do_bloop;
+void (*do_ploop_ptr)(fcode_env_t *env) = do_bploop;
+
+void unaligned_lstore(fcode_env_t *);
+void unaligned_wstore(fcode_env_t *);
+void unaligned_lfetch(fcode_env_t *);
+void unaligned_wfetch(fcode_env_t *);
+
+/* start with the simple maths functions */
+
+
+void
+add(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "+");
+ d = POP(DS);
+ TOS += d;
+}
+
+void
+subtract(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "-");
+ d = POP(DS);
+ TOS -= d;
+}
+
+void
+multiply(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "*");
+ d = POP(DS);
+ TOS *= d;
+}
+
+void
+slash_mod(fcode_env_t *env)
+{
+ fstack_t d, o, t, rem;
+ int sign = 1;
+
+ CHECK_DEPTH(env, 2, "/mod");
+ d = POP(DS);
+ o = t = POP(DS);
+
+ if (d == 0) {
+ throw_from_fclib(env, 1, "/mod divide by zero");
+ }
+ sign = ((d ^ t) < 0);
+ if (d < 0) {
+ d = -d;
+ if (sign) {
+ t += (d-1);
+ }
+ }
+ if (t < 0) {
+ if (sign) {
+ t -= (d-1);
+ }
+ t = -t;
+ }
+ t = t / d;
+ if ((o ^ sign) < 0) {
+ rem = (t * d) + o;
+ } else {
+ rem = o - (t*d);
+ }
+ if (sign) {
+ t = -t;
+ }
+ PUSH(DS, rem);
+ PUSH(DS, t);
+}
+
+/*
+ * 'u/mod' Fcode implementation.
+ */
+void
+uslash_mod(fcode_env_t *env)
+{
+ u_lforth_t u1, u2;
+
+ CHECK_DEPTH(env, 2, "u/mod");
+ u2 = POP(DS);
+ u1 = POP(DS);
+
+ if (u2 == 0)
+ forth_abort(env, "u/mod: divide by zero");
+ PUSH(DS, u1 % u2);
+ PUSH(DS, u1 / u2);
+}
+
+void
+divide(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "/");
+ slash_mod(env);
+ nip(env);
+}
+
+void
+mod(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "mod");
+ slash_mod(env);
+ drop(env);
+}
+
+void
+and(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "and");
+ d = POP(DS);
+ TOS &= d;
+}
+
+void
+or(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "or");
+ d = POP(DS);
+ TOS |= d;
+}
+
+void
+xor(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "xor");
+ d = POP(DS);
+ TOS ^= d;
+}
+
+void
+invert(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "invert");
+ TOS = ~TOS;
+}
+
+void
+lshift(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "lshift");
+ d = POP(DS);
+ TOS = TOS << d;
+}
+
+void
+rshift(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "rshift");
+ d = POP(DS);
+ TOS = ((ufstack_t)TOS) >> d;
+}
+
+void
+rshifta(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, ">>a");
+ d = POP(DS);
+ TOS = ((s_lforth_t)TOS) >> d;
+}
+
+void
+negate(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "negate");
+ TOS = -TOS;
+}
+
+void
+f_abs(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "abs");
+ if (TOS < 0) TOS = -TOS;
+}
+
+void
+f_min(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "min");
+ d = POP(DS);
+ if (d < TOS) TOS = d;
+}
+
+void
+f_max(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "max");
+ d = POP(DS);
+ if (d > TOS) TOS = d;
+}
+
+void
+to_r(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, ">r");
+ PUSH(RS, POP(DS));
+}
+
+void
+from_r(fcode_env_t *env)
+{
+ CHECK_RETURN_DEPTH(env, 1, "r>");
+ PUSH(DS, POP(RS));
+}
+
+void
+rfetch(fcode_env_t *env)
+{
+ CHECK_RETURN_DEPTH(env, 1, "r@");
+ PUSH(DS, *RS);
+}
+
+void
+f_exit(fcode_env_t *env)
+{
+ CHECK_RETURN_DEPTH(env, 1, "exit");
+ IP = (token_t *)POP(RS);
+}
+
+#define COMPARE(cmp, rhs) ((((s_lforth_t)TOS) cmp((s_lforth_t)(rhs))) ? \
+ TRUE : FALSE)
+#define UCOMPARE(cmp, rhs) ((((u_lforth_t)TOS) cmp((u_lforth_t)(rhs))) ? \
+ TRUE : FALSE)
+#define EQUALS ==
+#define NOTEQUALS !=
+#define LESSTHAN <
+#define LESSEQUALS <=
+#define GREATERTHAN >
+#define GREATEREQUALS >=
+
+void
+zero_equals(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "0=");
+ TOS = COMPARE(EQUALS, 0);
+}
+
+void
+zero_not_equals(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "0<>");
+ TOS = COMPARE(NOTEQUALS, 0);
+}
+
+void
+zero_less(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "0<");
+ TOS = COMPARE(LESSTHAN, 0);
+}
+
+void
+zero_less_equals(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "0<=");
+ TOS = COMPARE(LESSEQUALS, 0);
+}
+
+void
+zero_greater(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "0>");
+ TOS = COMPARE(GREATERTHAN, 0);
+}
+
+void
+zero_greater_equals(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "0>=");
+ TOS = COMPARE(GREATEREQUALS, 0);
+}
+
+void
+less(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "<");
+ d = POP(DS);
+ TOS = COMPARE(LESSTHAN, d);
+}
+
+void
+greater(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, ">");
+ d = POP(DS);
+ TOS = COMPARE(GREATERTHAN, d);
+}
+
+void
+equals(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "=");
+ d = POP(DS);
+ TOS = COMPARE(EQUALS, d);
+}
+
+void
+not_equals(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "<>");
+ d = POP(DS);
+ TOS = COMPARE(NOTEQUALS, d);
+}
+
+
+void
+unsign_greater(fcode_env_t *env)
+{
+ ufstack_t d;
+
+ CHECK_DEPTH(env, 2, "u>");
+ d = POP(DS);
+ TOS = UCOMPARE(GREATERTHAN, d);
+}
+
+void
+unsign_less_equals(fcode_env_t *env)
+{
+ ufstack_t d;
+
+ CHECK_DEPTH(env, 2, "u<=");
+ d = POP(DS);
+ TOS = UCOMPARE(LESSEQUALS, d);
+}
+
+void
+unsign_less(fcode_env_t *env)
+{
+ ufstack_t d;
+
+ CHECK_DEPTH(env, 2, "u<");
+ d = POP(DS);
+ TOS = UCOMPARE(LESSTHAN, d);
+}
+
+void
+unsign_greater_equals(fcode_env_t *env)
+{
+ ufstack_t d;
+
+ CHECK_DEPTH(env, 2, "u>=");
+ d = POP(DS);
+ TOS = UCOMPARE(GREATEREQUALS, d);
+}
+
+void
+greater_equals(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, ">=");
+ d = POP(DS);
+ TOS = COMPARE(GREATEREQUALS, d);
+}
+
+void
+less_equals(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "<=");
+ d = POP(DS);
+ TOS = COMPARE(LESSEQUALS, d);
+}
+
+void
+between(fcode_env_t *env)
+{
+ s_lforth_t hi, lo;
+
+ CHECK_DEPTH(env, 3, "between");
+ hi = (s_lforth_t)POP(DS);
+ lo = (s_lforth_t)POP(DS);
+ TOS = (((s_lforth_t)TOS >= lo) && ((s_lforth_t)TOS <= hi) ? -1 : 0);
+}
+
+void
+within(fcode_env_t *env)
+{
+ s_lforth_t lo, hi;
+
+ CHECK_DEPTH(env, 3, "within");
+ hi = (s_lforth_t)POP(DS);
+ lo = (s_lforth_t)POP(DS);
+ TOS = ((((s_lforth_t)TOS >= lo) && ((s_lforth_t)TOS < hi)) ? -1 : 0);
+}
+
+void
+do_literal(fcode_env_t *env)
+{
+ PUSH(DS, *IP);
+ IP++;
+}
+
+void
+literal(fcode_env_t *env)
+{
+ if (env->state) {
+ COMPILE_TOKEN(&blit_ptr);
+ compile_comma(env);
+ }
+}
+
+void
+do_also(fcode_env_t *env)
+{
+ token_t *d = *ORDER;
+
+ if (env->order_depth < (MAX_ORDER - 1)) {
+ env->order[++env->order_depth] = d;
+ debug_msg(DEBUG_CONTEXT, "CONTEXT:also: %d/%p/%p\n",
+ env->order_depth, CONTEXT, env->current);
+ } else
+ log_message(MSG_WARN, "Vocabulary search order exceeds: %d\n",
+ MAX_ORDER);
+}
+
+void
+do_previous(fcode_env_t *env)
+{
+ if (env->order_depth) {
+ env->order_depth--;
+ debug_msg(DEBUG_CONTEXT, "CONTEXT:previous: %d/%p/%p\n",
+ env->order_depth, CONTEXT, env->current);
+ }
+}
+
+#ifdef DEBUG
+void
+do_order(fcode_env_t *env)
+{
+ int i;
+
+ log_message(MSG_INFO, "Order: Depth: %ld: ", env->order_depth);
+ for (i = env->order_depth; i >= 0 && env->order[i]; i--)
+ log_message(MSG_INFO, "%p ", (void *)env->order[i]);
+ log_message(MSG_INFO, "\n");
+}
+#endif
+
+void
+noop(fcode_env_t *env)
+{
+ /* what a waste of cycles */
+}
+
+
+#define FW_PER_FL (sizeof (lforth_t)/sizeof (wforth_t))
+
+void
+lwsplit(fcode_env_t *env)
+{
+ union {
+ u_wforth_t l_wf[FW_PER_FL];
+ u_lforth_t l_lf;
+ } d;
+ int i;
+
+ CHECK_DEPTH(env, 1, "lwsplit");
+ d.l_lf = POP(DS);
+ for (i = 0; i < FW_PER_FL; i++)
+ PUSH(DS, d.l_wf[(FW_PER_FL - 1) - i]);
+}
+
+void
+wljoin(fcode_env_t *env)
+{
+ union {
+ u_wforth_t l_wf[FW_PER_FL];
+ u_lforth_t l_lf;
+ } d;
+ int i;
+
+ CHECK_DEPTH(env, FW_PER_FL, "wljoin");
+ for (i = 0; i < FW_PER_FL; i++)
+ d.l_wf[i] = POP(DS);
+ PUSH(DS, d.l_lf);
+}
+
+void
+lwflip(fcode_env_t *env)
+{
+ union {
+ u_wforth_t l_wf[FW_PER_FL];
+ u_lforth_t l_lf;
+ } d, c;
+ int i;
+
+ CHECK_DEPTH(env, 1, "lwflip");
+ d.l_lf = POP(DS);
+ for (i = 0; i < FW_PER_FL; i++)
+ c.l_wf[i] = d.l_wf[(FW_PER_FL - 1) - i];
+ PUSH(DS, c.l_lf);
+}
+
+void
+lbsplit(fcode_env_t *env)
+{
+ union {
+ uchar_t l_bytes[sizeof (lforth_t)];
+ u_lforth_t l_lf;
+ } d;
+ int i;
+
+ CHECK_DEPTH(env, 1, "lbsplit");
+ d.l_lf = POP(DS);
+ for (i = 0; i < sizeof (lforth_t); i++)
+ PUSH(DS, d.l_bytes[(sizeof (lforth_t) - 1) - i]);
+}
+
+void
+bljoin(fcode_env_t *env)
+{
+ union {
+ uchar_t l_bytes[sizeof (lforth_t)];
+ u_lforth_t l_lf;
+ } d;
+ int i;
+
+ CHECK_DEPTH(env, sizeof (lforth_t), "bljoin");
+ for (i = 0; i < sizeof (lforth_t); i++)
+ d.l_bytes[i] = POP(DS);
+ PUSH(DS, (fstack_t)d.l_lf);
+}
+
+void
+lbflip(fcode_env_t *env)
+{
+ union {
+ uchar_t l_bytes[sizeof (lforth_t)];
+ u_lforth_t l_lf;
+ } d, c;
+ int i;
+
+ CHECK_DEPTH(env, 1, "lbflip");
+ d.l_lf = POP(DS);
+ for (i = 0; i < sizeof (lforth_t); i++)
+ c.l_bytes[i] = d.l_bytes[(sizeof (lforth_t) - 1) - i];
+ PUSH(DS, c.l_lf);
+}
+
+void
+wbsplit(fcode_env_t *env)
+{
+ union {
+ uchar_t w_bytes[sizeof (wforth_t)];
+ u_wforth_t w_wf;
+ } d;
+ int i;
+
+ CHECK_DEPTH(env, 1, "wbsplit");
+ d.w_wf = POP(DS);
+ for (i = 0; i < sizeof (wforth_t); i++)
+ PUSH(DS, d.w_bytes[(sizeof (wforth_t) - 1) - i]);
+}
+
+void
+bwjoin(fcode_env_t *env)
+{
+ union {
+ uchar_t w_bytes[sizeof (wforth_t)];
+ u_wforth_t w_wf;
+ } d;
+ int i;
+
+ CHECK_DEPTH(env, sizeof (wforth_t), "bwjoin");
+ for (i = 0; i < sizeof (wforth_t); i++)
+ d.w_bytes[i] = POP(DS);
+ PUSH(DS, d.w_wf);
+}
+
+void
+wbflip(fcode_env_t *env)
+{
+ union {
+ uchar_t w_bytes[sizeof (wforth_t)];
+ u_wforth_t w_wf;
+ } c, d;
+ int i;
+
+ CHECK_DEPTH(env, 1, "wbflip");
+ d.w_wf = POP(DS);
+ for (i = 0; i < sizeof (wforth_t); i++)
+ c.w_bytes[i] = d.w_bytes[(sizeof (wforth_t) - 1) - i];
+ PUSH(DS, c.w_wf);
+}
+
+void
+upper_case(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "upc");
+ TOS = toupper(TOS);
+}
+
+void
+lower_case(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "lcc");
+ TOS = tolower(TOS);
+}
+
+void
+pack_str(fcode_env_t *env)
+{
+ char *buf;
+ size_t len;
+ char *str;
+
+ CHECK_DEPTH(env, 3, "pack");
+ buf = (char *)POP(DS);
+ len = (size_t)POP(DS);
+ str = (char *)TOS;
+ TOS = (fstack_t)buf;
+ *buf++ = (uchar_t)len;
+ strncpy(buf, str, (len&0xff));
+}
+
+void
+count_str(fcode_env_t *env)
+{
+ uchar_t *len;
+
+ CHECK_DEPTH(env, 1, "count");
+ len = (uchar_t *)TOS;
+ TOS += 1;
+ PUSH(DS, *len);
+}
+
+void
+to_body(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, ">body");
+ TOS = (fstack_t)(((acf_t)TOS)+1);
+}
+
+void
+to_acf(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "body>");
+ TOS = (fstack_t)(((acf_t)TOS)-1);
+}
+
+/*
+ * 'unloop' Fcode implementation, drop 3 loop ctrl elements off return stack.
+ */
+static void
+unloop(fcode_env_t *env)
+{
+ CHECK_RETURN_DEPTH(env, 3, "unloop");
+ RS -= 3;
+}
+
+/*
+ * 'um*' Fcode implementation.
+ */
+static void
+um_multiply(fcode_env_t *env)
+{
+ ufstack_t u1, u2;
+ dforth_t d;
+
+ CHECK_DEPTH(env, 2, "um*");
+ u1 = POP(DS);
+ u2 = POP(DS);
+ d = u1 * u2;
+ push_double(env, d);
+}
+
+/*
+ * um/mod (d.lo d.hi u -- urem uquot)
+ */
+static void
+um_slash_mod(fcode_env_t *env)
+{
+ u_dforth_t d;
+ uint32_t u, urem, uquot;
+
+ CHECK_DEPTH(env, 3, "um/mod");
+ u = (uint32_t)POP(DS);
+ d = pop_double(env);
+ urem = d % u;
+ uquot = d / u;
+ PUSH(DS, urem);
+ PUSH(DS, uquot);
+}
+
+/*
+ * d+ (d1.lo d1.hi d2.lo d2.hi -- dsum.lo dsum.hi)
+ */
+static void
+d_plus(fcode_env_t *env)
+{
+ dforth_t d1, d2;
+
+ CHECK_DEPTH(env, 4, "d+");
+ d2 = pop_double(env);
+ d1 = pop_double(env);
+ d1 += d2;
+ push_double(env, d1);
+}
+
+/*
+ * d- (d1.lo d1.hi d2.lo d2.hi -- ddif.lo ddif.hi)
+ */
+static void
+d_minus(fcode_env_t *env)
+{
+ dforth_t d1, d2;
+
+ CHECK_DEPTH(env, 4, "d-");
+ d2 = pop_double(env);
+ d1 = pop_double(env);
+ d1 -= d2;
+ push_double(env, d1);
+}
+
+void
+set_here(fcode_env_t *env, uchar_t *new_here, char *where)
+{
+ if (new_here < HERE) {
+ if (strcmp(where, "temporary_execute")) {
+ /*
+ * Other than temporary_execute, no one should set
+ * here backwards.
+ */
+ log_message(MSG_WARN, "Warning: set_here(%s) back: old:"
+ " %p new: %p\n", where, HERE, new_here);
+ }
+ }
+ if (new_here >= env->base + dict_size)
+ forth_abort(env, "Here (%p) set past dictionary end (%p)",
+ new_here, env->base + dict_size);
+ HERE = new_here;
+}
+
+static void
+unaligned_store(fcode_env_t *env)
+{
+ extern void unaligned_xstore(fcode_env_t *);
+
+ if (sizeof (fstack_t) == sizeof (lforth_t))
+ unaligned_lstore(env);
+ else
+ unaligned_xstore(env);
+}
+
+static void
+unaligned_fetch(fcode_env_t *env)
+{
+ extern void unaligned_xfetch(fcode_env_t *);
+
+ if (sizeof (fstack_t) == sizeof (lforth_t))
+ unaligned_lfetch(env);
+ else
+ unaligned_xfetch(env);
+}
+
+void
+comma(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, ",");
+ DEBUGF(COMMA, dump_comma(env, ","));
+ PUSH(DS, (fstack_t)HERE);
+ unaligned_store(env);
+ set_here(env, HERE + sizeof (fstack_t), "comma");
+}
+
+void
+lcomma(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "l,");
+ DEBUGF(COMMA, dump_comma(env, "l,"));
+ PUSH(DS, (fstack_t)HERE);
+ unaligned_lstore(env);
+ set_here(env, HERE + sizeof (u_lforth_t), "lcomma");
+}
+
+void
+wcomma(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "w,");
+ DEBUGF(COMMA, dump_comma(env, "w,"));
+ PUSH(DS, (fstack_t)HERE);
+ unaligned_wstore(env);
+ set_here(env, HERE + sizeof (u_wforth_t), "wcomma");
+}
+
+void
+ccomma(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "c,");
+ DEBUGF(COMMA, dump_comma(env, "c,"));
+ PUSH(DS, (fstack_t)HERE);
+ cstore(env);
+ set_here(env, HERE + sizeof (uchar_t), "ccomma");
+}
+
+void
+token_roundup(fcode_env_t *env, char *where)
+{
+ if ((((token_t)HERE) & (sizeof (token_t) - 1)) != 0) {
+ set_here(env, (uchar_t *)TOKEN_ROUNDUP(HERE), where);
+ }
+}
+
+void
+compile_comma(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "compile,");
+ DEBUGF(COMMA, dump_comma(env, "compile,"));
+ token_roundup(env, "compile,");
+ PUSH(DS, (fstack_t)HERE);
+ unaligned_store(env);
+ set_here(env, HERE + sizeof (fstack_t), "compile,");
+}
+
+void
+unaligned_lfetch(fcode_env_t *env)
+{
+ fstack_t addr;
+ int i;
+
+ CHECK_DEPTH(env, 1, "unaligned-l@");
+ addr = POP(DS);
+ for (i = 0; i < sizeof (lforth_t); i++, addr++) {
+ PUSH(DS, addr);
+ cfetch(env);
+ }
+ bljoin(env);
+ lbflip(env);
+}
+
+void
+unaligned_lstore(fcode_env_t *env)
+{
+ fstack_t addr;
+ int i;
+
+ CHECK_DEPTH(env, 2, "unaligned-l!");
+ addr = POP(DS);
+ lbsplit(env);
+ for (i = 0; i < sizeof (lforth_t); i++, addr++) {
+ PUSH(DS, addr);
+ cstore(env);
+ }
+}
+
+void
+unaligned_wfetch(fcode_env_t *env)
+{
+ fstack_t addr;
+ int i;
+
+ CHECK_DEPTH(env, 1, "unaligned-w@");
+ addr = POP(DS);
+ for (i = 0; i < sizeof (wforth_t); i++, addr++) {
+ PUSH(DS, addr);
+ cfetch(env);
+ }
+ bwjoin(env);
+ wbflip(env);
+}
+
+void
+unaligned_wstore(fcode_env_t *env)
+{
+ fstack_t addr;
+ int i;
+
+ CHECK_DEPTH(env, 2, "unaligned-w!");
+ addr = POP(DS);
+ wbsplit(env);
+ for (i = 0; i < sizeof (wforth_t); i++, addr++) {
+ PUSH(DS, addr);
+ cstore(env);
+ }
+}
+
+/*
+ * 'lbflips' Fcode implementation.
+ */
+static void
+lbflips(fcode_env_t *env)
+{
+ fstack_t len, addr;
+ int i;
+
+ CHECK_DEPTH(env, 2, "lbflips");
+ len = POP(DS);
+ addr = POP(DS);
+ for (i = 0; i < len; i += sizeof (lforth_t),
+ addr += sizeof (lforth_t)) {
+ PUSH(DS, addr);
+ unaligned_lfetch(env);
+ lbflip(env);
+ PUSH(DS, addr);
+ unaligned_lstore(env);
+ }
+}
+
+/*
+ * 'wbflips' Fcode implementation.
+ */
+static void
+wbflips(fcode_env_t *env)
+{
+ fstack_t len, addr;
+ int i;
+
+ CHECK_DEPTH(env, 2, "wbflips");
+ len = POP(DS);
+ addr = POP(DS);
+ for (i = 0; i < len; i += sizeof (wforth_t),
+ addr += sizeof (wforth_t)) {
+ PUSH(DS, addr);
+ unaligned_wfetch(env);
+ wbflip(env);
+ PUSH(DS, addr);
+ unaligned_wstore(env);
+ }
+}
+
+/*
+ * 'lwflips' Fcode implementation.
+ */
+static void
+lwflips(fcode_env_t *env)
+{
+ fstack_t len, addr;
+ int i;
+
+ CHECK_DEPTH(env, 2, "lwflips");
+ len = POP(DS);
+ addr = POP(DS);
+ for (i = 0; i < len; i += sizeof (lforth_t),
+ addr += sizeof (lforth_t)) {
+ PUSH(DS, addr);
+ unaligned_lfetch(env);
+ lwflip(env);
+ PUSH(DS, addr);
+ unaligned_lstore(env);
+ }
+}
+
+void
+base(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)&env->num_base);
+}
+
+void
+dot_s(fcode_env_t *env)
+{
+ output_data_stack(env, MSG_INFO);
+}
+
+void
+state(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)&env->state);
+}
+
+int
+is_digit(char digit, int num_base, fstack_t *dptr)
+{
+ int error = 0;
+ char base;
+
+ if (num_base < 10) {
+ base = '0' + (num_base-1);
+ } else {
+ base = 'a' + (num_base - 10);
+ }
+
+ *dptr = 0;
+ if (digit > '9') digit |= 0x20;
+ if (((digit < '0') || (digit > base)) ||
+ ((digit > '9') && (digit < 'a') && (num_base > 10)))
+ error = 1;
+ else {
+ if (digit <= '9')
+ digit -= '0';
+ else
+ digit = digit - 'a' + 10;
+ *dptr = digit;
+ }
+ return (error);
+}
+
+void
+dollar_number(fcode_env_t *env)
+{
+ char *buf;
+ fstack_t value;
+ int len, sign = 1, error = 0;
+
+ CHECK_DEPTH(env, 2, "$number");
+ buf = pop_a_string(env, &len);
+ if (*buf == '-') {
+ sign = -1;
+ buf++;
+ len--;
+ }
+ value = 0;
+ while (len-- && !error) {
+ fstack_t digit;
+
+ if (*buf == '.') {
+ buf++;
+ continue;
+ }
+ value *= env->num_base;
+ error = is_digit(*buf++, env->num_base, &digit);
+ value += digit;
+ }
+ if (error) {
+ PUSH(DS, -1);
+ } else {
+ value *= sign;
+ PUSH(DS, value);
+ PUSH(DS, 0);
+ }
+}
+
+void
+digit(fcode_env_t *env)
+{
+ fstack_t base;
+ fstack_t value;
+
+ CHECK_DEPTH(env, 2, "digit");
+ base = POP(DS);
+ if (is_digit(TOS, base, &value))
+ PUSH(DS, 0);
+ else {
+ TOS = value;
+ PUSH(DS, -1);
+ }
+}
+
+void
+space(fcode_env_t *env)
+{
+ PUSH(DS, ' ');
+}
+
+void
+backspace(fcode_env_t *env)
+{
+ PUSH(DS, '\b');
+}
+
+void
+bell(fcode_env_t *env)
+{
+ PUSH(DS, '\a');
+}
+
+void
+fc_bounds(fcode_env_t *env)
+{
+ fstack_t lo, hi;
+
+ CHECK_DEPTH(env, 2, "bounds");
+ lo = DS[-1];
+ hi = TOS;
+ DS[-1] = lo+hi;
+ TOS = lo;
+}
+
+void
+here(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)HERE);
+}
+
+void
+aligned(fcode_env_t *env)
+{
+ ufstack_t a;
+
+ CHECK_DEPTH(env, 1, "aligned");
+ a = (TOS & (sizeof (lforth_t) - 1));
+ if (a)
+ TOS += (sizeof (lforth_t) - a);
+}
+
+void
+instance(fcode_env_t *env)
+{
+ env->instance_mode |= 1;
+}
+
+void
+semi(fcode_env_t *env)
+{
+
+ env->state &= ~1;
+ COMPILE_TOKEN(&semi_ptr);
+
+ /*
+ * check if we need to supress expose action;
+ * If so this is an internal word and has no link field
+ * or it is a temporary compile
+ */
+
+ if (env->state == 0) {
+ expose_acf(env, "<semi>");
+ }
+ if (env->state & 8) {
+ env->state ^= 8;
+ }
+}
+
+void
+do_create(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)WA);
+}
+
+void
+drop(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "drop");
+ (void) POP(DS);
+}
+
+void
+f_dup(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 1, "dup");
+ d = TOS;
+ PUSH(DS, d);
+}
+
+void
+over(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "over");
+ d = DS[-1];
+ PUSH(DS, d);
+}
+
+void
+swap(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "swap");
+ d = DS[-1];
+ DS[-1] = DS[0];
+ DS[0] = d;
+}
+
+
+void
+rot(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 3, "rot");
+ d = DS[-2];
+ DS[-2] = DS[-1];
+ DS[-1] = TOS;
+ TOS = d;
+}
+
+void
+minus_rot(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 3, "-rot");
+ d = TOS;
+ TOS = DS[-1];
+ DS[-1] = DS[-2];
+ DS[-2] = d;
+}
+
+void
+tuck(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "tuck");
+ d = TOS;
+ swap(env);
+ PUSH(DS, d);
+}
+
+void
+nip(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "nip");
+ swap(env);
+ drop(env);
+}
+
+void
+qdup(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 1, "?dup");
+ d = TOS;
+ if (d)
+ PUSH(DS, d);
+}
+
+void
+depth(fcode_env_t *env)
+{
+ fstack_t d;
+
+ d = DS - env->ds0;
+ PUSH(DS, d);
+}
+
+void
+pick(fcode_env_t *env)
+{
+ fstack_t p;
+
+ CHECK_DEPTH(env, 1, "pick");
+ p = POP(DS);
+ if (p < 0 || p >= (env->ds - env->ds0))
+ forth_abort(env, "pick: invalid pick value: %d\n", (int)p);
+ p = DS[-p];
+ PUSH(DS, p);
+}
+
+void
+roll(fcode_env_t *env)
+{
+ fstack_t d, r;
+
+ CHECK_DEPTH(env, 1, "roll");
+ r = POP(DS);
+ if (r <= 0 || r >= (env->ds - env->ds0))
+ forth_abort(env, "roll: invalid roll value: %d\n", (int)r);
+
+ d = DS[-r];
+ while (r) {
+ DS[-r] = DS[ -(r-1) ];
+ r--;
+ }
+ TOS = d;
+}
+
+void
+two_drop(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "2drop");
+ DS -= 2;
+}
+
+void
+two_dup(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "2dup");
+ DS[1] = DS[-1];
+ DS[2] = TOS;
+ DS += 2;
+}
+
+void
+two_over(fcode_env_t *env)
+{
+ fstack_t a, b;
+
+ CHECK_DEPTH(env, 4, "2over");
+ a = DS[-3];
+ b = DS[-2];
+ PUSH(DS, a);
+ PUSH(DS, b);
+}
+
+void
+two_swap(fcode_env_t *env)
+{
+ fstack_t a, b;
+
+ CHECK_DEPTH(env, 4, "2swap");
+ a = DS[-3];
+ b = DS[-2];
+ DS[-3] = DS[-1];
+ DS[-2] = TOS;
+ DS[-1] = a;
+ TOS = b;
+}
+
+void
+two_rot(fcode_env_t *env)
+{
+ fstack_t a, b;
+
+ CHECK_DEPTH(env, 6, "2rot");
+ a = DS[-5];
+ b = DS[-4];
+ DS[-5] = DS[-3];
+ DS[-4] = DS[-2];
+ DS[-3] = DS[-1];
+ DS[-2] = TOS;
+ DS[-1] = a;
+ TOS = b;
+}
+
+void
+two_slash(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "2/");
+ TOS = TOS >> 1;
+}
+
+void
+utwo_slash(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "u2/");
+ TOS = (ufstack_t)((ufstack_t)TOS) >> 1;
+}
+
+void
+two_times(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "2*");
+ TOS = (ufstack_t)((ufstack_t)TOS) << 1;
+}
+
+void
+slash_c(fcode_env_t *env)
+{
+ PUSH(DS, sizeof (char));
+}
+
+void
+slash_w(fcode_env_t *env)
+{
+ PUSH(DS, sizeof (wforth_t));
+}
+
+void
+slash_l(fcode_env_t *env)
+{
+ PUSH(DS, sizeof (lforth_t));
+}
+
+void
+slash_n(fcode_env_t *env)
+{
+ PUSH(DS, sizeof (fstack_t));
+}
+
+void
+ca_plus(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "ca+");
+ d = POP(DS);
+ TOS += d * sizeof (char);
+}
+
+void
+wa_plus(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "wa+");
+ d = POP(DS);
+ TOS += d * sizeof (wforth_t);
+}
+
+void
+la_plus(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "la+");
+ d = POP(DS);
+ TOS += d * sizeof (lforth_t);
+}
+
+void
+na_plus(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "na+");
+ d = POP(DS);
+ TOS += d * sizeof (fstack_t);
+}
+
+void
+char_plus(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "char+");
+ TOS += sizeof (char);
+}
+
+void
+wa1_plus(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "wa1+");
+ TOS += sizeof (wforth_t);
+}
+
+void
+la1_plus(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "la1+");
+ TOS += sizeof (lforth_t);
+}
+
+void
+cell_plus(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "cell+");
+ TOS += sizeof (fstack_t);
+}
+
+void
+do_chars(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "chars");
+}
+
+void
+slash_w_times(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "/w*");
+ TOS *= sizeof (wforth_t);
+}
+
+void
+slash_l_times(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "/l*");
+ TOS *= sizeof (lforth_t);
+}
+
+void
+cells(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "cells");
+ TOS *= sizeof (fstack_t);
+}
+
+void
+do_on(fcode_env_t *env)
+{
+ variable_t *d;
+
+ CHECK_DEPTH(env, 1, "on");
+ d = (variable_t *)POP(DS);
+ *d = -1;
+}
+
+void
+do_off(fcode_env_t *env)
+{
+ variable_t *d;
+
+ CHECK_DEPTH(env, 1, "off");
+ d = (variable_t *)POP(DS);
+ *d = 0;
+}
+
+void
+fetch(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "@");
+ TOS = *((variable_t *)TOS);
+}
+
+void
+lfetch(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "l@");
+ TOS = *((lforth_t *)TOS);
+}
+
+void
+wfetch(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "w@");
+ TOS = *((wforth_t *)TOS);
+}
+
+void
+swfetch(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "<w@");
+ TOS = *((s_wforth_t *)TOS);
+}
+
+void
+cfetch(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "c@");
+ TOS = *((uchar_t *)TOS);
+}
+
+void
+store(fcode_env_t *env)
+{
+ variable_t *dptr;
+
+ CHECK_DEPTH(env, 2, "!");
+ dptr = (variable_t *)POP(DS);
+ *dptr = POP(DS);
+}
+
+void
+addstore(fcode_env_t *env)
+{
+ variable_t *dptr;
+
+ CHECK_DEPTH(env, 2, "+!");
+ dptr = (variable_t *)POP(DS);
+ *dptr = POP(DS) + *dptr;
+}
+
+void
+lstore(fcode_env_t *env)
+{
+ lforth_t *dptr;
+
+ CHECK_DEPTH(env, 2, "l!");
+ dptr = (lforth_t *)POP(DS);
+ *dptr = (lforth_t)POP(DS);
+}
+
+void
+wstore(fcode_env_t *env)
+{
+ wforth_t *dptr;
+
+ CHECK_DEPTH(env, 2, "w!");
+ dptr = (wforth_t *)POP(DS);
+ *dptr = (wforth_t)POP(DS);
+}
+
+void
+cstore(fcode_env_t *env)
+{
+ uchar_t *dptr;
+
+ CHECK_DEPTH(env, 2, "c!");
+ dptr = (uchar_t *)POP(DS);
+ *dptr = (uchar_t)POP(DS);
+}
+
+void
+two_fetch(fcode_env_t *env)
+{
+ variable_t *d;
+
+ CHECK_DEPTH(env, 1, "2@");
+ d = (variable_t *)POP(DS);
+ PUSH(DS, (fstack_t)(d + 1));
+ unaligned_fetch(env);
+ PUSH(DS, (fstack_t)d);
+ unaligned_fetch(env);
+}
+
+void
+two_store(fcode_env_t *env)
+{
+ variable_t *d;
+
+ CHECK_DEPTH(env, 3, "2!");
+ d = (variable_t *)POP(DS);
+ PUSH(DS, (fstack_t)d);
+ unaligned_store(env);
+ PUSH(DS, (fstack_t)(d + 1));
+ unaligned_store(env);
+}
+
+/*
+ * 'move' Fcode reimplemented in fcdriver to check for mapped addresses.
+ */
+void
+fc_move(fcode_env_t *env)
+{
+ void *dest, *src;
+ size_t len;
+
+ CHECK_DEPTH(env, 3, "move");
+ len = (size_t)POP(DS);
+ dest = (void *)POP(DS);
+ src = (void *)POP(DS);
+
+ memmove(dest, src, len);
+}
+
+void
+fc_fill(fcode_env_t *env)
+{
+ void *dest;
+ uchar_t val;
+ size_t len;
+
+ CHECK_DEPTH(env, 3, "fill");
+ val = (uchar_t)POP(DS);
+ len = (size_t)POP(DS);
+ dest = (void *)POP(DS);
+ memset(dest, val, len);
+}
+
+void
+fc_comp(fcode_env_t *env)
+{
+ char *str1, *str2;
+ size_t len;
+ int res;
+
+ CHECK_DEPTH(env, 3, "comp");
+ len = (size_t)POP(DS);
+ str1 = (char *)POP(DS);
+ str2 = (char *)POP(DS);
+ res = memcmp(str2, str1, len);
+ if (res > 0)
+ res = 1;
+ else if (res < 0)
+ res = -1;
+ PUSH(DS, res);
+}
+
+void
+set_temporary_compile(fcode_env_t *env)
+{
+ if (!env->state) {
+ token_roundup(env, "set_temporary_compile");
+ PUSH(RS, (fstack_t)HERE);
+ env->state = 3;
+ COMPILE_TOKEN(&do_colon);
+ }
+}
+
+void
+bmark(fcode_env_t *env)
+{
+ set_temporary_compile(env);
+ env->level++;
+ PUSH(DS, (fstack_t)HERE);
+}
+
+void
+temporary_execute(fcode_env_t *env)
+{
+ uchar_t *saved_here;
+
+ if ((env->level == 0) && (env->state & 2)) {
+ fstack_t d = POP(RS);
+
+ semi(env);
+
+ saved_here = HERE;
+ /* execute the temporary definition */
+ env->state &= ~2;
+ PUSH(DS, d);
+ execute(env);
+
+ /* now wind the dictionary back! */
+ if (saved_here != HERE) {
+ debug_msg(DEBUG_COMMA, "Ignoring set_here in"
+ " temporary_execute\n");
+ } else
+ set_here(env, (uchar_t *)d, "temporary_execute");
+ }
+}
+
+void
+bresolve(fcode_env_t *env)
+{
+ token_t *prev = (token_t *)POP(DS);
+
+ env->level--;
+ *prev = (token_t)HERE;
+ temporary_execute(env);
+}
+
+#define BRANCH_IP(ipp) ((token_t *)(*((token_t *)(ipp))))
+
+void
+do_bbranch(fcode_env_t *env)
+{
+ IP = BRANCH_IP(IP);
+}
+
+void
+do_bqbranch(fcode_env_t *env)
+{
+ fstack_t flag;
+
+ CHECK_DEPTH(env, 1, "b?branch");
+ flag = POP(DS);
+ if (flag) {
+ IP++;
+ } else {
+ IP = BRANCH_IP(IP);
+ }
+}
+
+void
+do_bofbranch(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "bofbranch");
+ d = POP(DS);
+ if (d == TOS) {
+ (void) POP(DS);
+ IP++;
+ } else {
+ IP = BRANCH_IP(IP);
+ }
+}
+
+void
+do_bleave(fcode_env_t *env)
+{
+ CHECK_RETURN_DEPTH(env, 3, "do_bleave");
+ (void) POP(RS);
+ (void) POP(RS);
+ IP = (token_t *)POP(RS);
+}
+
+void
+loop_inc(fcode_env_t *env, fstack_t inc)
+{
+ ufstack_t a;
+
+ CHECK_RETURN_DEPTH(env, 2, "loop_inc");
+
+ /*
+ * Note: end condition is when the sign bit of R[0] changes.
+ */
+ a = RS[0];
+ RS[0] += inc;
+ if (((a ^ RS[0]) & SIGN_BIT) == 0) {
+ IP = BRANCH_IP(IP);
+ } else {
+ do_bleave(env);
+ }
+}
+
+void
+do_bloop(fcode_env_t *env)
+{
+ loop_inc(env, 1);
+}
+
+void
+do_bploop(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 1, "+loop");
+ d = POP(DS);
+ loop_inc(env, d);
+}
+
+void
+loop_common(fcode_env_t *env, fstack_t ptr)
+{
+ short offset = get_short(env);
+
+ COMPILE_TOKEN(ptr);
+ env->level--;
+ compile_comma(env);
+ bresolve(env);
+}
+
+void
+bloop(fcode_env_t *env)
+{
+ loop_common(env, (fstack_t)&do_loop_ptr);
+}
+
+void
+bplusloop(fcode_env_t *env)
+{
+ loop_common(env, (fstack_t)&do_ploop_ptr);
+}
+
+void
+common_do(fcode_env_t *env, fstack_t endpt, fstack_t start, fstack_t limit)
+{
+ ufstack_t i, l;
+
+ /*
+ * Same computation as OBP, sets up so that loop_inc will terminate
+ * when the sign bit of RS[0] changes.
+ */
+ i = (start - limit) - SIGN_BIT;
+ l = limit + SIGN_BIT;
+ PUSH(RS, endpt);
+ PUSH(RS, l);
+ PUSH(RS, i);
+}
+
+void
+do_bdo(fcode_env_t *env)
+{
+ fstack_t lo, hi;
+ fstack_t endpt;
+
+ CHECK_DEPTH(env, 2, "bdo");
+ endpt = (fstack_t)BRANCH_IP(IP);
+ IP++;
+ lo = POP(DS);
+ hi = POP(DS);
+ common_do(env, endpt, lo, hi);
+}
+
+void
+do_bqdo(fcode_env_t *env)
+{
+ fstack_t lo, hi;
+ fstack_t endpt;
+
+ CHECK_DEPTH(env, 2, "b?do");
+ endpt = (fstack_t)BRANCH_IP(IP);
+ IP++;
+ lo = POP(DS);
+ hi = POP(DS);
+ if (lo == hi) {
+ IP = (token_t *)endpt;
+ } else {
+ common_do(env, endpt, lo, hi);
+ }
+}
+
+void
+compile_do_common(fcode_env_t *env, fstack_t ptr)
+{
+ set_temporary_compile(env);
+ COMPILE_TOKEN(ptr);
+ bmark(env);
+ COMPILE_TOKEN(0);
+ bmark(env);
+}
+
+void
+bdo(fcode_env_t *env)
+{
+ short offset = (short)get_short(env);
+ compile_do_common(env, (fstack_t)&do_bdo_ptr);
+}
+
+void
+bqdo(fcode_env_t *env)
+{
+ short offset = (short)get_short(env);
+ compile_do_common(env, (fstack_t)&do_bqdo_ptr);
+}
+
+void
+loop_i(fcode_env_t *env)
+{
+ fstack_t i;
+
+ CHECK_RETURN_DEPTH(env, 2, "i");
+ i = RS[0] + RS[-1];
+ PUSH(DS, i);
+}
+
+void
+loop_j(fcode_env_t *env)
+{
+ fstack_t j;
+
+ CHECK_RETURN_DEPTH(env, 5, "j");
+ j = RS[-3] + RS[-4];
+ PUSH(DS, j);
+}
+
+void
+bleave(fcode_env_t *env)
+{
+
+ if (env->state) {
+ COMPILE_TOKEN(&do_leave_ptr);
+ }
+}
+
+void
+push_string(fcode_env_t *env, char *str, int len)
+{
+#define NSTRINGS 16
+ static int string_count = 0;
+ static int buflen[NSTRINGS];
+ static char *buffer[NSTRINGS];
+ char *dest;
+
+ if (!len) {
+ PUSH(DS, 0);
+ PUSH(DS, 0);
+ return;
+ }
+ if (len != buflen[string_count]) {
+ if (buffer[string_count]) FREE(buffer[string_count]);
+ buffer[ string_count ] = (char *)MALLOC(len+1);
+ buflen[ string_count ] = len;
+ }
+ dest = buffer[ string_count++ ];
+ string_count = string_count%NSTRINGS;
+ memcpy(dest, str, len);
+ *(dest+len) = 0;
+ PUSH(DS, (fstack_t)dest);
+ PUSH(DS, len);
+#undef NSTRINGS
+}
+
+void
+parse_word(fcode_env_t *env)
+{
+ int len = 0;
+ char *next, *dest, *here = "";
+
+ if (env->input) {
+ here = env->input->scanptr;
+ while (*here == env->input->separator) here++;
+ next = strchr(here, env->input->separator);
+ if (next) {
+ len = next - here;
+ while (*next == env->input->separator) next++;
+ } else {
+ len = strlen(here);
+ next = here + len;
+ }
+ env->input->scanptr = next;
+ }
+ push_string(env, here, len);
+}
+
+void
+install_does(fcode_env_t *env)
+{
+ token_t *dptr;
+
+ dptr = (token_t *)LINK_TO_ACF(env->lastlink);
+
+ log_message(MSG_WARN, "install_does: Last acf at: %p\n", (void *)dptr);
+
+ *dptr = ((token_t)(IP+1)) | 1;
+}
+
+void
+does(fcode_env_t *env)
+{
+ token_t *dptr;
+
+ token_roundup(env, "does");
+
+ if (env->state) {
+ COMPILE_TOKEN(&does_ptr);
+ COMPILE_TOKEN(&semi_ptr);
+ } else {
+ dptr = (token_t *)LINK_TO_ACF(env->lastlink);
+ log_message(MSG_WARN, "does: Last acf at: %p\n", (void *)dptr);
+ *dptr = ((token_t)(HERE)) | 1;
+ env->state |= 1;
+ }
+ COMPILE_TOKEN(&do_colon);
+}
+
+void
+do_current(fcode_env_t *env)
+{
+ debug_msg(DEBUG_CONTEXT, "CONTEXT:pushing &CURRENT\n");
+ PUSH(DS, (fstack_t)&env->current);
+}
+
+void
+do_context(fcode_env_t *env)
+{
+ debug_msg(DEBUG_CONTEXT, "CONTEXT:pushing &CONTEXT\n");
+ PUSH(DS, (fstack_t)&CONTEXT);
+}
+
+void
+do_definitions(fcode_env_t *env)
+{
+ env->current = CONTEXT;
+ debug_msg(DEBUG_CONTEXT, "CONTEXT:definitions: %d/%p/%p\n",
+ env->order_depth, CONTEXT, env->current);
+}
+
+void
+make_header(fcode_env_t *env, int flags)
+{
+ int len;
+ char *name;
+
+ name = parse_a_string(env, &len);
+ header(env, name, len, flags);
+}
+
+void
+do_creator(fcode_env_t *env)
+{
+ make_header(env, 0);
+ COMPILE_TOKEN(&do_create);
+ expose_acf(env, "<create>");
+}
+
+void
+create(fcode_env_t *env)
+{
+ if (env->state) {
+ COMPILE_TOKEN(&create_ptr);
+ } else
+ do_creator(env);
+}
+
+void
+colon(fcode_env_t *env)
+{
+ make_header(env, 0);
+ env->state |= 1;
+ COMPILE_TOKEN(&do_colon);
+}
+
+void
+recursive(fcode_env_t *env)
+{
+ expose_acf(env, "<recursive>");
+}
+
+void
+compile_string(fcode_env_t *env)
+{
+ int len;
+ uchar_t *str, *tostr;
+
+ COMPILE_TOKEN(&quote_ptr);
+ len = POP(DS);
+ str = (uchar_t *)POP(DS);
+ tostr = HERE;
+ *tostr++ = len;
+ while (len--)
+ *tostr++ = *str++;
+ *tostr++ = '\0';
+ set_here(env, tostr, "compile_string");
+ token_roundup(env, "compile_string");
+}
+
+void
+run_quote(fcode_env_t *env)
+{
+ char osep;
+
+ osep = env->input->separator;
+ env->input->separator = '"';
+ parse_word(env);
+ env->input->separator = osep;
+
+ if (env->state) {
+ compile_string(env);
+ }
+}
+
+void
+does_vocabulary(fcode_env_t *env)
+{
+ CONTEXT = WA;
+ debug_msg(DEBUG_CONTEXT, "CONTEXT:vocabulary: %d/%p/%p\n",
+ env->order_depth, CONTEXT, env->current);
+}
+
+void
+do_vocab(fcode_env_t *env)
+{
+ make_header(env, 0);
+ COMPILE_TOKEN(does_vocabulary);
+ PUSH(DS, 0);
+ compile_comma(env);
+ expose_acf(env, "<vocabulary>");
+}
+
+void
+do_forth(fcode_env_t *env)
+{
+ CONTEXT = (token_t *)(&env->forth_voc_link);
+ debug_msg(DEBUG_CONTEXT, "CONTEXT:forth: %d/%p/%p\n",
+ env->order_depth, CONTEXT, env->current);
+}
+
+acf_t
+voc_find(fcode_env_t *env)
+{
+ token_t *voc;
+ token_t *dptr;
+ char *find_name, *name;
+
+ voc = (token_t *)POP(DS);
+ find_name = pop_a_string(env, NULL);
+
+ for (dptr = (token_t *)(*voc); dptr; dptr = (token_t *)(*dptr)) {
+ if ((name = get_name(dptr)) == NULL)
+ continue;
+ if (strcmp(find_name, name) == 0) {
+ debug_msg(DEBUG_VOC_FIND, "%s -> %p\n", find_name,
+ LINK_TO_ACF(dptr));
+ return (LINK_TO_ACF(dptr));
+ }
+ }
+ debug_msg(DEBUG_VOC_FIND, "%s not found\n", find_name);
+ return (NULL);
+}
+
+void
+dollar_find(fcode_env_t *env)
+{
+ acf_t acf = NULL;
+ int i;
+
+ CHECK_DEPTH(env, 2, "$find");
+ for (i = env->order_depth; i >= 0 && env->order[i] && !acf; i--) {
+ two_dup(env);
+ PUSH(DS, (fstack_t)env->order[i]);
+ acf = voc_find(env);
+ }
+ if (acf) {
+ two_drop(env);
+ PUSH(DS, (fstack_t)acf);
+ PUSH(DS, TRUE);
+ } else
+ PUSH(DS, FALSE);
+}
+
+void
+interpret(fcode_env_t *env)
+{
+ char *name;
+
+ parse_word(env);
+ while (TOS) {
+ two_dup(env);
+ dollar_find(env);
+ if (TOS) {
+ flag_t *flags;
+
+ drop(env);
+ nip(env);
+ nip(env);
+ flags = LINK_TO_FLAGS(ACF_TO_LINK(TOS));
+
+ if ((env->state) &&
+ ((*flags & IMMEDIATE) == 0)) {
+ /* Compile in references */
+ compile_comma(env);
+ } else {
+ execute(env);
+ }
+ } else {
+ int bad;
+ drop(env);
+ dollar_number(env);
+ bad = POP(DS);
+ if (bad) {
+ two_dup(env);
+ name = pop_a_string(env, NULL);
+ log_message(MSG_INFO, "%s?\n", name);
+ break;
+ } else {
+ nip(env);
+ nip(env);
+ literal(env);
+ }
+ }
+ parse_word(env);
+ }
+ two_drop(env);
+}
+
+void
+evaluate(fcode_env_t *env)
+{
+ input_typ *old_input = env->input;
+ input_typ *eval_bufp = MALLOC(sizeof (input_typ));
+
+ CHECK_DEPTH(env, 2, "evaluate");
+ eval_bufp->separator = ' ';
+ eval_bufp->maxlen = POP(DS);
+ eval_bufp->buffer = (char *)POP(DS);
+ eval_bufp->scanptr = eval_bufp->buffer;
+ env->input = eval_bufp;
+ interpret(env);
+ FREE(eval_bufp);
+ env->input = old_input;
+}
+
+void
+make_common_access(fcode_env_t *env,
+ char *name, int len,
+ int ncells,
+ int instance_mode,
+ void (*acf_instance)(fcode_env_t *env),
+ void (*acf_static)(fcode_env_t *env),
+ void (*set_action)(fcode_env_t *env, int))
+{
+ if (instance_mode && !MYSELF) {
+ system_message(env, "No instance context");
+ }
+
+ debug_msg(DEBUG_ACTIONS, "make_common_access:%s '%s', %d\n",
+ (instance_mode ? "instance" : ""),
+ (name ? name : ""), ncells);
+
+ if (len)
+ header(env, name, len, 0);
+ if (instance_mode) {
+ token_t *dptr;
+ int offset;
+
+ COMPILE_TOKEN(acf_instance);
+ dptr = alloc_instance_data(env, INIT_DATA, ncells, &offset);
+ debug_msg(DEBUG_ACTIONS, "Data: %p, offset %d\n", (char *)dptr,
+ offset);
+ PUSH(DS, offset);
+ compile_comma(env);
+ while (ncells--)
+ *dptr++ = MYSELF->data[INIT_DATA][offset++] = POP(DS);
+ env->instance_mode = 0;
+ } else {
+ COMPILE_TOKEN(acf_static);
+ while (ncells--)
+ compile_comma(env);
+ }
+ expose_acf(env, name);
+ if (set_action)
+ set_action(env, instance_mode);
+}
+
+void
+do_constant(fcode_env_t *env)
+{
+ PUSH(DS, (variable_t)(*WA));
+}
+
+void
+do_crash(fcode_env_t *env)
+{
+ forth_abort(env, "Unitialized defer");
+}
+
+/*
+ * 'behavior' Fcode retrieve execution behavior for a defer word.
+ */
+static void
+behavior(fcode_env_t *env)
+{
+ acf_t defer_xt;
+ token_t token;
+ acf_t contents_xt;
+
+ CHECK_DEPTH(env, 1, "behavior");
+ defer_xt = (acf_t)POP(DS);
+ token = *defer_xt;
+ contents_xt = (token_t *)(token & ~1);
+ if ((token & 1) == 0 || *contents_xt != (token_t)&do_default_action)
+ forth_abort(env, "behavior: bad xt: %p indir: %x/%p\n",
+ defer_xt, token & 1, *contents_xt);
+ defer_xt++;
+ PUSH(DS, *((variable_t *)defer_xt));
+}
+
+void
+fc_abort(fcode_env_t *env, char *type)
+{
+ forth_abort(env, "%s Fcode '%s' Executed", type,
+ acf_to_name(env, WA - 1));
+}
+
+void
+f_abort(fcode_env_t *env)
+{
+ fc_abort(env, "Abort");
+}
+
+/*
+ * Fcodes chosen not to support.
+ */
+void
+fc_unimplemented(fcode_env_t *env)
+{
+ fc_abort(env, "Unimplemented");
+}
+
+/*
+ * Fcodes that are Obsolete per P1275-1994.
+ */
+void
+fc_obsolete(fcode_env_t *env)
+{
+ fc_abort(env, "Obsolete");
+}
+
+/*
+ * Fcodes that are Historical per P1275-1994
+ */
+void
+fc_historical(fcode_env_t *env)
+{
+ fc_abort(env, "Historical");
+}
+
+void
+catch(fcode_env_t *env)
+{
+ error_frame *new;
+
+ CHECK_DEPTH(env, 1, "catch");
+ new = MALLOC(sizeof (error_frame));
+ new->ds = DS-1;
+ new->rs = RS;
+ new->myself = MYSELF;
+ new->next = env->catch_frame;
+ new->code = 0;
+ env->catch_frame = new;
+ execute(env);
+ PUSH(DS, new->code);
+ env->catch_frame = new->next;
+ FREE(new);
+}
+
+void
+throw_from_fclib(fcode_env_t *env, fstack_t errcode, char *fmt, ...)
+{
+ error_frame *efp;
+ va_list ap;
+ char msg[256];
+
+ va_start(ap, fmt);
+ vsprintf(msg, fmt, ap);
+
+ if (errcode) {
+
+ env->last_error = errcode;
+
+ /*
+ * No catch frame set => fatal error
+ */
+ efp = env->catch_frame;
+ if (!efp)
+ forth_abort(env, "%s: No catch frame", msg);
+
+ debug_msg(DEBUG_TRACING, "throw_from_fclib: throw: %s\n", msg);
+
+ /*
+ * Setting IP=0 will force the unwinding of the calls
+ * (see execute) which is how we will return (eventually)
+ * to the test in catch that follows 'execute'.
+ */
+ DS = efp->ds;
+ RS = efp->rs;
+ MYSELF = efp->myself;
+ IP = 0;
+ efp->code = errcode;
+ }
+}
+
+void
+throw(fcode_env_t *env)
+{
+ fstack_t t;
+
+ CHECK_DEPTH(env, 1, "throw");
+ t = POP(DS);
+ if (t >= -20 && t <= 20)
+ throw_from_fclib(env, t, "throw Fcode errcode: 0x%x", (int)t);
+ else {
+ if (t)
+ log_message(MSG_ERROR, "throw: errcode: 0x%x\n",
+ (int)t);
+ throw_from_fclib(env, t, "throw Fcode err: %s", (char *)t);
+ }
+}
+
+void
+tick_literal(fcode_env_t *env)
+{
+ if (env->state) {
+ COMPILE_TOKEN(&tlit_ptr);
+ compile_comma(env);
+ }
+}
+
+void
+do_tick(fcode_env_t *env)
+{
+ parse_word(env);
+ dollar_find(env);
+ invert(env);
+ throw(env);
+ tick_literal(env);
+}
+
+void
+bracket_tick(fcode_env_t *env)
+{
+ do_tick(env);
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ NOTICE;
+ ASSERT(env);
+
+ ANSI(0x019, 0, "i", loop_i);
+ ANSI(0x01a, 0, "j", loop_j);
+ ANSI(0x01d, 0, "execute", execute);
+ ANSI(0x01e, 0, "+", add);
+ ANSI(0x01f, 0, "-", subtract);
+ ANSI(0x020, 0, "*", multiply);
+ ANSI(0x021, 0, "/", divide);
+ ANSI(0x022, 0, "mod", mod);
+ FORTH(0, "/mod", slash_mod);
+ ANSI(0x023, 0, "and", and);
+ ANSI(0x024, 0, "or", or);
+ ANSI(0x025, 0, "xor", xor);
+ ANSI(0x026, 0, "invert", invert);
+ ANSI(0x027, 0, "lshift", lshift);
+ ANSI(0x028, 0, "rshift", rshift);
+ ANSI(0x029, 0, ">>a", rshifta);
+ ANSI(0x02a, 0, "/mod", slash_mod);
+ ANSI(0x02b, 0, "u/mod", uslash_mod);
+ ANSI(0x02c, 0, "negate", negate);
+ ANSI(0x02d, 0, "abs", f_abs);
+ ANSI(0x02e, 0, "min", f_min);
+ ANSI(0x02f, 0, "max", f_max);
+ ANSI(0x030, 0, ">r", to_r);
+ ANSI(0x031, 0, "r>", from_r);
+ ANSI(0x032, 0, "r@", rfetch);
+ ANSI(0x033, 0, "exit", f_exit);
+ ANSI(0x034, 0, "0=", zero_equals);
+ ANSI(0x035, 0, "0<>", zero_not_equals);
+ ANSI(0x036, 0, "0<", zero_less);
+ ANSI(0x037, 0, "0<=", zero_less_equals);
+ ANSI(0x038, 0, "0>", zero_greater);
+ ANSI(0x039, 0, "0>=", zero_greater_equals);
+ ANSI(0x03a, 0, "<", less);
+ ANSI(0x03b, 0, ">", greater);
+ ANSI(0x03c, 0, "=", equals);
+ ANSI(0x03d, 0, "<>", not_equals);
+ ANSI(0x03e, 0, "u>", unsign_greater);
+ ANSI(0x03f, 0, "u<=", unsign_less_equals);
+ ANSI(0x040, 0, "u<", unsign_less);
+ ANSI(0x041, 0, "u>=", unsign_greater_equals);
+ ANSI(0x042, 0, ">=", greater_equals);
+ ANSI(0x043, 0, "<=", less_equals);
+ ANSI(0x044, 0, "between", between);
+ ANSI(0x045, 0, "within", within);
+ ANSI(0x046, 0, "drop", drop);
+ ANSI(0x047, 0, "dup", f_dup);
+ ANSI(0x048, 0, "over", over);
+ ANSI(0x049, 0, "swap", swap);
+ ANSI(0x04a, 0, "rot", rot);
+ ANSI(0x04b, 0, "-rot", minus_rot);
+ ANSI(0x04c, 0, "tuck", tuck);
+ ANSI(0x04d, 0, "nip", nip);
+ ANSI(0x04e, 0, "pick", pick);
+ ANSI(0x04f, 0, "roll", roll);
+ ANSI(0x050, 0, "?dup", qdup);
+ ANSI(0x051, 0, "depth", depth);
+ ANSI(0x052, 0, "2drop", two_drop);
+ ANSI(0x053, 0, "2dup", two_dup);
+ ANSI(0x054, 0, "2over", two_over);
+ ANSI(0x055, 0, "2swap", two_swap);
+ ANSI(0x056, 0, "2rot", two_rot);
+ ANSI(0x057, 0, "2/", two_slash);
+ ANSI(0x058, 0, "u2/", utwo_slash);
+ ANSI(0x059, 0, "2*", two_times);
+ ANSI(0x05a, 0, "/c", slash_c);
+ ANSI(0x05b, 0, "/w", slash_w);
+ ANSI(0x05c, 0, "/l", slash_l);
+ ANSI(0x05d, 0, "/n", slash_n);
+ ANSI(0x05e, 0, "ca+", ca_plus);
+ ANSI(0x05f, 0, "wa+", wa_plus);
+ ANSI(0x060, 0, "la+", la_plus);
+ ANSI(0x061, 0, "na+", na_plus);
+ ANSI(0x062, 0, "char+", char_plus);
+ ANSI(0x063, 0, "wa1+", wa1_plus);
+ ANSI(0x064, 0, "la1+", la1_plus);
+ ANSI(0x065, 0, "cell+", cell_plus);
+ ANSI(0x066, 0, "chars", do_chars);
+ ANSI(0x067, 0, "/w*", slash_w_times);
+ ANSI(0x068, 0, "/l*", slash_l_times);
+ ANSI(0x069, 0, "cells", cells);
+ ANSI(0x06a, 0, "on", do_on);
+ ANSI(0x06b, 0, "off", do_off);
+ ANSI(0x06c, 0, "+!", addstore);
+ ANSI(0x06d, 0, "@", fetch);
+ ANSI(0x06e, 0, "l@", lfetch);
+ ANSI(0x06f, 0, "w@", wfetch);
+ ANSI(0x070, 0, "<w@", swfetch);
+ ANSI(0x071, 0, "c@", cfetch);
+ ANSI(0x072, 0, "!", store);
+ ANSI(0x073, 0, "l!", lstore);
+ ANSI(0x074, 0, "w!", wstore);
+ ANSI(0x075, 0, "c!", cstore);
+ ANSI(0x076, 0, "2@", two_fetch);
+ ANSI(0x077, 0, "2!", two_store);
+ ANSI(0x078, 0, "move", fc_move);
+ ANSI(0x079, 0, "fill", fc_fill);
+ ANSI(0x07a, 0, "comp", fc_comp);
+ ANSI(0x07b, 0, "noop", noop);
+ ANSI(0x07c, 0, "lwsplit", lwsplit);
+ ANSI(0x07d, 0, "wljoin", wljoin);
+ ANSI(0x07e, 0, "lbsplit", lbsplit);
+ ANSI(0x07f, 0, "bljoin", bljoin);
+ ANSI(0x080, 0, "wbflip", wbflip);
+ ANSI(0x081, 0, "upc", upper_case);
+ ANSI(0x082, 0, "lcc", lower_case);
+ ANSI(0x083, 0, "pack", pack_str);
+ ANSI(0x084, 0, "count", count_str);
+ ANSI(0x085, 0, "body>", to_acf);
+ ANSI(0x086, 0, ">body", to_body);
+
+ ANSI(0x089, 0, "unloop", unloop);
+
+ ANSI(0x09f, 0, ".s", dot_s);
+ ANSI(0x0a0, 0, "base", base);
+ FCODE(0x0a1, 0, "convert", fc_historical);
+ ANSI(0x0a2, 0, "$number", dollar_number);
+ ANSI(0x0a3, 0, "digit", digit);
+
+ ANSI(0x0a9, 0, "bl", space);
+ ANSI(0x0aa, 0, "bs", backspace);
+ ANSI(0x0ab, 0, "bell", bell);
+ ANSI(0x0ac, 0, "bounds", fc_bounds);
+ ANSI(0x0ad, 0, "here", here);
+
+ ANSI(0x0af, 0, "wbsplit", wbsplit);
+ ANSI(0x0b0, 0, "bwjoin", bwjoin);
+
+ P1275(0x0cb, 0, "$find", dollar_find);
+
+ ANSI(0x0d0, 0, "c,", ccomma);
+ ANSI(0x0d1, 0, "w,", wcomma);
+ ANSI(0x0d2, 0, "l,", lcomma);
+ ANSI(0x0d3, 0, ",", comma);
+ ANSI(0x0d4, 0, "um*", um_multiply);
+ ANSI(0x0d5, 0, "um/mod", um_slash_mod);
+
+ ANSI(0x0d8, 0, "d+", d_plus);
+ ANSI(0x0d9, 0, "d-", d_minus);
+
+ ANSI(0x0dc, 0, "state", state);
+ ANSI(0x0de, 0, "behavior", behavior);
+ ANSI(0x0dd, 0, "compile,", compile_comma);
+
+ ANSI(0x216, 0, "abort", f_abort);
+ ANSI(0x217, 0, "catch", catch);
+ ANSI(0x218, 0, "throw", throw);
+
+ ANSI(0x226, 0, "lwflip", lwflip);
+ ANSI(0x227, 0, "lbflip", lbflip);
+ ANSI(0x228, 0, "lbflips", lbflips);
+
+ ANSI(0x236, 0, "wbflips", wbflips);
+ ANSI(0x237, 0, "lwflips", lwflips);
+
+ FORTH(0, "forth", do_forth);
+ FORTH(0, "current", do_current);
+ FORTH(0, "context", do_context);
+ FORTH(0, "definitions", do_definitions);
+ FORTH(0, "vocabulary", do_vocab);
+ FORTH(IMMEDIATE, ":", colon);
+ FORTH(IMMEDIATE, ";", semi);
+ FORTH(IMMEDIATE, "create", create);
+ FORTH(IMMEDIATE, "does>", does);
+ FORTH(IMMEDIATE, "recursive", recursive);
+ FORTH(0, "parse-word", parse_word);
+ FORTH(IMMEDIATE, "\"", run_quote);
+ FORTH(IMMEDIATE, "order", do_order);
+ FORTH(IMMEDIATE, "also", do_also);
+ FORTH(IMMEDIATE, "previous", do_previous);
+ FORTH(IMMEDIATE, "'", do_tick);
+ FORTH(IMMEDIATE, "[']", bracket_tick);
+ FORTH(0, "unaligned-l@", unaligned_lfetch);
+ FORTH(0, "unaligned-l!", unaligned_lstore);
+ FORTH(0, "unaligned-w@", unaligned_wfetch);
+ FORTH(0, "unaligned-w!", unaligned_wstore);
+}
diff --git a/usr/src/lib/efcode/engine/framebuffer.c b/usr/src/lib/efcode/engine/framebuffer.c
new file mode 100644
index 0000000000..aaf3a44f53
--- /dev/null
+++ b/usr/src/lib/efcode/engine/framebuffer.c
@@ -0,0 +1,71 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <fcode/private.h>
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ FCODE(0x11c, 0, "is-install", fc_unimplemented);
+ FCODE(0x11d, 0, "is-remove", fc_unimplemented);
+ FCODE(0x11e, 0, "is-selftest", fc_unimplemented);
+
+ FCODE(0x121, 0, "display-status", fc_unimplemented);
+
+ FCODE(0x150, 0, "#lines", fc_unimplemented);
+ FCODE(0x151, 0, "#columns", fc_unimplemented);
+ FCODE(0x152, 0, "line#", fc_unimplemented);
+ FCODE(0x153, 0, "column#", fc_unimplemented);
+ FCODE(0x154, 0, "inverse?", fc_unimplemented);
+ FCODE(0x155, 0, "inverse-screen?", fc_unimplemented);
+ FCODE(0x156, 0, "frame-buffer-busy?", fc_historical);
+ FCODE(0x157, 0, "draw-character", fc_unimplemented);
+ FCODE(0x158, 0, "reset-screen", fc_unimplemented);
+ FCODE(0x159, 0, "toggle-cursor", fc_unimplemented);
+ FCODE(0x15a, 0, "erase-screen", fc_unimplemented);
+ FCODE(0x15b, 0, "blink-screen", fc_unimplemented);
+ FCODE(0x15c, 0, "invert-screen", fc_unimplemented);
+ FCODE(0x15d, 0, "insert-characters", fc_unimplemented);
+ FCODE(0x15e, 0, "delete-characters", fc_unimplemented);
+ FCODE(0x15f, 0, "insert-lines", fc_unimplemented);
+ FCODE(0x160, 0, "delete-lines", fc_unimplemented);
+ FCODE(0x161, 0, "draw-logo", fc_unimplemented);
+ FCODE(0x162, 0, "frame-buffer-adr", fc_unimplemented);
+ FCODE(0x163, 0, "screen-height", fc_unimplemented);
+ FCODE(0x164, 0, "screen-width", fc_unimplemented);
+ FCODE(0x165, 0, "window-top", fc_unimplemented);
+ FCODE(0x166, 0, "window-left", fc_unimplemented);
+}
diff --git a/usr/src/lib/efcode/engine/init.c b/usr/src/lib/efcode/engine/init.c
new file mode 100644
index 0000000000..128476cf4e
--- /dev/null
+++ b/usr/src/lib/efcode/engine/init.c
@@ -0,0 +1,139 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+fcode_env_t *initial_env = 0;
+int dict_size = 0x100000; /* 1Mb, hopefully big enough... */
+int stack_size = 0x200;
+
+void *
+safe_malloc(size_t n, char *f, int l)
+{
+ void *p;
+
+ p = malloc((size_t) n);
+#if defined(__sparcv9)
+ /*
+ * For Ultrasparc, we must force addresses to be less than 4Gb,
+ * since Fcode assumes that addresses can be stored in 32 bits.
+ * To get around this would require turning all addresses into
+ * cookies, which is a lot of work.
+ */
+ if (((uint64_t)p) >= 0x100000000) {
+ log_message(MSG_WARN, "Malloc returned address > 4Gb\n");
+ }
+#endif /* __sparcv9 */
+ if (p) {
+ memset(p, 0, (size_t) n);
+ } else
+ log_message(MSG_ERROR, "%s:%d:Malloc(%llx) failed\n", f, l,
+ (uint64_t)n);
+ return (p);
+}
+
+void *
+safe_realloc(void *p, size_t n, char *f, int l)
+{
+ void *newp;
+
+ if ((newp = safe_malloc(n, f, l)) == NULL) {
+ log_message(MSG_ERROR, "%s:%d:realloc(%p, %x) failed\n", f, l,
+ p, n);
+ safe_free(p, f, l);
+ return (NULL);
+ }
+ if (p) {
+ memcpy(newp, p, n);
+ safe_free(p, f, l);
+ }
+ return (newp);
+}
+
+void
+safe_free(void *p, char *f, int l)
+{
+ if (p) {
+ free(p);
+ }
+}
+
+char *
+safe_strdup(char *s, char *f, int l)
+{
+ char *p = strdup(s);
+
+ return (p);
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ int i;
+ acf_t f_error_addr;
+ fcode_env_t *env;
+
+ NOTICE;
+
+ fcode_impl_count = 0;
+ env = MALLOC(sizeof (fcode_env_t));
+ env->table = MALLOC((MAX_FCODE + 1) * sizeof (fcode_token));
+ env->base = MALLOC(dict_size);
+ env->here = env->base;
+ env->ds = env->ds0 = MALLOC(stack_size * sizeof (fstack_t));
+ env->rs = env->rs0 = MALLOC(stack_size * sizeof (fstack_t));
+ env->order = MALLOC(MAX_ORDER * sizeof (token_t));
+ env->input = MALLOC(sizeof (input_typ));
+ env->num_base = 0x10;
+
+ /* Setup the initial forth environment */
+ do_forth(env);
+ do_definitions(env);
+ install_handlers(env);
+
+ initial_env = env;
+
+ /*
+ * Need to define this early because it is the default for
+ * all unimpl, FCODE functions
+ */
+ P1275(0x0fc, IMMEDIATE, "ferror", f_error);
+ f_error_addr = LINK_TO_ACF(env->lastlink);
+ for (i = 0; i <= MAX_FCODE; i++) {
+ DEBUGF(ANY, env->table[i].usage = 0);
+ SET_TOKEN(i, IMMEDIATE, "ferror", f_error_addr);
+ }
+ fcode_impl_count = 0;
+}
diff --git a/usr/src/lib/efcode/engine/instance.c b/usr/src/lib/efcode/engine/instance.c
new file mode 100644
index 0000000000..380d1d6297
--- /dev/null
+++ b/usr/src/lib/efcode/engine/instance.c
@@ -0,0 +1,117 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+
+#include <fcode/private.h>
+
+/*
+ * Return a pointer to the allocated instance data.
+ * If the data was initialised then return a pointer to the initialisation
+ * buffer otherwise return a pointer to the un-init data.
+ */
+token_t *
+alloc_instance_data(fcode_env_t *env, int init, int n, int *offset)
+{
+ int ptr;
+
+ *offset = ptr = MYSELF->device->data_size[init];
+ MYSELF->device->data_size[init] += n;
+ if (init == INIT_DATA)
+ return (&MYSELF->device->init_data[ptr]);
+ else
+ return (&MYSELF->data[init][ptr]);
+}
+
+token_t *
+get_instance_address(fcode_env_t *env)
+{
+ int which;
+ token_t *ptr;
+ token_t offset;
+
+ CHECK_DEPTH(env, 1, "get_instance_address");
+ ptr = (token_t *) POP(DS);
+ offset = *ptr;
+ if (offset < 0) {
+ offset = -offset;
+ which = UINIT_DATA;
+ } else {
+ which = INIT_DATA;
+ }
+ return (&MYSELF->data[which][offset]);
+}
+
+void
+fetch_instance_data(fcode_env_t *env)
+{
+ token_t *ptr;
+
+ CHECK_DEPTH(env, 1, "get_instance_data");
+ ptr = get_instance_address(env);
+ PUSH(DS, *ptr);
+}
+
+void
+set_instance_data(fcode_env_t *env)
+{
+ token_t *ptr;
+
+ CHECK_DEPTH(env, 2, "set_instance_data");
+ ptr = get_instance_address(env);
+ *ptr = POP(DS);
+}
+
+void
+address_instance_data(fcode_env_t *env)
+{
+ token_t *ptr;
+
+ CHECK_DEPTH(env, 1, "address_instance_data");
+ ptr = get_instance_address(env);
+ PUSH(DS, (fstack_t) ptr);
+}
+
+void
+instance_variable(fcode_env_t *env)
+{
+ token_t *ptr;
+
+ PUSH(DS, (fstack_t) WA);
+ ptr = get_instance_address(env);
+ PUSH(DS, (fstack_t) ptr);
+}
+
+void
+idefer_exec(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "idefer_exec");
+ fetch_instance_data(env);
+ execute(env);
+}
diff --git a/usr/src/lib/efcode/engine/interactive.c b/usr/src/lib/efcode/engine/interactive.c
new file mode 100644
index 0000000000..398f52a686
--- /dev/null
+++ b/usr/src/lib/efcode/engine/interactive.c
@@ -0,0 +1,808 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <sys/stat.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+void (*to_ptr)(fcode_env_t *env) = do_set_action;
+jmp_buf *jmp_buf_ptr = NULL;
+
+char *
+parse_a_string(fcode_env_t *env, int *lenp)
+{
+ parse_word(env);
+ return (pop_a_string(env, lenp));
+}
+
+void
+constant(fcode_env_t *env)
+{
+ char *name;
+ int len;
+
+ name = parse_a_string(env, &len);
+ env->instance_mode = 0;
+ make_common_access(env, name, len, 1, 0,
+ &do_constant, &do_constant, NULL);
+}
+
+void
+buffer_colon(fcode_env_t *env)
+{
+ char *name;
+ int len;
+
+ PUSH(DS, 0);
+ name = parse_a_string(env, &len);
+ make_common_access(env, name, len, 2,
+ env->instance_mode, &noop, &noop, &set_buffer_actions);
+}
+
+void
+value(fcode_env_t *env)
+{
+ char *name;
+ int len;
+
+ name = parse_a_string(env, &len);
+ make_common_access(env, name, len, 1,
+ env->instance_mode, &noop, &noop, &set_value_actions);
+}
+
+void
+variable(fcode_env_t *env)
+{
+ char *name;
+ int len;
+
+ PUSH(DS, 0);
+ name = parse_a_string(env, &len);
+ make_common_access(env, name, len, 1,
+ env->instance_mode, &instance_variable, &do_create, NULL);
+}
+
+void
+defer(fcode_env_t *env)
+{
+ static void (*crash_ptr)(fcode_env_t *env) = do_crash;
+ char *name;
+ int len;
+
+ PUSH(DS, (fstack_t)&crash_ptr);
+ name = parse_a_string(env, &len);
+ make_common_access(env, name, len, 1,
+ env->instance_mode, &noop, &noop, &set_defer_actions);
+}
+
+void
+field(fcode_env_t *env)
+{
+ char *name;
+ int len;
+
+ over(env);
+ name = parse_a_string(env, &len);
+ make_common_access(env, name, len, 1, 0, &do_field, &do_field, NULL);
+ add(env);
+}
+
+void
+bye(fcode_env_t *env)
+{
+ exit(0);
+}
+
+void
+do_resume(fcode_env_t *env)
+{
+ if (env->interactive) env->interactive--;
+ COMPLETE_INTERRUPT;
+}
+
+/*
+ * In interactive mode, jmp_buf_ptr should be non-null.
+ */
+void
+return_to_interact(fcode_env_t *env)
+{
+ if (jmp_buf_ptr)
+ longjmp(*jmp_buf_ptr, 1);
+}
+
+void
+do_interact(fcode_env_t *env)
+{
+ int level;
+ jmp_buf jmp_env;
+ jmp_buf *ojmp_ptr;
+ error_frame new;
+ input_typ *old_input = env->input;
+
+ log_message(MSG_INFO, "Type resume to return\n");
+ env->interactive++;
+ level = env->interactive;
+
+ ojmp_ptr = jmp_buf_ptr;
+ jmp_buf_ptr = &jmp_env;
+ env->input->separator = ' ';
+ env->input->maxlen = 256;
+ env->input->buffer = MALLOC(env->input->maxlen);
+ env->input->scanptr = env->input->buffer;
+
+ if (setjmp(jmp_env)) {
+ if (in_forth_abort > 1) {
+ RS = env->rs0;
+ DS = env->ds0;
+ MYSELF = 0;
+ IP = 0;
+ env->input = old_input;
+ env->order_depth = 0;
+ } else {
+ RS = new.rs;
+ DS = new.ds;
+ MYSELF = new.myself;
+ IP = new.ip;
+ env->input = old_input;
+ }
+ do_forth(env);
+ do_definitions(env);
+ in_forth_abort = 0;
+ } else {
+ new.rs = RS;
+ new.ds = DS;
+ new.myself = MYSELF;
+ new.ip = IP;
+ }
+
+ while (env->interactive == level) {
+ int wlen;
+ char *p;
+
+ DEBUGF(SHOW_RS, output_return_stack(env, 0, MSG_FC_DEBUG));
+ DEBUGF(SHOW_STACK, output_data_stack(env, MSG_FC_DEBUG));
+
+#define USE_READLINE
+#ifdef USE_READLINE
+ {
+ char *line;
+ void read_line(fcode_env_t *);
+
+ read_line(env);
+ if ((line = pop_a_string(env, NULL)) == NULL)
+ continue;
+
+ env->input->scanptr = strcpy(env->input->buffer, line);
+ }
+#else
+ if (isatty(fileno(stdin)))
+ printf("ok ");
+
+ env->input->scanptr = fgets(env->input->buffer,
+ env->input->maxlen, stdin);
+
+ if (feof(stdin))
+ break;
+
+ if (env->input->scanptr == NULL)
+ continue;
+#endif
+
+ if ((p = strpbrk(env->input->scanptr, "\n\r")) != NULL)
+ *p = '\0';
+
+ if ((wlen = strlen(env->input->scanptr)) == 0)
+ continue;
+
+ PUSH(DS, (fstack_t)env->input->buffer);
+ PUSH(DS, wlen);
+ evaluate(env);
+ }
+
+ jmp_buf_ptr = ojmp_ptr;
+ FREE(env->input->buffer);
+}
+
+static void
+temp_base(fcode_env_t *env, fstack_t base)
+{
+ fstack_t obase;
+
+ obase = env->num_base;
+ env->num_base = base;
+ parse_word(env);
+ evaluate(env);
+ env->num_base = obase;
+}
+
+static void
+temp_decimal(fcode_env_t *env)
+{
+ temp_base(env, 10);
+}
+
+static void
+temp_hex(fcode_env_t *env)
+{
+ temp_base(env, 0x10);
+}
+
+static void
+temp_binary(fcode_env_t *env)
+{
+ temp_base(env, 2);
+}
+
+static void
+do_hex(fcode_env_t *env)
+{
+ env->num_base = 0x10;
+}
+
+static void
+do_decimal(fcode_env_t *env)
+{
+ env->num_base = 10;
+}
+
+static void
+do_binary(fcode_env_t *env)
+{
+ env->num_base = 2;
+}
+
+static void
+do_clear(fcode_env_t *env)
+{
+ DS = env->ds0;
+}
+
+static void
+action_one(fcode_env_t *env)
+{
+
+ do_tick(env);
+ if (env->state) {
+ COMPILE_TOKEN(&to_ptr);
+ } else {
+ PUSH(DS, 1);
+ perform_action(env);
+ }
+}
+
+void
+do_if(fcode_env_t *env)
+{
+ branch_common(env, 1, 1, 0);
+}
+
+void
+do_else(fcode_env_t *env)
+{
+ branch_common(env, 1, 0, 1);
+ bresolve(env);
+}
+
+void
+do_then(fcode_env_t *env)
+{
+ bresolve(env);
+}
+
+void
+do_of(fcode_env_t *env)
+{
+ branch_common(env, 0, 2, 0);
+}
+
+void
+load_file(fcode_env_t *env)
+{
+ int fd;
+ int len, n;
+ char *name;
+ char *buffer;
+ struct stat buf;
+
+ CHECK_DEPTH(env, 2, "load-file");
+ name = pop_a_string(env, &len);
+ log_message(MSG_INFO, "load_file: '%s'\n", name);
+ fd = open(name, O_RDONLY);
+ if (fd < 0) {
+ forth_perror(env, "Can't open '%s'", name);
+ }
+ fstat(fd, &buf);
+ len = buf.st_size;
+ buffer = MALLOC(len);
+ if (buffer == 0)
+ forth_perror(env, "load_file: MALLOC(%d)", len);
+
+ if ((n = read(fd, buffer, len)) < 0)
+ forth_perror(env, "read error '%s'", name);
+
+ close(fd);
+ PUSH(DS, (fstack_t)buffer);
+ PUSH(DS, (fstack_t)n);
+}
+
+void
+load(fcode_env_t *env)
+{
+ parse_word(env);
+ if (TOS > 0)
+ load_file(env);
+}
+
+void
+fevaluate(fcode_env_t *env)
+{
+ char *buffer;
+ int bytes, len;
+
+ two_dup(env);
+ buffer = pop_a_string(env, &len);
+ for (bytes = 0; bytes < len; bytes++) {
+ if ((buffer[bytes] == '\n') || (buffer[bytes] == '\r'))
+ buffer[bytes] = ' ';
+ }
+ evaluate(env);
+}
+
+void
+fload(fcode_env_t *env)
+{
+ char *buffer;
+
+ load(env);
+ two_dup(env);
+ buffer = pop_a_string(env, NULL);
+ fevaluate(env);
+ FREE(buffer);
+}
+
+#include <sys/termio.h>
+
+#define MAX_LINE_BUF 20
+
+static char *history_lines[MAX_LINE_BUF];
+int num_lines = 0;
+
+static void
+add_line_to_history(fcode_env_t *env, char *line)
+{
+ int i;
+
+ if (num_lines < MAX_LINE_BUF)
+ history_lines[num_lines++] = STRDUP(line);
+ else {
+ FREE(history_lines[0]);
+ for (i = 0; i < MAX_LINE_BUF - 1; i++)
+ history_lines[i] = history_lines[i + 1];
+ history_lines[MAX_LINE_BUF - 1] = STRDUP(line);
+ }
+}
+
+static void
+do_emit_chars(fcode_env_t *env, char c, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ do_emit(env, c);
+}
+
+static void
+do_emit_str(fcode_env_t *env, char *str, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ do_emit(env, *str++);
+}
+
+static char *
+find_next_word(char *cursor, char *eol)
+{
+ while (cursor < eol && *cursor != ' ')
+ cursor++;
+ while (cursor < eol && *cursor == ' ')
+ cursor++;
+ return (cursor);
+}
+
+static char *
+find_prev_word(char *buf, char *cursor)
+{
+ int skippedword = 0;
+
+ if (cursor == buf)
+ return (cursor);
+ cursor--;
+ while (cursor > buf && *cursor == ' ')
+ cursor--;
+ while (cursor > buf && *cursor != ' ') {
+ skippedword++;
+ cursor--;
+ }
+ if (skippedword && *cursor == ' ')
+ cursor++;
+ return (cursor);
+}
+
+void
+redraw_line(fcode_env_t *env, char *prev_l, char *prev_cursor, char *prev_eol,
+ char *new_l, char *new_cursor, char *new_eol)
+{
+ int len;
+
+ /* backup to beginning of previous line */
+ do_emit_chars(env, '\b', prev_cursor - prev_l);
+
+ /* overwrite new line */
+ do_emit_str(env, new_l, new_eol - new_l);
+
+ /* Output blanks to erase previous line chars if old line was longer */
+ len = max(0, (prev_eol - prev_l) - (new_eol - new_l));
+ do_emit_chars(env, ' ', len);
+
+ /* Backup cursor for new line */
+ do_emit_chars(env, '\b', len + (new_eol - new_cursor));
+}
+
+#define MAX_LINE_SIZE 256
+
+static void
+do_save_buf(char *save_buf, char *buf, int n)
+{
+ n = max(0, min(n, MAX_LINE_SIZE));
+ memcpy(save_buf, buf, n);
+ save_buf[n] = '\0';
+}
+
+char prompt_string[80] = "ok ";
+
+void
+read_line(fcode_env_t *env)
+{
+ char buf[MAX_LINE_SIZE+1], save_buf[MAX_LINE_SIZE+1];
+ char save_line[MAX_LINE_SIZE+1];
+ char *p, *cursor, *eol, *tp, *cp;
+ fstack_t d;
+ int saw_esc = 0, do_quote = 0, i, cur_line, len, my_line, save_cursor;
+ struct termio termio, savetermio;
+
+ if (!isatty(fileno(stdin))) {
+ fgets(buf, sizeof (buf), stdin);
+ push_string(env, buf, strlen(buf));
+ return;
+ }
+ printf(prompt_string);
+ fflush(stdout);
+ ioctl(fileno(stdin), TCGETA, &termio);
+ savetermio = termio;
+ termio.c_lflag &= ~(ICANON|ECHO|ECHOE|IEXTEN);
+ termio.c_cc[VTIME] = 0;
+ termio.c_cc[VMIN] = 1;
+ ioctl(fileno(stdin), TCSETA, &termio);
+ my_line = cur_line = num_lines;
+ save_buf[0] = '\0';
+ for (cursor = eol = buf; ; ) {
+ for (d = FALSE; d == FALSE; d = POP(DS))
+ keyquestion(env);
+ key(env);
+ d = POP(DS);
+ if (do_quote) {
+ do_quote = 0;
+ if ((cursor - buf) < MAX_LINE_SIZE) {
+ *cursor++ = d;
+ if (cursor > eol)
+ eol = cursor;
+ do_emit(env, d);
+ }
+ continue;
+ }
+ if (saw_esc) {
+ saw_esc = 0;
+ switch (d) {
+
+ default: /* Ignore anything else */
+ continue;
+
+ case 'b': /* Move backward one word */
+ case 'B':
+ tp = find_prev_word(buf, cursor);
+ if (tp < cursor) {
+ do_emit_chars(env, '\b', cursor - tp);
+ cursor = tp;
+ }
+ continue;
+
+ case 'f': /* Move forward one word */
+ case 'F':
+ tp = find_next_word(cursor, eol);
+ if (tp > cursor) {
+ do_emit_str(env, tp, tp - cursor);
+ cursor = tp;
+ }
+ continue;
+
+ case 'h': /* Erase from beginning of word to */
+ case 'H': /* just before cursor, saving chars */
+ d = CTRL('w');
+ break;
+
+ case 'd':
+ case 'D':
+ tp = find_next_word(cursor, eol);
+ if (tp <= cursor)
+ continue;
+ len = tp - cursor;
+ do_save_buf(save_buf, cursor, len);
+ memmove(cursor, tp, eol - tp);
+ redraw_line(env, buf, cursor, eol, buf, cursor,
+ eol - len);
+ eol -= len;
+ continue;
+ }
+ }
+ switch (d) {
+
+ default:
+ if ((cursor - buf) < MAX_LINE_SIZE) {
+ *cursor++ = d;
+ if (cursor > eol)
+ eol = cursor;
+ do_emit(env, d);
+ }
+ continue;
+
+ case CTRL('['): /* saw esc. character */
+ saw_esc = 1;
+ continue;
+
+ case CTRL('f'): /* move forward one char */
+ if (cursor < eol)
+ do_emit(env, *cursor++);
+ continue;
+
+ case CTRL('a'): /* cursor to beginning of line */
+ do_emit_chars(env, '\b', cursor - buf);
+ cursor = buf;
+ continue;
+
+ case CTRL('e'): /* cursor to end of line */
+ do_emit_str(env, cursor, eol - cursor);
+ cursor = eol;
+ continue;
+
+
+ case CTRL('n'): /* Move to next line in buffer */
+ case CTRL('p'): /* Move to previous line in buffer */
+ if (d == CTRL('p')) {
+ if (cur_line <= 0)
+ continue;
+ if (my_line == cur_line) {
+ do_save_buf(save_line, buf, eol - buf);
+ save_cursor = cursor - buf;
+ }
+ cur_line--;
+ } else {
+ if (cur_line >= num_lines)
+ continue;
+ cur_line++;
+ if (cur_line == num_lines) {
+ len = strlen(save_line);
+ redraw_line(env, buf, cursor, eol,
+ save_line, save_line + save_cursor,
+ save_line + len);
+ strcpy(buf, save_line);
+ eol = buf + len;
+ cursor = buf + save_cursor;
+ continue;
+ }
+ }
+ p = history_lines[cur_line];
+ len = strlen(p);
+ redraw_line(env, buf, cursor, eol, p, p, p + len);
+ strcpy(buf, history_lines[cur_line]);
+ cursor = buf;
+ eol = buf + len;
+ continue;
+
+ case CTRL('o'): /* Insert newline */
+ continue;
+
+ case CTRL('k'): /* Erase from cursor to eol, saving */
+ /* chars, at eol, joins two lines */
+ if (cursor == eol) {
+ if (cur_line >= num_lines)
+ continue;
+ if (cur_line == num_lines - 1) {
+ p = save_line;
+ len = strlen(save_line);
+ num_lines -= 1;
+ my_line = num_lines;
+ } else {
+ cur_line++;
+ p = history_lines[cur_line];
+ len = strlen(p);
+ }
+ len = min(len, MAX_LINE_SIZE - (eol - buf));
+ memcpy(eol, p, len);
+ redraw_line(env, buf, cursor, eol, buf, cursor,
+ eol + len);
+ eol += len;
+ continue;
+ }
+ do_save_buf(save_buf, cursor, eol - cursor);
+ redraw_line(env, buf, cursor, eol, buf, cursor,
+ cursor);
+ eol = cursor;
+ continue;
+
+ case CTRL('w'): /* Erase word */
+ tp = find_prev_word(buf, cursor);
+ if (tp == cursor)
+ continue;
+ len = cursor - tp;
+ do_save_buf(save_buf, tp, len);
+ memmove(tp, cursor, eol - cursor);
+ redraw_line(env, buf, cursor, eol, buf, cursor - len,
+ eol - len);
+ eol -= len;
+ cursor -= len;
+ continue;
+
+ case CTRL('u'): /* Erases line, saving chars */
+ do_save_buf(save_buf, buf, eol - buf);
+ redraw_line(env, buf, cursor, eol, buf, buf, buf);
+ cursor = buf;
+ eol = buf;
+ continue;
+
+ case CTRL('y'): /* Insert save buffer before cursor */
+ len = min(strlen(save_buf),
+ MAX_LINE_SIZE - (eol - buf));
+ if (len == 0)
+ continue;
+ memmove(cursor + len, cursor, eol - cursor);
+ memcpy(cursor, save_buf, len);
+ redraw_line(env, buf, cursor, eol, buf, cursor + len,
+ eol + len);
+ cursor += len;
+ eol += len;
+ continue;
+
+ case CTRL('q'): /* Quote next char */
+ do_quote = 1;
+ continue;
+
+ case CTRL('l'): /* Display edit buffer */
+ do_emit(env, '\n');
+ for (i = 0; i < num_lines; i++) {
+ do_emit_str(env, history_lines[i],
+ strlen(history_lines[i]));
+ do_emit(env, '\n');
+ }
+ redraw_line(env, buf, buf, buf, buf, cursor, eol);
+ continue;
+
+ case CTRL('r'): /* redraw line */
+ redraw_line(env, buf, cursor, eol, buf, cursor, eol);
+ continue;
+
+ case CTRL('c'): /* Exit script editor */
+ continue;
+
+ case CTRL('b'): /* backup cursor */
+ if (cursor <= buf)
+ continue;
+ cursor--;
+ do_emit(env, '\b');
+ continue;
+
+ case CTRL('h'): /* Backspace */
+ case 0x7f: /* DEL */
+ if (cursor <= buf)
+ continue;
+ memmove(cursor - 1, cursor, eol - cursor);
+ redraw_line(env, buf, cursor, eol, buf, cursor - 1,
+ eol - 1);
+ cursor--;
+ eol--;
+ continue;
+
+ case '\r':
+ case '\n':
+ *eol = '\0';
+ do_emit(env, '\n');
+ break;
+ }
+ break;
+ }
+ add_line_to_history(env, buf);
+ ioctl(fileno(stdin), TCSETA, &savetermio);
+ push_string(env, buf, strlen(buf));
+}
+
+static void
+set_prompt(fcode_env_t *env)
+{
+ char *prompt;
+
+ if ((prompt = parse_a_string(env, NULL)) != NULL)
+ strncpy(prompt_string, prompt, sizeof (prompt_string));
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ FORTH(IMMEDIATE, "if", do_if);
+ FORTH(IMMEDIATE, "else", do_else);
+ FORTH(IMMEDIATE, "then", do_then);
+ FORTH(IMMEDIATE, "case", bcase);
+ FORTH(IMMEDIATE, "of", do_of);
+ FORTH(IMMEDIATE, "endof", do_else);
+ FORTH(IMMEDIATE, "endcase", bendcase);
+ FORTH(IMMEDIATE, "value", value);
+ FORTH(IMMEDIATE, "variable", variable);
+ FORTH(IMMEDIATE, "constant", constant);
+ FORTH(IMMEDIATE, "defer", defer);
+ FORTH(IMMEDIATE, "buffer:", buffer_colon);
+ FORTH(IMMEDIATE, "field", field);
+ FORTH(IMMEDIATE, "struct", zero);
+ FORTH(IMMEDIATE, "to", action_one);
+ FORTH(IMMEDIATE, "d#", temp_decimal);
+ FORTH(IMMEDIATE, "h#", temp_hex);
+ FORTH(IMMEDIATE, "b#", temp_binary);
+ FORTH(0, "decimal", do_decimal);
+ FORTH(0, "hex", do_hex);
+ FORTH(0, "binary", do_binary);
+ FORTH(0, "clear", do_clear);
+ FORTH(IMMEDIATE, "bye", bye);
+ FORTH(0, "interact", do_interact);
+ FORTH(IMMEDIATE, "resume", do_resume);
+ FORTH(0, "fload", fload);
+ FORTH(0, "load", load);
+ FORTH(0, "read-line", read_line);
+ FORTH(0, "set-prompt", set_prompt);
+}
diff --git a/usr/src/lib/efcode/engine/interface.c b/usr/src/lib/efcode/engine/interface.c
new file mode 100644
index 0000000000..31f0cc9e91
--- /dev/null
+++ b/usr/src/lib/efcode/engine/interface.c
@@ -0,0 +1,273 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+/*
+ * the external start point for this goo
+ */
+
+void
+push_ds(fcode_env_t *env, fstack_t d)
+{
+ PUSH(DS, d);
+}
+
+fstack_t
+pop_ds(fcode_env_t *env)
+{
+ return (POP(DS));
+}
+
+void
+push_rs(fcode_env_t *env, fstack_t d)
+{
+ PUSH(RS, d);
+}
+
+fstack_t
+pop_rs(fcode_env_t *env)
+{
+ return (POP(RS));
+}
+
+/*
+ * Pushes a C string on the stack.
+ */
+void
+push_a_string(fcode_env_t *env, char *str)
+{
+ if (str) {
+ PUSH(DS, (fstack_t)str);
+ PUSH(DS, strlen(str));
+ } else {
+ PUSH(DS, 0);
+ PUSH(DS, 0);
+ }
+}
+
+/*
+ * Pops a (potentially null) string off the stack.
+ */
+char *
+pop_a_string(fcode_env_t *env, int *lenp)
+{
+ int len;
+ char *str;
+
+ len = POP(DS);
+ str = (char *)POP(DS);
+ if (len == 0)
+ str = NULL;
+ else if (str == NULL)
+ len = 0;
+ if (lenp)
+ *lenp = len;
+ return (str);
+}
+
+/*
+ * Pops & strdup's a string off the stack, handles NULL strings.
+ */
+char *
+pop_a_duped_string(fcode_env_t *env, int *lenp)
+{
+ char *str;
+
+ str = pop_a_string(env, lenp);
+ if (str)
+ return (STRDUP(str));
+ return (NULL);
+}
+
+/*
+ * Push Forth Double type.
+ */
+void
+push_double(fcode_env_t *env, dforth_t d)
+{
+ fstack_t lo, hi;
+
+ lo = DFORTH_LO(d);
+ hi = DFORTH_HI(d);
+ PUSH(DS, lo);
+ PUSH(DS, hi);
+}
+
+/*
+ * Pop Forth Double type.
+ */
+dforth_t
+pop_double(fcode_env_t *env)
+{
+ fstack_t lo, hi;
+
+ hi = POP(DS);
+ lo = POP(DS);
+ return (MAKE_DFORTH(hi, lo));
+}
+
+/*
+ * Peek at top of stack Forth Double type.
+ */
+dforth_t
+peek_double(fcode_env_t *env)
+{
+ dforth_t a;
+
+ a = pop_double(env);
+ push_double(env, a);
+ return (a);
+}
+
+void
+run_fcode(fcode_env_t *env, uchar_t *buff, int len)
+{
+ int i;
+
+ /*
+ * Really just checking to see if buff is all ascii characters.
+ * Fcode normally starts with 0xfd, so for fcode, this should be
+ * a fast check.
+ */
+ for (i = 0; i < len; i++)
+ if (buff[i] >= 0x80)
+ break;
+ PUSH(DS, (fstack_t)buff);
+ if (i < len) {
+ /* Non-ascii found, probably Fcode */
+ PUSH(DS, (fstack_t)1);
+ byte_load(env);
+ } else {
+ /* All ascii found, probably ascii */
+ PUSH(DS, len);
+ fevaluate(env);
+ }
+}
+
+void
+run_fcode_from_file(fcode_env_t *env, char *fname, int aout_flag)
+{
+ uchar_t *p;
+ int len;
+
+ push_a_string(env, fname);
+ load_file(env);
+ len = POP(DS);
+ p = (uchar_t *)POP(DS);
+ if (aout_flag) {
+ p += 0x20;
+ len -= 0x20;
+ }
+ run_fcode(env, p, len);
+}
+
+fcode_env_t *
+clone_environment(fcode_env_t *src, void *private)
+{
+ fcode_env_t *env;
+
+ if (!src) {
+ src = initial_env;
+ src->private = private;
+ return (src);
+ }
+
+#if 0
+ src->private = private;
+ if (src->my_self || src->state) {
+ log_message(MSG_WARN, "Can't clone an active instance or"
+ " compile state!\n");
+ return (NULL);
+ }
+
+ log_message(MSG_WARN, "Warning: Device-tree state is shared!\n");
+#endif
+
+ env = MALLOC(sizeof (fcode_env_t));
+ memcpy(env, src, sizeof (fcode_env_t));
+
+#if 0
+ env->table = MALLOC((MAX_FCODE + 1) * sizeof (fcode_token));
+ memcpy(env->table, src->table, (MAX_FCODE + 1) * sizeof (fcode_token));
+
+ /*
+ * Note that cloning the dictionary doesn't make sense unless the
+ * ptrs + XT's in the dictionary are relative to BASE.
+ */
+ env->base = MALLOC(dict_size);
+ memcpy(env->base, src->base, dict_size);
+
+ env->here = src->base - (uchar_t *)src + env->base;
+#endif
+
+ env->ds0 = MALLOC(stack_size * sizeof (fstack_t));
+ memcpy(env->ds0, src->ds0, stack_size * sizeof (fstack_t));
+ env->ds = src->ds - src->ds0 + env->ds0;
+
+ env->rs0 = MALLOC(stack_size * sizeof (fstack_t));
+ memcpy(env->rs0, src->rs0, stack_size * sizeof (fstack_t));
+ env->rs = src->rs - src->rs0 + env->rs0;
+
+ env->order = MALLOC(MAX_ORDER * sizeof (token_t));
+ memcpy(env->order, src->order, MAX_ORDER * sizeof (token_t));
+
+ env->input = MALLOC(sizeof (input_typ));
+
+ env->catch_frame = 0;
+
+ IP = 0;
+
+ return (env);
+}
+
+void
+destroy_environment(fcode_env_t *env)
+{
+ FREE(env->input);
+ FREE(env->order);
+ FREE(env->ds0);
+ FREE(env->rs0);
+#if 0
+ FREE(env->base);
+ FREE(env->table);
+#endif
+ FREE(env);
+
+ if (env == initial_env) {
+ /* This call only happens internally */
+
+ initial_env = NULL;
+ /* You had better not exercise the engine anymore! */
+ }
+}
diff --git a/usr/src/lib/efcode/engine/interp.c b/usr/src/lib/efcode/engine/interp.c
new file mode 100644
index 0000000000..e0e41dba01
--- /dev/null
+++ b/usr/src/lib/efcode/engine/interp.c
@@ -0,0 +1,121 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+void
+do_run(fcode_env_t *env, int next)
+{
+ token_t target, indirect;
+ void (*fn)(fcode_env_t *env);
+ int debug_state = current_debug_state(env);
+ extern void do_memory_watch(fcode_env_t *env);
+
+ for (; ; ) {
+ if (next) {
+ DEBUGF(NEXT_VITALS, output_vitals(env);
+ log_message(MSG_FC_DEBUG, "\n"));
+ CHECK_INTERRUPT;
+ if (IP == NULL)
+ break;
+ WA = (token_t *) *IP;
+ IP++;
+ }
+ check_for_debug_entry(env);
+ indirect = *WA;
+ if (indirect & 1) {
+ target = indirect & ~1;
+ target = *((token_t *)target);
+ } else
+ target = indirect;
+ fn = (void (*)(fcode_env_t *)) target;
+ if (do_exec_debug(env, (void *)fn))
+ break;
+ if (indirect & 1) {
+ PUSH(DS, (fstack_t) (WA+1));
+ WA = (token_t *) target;
+ }
+ WA++;
+ fn(env);
+ check_vitals(env);
+ check_for_debug_exit(env);
+ do_memory_watch(env);
+ next = 1;
+ }
+ clear_debug_state(env, debug_state);
+}
+
+void
+do_semi(fcode_env_t *env)
+{
+ CHECK_RETURN_DEPTH(env, 1, ";");
+ check_semi_debug_exit(env);
+ IP = (token_t *) POP(RS);
+}
+
+void
+do_colon(fcode_env_t *env)
+{
+ PUSH(RS, (fstack_t) IP);
+ IP = WA;
+}
+
+void
+do_alias(fcode_env_t *env)
+{
+ token_t *ip;
+
+ ip = IP;
+ IP = 0;
+ WA = (token_t *) *WA;
+ do_run(env, 0);
+ IP = ip;
+}
+
+void
+execute(fcode_env_t *env)
+{
+ token_t *ip, *wa;
+
+ /*
+ * In order to ensure that only this token executes we
+ * force IP to zero after stashing it, then when the stack
+ * unwinds (do_run returns) we can restore the old value.
+ */
+ CHECK_DEPTH(env, 1, "execute");
+ ip = IP;
+ wa = WA;
+ IP = 0;
+ WA = (token_t *) POP(DS);
+ do_run(env, 0);
+ IP = ip;
+ WA = wa;
+}
diff --git a/usr/src/lib/efcode/engine/log.c b/usr/src/lib/efcode/engine/log.c
new file mode 100644
index 0000000000..b17f38b8c4
--- /dev/null
+++ b/usr/src/lib/efcode/engine/log.c
@@ -0,0 +1,361 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Daemon log message. This can direct log messages to either stdout,
+ * an error log file or syslog (or any combination).
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#define LOG_LINESIZE 256
+#define LOG_EMIT_BUFSIZE LOG_LINESIZE
+
+static FILE *error_log_fp = NULL;
+static int syslog_opened = 0;
+static int error_log_flags;
+static int syslog_log_flags;
+static int do_emit_flag = -1;
+static int daemon_log_flag;
+static int min_syslog_level = LOG_ERR;
+
+static int log_to_stdout(int);
+static int log_to_error_log(int);
+static int log_to_syslog(int);
+static int msg_level_to_syslog(int);
+
+/*
+ * Complicated by not wanting to do any emit processing if no one's actually
+ * going to see it.
+ */
+void
+log_emit(char c)
+{
+ static char emit_buf[LOG_EMIT_BUFSIZE];
+ static char *emit_p = emit_buf;
+ static int lastnl = 1;
+
+ /*
+ * No one has set the do_emit_flag, go ahead and figure it out.
+ */
+ if (do_emit_flag < 0) {
+ do_emit_flag = (log_to_stdout(MSG_EMIT) |
+ log_to_error_log(MSG_EMIT) | log_to_syslog(MSG_EMIT));
+ }
+
+ if (!do_emit_flag)
+ return;
+
+ /*
+ * Check for buffer overflow.
+ */
+ if (emit_p >= &emit_buf[LOG_EMIT_BUFSIZE - 1]) {
+ *emit_p = '\0';
+ log_message(MSG_EMIT, "emit: %s\n", emit_buf);
+ emit_p = emit_buf;
+ lastnl = 1;
+ }
+
+ /*
+ * Fcode emit's may output both CR/LF, we go ahead and eat multiple
+ * ones in succession.
+ */
+ if (c == '\n' || c == '\r') {
+ if (!lastnl) {
+ *emit_p = '\0';
+ log_message(MSG_EMIT, "emit: %s\n", emit_buf);
+ emit_p = emit_buf;
+ }
+ lastnl = 1;
+ } else {
+ lastnl = 0;
+ *emit_p++ = c;
+ }
+}
+
+/*
+ * If stdout is a tty and this is MSG_EMIT, we should have alredy output it.
+ * If running as daemon, output to stdout is a waste of time.
+ */
+static int
+log_to_stdout(int msg_level)
+{
+ if (isatty(fileno(stdin)) && (msg_level & MSG_EMIT) != 0)
+ return (0);
+ return (daemon_log_flag == 0);
+}
+
+/*
+ * Can't turn off FATAL or ERROR messages to error log file.
+ */
+static int
+log_to_error_log(int msg_level)
+{
+ if (!error_log_fp)
+ return (0);
+ if (msg_level & (MSG_FATAL|MSG_ERROR))
+ return (1);
+ return (msg_level & error_log_flags);
+}
+
+/*
+ * Can't turn off FATAL or ERROR messages to syslog.
+ */
+static int
+log_to_syslog(int msg_level)
+{
+ if (!syslog_opened)
+ return (0);
+ if (msg_level & (MSG_FATAL|MSG_ERROR))
+ return (1);
+ return (msg_level & syslog_log_flags);
+}
+
+/*
+ * Turn internal MSG level to syslog msg level. Don't return a msg level
+ * lower priority than min_syslog_level.
+ */
+static int
+msg_level_to_syslog(int msg_level)
+{
+ if (min_syslog_level <= LOG_ERR)
+ return (min_syslog_level);
+ if (msg_level & (MSG_FATAL|MSG_ERROR))
+ return (LOG_ERR);
+ if (min_syslog_level <= LOG_WARNING)
+ return (min_syslog_level);
+ if (msg_level & MSG_WARN)
+ return (LOG_WARNING);
+ if (min_syslog_level <= LOG_NOTICE)
+ return (min_syslog_level);
+ if (msg_level & MSG_NOTE)
+ return (LOG_NOTICE);
+ if (min_syslog_level <= LOG_INFO)
+ return (min_syslog_level);
+ if (msg_level & MSG_INFO)
+ return (LOG_INFO);
+ return (min(min_syslog_level, LOG_DEBUG));
+}
+
+/*
+ * Log a message to the appropriate places.
+ */
+void
+log_message(int msg_level, char *fmt, ...)
+{
+ va_list ap;
+ char msg[LOG_LINESIZE], *p;
+ static char log_msg[LOG_LINESIZE];
+
+ va_start(ap, fmt);
+
+ vsprintf(msg, fmt, ap);
+
+ if (log_to_stdout(msg_level)) {
+ printf(msg);
+ fflush(stdout);
+ }
+ if (log_to_error_log(msg_level)) {
+ fprintf(error_log_fp, msg);
+ fflush(error_log_fp);
+ }
+ if (log_to_syslog(msg_level)) {
+ if (strlen(log_msg) + strlen(msg) > LOG_LINESIZE - 1) {
+ syslog(msg_level_to_syslog(msg_level), log_msg);
+ log_msg[0] = '\0';
+ }
+ strcat(log_msg, msg);
+ if ((p = strchr(log_msg, '\n')) != NULL) {
+ *p = '\0';
+ syslog(msg_level_to_syslog(msg_level), log_msg);
+ log_msg[0] = '\0';
+ }
+ }
+}
+
+/*
+ * Output debug message
+ */
+void
+debug_msg(int debug_level, char *fmt, ...)
+{
+ va_list ap;
+ char msg[LOG_LINESIZE];
+
+ if ((debug_level & get_interpreter_debug_level()) == 0)
+ return;
+
+ va_start(ap, fmt);
+
+ vsprintf(msg, fmt, ap);
+
+ log_message(MSG_DEBUG, msg);
+}
+
+/*
+ * Log a perror message to the appropriate places.
+ */
+void
+log_perror(int msg_level, char *fmt, ...)
+{
+ va_list ap;
+ char msg[LOG_LINESIZE], tmp[LOG_LINESIZE];
+
+ va_start(ap, fmt);
+
+ vsprintf(msg, fmt, ap);
+ sprintf(tmp, "%s: %s\n", msg, strerror(errno));
+ log_message(msg_level, tmp);
+}
+
+void
+set_min_syslog_level(int level)
+{
+ min_syslog_level = level;
+}
+
+char *error_log_name;
+
+void
+open_error_log(char *fname, int errflags)
+{
+ if ((error_log_fp = fopen(fname, "a")) == NULL) {
+ log_perror(MSG_FATAL, fname);
+ exit(1);
+ }
+ error_log_name = STRDUP(fname);
+ error_log_flags = errflags;
+ do_emit_flag = (log_to_stdout(MSG_EMIT) | log_to_error_log(MSG_EMIT) |
+ log_to_syslog(MSG_EMIT));
+}
+
+void
+open_syslog_log(char *logname, int logflags)
+{
+ openlog(logname, LOG_PID, LOG_DAEMON);
+ syslog_log_flags = logflags;
+ do_emit_flag = (log_to_stdout(MSG_EMIT) | log_to_error_log(MSG_EMIT) |
+ log_to_syslog(MSG_EMIT));
+ syslog_opened = 1;
+}
+
+/*
+ * Turn on/off syslog LOG_DAEMON flag to syslog messages. Also controls
+ * outputting to stdout, which is a waste of time when we're running as a
+ * daemon.
+ */
+void
+set_daemon_log_flag(int flag)
+{
+ if (flag)
+ daemon_log_flag = LOG_DAEMON;
+ else
+ daemon_log_flag = 0;
+}
+
+int
+parse_msg_flags(char *flags)
+{
+ int msgflags = 0;
+ char c;
+
+ while ((c = *flags++) != '\0') {
+ switch (c) {
+ case 'f': msgflags |= MSG_FATAL; break;
+ case 'e': msgflags |= MSG_ERROR; break;
+ case 'w': msgflags |= MSG_WARN; break;
+ case 'i': msgflags |= MSG_INFO; break;
+ case 'd': msgflags |= MSG_DEBUG; break;
+ case 'D': msgflags |= MSG_FC_DEBUG; break;
+
+ default:
+ log_message(MSG_ERROR, "Invalid msglvl flag: %c\n", c);
+ break;
+ }
+ }
+ return (msgflags);
+}
+
+#define MAXERRBUF 256
+char error_buffer[MAXERRBUF];
+
+static void
+dot_error_buffer(fcode_env_t *env)
+{
+ log_message(MSG_INFO, "%s\n", error_buffer);
+}
+
+static void
+set_error_log(fcode_env_t *env)
+{
+ char *fname;
+ FILE *fp;
+
+ parse_word(env);
+ fname = pop_a_string(env, NULL);
+ if (fname != NULL) {
+ if ((fp = fopen(fname, "a")) == NULL) {
+ log_perror(MSG_ERROR, "Can't open '%s'\n", fname);
+ return;
+ }
+ if (error_log_fp)
+ fclose(error_log_fp);
+ if (error_log_name)
+ FREE(error_log_name);
+ error_log_fp = fp;
+ error_log_name = STRDUP(fname);
+ error_log_flags = MSG_FATAL|MSG_ERROR|MSG_WARN|MSG_INFO|
+ MSG_DEBUG|MSG_FC_DEBUG;
+ } else if (error_log_name)
+ log_message(MSG_INFO, "%s\n", error_log_name);
+ else
+ log_message(MSG_INFO, "NULL\n");
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ FORTH(0, ".error-buffer", dot_error_buffer);
+ FORTH(0, "set-error-log", set_error_log);
+}
diff --git a/usr/src/lib/efcode/engine/mcookie.c b/usr/src/lib/efcode/engine/mcookie.c
new file mode 100644
index 0000000000..8a12bf547a
--- /dev/null
+++ b/usr/src/lib/efcode/engine/mcookie.c
@@ -0,0 +1,237 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+#define MAX_MAPS 16
+
+#define MAP_IS_VALID 0x01
+
+struct map_table {
+ int map_flags;
+ uint64_t map_add;
+ size_t map_size;
+ uint64_t adj_virt;
+ size_t adj_length;
+} map_table[MAX_MAPS];
+
+/*
+ * Originally, this code translated kernel supplied virtual addresses into
+ * "memory cookies", which was a 32-bit number with ascii-M in the upper 8
+ * bits, a 4-bit index and a 20-bit offset. However, this caused two
+ * problems: 1) the 20-bit offset was too small for some devices, esp. some
+ * with frame-buffers; 2) if the fcode used the cookie to program the
+ * hardware, there was no easy way for the software to detect that a
+ * translation needed to be done.
+ *
+ * For that reason, "memory cookies" are now just the kernel-supplied
+ * virtual address, and we now check each memory access to see if it's
+ * attempting to access kernel-supplied memory. The only important thing
+ * now is that "is_mcookie" returns 1 (or true) if the tested mcookie
+ * is a kernel virtual address.
+ *
+ * There is a potential bug if the kernel virtual address happens to
+ * conflict with a user virtual address. However, the current implementation
+ * of Solaris avoids this conflict.
+ */
+
+fstack_t
+mapping_to_mcookie(uint64_t req_add, size_t req_size, uint64_t adj_virt,
+ size_t adj_length)
+{
+ int i;
+ struct map_table *mp;
+
+ for (i = 0, mp = map_table; i < MAX_MAPS; i++, mp++)
+ if ((mp->map_flags & MAP_IS_VALID) == 0)
+ break;
+ if (i == MAX_MAPS) {
+ log_message(MSG_WARN, "Warning: too many mappings\n");
+ return (0);
+ }
+ debug_msg(DEBUG_REG_ACCESS, "Allocating mapping: %d add: 0x%llx"
+ " size: 0x%x\n", i, req_add, req_size);
+ mp->map_flags |= MAP_IS_VALID;
+ mp->map_add = req_add;
+ mp->map_size = req_size;
+ mp->adj_virt = adj_virt;
+ mp->adj_length = adj_length;
+ if (mp->adj_length != 0)
+ return (adj_virt);
+ else
+ return (req_add);
+}
+
+void
+delete_mapping(fstack_t mcookie)
+{
+ int i;
+ struct map_table *mp;
+
+ for (i = 0, mp = map_table; i < MAX_MAPS; i++, mp++) {
+ if ((mp->map_flags & MAP_IS_VALID) &&
+ mcookie >= mp->map_add &&
+ mcookie < mp->map_add + mp->map_size) {
+ debug_msg(DEBUG_REG_ACCESS, "Deallocating mapping: %d"
+ " add: 0x%llx size: 0x%x\n", i, mp->map_add,
+ mp->map_size);
+ mp->map_flags &= ~MAP_IS_VALID;
+ mp->map_add = 0;
+ mp->map_size = 0;
+ mp->adj_virt = 0;
+ mp->adj_length = 0;
+ return;
+ }
+ }
+ log_message(MSG_WARN, "Warning: delete_mapping: invalid"
+ " mcookie: %llx\n", (uint64_t)mcookie);
+}
+
+int
+is_mcookie(fstack_t mcookie)
+{
+ struct map_table *mp;
+ int i;
+
+ for (i = 0, mp = map_table; i < MAX_MAPS; i++, mp++)
+ if ((mp->map_flags & MAP_IS_VALID) &&
+ mcookie >= mp->map_add &&
+ mcookie < mp->map_add + mp->map_size)
+ return (1);
+ return (0);
+}
+
+uint64_t
+mcookie_to_addr(fstack_t mcookie)
+{
+ return (mcookie);
+}
+
+fstack_t
+mcookie_to_rlen(fstack_t mcookie)
+{
+ int i;
+ struct map_table *mp;
+
+ for (i = 0, mp = map_table; i < MAX_MAPS; i++, mp++) {
+ if ((mp->map_flags & MAP_IS_VALID) &&
+ mcookie >= mp->map_add &&
+ mcookie < mp->map_add + mp->map_size) {
+ return (mp->map_size);
+ }
+ }
+ log_message(MSG_WARN, "Warning: mcookie_to_rlen: invalid"
+ " mcookie: %llx\n", (uint64_t)mcookie);
+}
+
+fstack_t
+mcookie_to_rvirt(fstack_t mcookie)
+{
+ int i;
+ struct map_table *mp;
+
+ for (i = 0, mp = map_table; i < MAX_MAPS; i++, mp++) {
+ if ((mp->map_flags & MAP_IS_VALID) &&
+ mcookie >= mp->map_add &&
+ mcookie < mp->map_add + mp->map_size) {
+ return (mp->map_add);
+ }
+ }
+ log_message(MSG_WARN, "Warning: mcookie_to_rvirt: invalid"
+ " mcookie: %llx\n", (uint64_t)mcookie);
+}
+
+static void
+dot_maps(fcode_env_t *env)
+{
+ int i;
+
+ log_message(MSG_DEBUG, "idx base-addr size\n");
+ for (i = 0; i < MAX_MAPS; i++) {
+ if (map_table[i].map_flags & MAP_IS_VALID)
+ log_message(MSG_DEBUG, "%3d %016llx %8x\n", i,
+ map_table[i].map_add, map_table[i].map_size);
+ }
+}
+
+static void
+map_qmark(fcode_env_t *env)
+{
+ fstack_t d = POP(DS);
+
+ if (!is_mcookie(d))
+ log_message(MSG_INFO, "%llx: not mcookie\n", (uint64_t)d);
+ else
+ log_message(MSG_INFO, "%llx -> %llx\n", (uint64_t)d,
+ mcookie_to_addr(d));
+}
+
+static void
+add_map(fcode_env_t *env)
+{
+ fstack_t size, addr;
+
+ size = POP(DS);
+ addr = POP(DS);
+ addr = mapping_to_mcookie(addr, size, NULL, NULL);
+ PUSH(DS, addr);
+}
+
+static void
+del_map(fcode_env_t *env)
+{
+ fstack_t addr;
+
+ addr = POP(DS);
+ delete_mapping(addr);
+}
+
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ FORTH(0, ".maps", dot_maps);
+ FORTH(0, "map?", map_qmark);
+ FORTH(0, "add-map", add_map);
+ FORTH(0, "del-map", del_map);
+}
diff --git a/usr/src/lib/efcode/engine/package.c b/usr/src/lib/efcode/engine/package.c
new file mode 100644
index 0000000000..b32773f45d
--- /dev/null
+++ b/usr/src/lib/efcode/engine/package.c
@@ -0,0 +1,1077 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+#define MIN_VALUES 100
+
+static void
+check_my_self(fcode_env_t *env, char *fn)
+{
+ if (!MYSELF)
+ forth_abort(env, "%s: MYSELF is NULL", fn);
+}
+
+uint_t
+get_number_of_parent_address_cells(fcode_env_t *env)
+{
+ uint_t ncells;
+ device_t *d;
+ static char func_name[] = "get_number_of_parent_address_cells";
+
+ if (MYSELF == NULL) /* Kludge for testing */
+ return (2);
+ d = MYSELF->device;
+ ncells = d->parent_adr_cells;
+ if (ncells == 0) {
+ ncells = get_default_intprop(env, "#address-cells", d->parent,
+ 2);
+ if (ncells > MAX_MY_ADDR) {
+ log_message(MSG_ERROR, "%s: %s:"
+ " ncells (%d) > MAX_MY_ADDR (%d)\n", func_name,
+ get_path(env, d->parent), ncells, MAX_MY_ADDR);
+ ncells = MAX_MY_ADDR;
+ }
+ d->parent_adr_cells = ncells;
+ }
+ return (ncells);
+}
+
+instance_t *
+create_ihandle(fcode_env_t *env, device_t *phandle, instance_t *parent)
+{
+ instance_t *ihandle;
+ int i;
+
+ ihandle = MALLOC(sizeof (instance_t));
+
+ i = max(phandle->data_size[INIT_DATA], MIN_VALUES);
+ ihandle->data[INIT_DATA] = MALLOC(sizeof (fstack_t) * i);
+ memcpy(ihandle->data[INIT_DATA], phandle->init_data,
+ (size_t) (sizeof (fstack_t) * i));
+
+ i = max(phandle->data_size[UINIT_DATA], MIN_VALUES);
+ ihandle->data[UINIT_DATA] = MALLOC(sizeof (fstack_t) * i);
+
+ ihandle->my_space = phandle->my_space;
+ memcpy(ihandle->my_addr, phandle->my_addr, sizeof (ihandle->my_addr));
+ ihandle->parent = parent;
+ ihandle->device = phandle;
+ return (ihandle);
+}
+
+device_t *
+create_phandle(fcode_env_t *env, device_t *parent)
+{
+ device_t *phandle;
+
+ phandle = MALLOC(sizeof (device_t));
+ phandle->init_data = MALLOC(sizeof (fstack_t) * MIN_VALUES);
+ phandle->data_size[INIT_DATA] = 0;
+ phandle->data_size[UINIT_DATA] = 0;
+ phandle->parent = parent;
+ return (phandle);
+}
+
+
+static void
+do_push_package(fcode_env_t *env, device_t *d)
+{
+ do_previous(env);
+ do_also(env);
+ if (d != NULL) {
+ CONTEXT = (token_t *)(&d->vocabulary);
+ debug_msg(DEBUG_CONTEXT, "CONTEXT:push_package: %s%d/%p/%p\n",
+ get_path(env, d), env->order_depth, CONTEXT, env->current);
+ }
+}
+
+static void
+push_package(fcode_env_t *env)
+{
+ device_t *d;
+ phandle_t ph;
+
+ CHECK_DEPTH(env, 1, "push-package");
+ ph = POP(DS);
+ CONVERT_PHANDLE(env, d, ph);
+ do_push_package(env, d);
+}
+
+static void
+pop_package(fcode_env_t *env)
+{
+ do_previous(env);
+ do_definitions(env);
+}
+
+static void
+interpose(fcode_env_t *env)
+{
+ TODO; /* interpose - not yet implemented */
+}
+
+void
+activate_device(fcode_env_t *env, device_t *d)
+{
+ env->current_device = d;
+ do_push_package(env, d);
+ do_definitions(env);
+}
+
+void
+deactivate_device(fcode_env_t *env, device_t *d)
+{
+ env->current_device = d;
+ do_previous(env);
+ if (d != NULL) {
+ CONTEXT = (token_t *)(&d->vocabulary);
+ debug_msg(DEBUG_CONTEXT, "CONTEXT:deactivate_device:"
+ " %s%d/%p/%p\n", get_path(env, d), env->order_depth,
+ CONTEXT, env->current);
+ }
+ do_definitions(env);
+}
+
+/*
+ * Starfire hack to set '/' device_type to 'upa'
+ */
+#include <sys/systeminfo.h>
+static void
+starfire_hack(fcode_env_t *env)
+{
+ char platform[100];
+
+ sysinfo(SI_PLATFORM, platform, sizeof (platform));
+ if (strcmp(platform, "SUNW,Ultra-Enterprise-10000") == 0 &&
+ find_property(env->root_node, "device_type") == NULL) {
+ create_string_prop(env, "device_type", "upa");
+ }
+}
+
+void
+root_node(fcode_env_t *env)
+{
+ do_also(env);
+ activate_device(env, env->root_node);
+ starfire_hack(env);
+}
+
+void
+child_node(fcode_env_t *env)
+{
+ device_t *d;
+
+ CHECK_DEPTH(env, 1, "child");
+ CONVERT_PHANDLE(env, d, TOS);
+ TOS = (fstack_t)d->child;
+ REVERT_PHANDLE(env, TOS, d->child);
+}
+
+void
+peer_node(fcode_env_t *env)
+{
+ device_t *d;
+
+ CHECK_DEPTH(env, 1, "peer");
+ CONVERT_PHANDLE(env, d, TOS);
+ REVERT_PHANDLE(env, TOS, d->peer);
+}
+
+void
+new_device(fcode_env_t *env)
+{
+ device_t *phandle, *parent;
+ device_t *peer;
+
+ check_my_self(env, "new-device");
+
+ parent = MYSELF->device;
+ phandle = create_phandle(env, parent);
+ MYSELF = create_ihandle(env, phandle, MYSELF);
+ activate_device(env, phandle);
+ if (parent->child) {
+ /* Insert new child at end of peer list */
+ for (peer = parent->child; peer->peer; peer = peer->peer)
+ ;
+ peer->peer = phandle;
+ } else
+ parent->child = phandle; /* First child */
+ ALLOCATE_PHANDLE(env);
+}
+
+void
+finish_device(fcode_env_t *env)
+{
+ fstack_t *mem;
+ device_t *my_dev, *parent_dev;
+ instance_t *parent, *myself = MYSELF;
+ int n;
+
+ check_my_self(env, "finish-device");
+ ASSERT(myself->device);
+ ASSERT(env->current_device);
+ n = myself->device->data_size[INIT_DATA];
+
+ /*
+ * Paranoia.. reserve a little more instance data than we need
+ */
+ mem = MALLOC(sizeof (fstack_t) * (n+8));
+ memcpy(mem, MYSELF->device->init_data, sizeof (fstack_t) * n);
+ FREE(myself->device->init_data);
+ my_dev = myself->device;
+ my_dev->init_data = mem;
+ parent = MYSELF->parent;
+ parent_dev = env->current_device->parent;
+ FREE(MYSELF);
+ MYSELF = parent;
+ activate_device(env, parent_dev);
+}
+
+static void
+create_internal_value(fcode_env_t *env, char *name, int offset, int token)
+{
+ header(env, name, strlen(name), 0);
+ COMPILE_TOKEN(&noop);
+ EXPOSE_ACF;
+ if (token) {
+ SET_TOKEN(token, 0, name, LINK_TO_ACF(env->lastlink));
+ }
+ PUSH(DS, offset);
+ lcomma(env);
+ set_internal_value_actions(env);
+}
+
+static void
+create_my_self(fcode_env_t *env)
+{
+ int offset = offsetof(fcode_env_t, my_self);
+
+ create_internal_value(env, "my-self", offset, 0x203);
+}
+
+static void
+create_my_space(fcode_env_t *env)
+{
+ int offset = offsetof(instance_t, my_space);
+
+ create_internal_value(env, "my-space", -offset, 0x103);
+}
+
+void
+my_address(fcode_env_t *env)
+{
+ fstack_t *adr_ptr;
+ uint_t ncells;
+
+ check_my_self(env, "my-address");
+ ncells = get_number_of_parent_address_cells(env);
+ adr_ptr = MYSELF->my_addr;
+ while (--ncells) {
+ PUSH(DS, *adr_ptr);
+ adr_ptr++;
+ }
+}
+
+void
+my_unit(fcode_env_t *env)
+{
+ check_my_self(env, "my-unit");
+ my_address(env);
+ PUSH(DS, MYSELF->my_space);
+}
+
+static void
+my_args(fcode_env_t *env)
+{
+ check_my_self(env, "my-args");
+ PUSH(DS, (fstack_t)MYSELF->my_args);
+ PUSH(DS, (fstack_t)MYSELF->my_args_len);
+}
+
+int
+call_my_parent(fcode_env_t *env, char *method)
+{
+ push_a_string(env, method);
+ dollar_call_parent(env);
+ return (env->last_error);
+}
+
+void
+set_args(fcode_env_t *env)
+{
+ int args_len;
+ common_data_t *cdp;
+ uint_t ncells;
+ fstack_t *adr_ptr, *adr_ptr1, space;
+
+ CHECK_DEPTH(env, 4, "set-args");
+
+ check_my_self(env, "set-args");
+
+ /*
+ * Handle args argument of set-args.
+ */
+ if (MYSELF->my_args) {
+ FREE(MYSELF->my_args);
+ MYSELF->my_args = NULL;
+ }
+ two_swap(env);
+ MYSELF->my_args = pop_a_duped_string(env, &args_len);
+ MYSELF->my_args_len = args_len;
+
+ if (call_my_parent(env, "decode-unit"))
+ forth_abort(env, "set-args: decode-unit failed");
+
+ ncells = get_number_of_parent_address_cells(env);
+
+ /*
+ * Kludge: For GP2, my-space comes from decode-unit hi.address.
+ * for PCI, my-space from decode-unit won't have the bus#, so we need
+ * to get it from config_address. Unfortunately, there is no easy
+ * way to figure out here which one we're looking at. We take the
+ * expediant of or'ing the two values together.
+ */
+ space = POP(DS); /* pop phys.hi */
+ if ((cdp = (common_data_t *)env->private) != NULL)
+ space |= cdp->fc.config_address;
+
+ MYSELF->device->my_space = MYSELF->my_space = space;
+
+ adr_ptr = MYSELF->my_addr;
+ adr_ptr1 = MYSELF->device->my_addr;
+ while (--ncells) {
+ *adr_ptr++ = *adr_ptr1++ = POP(DS);
+ }
+}
+
+void
+my_parent(fcode_env_t *env)
+{
+ check_my_self(env, "my-parent");
+ PUSH(DS, (fstack_t)MYSELF->parent);
+}
+
+instance_t *
+open_instance_chain(fcode_env_t *env, device_t *phandle, int exec)
+{
+ instance_t *parent;
+
+ if (!phandle)
+ return (NULL);
+ parent = open_instance_chain(env, phandle->parent, exec);
+ return (create_ihandle(env, phandle, parent));
+}
+
+void
+close_instance_chain(fcode_env_t *env, instance_t *ihandle, int exec)
+{
+ instance_t *parent;
+
+ if (ihandle) {
+ parent = ihandle->parent;
+ close_instance_chain(env, parent, exec);
+ if (ihandle->my_args)
+ FREE(ihandle->my_args);
+ FREE(ihandle);
+ }
+}
+
+void
+begin_package(fcode_env_t *env)
+{
+ fstack_t ok;
+ char *name;
+
+ CHECK_DEPTH(env, 6, "begin-package");
+ two_dup(env);
+ name = pop_a_string(env, NULL);
+ find_package(env);
+ ok = POP(DS);
+ if (ok) {
+ PUSH(DS, 0);
+ PUSH(DS, 0);
+ rot(env);
+ open_package(env);
+ MYSELF = (instance_t *)POP(DS);
+ check_my_self(env, "begin-package");
+ new_device(env);
+ set_args(env);
+ } else {
+ log_message(MSG_INFO, "Package '%s' not found\n", name);
+ }
+}
+
+void
+open_package(fcode_env_t *env)
+{
+ device_t *phandle;
+ instance_t *ihandle;
+ int len;
+
+ CHECK_DEPTH(env, 3, "open-package");
+ CONVERT_PHANDLE(env, phandle, POP(DS));
+ ihandle = open_instance_chain(env, phandle, 1);
+ ihandle->my_args = pop_a_duped_string(env, &len);
+ ihandle->my_args_len = len;
+ PUSH(DS, (fstack_t)ihandle);
+}
+
+void
+dollar_open_package(fcode_env_t *env)
+{
+ fstack_t ok;
+
+ CHECK_DEPTH(env, 4, "$open-package");
+ find_package(env);
+ ok = POP(DS);
+ if (ok) {
+ open_package(env);
+ } else {
+ PUSH(DS, 0);
+ }
+}
+
+void
+close_package(fcode_env_t *env)
+{
+ instance_t *ihandle;
+
+ CHECK_DEPTH(env, 1, "close-package");
+ ihandle = (instance_t *)POP(DS);
+ close_instance_chain(env, ihandle, 1);
+}
+
+static void (*find_method_hook)(fcode_env_t *);
+
+void
+set_find_method_hook(fcode_env_t *env, void (*hook)(fcode_env_t *))
+{
+ find_method_hook = hook;
+}
+
+void
+find_method(fcode_env_t *env)
+{
+ fstack_t d;
+ device_t *device;
+ acf_t acf = 0;
+
+ CHECK_DEPTH(env, 3, "find-method");
+ if (find_method_hook) {
+ (*find_method_hook)(env);
+ if (TOS) /* Found it */
+ return;
+ POP(DS);
+ }
+
+ d = POP(DS);
+ CONVERT_PHANDLE(env, device, d);
+ PUSH(DS, (fstack_t)&device->vocabulary);
+ acf = voc_find(env);
+ PUSH(DS, (fstack_t)acf);
+ if (acf) {
+ PUSH(DS, TRUE);
+ }
+}
+
+/*
+ * 'call-package' Fcode
+ */
+void
+call_package(fcode_env_t *env)
+{
+ instance_t *ihandle, *saved_myself;
+
+ CHECK_DEPTH(env, 2, "call-package");
+ ihandle = (instance_t *)POP(DS);
+ saved_myself = MYSELF;
+ MYSELF = ihandle;
+ execute(env);
+ MYSELF = saved_myself;
+}
+
+void
+ihandle_to_phandle(fcode_env_t *env)
+{
+ instance_t *i;
+
+ CHECK_DEPTH(env, 1, "ihandle>phandle");
+ i = (instance_t *)TOS;
+ REVERT_PHANDLE(env, TOS, i->device);
+}
+
+char *
+get_package_name(fcode_env_t *env, device_t *d)
+{
+ char *name;
+ prop_t *prop;
+
+ prop = lookup_package_property(env, "name", d);
+ if (prop == NULL) {
+ name = "<Unnamed>";
+ } else {
+ name = (char *)prop->data;
+ }
+ return (name);
+}
+
+static char *package_search_path = "/packages:/openprom";
+
+device_t *
+match_package_path(fcode_env_t *env, char *path)
+{
+ device_t *d;
+ char *name;
+ int len;
+
+ if (*path == '/') {
+ d = env->root_node->child;
+ path++;
+ } else
+ d = env->current_device;
+ while (*path != '\0' && d != NULL) {
+ name = get_package_name(env, d);
+ len = strlen(name);
+ if (strncmp(name, path, len) == 0) {
+ path += len;
+ if (*path == '\0') {
+ return (d);
+ }
+ /* skip the '/' */
+ if (*path++ != '/')
+ break;
+ d = d->child;
+ } else {
+ d = d->peer;
+ }
+ }
+ return (NULL);
+}
+
+device_t *
+locate_package(fcode_env_t *env, char *start)
+{
+ device_t *d;
+ char *p, *next_p;
+ char *tpath, *fpath;
+
+ if ((d = match_package_path(env, start)) != NULL)
+ return (d);
+
+ /*
+ * ignore starting '/'
+ */
+ if (*start == '/')
+ *start++;
+
+ fpath = STRDUP(package_search_path);
+ for (p = fpath; p != NULL; p = next_p) {
+ if ((next_p = strchr(p, ':')) != NULL)
+ *next_p++ = '\0';
+ tpath = MALLOC(strlen(p) + strlen(start) + 2);
+ sprintf(tpath, "%s/%s", p, start);
+ if ((d = match_package_path(env, tpath)) != NULL) {
+ FREE(fpath);
+ FREE(tpath);
+ return (d);
+ }
+ FREE(tpath);
+ }
+ FREE(fpath);
+ return (NULL);
+}
+
+void
+find_package(fcode_env_t *env)
+{
+ char *path;
+ device_t *package;
+ fstack_t ph = 0;
+
+ CHECK_DEPTH(env, 2, "find-package");
+ if ((path = pop_a_duped_string(env, NULL)) != NULL) {
+ if (strcmp(path, "/") == 0)
+ package = env->root_node;
+ else
+ package = locate_package(env, path);
+ FREE(path);
+ REVERT_PHANDLE(env, ph, package);
+ }
+ PUSH(DS, ph);
+ if (package)
+ PUSH(DS, TRUE);
+}
+
+static void
+encode_unit_hack(fcode_env_t *env)
+{
+ int hi, i;
+ uint_t ncells = get_number_of_parent_address_cells(env);
+
+ for (i = 0; i < ncells; i++)
+ POP(DS);
+ push_a_string(env, NULL);
+}
+
+void
+dollar_call_method(fcode_env_t *env)
+{
+ instance_t *old_myself;
+ instance_t *myself;
+ device_t *device;
+ char *method;
+
+ CHECK_DEPTH(env, 3, "$call-method");
+ check_my_self(env, "$call-method");
+ old_myself = MYSELF;
+ myself = (instance_t *)POP(DS);
+
+ method = (char *)DS[-1];
+ debug_msg(DEBUG_CALL_METHOD, "$call_method %s\n", method);
+
+ if (old_myself && !myself) {
+ /* We hit the root of our tree */
+ device = old_myself->device;
+ return;
+ }
+
+ MYSELF = myself;
+ check_my_self(env, "$call-method");
+ device = MYSELF->device;
+ do_push_package(env, device);
+ PUSH(DS, (fstack_t)device);
+ REVERT_PHANDLE(env, TOS, device);
+ find_method(env);
+ if (TOS) {
+ (void) POP(DS);
+ execute(env);
+ } else if (strcmp(method, "encode-unit") == 0) {
+ encode_unit_hack(env);
+ } else {
+ throw_from_fclib(env, 1, "Unimplemented package method: %s%s",
+ get_path(env, device), method);
+ }
+ MYSELF = old_myself;
+ do_push_package(env, MYSELF->device);
+}
+
+void
+dollar_call_parent(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "$call-parent");
+
+ check_my_self(env, "$call-parent");
+
+ PUSH(DS, (fstack_t)MYSELF->parent);
+ dollar_call_method(env);
+}
+
+#ifdef DEBUG
+void
+current_device(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)&env->current_device);
+}
+
+char *
+get_path(fcode_env_t *env, device_t *d)
+{
+ char *pre_path, *name, *path;
+ int n;
+
+ if (d->parent)
+ pre_path = get_path(env, d->parent);
+ else
+ pre_path = STRDUP("");
+
+ name = get_package_name(env, d);
+ n = strlen(pre_path) + strlen(name) + 1;
+ path = MALLOC(n);
+ strcpy(path, pre_path);
+ strcat(path, name);
+ if (d->child && d->parent)
+ strcat(path, "/");
+ FREE(pre_path);
+ return (path);
+}
+
+static void
+pwd_dollar(fcode_env_t *env)
+{
+ if (env->current_device)
+ push_a_string(env, get_path(env, env->current_device));
+ else
+ push_a_string(env, NULL);
+}
+
+void
+pwd(fcode_env_t *env)
+{
+ if (env->current_device) {
+ log_message(MSG_INFO, "%s\n",
+ get_path(env, env->current_device));
+ } else {
+ log_message(MSG_INFO, "No device context\n");
+ }
+}
+
+void
+do_ls(fcode_env_t *env)
+{
+ device_t *d;
+
+ if (env->current_device == NULL) {
+ log_message(MSG_INFO, "No device context\n");
+ return;
+ }
+
+ d = env->current_device->child;
+ while (d) {
+ char *name;
+ fstack_t ph;
+ name = get_package_name(env, d);
+ REVERT_PHANDLE(env, ph, d);
+ log_message(MSG_INFO, "%llx %s\n", (uint64_t)ph, name);
+ d = d->peer;
+ }
+}
+
+void
+paren_cd(fcode_env_t *env)
+{
+ char *str;
+ device_t *p;
+
+ str = pop_a_string(env, NULL);
+ if (strcmp(str, "/") == 0) {
+ root_node(env);
+ return;
+ }
+
+ if (env->current_device == NULL) {
+ log_message(MSG_INFO, "No device context\n");
+ return;
+ }
+
+ if (strcmp(str, "..") == 0)
+ p = env->current_device->parent;
+ else {
+ device_t *n = env->current_device->child;
+
+ p = NULL;
+ while (n) {
+ char *name;
+
+ name = get_package_name(env, n);
+ if (strcmp(name, str) == 0) {
+ p = n;
+ break;
+ }
+ n = n->peer;
+ }
+ }
+
+ if (p) {
+ activate_device(env, p);
+ } else {
+ log_message(MSG_INFO, "No such node: %s\n", str);
+ }
+}
+
+void
+do_cd(fcode_env_t *env)
+{
+ parse_word(env);
+ paren_cd(env);
+}
+
+void
+do_unselect_dev(fcode_env_t *env)
+{
+ check_my_self(env, "unselect-dev");
+ PUSH(DS, (fstack_t)MYSELF);
+ close_package(env);
+ deactivate_device(env, NULL);
+}
+
+void
+do_select_dev(fcode_env_t *env)
+{
+ PUSH(DS, 0);
+ PUSH(DS, 0);
+ two_swap(env);
+ dollar_open_package(env);
+ if (TOS) {
+ MYSELF = (instance_t *)POP(DS);
+ check_my_self(env, "select-dev");
+ activate_device(env, MYSELF->device);
+ } else {
+ drop(env);
+ log_message(MSG_INFO, "Can't open package\n");
+ }
+}
+
+void
+device_end(fcode_env_t *env)
+{
+ if (env->current_device) {
+ deactivate_device(env, NULL);
+ }
+}
+
+void
+end_package(fcode_env_t *env)
+{
+ finish_device(env);
+ close_instance_chain(env, MYSELF, 0);
+ device_end(env);
+ MYSELF = NULL;
+}
+
+void
+exec_parent_method(fcode_env_t *env)
+{
+ instance_t *old_myself;
+ instance_t *myself;
+ device_t *device;
+ char *method;
+ fstack_t d;
+
+ check_my_self(env, "exec-parent-method");
+ old_myself = MYSELF;
+ MYSELF = MYSELF->parent;
+
+ method = (char *)DS[-1];
+ debug_msg(DEBUG_FIND_FCODE, "exec_parent_method: '%s'\n", method);
+
+ check_my_self(env, "exec-parent-method");
+ device = MYSELF->device;
+ do_push_package(env, device);
+ PUSH(DS, (fstack_t)device);
+ REVERT_PHANDLE(env, TOS, device);
+ find_method(env);
+ d = POP(DS);
+ if (d) {
+ debug_msg(DEBUG_FIND_FCODE, "exec-parent-method: '%s'/%x"
+ " execute\n", method, (int)TOS);
+ execute(env);
+ PUSH(DS, TRUE);
+ } else {
+ debug_msg(DEBUG_FIND_FCODE, "exec-parent-method: '%s'"
+ " not found\n", method);
+ PUSH(DS, FALSE);
+ }
+ MYSELF = old_myself;
+ do_push_package(env, MYSELF->device);
+}
+
+void
+dump_device(fcode_env_t *env)
+{
+ device_t *phandle;
+ int i;
+
+ CONVERT_PHANDLE(env, phandle, POP(DS));
+ log_message(MSG_DEBUG, "Node: %p\n", phandle);
+ log_message(MSG_DEBUG, " Parent: (%8p) %p\n",
+ &phandle->parent, phandle->parent);
+ log_message(MSG_DEBUG, " Child: (%8p) %p\n",
+ &phandle->child, phandle->child);
+ log_message(MSG_DEBUG, " Peer: (%8p) %p\n",
+ &phandle->peer, phandle->peer);
+ log_message(MSG_DEBUG, " Private: (%8p) %p\n",
+ &phandle->private, phandle->private);
+ log_message(MSG_DEBUG, " Props: (%8p) %p\n",
+ &phandle->properties, phandle->properties);
+ log_message(MSG_DEBUG, " Voc: (%8p) %p\n",
+ &phandle->vocabulary, phandle->vocabulary);
+ log_message(MSG_DEBUG, " sizes: (%8p) %d %d\n",
+ &phandle->data_size,
+ phandle->data_size[INIT_DATA],
+ phandle->data_size[UINIT_DATA]);
+ log_message(MSG_DEBUG, " my_space: %x\n", phandle->my_space);
+ log_message(MSG_DEBUG, " my_addr :");
+ for (i = 0; i < MAX_MY_ADDR; i++)
+ log_message(MSG_DEBUG, " %x", (int)phandle->my_addr[i]);
+ log_message(MSG_DEBUG, "\n");
+ log_message(MSG_DEBUG, " data: (%8p)\n", phandle->init_data);
+ for (i = 0; i < phandle->data_size[INIT_DATA]; i++) {
+ log_message(MSG_DEBUG, " %3d -> (%8p) %x\n", i,
+ &phandle->init_data[i], phandle->init_data[i]);
+ }
+}
+
+void
+dump_instance(fcode_env_t *env)
+{
+ int i;
+ instance_t *ihandle;
+
+ ihandle = (instance_t *)POP(DS);
+ log_message(MSG_DEBUG, "Ihandle: %p\n", ihandle);
+ log_message(MSG_DEBUG, " Parent: (%8p) %p\n",
+ &ihandle->parent, ihandle->parent);
+ log_message(MSG_DEBUG, " Device: (%8p) %p\n",
+ &ihandle->device, ihandle->device);
+ log_message(MSG_DEBUG, " args: '%s'\n",
+ ((ihandle->my_args) ? ihandle->my_args : ""));
+ log_message(MSG_DEBUG, " my-space: %x\n", ihandle->my_space);
+ log_message(MSG_DEBUG, " my_addr :");
+ for (i = 0; i < MAX_MY_ADDR; i++)
+ log_message(MSG_DEBUG, " %x", (int)ihandle->my_addr[i]);
+ log_message(MSG_DEBUG, "\n");
+ log_message(MSG_DEBUG, " sizes: %d %d\n",
+ ihandle->device->data_size[INIT_DATA],
+ ihandle->device->data_size[UINIT_DATA]);
+ log_message(MSG_DEBUG, " data: (%8p) %x %x\n",
+ ihandle->data, ihandle->data[0], ihandle->data[1]);
+ if (ihandle->device->data_size[INIT_DATA]) {
+ log_message(MSG_DEBUG, " Initialised:\n");
+ for (i = 0; i < ihandle->device->data_size[INIT_DATA]; i++) {
+ log_message(MSG_DEBUG, " %3d -> (%8p) %x\n", i,
+ &ihandle->data[INIT_DATA][i],
+ ihandle->data[INIT_DATA][i]);
+ }
+ }
+ if (ihandle->device->data_size[INIT_DATA]) {
+ log_message(MSG_DEBUG, " UnInitialised:\n");
+ for (i = 0; i < ihandle->device->data_size[UINIT_DATA]; i++) {
+ log_message(MSG_DEBUG, " %3d -> (%8p) %x\n", i,
+ &ihandle->data[UINIT_DATA][i],
+ ihandle->data[UINIT_DATA][i]);
+ }
+ }
+}
+
+#endif
+
+#pragma init(_init)
+
+#ifdef CONVERT_HANDLES
+static device_t *
+safe_convert_phandle(fcode_env_t *env, fstack_t d)
+{
+ return ((device_t *)d);
+}
+
+static fstack_t
+safe_revert_phandle(fcode_env_t *env, device_t *d)
+{
+ return ((fstack_t)d);
+}
+
+static void
+safe_allocate_phandle(fcode_env_t *env)
+{
+}
+
+#endif
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+ char *name = "/";
+ device_t *d;
+
+ ASSERT(env);
+ NOTICE;
+
+#ifdef CONVERT_HANDLES
+ env->convert_phandle = safe_convert_phandle;
+ env->revert_phandle = safe_revert_phandle;
+ env->allocate_phandle = safe_allocate_phandle;
+#endif
+
+ /* build the root node */
+ d = create_phandle(env, NULL);
+ env->current_device = d;
+ env->root_node = d;
+ push_a_string(env, name);
+ device_name(env);
+ env->current_device = NULL;
+
+ create_my_self(env);
+ create_my_space(env);
+
+ P1275(0x102, 0, "my-address", my_address);
+ /* Fcode 0x103 "my-space" is created using create_internal_value */
+
+ P1275(0x11f, 0, "new-device", new_device);
+
+ P1275(0x127, 0, "finish-device", finish_device);
+
+ FCODE(0x129, 0, "push-package", push_package);
+ FCODE(0x12a, 0, "pop-package", pop_package);
+ FCODE(0x12b, 0, "interpose", interpose);
+
+ P1275(0x202, 0, "my-args", my_args);
+ /* Fcode 0x203 "my-self" is created using create_internal_value */
+ P1275(0x204, 0, "find-package", find_package);
+ P1275(0x205, 0, "open-package", open_package);
+ P1275(0x206, 0, "close-package", close_package);
+ P1275(0x207, 0, "find-method", find_method);
+ P1275(0x208, 0, "call-package", call_package);
+ P1275(0x209, 0, "$call-parent", dollar_call_parent);
+ P1275(0x20a, 0, "my-parent", my_parent);
+ P1275(0x20b, 0, "ihandle>phandle", ihandle_to_phandle);
+
+ P1275(0x20d, 0, "my-unit", my_unit);
+ P1275(0x20e, 0, "$call-method", dollar_call_method);
+ P1275(0x20f, 0, "$open-package", dollar_open_package);
+
+ P1275(0x23b, 0, "child", child_node);
+ P1275(0x23c, 0, "peer", peer_node);
+
+ P1275(0x23f, 0, "set-args", set_args);
+
+ FORTH(IMMEDIATE, "root-node", root_node);
+ FORTH(0, "current-device", current_device);
+ FORTH(0, "pwd$", pwd_dollar);
+ FORTH(IMMEDIATE, "pwd", pwd);
+ FORTH(IMMEDIATE, "ls", do_ls);
+ FORTH(IMMEDIATE, "(cd)", paren_cd);
+ FORTH(IMMEDIATE, "cd", do_cd);
+ FORTH(IMMEDIATE, "device-end", device_end);
+ FORTH(0, "select-dev", do_select_dev);
+ FORTH(0, "unselect-dev", do_unselect_dev);
+ FORTH(0, "begin-package", begin_package);
+ FORTH(0, "end-package", end_package);
+ FORTH(IMMEDIATE, "dump-device", dump_device);
+ FORTH(IMMEDIATE, "dump-instance", dump_instance);
+ FORTH(0, "exec-parent-method", exec_parent_method);
+}
diff --git a/usr/src/lib/efcode/engine/prims64.c b/usr/src/lib/efcode/engine/prims64.c
new file mode 100644
index 0000000000..7a4f7fa9d1
--- /dev/null
+++ b/usr/src/lib/efcode/engine/prims64.c
@@ -0,0 +1,464 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcode/private.h>
+#include <fcdriver/fcdriver.h>
+
+#define LF_PER_XF (sizeof (xforth_t)/sizeof (lforth_t))
+#define WF_PER_XF (sizeof (xforth_t)/sizeof (wforth_t))
+
+void unaligned_xfetch(fcode_env_t *);
+void unaligned_xstore(fcode_env_t *);
+static void xbsplit(fcode_env_t *);
+
+xforth_t
+pop_xforth(fcode_env_t *env)
+{
+ if (sizeof (xforth_t) == sizeof (fstack_t))
+ return (POP(DS));
+ return ((xforth_t)pop_double(env));
+}
+
+xforth_t
+peek_xforth(fcode_env_t *env)
+{
+ xforth_t d;
+
+ d = pop_xforth(env);
+ push_xforth(env, d);
+ return (d);
+}
+
+void
+push_xforth(fcode_env_t *env, xforth_t a)
+{
+ if (sizeof (xforth_t) == sizeof (fstack_t))
+ PUSH(DS, a);
+ else
+ push_double(env, (dforth_t)a);
+}
+
+/*
+ * bxjoin ( b.lo b.2 b.3 b.4 b.5 b.6 b.7 b.hi -- o )
+ */
+static void
+bxjoin(fcode_env_t *env)
+{
+ union {
+ uchar_t b_bytes[sizeof (xforth_t)];
+ xforth_t b_xf;
+ } b;
+ int i;
+
+ CHECK_DEPTH(env, sizeof (xforth_t), "bxjoin");
+ for (i = 0; i < sizeof (xforth_t); i++)
+ b.b_bytes[i] = POP(DS);
+ push_xforth(env, b.b_xf);
+}
+
+/*
+ * <l@ ( qaddr -- n )
+ */
+static void
+lsfetch(fcode_env_t *env)
+{
+ s_lforth_t *addr;
+ xforth_t a;
+
+ CHECK_DEPTH(env, 1, "<l@");
+ addr = (s_lforth_t *)POP(DS);
+ a = *addr;
+ push_xforth(env, a);
+}
+
+/*
+ * lxjoin ( quad.lo quad.hi -- o )
+ */
+static void
+lxjoin(fcode_env_t *env)
+{
+ union {
+ lforth_t b_lf[LF_PER_XF];
+ xforth_t b_xf;
+ } b;
+ int i;
+
+ CHECK_DEPTH(env, LF_PER_XF, "lxjoin");
+ for (i = 0; i < LF_PER_XF; i++)
+ b.b_lf[i] = POP(DS);
+ push_xforth(env, b.b_xf);
+}
+
+/*
+ * wxjoin ( w.lo w.2 w.3 w.hi -- o )
+ */
+static void
+wxjoin(fcode_env_t *env)
+{
+ union {
+ wforth_t b_wf[WF_PER_XF];
+ xforth_t b_xf;
+ } b;
+ int i;
+
+ CHECK_DEPTH(env, WF_PER_XF, "wxjoin");
+ for (i = 0; i < WF_PER_XF; i++)
+ b.b_wf[i] = POP(DS);
+ push_xforth(env, b.b_xf);
+}
+
+/*
+ * x, ( o -- )
+ */
+static void
+xcomma(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "x,");
+ DEBUGF(COMMA, dump_comma(env, "x,"));
+ PUSH(DS, (fstack_t)HERE);
+ unaligned_xstore(env);
+ set_here(env, HERE + sizeof (xforth_t), "xcomma");
+}
+
+/*
+ * x@ ( xaddr -- o )
+ */
+void
+xfetch(fcode_env_t *env)
+{
+ xforth_t *addr;
+ xforth_t a;
+
+ CHECK_DEPTH(env, 1, "x@");
+ addr = (xforth_t *)POP(DS);
+ a = *addr;
+ push_xforth(env, a);
+}
+
+/*
+ * x! ( o xaddr -- )
+ */
+void
+xstore(fcode_env_t *env)
+{
+ xforth_t *addr;
+ xforth_t a;
+
+ CHECK_DEPTH(env, 2, "x!");
+ addr = (xforth_t *)POP(DS);
+ a = pop_xforth(env);
+ *addr = a;
+}
+
+/*
+ * /x ( -- n )
+ */
+static void
+slash_x(fcode_env_t *env)
+{
+ PUSH(DS, sizeof (xforth_t));
+}
+
+/*
+ * /x* ( nu1 -- nu2 )
+ */
+static void
+slash_x_times(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "/x*");
+ TOS *= sizeof (xforth_t);
+}
+
+/*
+ * xa+ ( addr1 index -- addr2 )
+ */
+static void
+xa_plus(fcode_env_t *env)
+{
+ fstack_t index;
+
+ CHECK_DEPTH(env, 2, "xa+");
+ index = POP(DS);
+ TOS += index * sizeof (xforth_t);
+}
+
+/*
+ * xa1+ ( addr1 -- addr2 )
+ */
+static void
+xa_one_plus(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "xa1+");
+ TOS += sizeof (xforth_t);
+}
+
+/*
+ * xbflip ( oct1 -- oct2 )
+ */
+void
+xbflip(fcode_env_t *env)
+{
+ union {
+ uchar_t b_bytes[sizeof (xforth_t)];
+ xforth_t b_xf;
+ } b, c;
+ int i;
+
+ CHECK_DEPTH(env, 1, "xbflip");
+ b.b_xf = pop_xforth(env);
+ for (i = 0; i < sizeof (xforth_t); i++)
+ c.b_bytes[i] = b.b_bytes[(sizeof (xforth_t) - 1) - i];
+ push_xforth(env, c.b_xf);
+}
+
+void
+unaligned_xfetch(fcode_env_t *env)
+{
+ fstack_t addr;
+ int i;
+
+ CHECK_DEPTH(env, 1, "unaligned-x@");
+ addr = POP(DS);
+ for (i = 0; i < sizeof (xforth_t); i++, addr++) {
+ PUSH(DS, addr);
+ cfetch(env);
+ }
+ bxjoin(env);
+ xbflip(env);
+}
+
+void
+unaligned_xstore(fcode_env_t *env)
+{
+ fstack_t addr;
+ int i;
+
+ CHECK_DEPTH(env, 2, "unaligned-x!");
+ addr = POP(DS);
+ xbsplit(env);
+ for (i = 0; i < sizeof (xforth_t); i++, addr++) {
+ PUSH(DS, addr);
+ cstore(env);
+ }
+}
+
+/*
+ * xbflips ( xaddr len -- )
+ */
+static void
+xbflips(fcode_env_t *env)
+{
+ fstack_t len, addr;
+ int i;
+
+ CHECK_DEPTH(env, 2, "xbflips");
+ len = POP(DS);
+ addr = POP(DS);
+ for (i = 0; i < len; i += sizeof (xforth_t),
+ addr += sizeof (xforth_t)) {
+ PUSH(DS, addr);
+ unaligned_xfetch(env);
+ xbflip(env);
+ PUSH(DS, addr);
+ unaligned_xstore(env);
+ }
+}
+
+/*
+ * xbsplit ( o -- b.lo b.2 b.3 b.4 b.5 b.6 b.7 b.hi )
+ */
+static void
+xbsplit(fcode_env_t *env)
+{
+ union {
+ uchar_t b_bytes[sizeof (xforth_t)];
+ xforth_t b_xf;
+ } b;
+ int i;
+
+ CHECK_DEPTH(env, 1, "xbsplit");
+ b.b_xf = pop_xforth(env);
+ for (i = 0; i < sizeof (xforth_t); i++)
+ PUSH(DS, b.b_bytes[(sizeof (xforth_t) - 1) - i]);
+}
+
+/*
+ * xlflip ( oct1 -- oct2 )
+ */
+void
+xlflip(fcode_env_t *env)
+{
+ union {
+ lforth_t b_lf[LF_PER_XF];
+ xforth_t b_xf;
+ } b, c;
+ int i;
+
+ CHECK_DEPTH(env, 1, "xlflip");
+ b.b_xf = pop_xforth(env);
+ for (i = 0; i < LF_PER_XF; i++)
+ c.b_lf[i] = b.b_lf[(LF_PER_XF - 1) - i];
+ push_xforth(env, c.b_xf);
+}
+
+/*
+ * xlflips ( xaddr len -- )
+ */
+static void
+xlflips(fcode_env_t *env)
+{
+ fstack_t len, addr;
+ int i;
+
+ CHECK_DEPTH(env, 2, "xlflips");
+ len = POP(DS);
+ addr = POP(DS);
+ for (i = 0; i < len; i += sizeof (xforth_t),
+ addr += sizeof (xforth_t)) {
+ PUSH(DS, addr);
+ unaligned_xfetch(env);
+ xlflip(env);
+ PUSH(DS, addr);
+ unaligned_xstore(env);
+ }
+}
+
+/*
+ * xlsplit ( o -- quad.lo quad.hi )
+ */
+static void
+xlsplit(fcode_env_t *env)
+{
+ union {
+ lforth_t b_lf[LF_PER_XF];
+ xforth_t b_xf;
+ } b;
+ int i;
+
+ CHECK_DEPTH(env, 1, "xlsplit");
+ b.b_xf = pop_xforth(env);
+ for (i = 0; i < LF_PER_XF; i++)
+ PUSH(DS, b.b_lf[(LF_PER_XF - 1) - i]);
+}
+
+
+/*
+ * xwflip ( oct1 -- oct2 )
+ */
+static void
+xwflip(fcode_env_t *env)
+{
+ union {
+ wforth_t b_wf[WF_PER_XF];
+ xforth_t b_xf;
+ } b, c;
+ int i;
+
+ CHECK_DEPTH(env, 1, "xwflip");
+ b.b_xf = pop_xforth(env);
+ for (i = 0; i < WF_PER_XF; i++)
+ c.b_wf[i] = b.b_wf[(WF_PER_XF - 1) - i];
+ push_xforth(env, c.b_xf);
+}
+
+/*
+ * xwflips ( xaddr len -- )
+ */
+static void
+xwflips(fcode_env_t *env)
+{
+ fstack_t len, addr;
+ int i;
+
+ CHECK_DEPTH(env, 2, "xwflips");
+ len = POP(DS);
+ addr = POP(DS);
+ for (i = 0; i < len; i += sizeof (xforth_t),
+ addr += sizeof (xforth_t)) {
+ PUSH(DS, addr);
+ unaligned_xfetch(env);
+ xwflip(env);
+ PUSH(DS, addr);
+ unaligned_xstore(env);
+ }
+}
+
+/*
+ * xwsplit ( o -- w.lo w.2 w.3 w.hi )
+ */
+static void
+xwsplit(fcode_env_t *env)
+{
+ union {
+ wforth_t b_wf[WF_PER_XF];
+ xforth_t b_xf;
+ } b;
+ int i;
+
+ CHECK_DEPTH(env, 1, "xwsplit");
+ b.b_xf = pop_xforth(env);
+ for (i = 0; i < WF_PER_XF; i++)
+ PUSH(DS, b.b_wf[(WF_PER_XF - 1) - i]);
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+ P1275(0x241, 0, "bxjoin", bxjoin);
+ P1275(0x242, 0, "<l@", lsfetch);
+ P1275(0x243, 0, "lxjoin", lxjoin);
+ P1275(0x244, 0, "wxjoin", wxjoin);
+ P1275(0x245, 0, "x,", xcomma);
+ P1275(0x246, 0, "x@", xfetch);
+ P1275(0x247, 0, "x!", xstore);
+ P1275(0x248, 0, "/x", slash_x);
+ P1275(0x249, 0, "/x*", slash_x_times);
+ P1275(0x24a, 0, "xa+", xa_plus);
+ P1275(0x24b, 0, "xa1+", xa_one_plus);
+ P1275(0x24c, 0, "xbflip", xbflip);
+ P1275(0x24d, 0, "xbflips", xbflips);
+ P1275(0x24e, 0, "xbsplit", xbsplit);
+ P1275(0x24f, 0, "xlflip", xlflip);
+ P1275(0x250, 0, "xlflips", xlflips);
+ P1275(0x251, 0, "xlsplit", xlsplit);
+ P1275(0x252, 0, "xwflip", xwflip);
+ P1275(0x253, 0, "xwflips", xwflips);
+ P1275(0x254, 0, "xwsplit", xwsplit);
+
+ FORTH(0, "unaligned-x@", unaligned_xfetch);
+ FORTH(0, "unaligned-x!", unaligned_xstore);
+}
diff --git a/usr/src/lib/efcode/engine/print.c b/usr/src/lib/efcode/engine/print.c
new file mode 100644
index 0000000000..0db6d6bf49
--- /dev/null
+++ b/usr/src/lib/efcode/engine/print.c
@@ -0,0 +1,265 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcode/private.h>
+
+#define DIGIT(x) (((x) > 9) ? ((x) + 'a' - 10) : ((x) + '0'))
+
+void
+to_digit(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, ">digit");
+ TOS = DIGIT(TOS);
+}
+
+void
+pic_hold(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "hold");
+ *(--env->picturebufpos) = (char) POP(DS);
+}
+
+void
+pic_start(fcode_env_t *env)
+{
+ env->picturebufpos = env->picturebuf + env->picturebuflen - 1;
+ *env->picturebufpos = 0;
+}
+
+void
+pic_ustop(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "u#>");
+ (void) POP(DS);
+ push_string(env, env->picturebufpos, strlen(env->picturebufpos));
+}
+
+void
+pic_unsigned(fcode_env_t *env)
+{
+ ufstack_t a, b;
+
+ CHECK_DEPTH(env, 1, "u#");
+ a = (ufstack_t) TOS;
+ b = a % env->num_base;
+ TOS = (fstack_t) (a / env->num_base);
+ *(--env->picturebufpos) = DIGIT(b);
+}
+
+void
+pic_sign(fcode_env_t *env)
+{
+ fstack_t s;
+
+ CHECK_DEPTH(env, 1, "sign");
+ s = POP(DS);
+ if (s < 0) {
+ PUSH(DS, '-');
+ pic_hold(env);
+ }
+}
+
+static void
+pic_uremainder(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "u#s");
+ do {
+ pic_unsigned(env);
+ } while (TOS);
+}
+
+void
+format_number(fcode_env_t *env, int neg, int width)
+{
+ pic_start(env);
+ if (width == 0) {
+ PUSH(DS, ' ');
+ pic_hold(env);
+ }
+ pic_uremainder(env);
+ if (env->num_base == 10 && neg) {
+ PUSH(DS, '-');
+ pic_hold(env);
+ }
+ width -= strlen(env->picturebufpos);
+ while (width > 0) {
+ PUSH(DS, ' ');
+ pic_hold(env);
+ width--;
+ }
+ pic_ustop(env);
+}
+
+static void
+convert_num(fcode_env_t *env)
+{
+ int n;
+
+ CHECK_DEPTH(env, 1, "(.)");
+ n = 0;
+ if (env->num_base == 10 && TOS < 0) {
+ TOS = -TOS;
+ n = 1;
+ }
+ format_number(env, n, 0);
+}
+
+void
+do_dot_r(fcode_env_t *env)
+{
+ int w, n;
+
+ CHECK_DEPTH(env, 2, ".r");
+ n = 0;
+ w = (int) POP(DS);
+ if (env->num_base == 10 && TOS < 0) {
+ TOS = -TOS;
+ n = 1;
+ }
+ format_number(env, n, w);
+ type(env);
+}
+
+void
+do_udot_r(fcode_env_t *env)
+{
+ int w;
+
+ CHECK_DEPTH(env, 2, "u.r");
+ w = (int) POP(DS);
+ format_number(env, 0, w);
+ type(env);
+}
+
+void
+do_dot(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, ".");
+ PUSH(DS, 0);
+ do_dot_r(env);
+}
+
+void
+do_dot_d(fcode_env_t *env)
+{
+ int base;
+
+ CHECK_DEPTH(env, 1, ".d");
+ base = env->num_base;
+ env->num_base = 10;
+ do_dot(env);
+ env->num_base = base;
+}
+
+void
+do_dot_x(fcode_env_t *env)
+{
+ int base;
+
+ CHECK_DEPTH(env, 1, ".x");
+ base = env->num_base;
+ env->num_base = 16;
+ do_dot(env);
+ env->num_base = base;
+}
+
+void
+do_udot(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 1, "u.");
+ PUSH(DS, 0);
+ do_udot_r(env);
+}
+
+void
+pic_dunsigned(fcode_env_t *env)
+{
+ ufstack_t b;
+ u_dforth_t a;
+
+ CHECK_DEPTH(env, 2, "#");
+ a = pop_double(env);
+ b = a % env->num_base;
+ a /= env->num_base;
+ push_double(env, a);
+ *(--env->picturebufpos) = DIGIT(b);
+}
+
+void
+pic_dremainder(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "#s");
+ do {
+ pic_dunsigned(env);
+ } while (peek_double(env));
+}
+
+void
+pic_dstop(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "#>");
+ (void) pop_double(env);
+ push_string(env, env->picturebufpos, strlen(env->picturebufpos));
+}
+
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+ ASSERT(env);
+ NOTICE;
+
+ env->picturebuflen = 0x100;
+ env->picturebuf = MALLOC(env->picturebuflen);
+
+ ANSI(0x095, 0, "hold", pic_hold);
+ ANSI(0x096, 0, "<#", pic_start);
+ ANSI(0x097, 0, "u#>", pic_ustop);
+ ANSI(0x098, 0, "sign", pic_sign);
+ ANSI(0x099, 0, "u#", pic_unsigned);
+ ANSI(0x09a, 0, "u#s", pic_uremainder);
+ ANSI(0x09b, 0, "u.", do_udot);
+ P1275(0x09c, 0, "u.r", do_udot_r);
+ P1275(0x09d, 0, ".", do_dot);
+ ANSI(0x09e, 0, ".r", do_dot_r);
+
+ ANSI(0x0c7, 0, "#", pic_dunsigned);
+ ANSI(0x0c8, 0, "#s", pic_dremainder);
+ ANSI(0x0c9, 0, "#>", pic_dstop);
+
+ FORTH(0, ">digit", to_digit);
+ FORTH(0, "(.)", convert_num);
+ FORTH(0, ".d", do_dot_d);
+ FORTH(0, ".x", do_dot_x);
+}
diff --git a/usr/src/lib/efcode/engine/properties.c b/usr/src/lib/efcode/engine/properties.c
new file mode 100644
index 0000000000..ff14c1f03c
--- /dev/null
+++ b/usr/src/lib/efcode/engine/properties.c
@@ -0,0 +1,808 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+void
+create_prop(fcode_env_t *env, char *name)
+{
+ push_a_string(env, name);
+ property(env);
+}
+
+void
+create_int_prop(fcode_env_t *env, char *name, int val)
+{
+ PUSH(DS, val);
+ encode_int(env);
+ create_prop(env, name);
+}
+
+void
+create_string_prop(fcode_env_t *env, char *name, char *val)
+{
+ push_a_string(env, val);
+ encode_string(env);
+ create_prop(env, name);
+}
+
+static int
+addr_cmp(void *a, void *b)
+{
+ return ((uchar_t *)a == (uchar_t *)b);
+}
+
+static void *
+add_property_buffer(fcode_env_t *env, int len)
+{
+ void *data = MALLOC(len+1);
+ return (add_resource(&env->propbufs, data, addr_cmp));
+}
+
+static void
+free_property_buffer(fcode_env_t *env, void *buffer)
+{
+ free_resource(&env->propbufs, buffer, addr_cmp);
+ FREE(buffer);
+}
+
+/*
+ * Golden Rule:
+ * DO NOT cache the value of the head of the property list *before*
+ * looking up a property.
+ * This routine is also responsible for purging dead properties
+ * and that *can* affect the head pointer.
+ * you have been warned!
+ */
+prop_t *
+find_property(device_t *d, char *name)
+{
+ prop_t *p = d->properties, *prev;
+ prop_t *found = NULL;
+
+ prev = NULL;
+ while (p && !found) {
+ if (p->name) {
+ if (strcmp(name, p->name) == 0) {
+ found = p;
+ }
+ prev = p;
+ p = p->next;
+ } else {
+ prop_t *dead;
+
+ if (prev)
+ prev->next = p->next;
+ else {
+ /* last prop in chain */
+ d->properties = p->next;
+ }
+ dead = p;
+ p = p->next;
+ FREE(dead->name);
+ FREE(dead->data);
+ FREE(dead);
+ }
+ }
+ return (found);
+}
+
+static prop_t *
+stack_find_property(fcode_env_t *env, device_t *d)
+{
+ char *propname;
+
+ propname = pop_a_string(env, NULL);
+ return (find_property(d, propname));
+}
+
+void
+property(fcode_env_t *env)
+{
+ int datalen;
+ char *propname, *srcptr;
+ prop_t *p;
+ device_t *d;
+
+ CHECK_DEPTH(env, 4, "property");
+ if (MYSELF) {
+ d = MYSELF->device;
+ } else {
+ d = env->current_device;
+ if (!d) {
+ void *buffer;
+
+ two_drop(env);
+ if ((buffer = pop_a_string(env, NULL)) != NULL)
+ free_property_buffer(env, buffer);
+ return;
+ }
+ }
+ propname = pop_a_string(env, NULL);
+ p = find_property(d, propname);
+ if (p == NULL) {
+ p = MALLOC(sizeof (prop_t));
+ p->next = d->properties;
+ d->properties = p;
+ p->name = STRDUP(propname);
+ } else if (p->data)
+ FREE(p->data); /* release old resources */
+ srcptr = pop_a_string(env, &datalen);
+ p->data = MALLOC(datalen+1);
+ p->size = datalen;
+ memcpy(p->data, srcptr, datalen);
+ p->data[datalen] = 0;
+ if (srcptr)
+ free_property_buffer(env, srcptr);
+}
+
+prop_t *
+lookup_package_property(fcode_env_t *env, char *propname, device_t *d)
+{
+ prop_t *p;
+
+ p = find_property(d, propname);
+ if (p) {
+ return (p);
+ }
+ if (d->vectors.get_package_prop) {
+ static prop_t sp;
+ fstack_t fail, n;
+
+ /* recreate the FORTH environment for the remote call */
+ push_a_string(env, propname);
+ REVERT_PHANDLE(env, n, d);
+ PUSH(DS, n);
+ d->vectors.get_package_prop(env);
+ fail = POP(DS);
+ if (fail)
+ return (NULL);
+ sp.size = POP(DS);
+ sp.data = (uchar_t *)POP(DS);
+ sp.name = propname;
+ sp.next = NULL;
+ return (&sp);
+ }
+ return (NULL);
+}
+
+void
+get_package_property(fcode_env_t *env)
+{
+ prop_t *p;
+ device_t *d;
+ char *propname;
+
+ CHECK_DEPTH(env, 3, "get-package-property");
+ CONVERT_PHANDLE(env, d, POP(DS));
+ propname = pop_a_string(env, NULL);
+ p = lookup_package_property(env, propname, d);
+ if (p) {
+ PUSH(DS, (fstack_t)p->data);
+ PUSH(DS, p->size);
+ PUSH(DS, FALSE);
+ } else
+ PUSH(DS, TRUE);
+}
+
+void
+get_inherited_prop(fcode_env_t *env)
+{
+ instance_t *ih;
+ device_t *dev;
+ prop_t *prop;
+ char *pname;
+ int plen;
+
+ /*
+ * First, we look thru the in-memory device tree for the property.
+ * If we don't find it, we call get_inherited_prop, which "knows" it's
+ * not going to find the property below the attachment point.
+ */
+
+ CHECK_DEPTH(env, 2, "get-inherited-property");
+ pname = pop_a_string(env, &plen);
+ ih = MYSELF;
+ if (ih) {
+ for (; ih; ih = ih->parent) {
+ dev = ih->device;
+ prop = find_property(dev, pname);
+ if (prop) {
+ PUSH(DS, (fstack_t)prop->data);
+ PUSH(DS, (fstack_t)prop->size);
+ PUSH(DS, FALSE);
+ return;
+ }
+ }
+ if (dev->vectors.get_inherited_prop) {
+ push_a_string(env, pname);
+ dev->vectors.get_inherited_prop(env);
+ return;
+ }
+ }
+ PUSH(DS, TRUE);
+}
+
+void
+delete_property(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "delete-property");
+ if (MYSELF) {
+ prop_t *p;
+
+ p = stack_find_property(env, MYSELF->device);
+ if (p) {
+ /*
+ * write the name as NULL; the space will be free'd
+ * the next time a property lookup passes this node
+ */
+ p->name = NULL;
+ }
+ } else {
+ two_drop(env);
+ }
+}
+
+void
+get_my_property(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "get-my-property");
+ PUSH(DS, (fstack_t)MYSELF);
+ ihandle_to_phandle(env);
+ get_package_property(env);
+}
+
+void
+encode_string(fcode_env_t *env)
+{
+ char *str;
+ char *prop;
+ int len;
+
+ CHECK_DEPTH(env, 2, "encode-string");
+ str = pop_a_string(env, &len);
+
+ prop = add_property_buffer(env, len);
+ memcpy(prop, str, len);
+ prop[len] = 0;
+ PUSH(DS, (fstack_t)prop);
+ PUSH(DS, len + 1);
+}
+
+void
+encode_int(fcode_env_t *env)
+{
+ uchar_t *ptr;
+ uint32_t p;
+
+ CHECK_DEPTH(env, 1, "encode-int");
+ p = POP(DS);
+ ptr = add_property_buffer(env, sizeof (uint32_t));
+
+ memcpy(ptr, (char *)&p, sizeof (uint32_t));
+ PUSH(DS, (fstack_t)ptr);
+ PUSH(DS, sizeof (uint32_t));
+}
+
+void
+encode_phys(fcode_env_t *env)
+{
+ uint_t ncells;
+
+ ncells = get_number_of_parent_address_cells(env);
+ CHECK_DEPTH(env, ncells, "encode-phys");
+ encode_int(env);
+ while (--ncells) {
+ rot(env);
+ encode_int(env);
+ encode_plus(env);
+ }
+}
+
+static fstack_t
+get_decoded_int(uchar_t *dp)
+{
+ uint32_t d;
+
+ memcpy((char *)&d, dp, sizeof (uint32_t));
+ return (d);
+}
+
+int
+get_default_intprop(fcode_env_t *env, char *name, device_t *d, int def)
+{
+ prop_t *p;
+
+ if (!d) /* Kludge for testing */
+ return (def);
+ p = lookup_package_property(env, name, d);
+ if (p == NULL)
+ return (def);
+ return (get_decoded_int(p->data));
+}
+
+int
+get_num_addr_cells(fcode_env_t *env, device_t *d)
+{
+ return (get_default_intprop(env, "#address-cells", d, 2));
+}
+
+int
+get_num_size_cells(fcode_env_t *env, device_t *d)
+{
+ return (get_default_intprop(env, "#size-cells", d, 1));
+}
+
+void
+decode_phys(fcode_env_t *env)
+{
+ char *ptr;
+ int len;
+ int adr_cells;
+ int offset;
+
+ CHECK_DEPTH(env, 2, "decode-phys");
+ ptr = pop_a_string(env, &len);
+
+ adr_cells = get_num_addr_cells(env, env->current_device->parent);
+
+ offset = sizeof (uint32_t) * adr_cells;
+
+ PUSH(DS, (fstack_t)(ptr + offset));
+ PUSH(DS, len + offset);
+
+ while (adr_cells--) {
+ fstack_t d;
+ offset -= sizeof (uint32_t);
+ d = get_decoded_int((uchar_t *)(ptr + offset));
+ PUSH(DS, d);
+ }
+}
+
+/*
+ * 'reg' Fcode 0x116
+ */
+void
+reg_prop(fcode_env_t *env)
+{
+ fstack_t size;
+
+ CHECK_DEPTH(env, 1, "reg");
+ size = POP(DS);
+ encode_phys(env);
+ PUSH(DS, size);
+ encode_int(env);
+ encode_plus(env);
+ create_prop(env, "reg");
+}
+
+void
+encode_bytes(fcode_env_t *env)
+{
+ char *str;
+ char *prop;
+ int len;
+
+ CHECK_DEPTH(env, 2, "encode-bytes");
+ str = pop_a_string(env, &len);
+ prop = add_property_buffer(env, len);
+ memcpy(prop, str, len);
+ prop[len] = 0;
+ PUSH(DS, (fstack_t)prop);
+ PUSH(DS, len);
+}
+
+void
+decode_int(fcode_env_t *env)
+{
+ char *dp;
+ fstack_t d;
+ int len;
+
+ CHECK_DEPTH(env, 2, "decode-int");
+ dp = pop_a_string(env, &len);
+ PUSH(DS, (fstack_t)(dp + sizeof (uint32_t)));
+ PUSH(DS, len - sizeof (uint32_t));
+ d = get_decoded_int((uchar_t *)dp);
+ PUSH(DS, d);
+}
+
+void
+decode_string(fcode_env_t *env)
+{
+ int plen, len;
+ char *dp;
+
+ CHECK_DEPTH(env, 2, "decode-string");
+ dp = pop_a_string(env, &plen);
+ len = strlen(dp) + 1;
+ PUSH(DS, (fstack_t)(dp + len));
+ PUSH(DS, plen - len);
+ PUSH(DS, (fstack_t)dp);
+ PUSH(DS, len - 1);
+}
+
+void
+encode_plus(fcode_env_t *env)
+{
+ int len1, len2;
+ char *src1, *src2;
+ uchar_t *new;
+
+ CHECK_DEPTH(env, 4, "encode+");
+ src1 = pop_a_string(env, &len1);
+ src2 = pop_a_string(env, &len2);
+ new = add_property_buffer(env, len1 + len2);
+ if (src2) {
+ memcpy(new, src2, len2);
+ free_property_buffer(env, src2);
+ }
+ if (src1) {
+ memcpy(new + len2, src1, len1);
+ free_property_buffer(env, src1);
+ }
+ PUSH(DS, (fstack_t)new);
+ PUSH(DS, len1 + len2);
+}
+
+static void
+make_special_property(fcode_env_t *env, char *name)
+{
+ push_a_string(env, name);
+ property(env);
+}
+
+void
+device_name(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "device-name");
+ encode_string(env);
+ make_special_property(env, "name");
+}
+
+void
+model_prop(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "model");
+ encode_string(env);
+ make_special_property(env, "model");
+}
+
+void
+device_type(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "device-type");
+ encode_string(env);
+ make_special_property(env, "device_type");
+}
+
+/*
+ * 'next-property' Fcode implementation.
+ */
+void
+next_property(fcode_env_t *env)
+{
+ device_t *phandle;
+ char *previous;
+ prop_t *p;
+
+ CHECK_DEPTH(env, 3, "next-property");
+ phandle = (device_t *)POP(DS);
+ previous = pop_a_string(env, NULL);
+ p = phandle->properties;
+ if (previous == NULL)
+ p = phandle->properties;
+ else if (p = find_property(phandle, previous))
+ p = p->next;
+
+ for (; p != NULL && p->name == NULL; p = p->next)
+ ;
+
+ if (p)
+ push_a_string(env, p->name);
+ else
+ push_a_string(env, "");
+ PUSH(DS, TRUE);
+}
+
+void
+get_property(fcode_env_t *env)
+{
+ if (MYSELF)
+ get_my_property(env);
+ else if (env->current_device) {
+ fstack_t d;
+
+ REVERT_PHANDLE(env, d, env->current_device);
+ PUSH(DS, d);
+ get_package_property(env);
+ } else {
+ two_drop(env);
+ log_message(MSG_WARN, "No device context\n");
+ }
+}
+
+#ifdef DEBUG
+
+static void
+print_indented(char *name)
+{
+ log_message(MSG_INFO, "%-28s", name);
+}
+
+static void
+print_string(fcode_env_t *env, uchar_t *data, int len)
+{
+ while (len > 0) {
+ int nlen = (strlen((char *)data)+1);
+ log_message(MSG_INFO, "%s\n", data);
+ len -= nlen;
+ data += nlen;
+ if (len > 0)
+ print_indented("");
+ }
+}
+
+static void
+print_ints(uchar_t *data, int len, int crlf)
+{
+ uint32_t d;
+
+ while (len--) {
+ d = get_decoded_int(data);
+ log_message(MSG_INFO, "%8.8lx ", d);
+ data += sizeof (uint32_t);
+ }
+ if (crlf)
+ log_message(MSG_INFO, "\n");
+}
+
+static void
+print_integer(fcode_env_t *env, uchar_t *data, int len)
+{
+ print_ints(data, len/sizeof (uint32_t), 1);
+}
+
+static void
+print_bytes(fcode_env_t *env, uchar_t *data, int len)
+{
+ while (len--) {
+ log_message(MSG_INFO, "%2.2x ", *data++);
+ }
+ log_message(MSG_INFO, "\n");
+}
+
+static void
+print_bytes_indented(fcode_env_t *env, uchar_t *data, int len)
+{
+ int nbytes;
+
+ for (; ; ) {
+ nbytes = min(len, 16);
+ print_bytes(env, data, nbytes);
+ len -= nbytes;
+ data += nbytes;
+ if (len == 0)
+ break;
+ print_indented("");
+ }
+}
+
+static void
+print_reg(fcode_env_t *env, uchar_t *data, int len)
+{
+ int pcells, nlen;
+
+ if (env->current_device != NULL &&
+ env->current_device->parent != NULL) {
+ pcells = get_num_size_cells(env, env->current_device->parent);
+ pcells += get_num_addr_cells(env, env->current_device->parent);
+ nlen = pcells*sizeof (uint32_t);
+ while (len > 0) {
+ print_ints(data, pcells, 1);
+ len -= nlen;
+ data += nlen;
+ if (len > 0)
+ print_indented("");
+ }
+ } else
+ print_bytes_indented(env, data, len);
+}
+
+static void
+print_imap(fcode_env_t *env, uchar_t *dp, int len)
+{
+ int n, icells;
+
+ if (env->current_device == NULL) {
+ print_bytes_indented(env, dp, len);
+ return;
+ }
+ n = get_num_addr_cells(env, env->current_device);
+
+ while (len) {
+ int offset;
+ fstack_t data;
+ device_t *node;
+
+ offset = 0;
+ data = get_decoded_int(dp+((n+1)*sizeof (uint32_t)));
+ CONVERT_PHANDLE(env, node, data);
+ offset += (n+2)*sizeof (uint32_t);
+ print_ints(dp, (n+2), 0);
+ icells = get_default_intprop(env, "#interrupt-cells", node, 1);
+ print_ints(dp+offset, icells, 1);
+ offset += icells*sizeof (uint32_t);
+ dp += offset;
+ len -= offset;
+ if (len)
+ print_indented("");
+ }
+}
+
+static void
+print_ranges(fcode_env_t *env, uchar_t *data, int len)
+{
+ int pcells, nlen;
+
+ if (env->current_device != NULL &&
+ env->current_device->parent != NULL) {
+ pcells = get_num_addr_cells(env, env->current_device);
+ pcells += get_num_addr_cells(env, env->current_device->parent);
+ pcells += get_num_size_cells(env, env->current_device);
+ nlen = pcells*sizeof (uint32_t);
+ while (len > 0) {
+ print_ints(data, pcells, 1);
+ len -= nlen;
+ data += nlen;
+ if (len > 0)
+ print_indented("");
+ }
+ } else
+ print_bytes_indented(env, data, len);
+}
+
+typedef struct MAGIC_PROP {
+ char *name;
+ void (*fn)(fcode_env_t *env, uchar_t *data, int len);
+} magic_prop_t;
+
+static magic_prop_t magic_props[] = {
+ { "name", print_string },
+ { "device_type", print_string },
+ { "model", print_string },
+ { "reg", print_reg },
+ { "assigned-addresses", print_reg },
+ { "interrupt-map", print_imap },
+ { "#interrupt-cells", print_integer },
+ { "interrupt-map-mask", print_integer },
+ { "#size-cells", print_integer },
+ { "#address-cells", print_integer },
+ { "ranges", print_ranges },
+ { "device-id", print_integer },
+ { "vendor-id", print_integer },
+ { "class-code", print_integer },
+ { "compatible", print_string },
+ { "version", print_string },
+ { "manufacturer", print_string },
+ { NULL, NULL }
+};
+
+static void
+print_content(fcode_env_t *env, char *prop, uchar_t *data, int len)
+{
+ magic_prop_t *p;
+
+ for (p = magic_props; p->name; p++)
+ if (strcmp(prop, p->name) == 0) {
+ (*p->fn)(env, data, len);
+ return;
+ }
+ print_bytes_indented(env, data, len);
+}
+
+void
+print_property(fcode_env_t *env, prop_t *p, char *prepend)
+{
+ char buf[40];
+ char *name = (p->name ? p->name : "<noname>");
+
+ if (prepend) {
+ sprintf(buf, "%s %s", prepend, name);
+ name = buf;
+ }
+ print_indented(name);
+ if (p->name)
+ print_content(env, p->name, p->data, p->size);
+ else
+ print_bytes_indented(env, p->data, p->size);
+}
+
+void
+dot_properties(fcode_env_t *env)
+{
+ prop_t *p;
+ instance_t *omyself;
+
+ omyself = MYSELF;
+ MYSELF = NULL;
+
+ if (env->current_device) {
+ for (p = env->current_device->properties; p; p = p->next)
+ print_property(env, p, NULL);
+ } else {
+ log_message(MSG_INFO, "No device context\n");
+ }
+ MYSELF = omyself;
+}
+
+#endif
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ P1275(0x110, 0, "property", property);
+ P1275(0x111, 0, "encode-int", encode_int);
+ P1275(0x112, 0, "encode+", encode_plus);
+ P1275(0x113, 0, "encode-phys", encode_phys);
+ P1275(0x114, 0, "encode-string", encode_string);
+ P1275(0x115, 0, "encode-bytes", encode_bytes);
+ P1275(0x116, 0, "reg", reg_prop);
+ FCODE(0x117, 0, "intr", fc_obsolete);
+ FCODE(0x118, 0, "driver", fc_historical);
+ P1275(0x119, 0, "model", model_prop);
+ P1275(0x11a, 0, "device-type", device_type);
+
+ P1275(0x128, 0, "decode-phys", decode_phys);
+
+ P1275(0x201, 0, "device-name", device_name);
+
+ P1275(0x21a, 0, "get-my-property", get_my_property);
+ P1275(0x21b, 0, "decode-int", decode_int);
+ P1275(0x21c, 0, "decode-string", decode_string);
+ P1275(0x21d, 0, "get-inherited-property", get_inherited_prop);
+ P1275(0x21e, 0, "delete-property", delete_property);
+ P1275(0x21f, 0, "get-package-property", get_package_property);
+
+ P1275(0x23d, 0, "next-property", next_property);
+
+ FORTH(0, "get-property", get_property);
+ FORTH(0, ".properties", dot_properties);
+}
diff --git a/usr/src/lib/efcode/engine/resource.c b/usr/src/lib/efcode/engine/resource.c
new file mode 100644
index 0000000000..5ede6eea74
--- /dev/null
+++ b/usr/src/lib/efcode/engine/resource.c
@@ -0,0 +1,134 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+fc_resource_t *
+find_resource(fc_resource_t **head, void *ptr, int (cmp)(void *, void *))
+{
+ fc_resource_t *f, *prev, *r = *head;
+
+ f = NULL;
+ prev = NULL;
+ while (r) {
+ if (r->data == NULL) {
+ fc_resource_t *dead;
+
+ if (prev)
+ prev->next = r->next;
+ else {
+ *head = r->next;
+ }
+ dead = r;
+ r = r->next;
+ FREE(dead);
+ } else {
+ if (cmp(ptr, r->data)) {
+ f = r;
+ break;
+ }
+ prev = r;
+ r = r->next;
+ }
+ }
+ return (f);
+}
+
+void *
+add_resource(fc_resource_t **head, void *ptr, int (cmp)(void *, void *))
+{
+ fc_resource_t *r;
+
+ r = find_resource(head, ptr, cmp);
+ if (r == NULL) {
+ r = MALLOC(sizeof (fc_resource_t));
+ r->data = ptr;
+ r->next = *head;
+ *head = r;
+ return (r->data);
+ }
+ log_message(MSG_ERROR, "add_resource: Duplicate entry: %p\n", ptr);
+ return (NULL);
+}
+
+void
+free_resource(fc_resource_t **head, void *ptr, int (cmp)(void *, void *))
+{
+ fc_resource_t *r;
+
+ if ((r = find_resource(head, ptr, cmp)) != NULL)
+ r->data = NULL;
+ else
+ log_message(MSG_ERROR, "free_resource: No such Entry: %p\n",
+ ptr);
+}
+
+#ifdef DEBUG
+
+static int
+dump_print(void *s, void *d)
+{
+ log_message(MSG_DEBUG, "Buffer: %p\n", d);
+ return (0);
+}
+
+void
+dump_resources(fcode_env_t *env)
+{
+ fc_resource_t **head;
+
+ head = (fc_resource_t **) POP(DS);
+ (void) find_resource(head, NULL, dump_print);
+}
+
+void
+propbufs(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t) &env->propbufs);
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ NOTICE;
+ ASSERT(env);
+
+ FORTH(0, "propbufs", propbufs);
+ FORTH(0, "dump-resource", dump_resources);
+}
+
+#endif
diff --git a/usr/src/lib/efcode/engine/signal.c b/usr/src/lib/efcode/engine/signal.c
new file mode 100644
index 0000000000..a023bfd857
--- /dev/null
+++ b/usr/src/lib/efcode/engine/signal.c
@@ -0,0 +1,91 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <sys/time.h>
+#include <sys/termio.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+static fcode_env_t *saved_envp;
+static struct termio saved_termio;
+
+static void
+process_signal(int sig, siginfo_t *sip, void *addr)
+{
+ /*
+ * Format appropriate error message, want fault addr if Bus Error
+ * or Segmentation Violation.
+ */
+ switch (sig) {
+ case SIGSEGV:
+ case SIGBUS:
+ case SIGILL:
+ case SIGFPE:
+ forth_abort(saved_envp, "%s: Fault Addr: 0x%08x",
+ strsignal(sig), sip->si_addr);
+
+ case SIGQUIT:
+ ioctl(fileno(stdin), TCSETA, &saved_termio);
+ log_message(MSG_FATAL, "SIGQUIT\n");
+ abort();
+
+ case SIGINT:
+ ioctl(fileno(stdin), TCSETA, &saved_termio);
+ break;
+ }
+ forth_abort(saved_envp, strsignal(sig));
+}
+
+void
+install_handlers(fcode_env_t *env)
+{
+ struct sigaction sa;
+
+ saved_envp = env;
+
+ ioctl(fileno(stdin), TCGETA, &saved_termio);
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO|SA_NODEFER;
+ sa.sa_handler = 0;
+ sa.sa_sigaction = process_signal;
+
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGQUIT, &sa, NULL);
+ sigaction(SIGSEGV, &sa, NULL);
+ sigaction(SIGBUS, &sa, NULL);
+ sigaction(SIGUSR1, &sa, NULL);
+ sigaction(SIGFPE, &sa, NULL);
+}
diff --git a/usr/src/lib/efcode/engine/sparcv9/Makefile b/usr/src/lib/efcode/engine/sparcv9/Makefile
new file mode 100644
index 0000000000..af568ee0b3
--- /dev/null
+++ b/usr/src/lib/efcode/engine/sparcv9/Makefile
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+include $(SRC)/lib/Makefile.lib.64
+
+sparcv9_C_PICFLAGS = -KPIC
+
+install: all $(ROOTLIBS64)
diff --git a/usr/src/lib/efcode/engine/tracing.c b/usr/src/lib/efcode/engine/tracing.c
new file mode 100644
index 0000000000..43ade86faa
--- /dev/null
+++ b/usr/src/lib/efcode/engine/tracing.c
@@ -0,0 +1,223 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <dlfcn.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#ifdef DEBUG
+
+static void (*trace_fn)(fcode_env_t *);
+
+void
+set_tracer(fcode_env_t *env, void (*tracer)(fcode_env_t *))
+{
+ trace_fn = tracer;
+}
+
+void
+set_level(long lvl)
+{
+ long debug;
+
+ debug = get_interpreter_debug_level();
+ set_interpreter_debug_level(debug | lvl);
+}
+
+void
+unset_level(long lvl)
+{
+ long debug;
+
+ debug = get_interpreter_debug_level();
+ set_interpreter_debug_level(debug & ~lvl);
+}
+
+void
+enable_trace(fcode_env_t *env)
+{
+ set_level(DEBUG_TRACING);
+}
+
+void
+enable_stack_trace(fcode_env_t *env)
+{
+ set_level(DEBUG_TRACE_STACK);
+}
+
+void
+disable_stack_trace(fcode_env_t *env)
+{
+ unset_level(DEBUG_TRACE_STACK);
+}
+
+void
+disable_trace(fcode_env_t *env)
+{
+ unset_level(DEBUG_TRACING);
+}
+
+void
+call_trace(fcode_env_t *env)
+{
+ set_level(DEBUG_CALL_METHOD);
+}
+
+void
+no_call_trace(fcode_env_t *env)
+{
+ unset_level(DEBUG_CALL_METHOD);
+}
+
+void
+do_fclib_trace(fcode_env_t *env, void *fn)
+{
+ void *address;
+ Dl_info dlip;
+ static char buf[80];
+
+ if (dladdr((void *) fn, &dlip)) {
+ int offset;
+
+ address = dlsym(RTLD_DEFAULT, dlip.dli_sname);
+ offset = ((char *) fn) - ((char *) address);
+ if (offset == 0) {
+ log_message(MSG_FC_DEBUG, "%s: tracing %s()\n",
+ dlip.dli_fname, dlip.dli_sname);
+ } else {
+ log_message(MSG_FC_DEBUG, "%s: tracing %s%s0x%x()\n",
+ dlip.dli_fname, dlip.dli_sname,
+ ((offset < 0) ? "-" : "+"),
+ ((offset < 0) ? -offset : offset));
+ }
+ } else {
+ log_message(MSG_FC_DEBUG, "do_fclib_trace: <Unknown> %p\n", fn);
+ }
+ if (trace_fn)
+ trace_fn(env);
+}
+
+void
+output_step_message(fcode_env_t *env)
+{
+ log_message(MSG_INFO, "Step keys: <space>, Continue, Forth, Go,"
+ " Help, Step, Quit\n");
+}
+
+void
+enable_step(fcode_env_t *env)
+{
+ output_step_message(env);
+ set_level(DEBUG_STEPPING);
+}
+
+
+void
+disable_step(fcode_env_t *env)
+{
+ unset_level(DEBUG_STEPPING);
+}
+
+/*
+ * Output of state info is done elsewhere
+ */
+int
+do_fclib_step(fcode_env_t *env)
+{
+ int c;
+ fcode_env_t *new_env;
+
+ for (; ; ) {
+ c = getchar();
+ if (c != '\n') {
+ while (getchar() != '\n')
+ ;
+ }
+ switch (c) {
+ case EOF:
+ case 'q':
+ unbug(env);
+ IP = 0;
+ return (1);
+
+ case 'c':
+ debug_set_level(env,
+ DEBUG_EXEC_TRACE|DEBUG_EXEC_DUMP_DS);
+ break;
+
+ case 'g':
+ unbug(env);
+ break;
+
+ case 'f':
+ unset_level(DEBUG_STEPPING);
+ new_env = clone_environment(env, NULL);
+ do_interact(new_env);
+ destroy_environment(new_env);
+ set_level(DEBUG_STEPPING);
+ continue;
+
+ case ' ':
+ case '\n':
+ break;
+
+ case 'd': /* Unimplemented */
+ case 'u': /* Unimplemented */
+ default:
+ output_step_message(env);
+ continue;
+ }
+ break;
+ }
+ return (0);
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+
+ FORTH(0, "stack-trace", enable_stack_trace);
+ FORTH(0, "no-stack-trace", disable_stack_trace);
+ FORTH(0, "trace-on", enable_trace);
+ FORTH(0, "trace-off", disable_trace);
+ FORTH(0, "call-trace", call_trace);
+ FORTH(0, "no-call-trace", no_call_trace);
+ FORTH(0, "step-on", enable_step);
+ FORTH(0, "step-off", disable_step);
+}
+
+#endif
diff --git a/usr/src/lib/efcode/extend/Makefile b/usr/src/lib/efcode/extend/Makefile
new file mode 100644
index 0000000000..29132d88a1
--- /dev/null
+++ b/usr/src/lib/efcode/extend/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.subdirs
diff --git a/usr/src/lib/efcode/extend/Makefile.com b/usr/src/lib/efcode/extend/Makefile.com
new file mode 100644
index 0000000000..7b25d08906
--- /dev/null
+++ b/usr/src/lib/efcode/extend/Makefile.com
@@ -0,0 +1,38 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+OBJECTS = fthread.o
+LIBRARY = fcthread.a
+
+include ../../Makefile.efcode
+
+#
+# One of our symbols, `env', comes from the fcode interpreter itself,
+# so turn off symbol checking. Yuck.
+#
+ZDEFS =
diff --git a/usr/src/lib/efcode/extend/fthread.c b/usr/src/lib/efcode/extend/fthread.c
new file mode 100644
index 0000000000..4c2c698a4e
--- /dev/null
+++ b/usr/src/lib/efcode/extend/fthread.c
@@ -0,0 +1,96 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+static int envp;
+static int envc;
+static fcode_env_t *envs[4];
+
+static void
+do_clone(fcode_env_t *cenv)
+{
+ fcode_env_t *new;
+
+ if (envc < 4) {
+ envs[envc] = env;
+ envc++;
+ new = clone_environment(cenv, NULL);
+ if (new) {
+ envs[envc] = new;
+ env = new;
+ return;
+ }
+ }
+ system_message(cenv, "clone failed");
+}
+
+static void
+do_switch(fcode_env_t *cenv)
+{
+ int bail = 4;
+ do {
+ envp = (envp+1)%4;
+ env = envs[envp];
+ bail--;
+ } while ((env == NULL) && (!bail));
+ log_message(MSG_INFO, "Env: %x\n", env);
+}
+
+static void
+do_release(fcode_env_t *cenv)
+{
+ int bail = 4;
+ destroy_environment(envs[envp]);
+ envs[envp] = NULL;
+ do {
+ envp = (envp+1)%4;
+ env = envs[envp];
+ bail--;
+ } while ((env == NULL) && (!bail));
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ envp = 0;
+ envc = 0;
+
+ FORTH(0, "clone", do_clone);
+ FORTH(0, "switch", do_switch);
+ FORTH(0, "release", do_release);
+}
diff --git a/usr/src/lib/efcode/extend/sparcv9/Makefile b/usr/src/lib/efcode/extend/sparcv9/Makefile
new file mode 100644
index 0000000000..1c13ef5f37
--- /dev/null
+++ b/usr/src/lib/efcode/extend/sparcv9/Makefile
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+include $(SRC)/lib/Makefile.lib.64
+
+DYNFLAGS += $(FCODE64)
+
+install: all $(ROOTLIBS64)
diff --git a/usr/src/lib/efcode/fcdriver/Makefile b/usr/src/lib/efcode/fcdriver/Makefile
new file mode 100644
index 0000000000..29132d88a1
--- /dev/null
+++ b/usr/src/lib/efcode/fcdriver/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.subdirs
diff --git a/usr/src/lib/efcode/fcdriver/Makefile.com b/usr/src/lib/efcode/fcdriver/Makefile.com
new file mode 100644
index 0000000000..48cbb283fb
--- /dev/null
+++ b/usr/src/lib/efcode/fcdriver/Makefile.com
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+OBJECTS = ioctl.o misc.o dma.o property.o fcdebug.o phandle.o build_tree.o \
+ load_node.o upload.o get_req.o
+LIBRARY = fcdriver.a
+
+include ../../Makefile.efcode
diff --git a/usr/src/lib/efcode/fcdriver/build_tree.c b/usr/src/lib/efcode/fcdriver/build_tree.c
new file mode 100644
index 0000000000..9abcbe9fbc
--- /dev/null
+++ b/usr/src/lib/efcode/fcdriver/build_tree.c
@@ -0,0 +1,250 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+#include <fcntl.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+static fc_phandle_t
+fc_nodeop(common_data_t *cdp, fc_phandle_t node, char *svc)
+{
+ fc_cell_t hcell;
+ int error;
+
+ error = fc_run_priv(cdp, svc, 1, 1, fc_phandle2cell(node), &hcell);
+ if (error)
+ return (NULL);
+ return (fc_cell2phandle(hcell));
+}
+
+void
+recurse_tree(fcode_env_t *env, device_t *d,
+ void (*fn)(fcode_env_t *, device_t *))
+{
+ if (d != NULL) {
+ device_t *p;
+
+ fn(env, d);
+ recurse_tree(env, d->child, fn);
+ recurse_tree(env, d->peer, fn);
+ }
+}
+
+static void
+get_prom_nodeid(fcode_env_t *env, device_t *d)
+{
+ common_data_t *cdp = env->private;
+ private_data_t *pd = d->private;
+ char *name;
+ int namelen;
+ char *namebuf;
+
+ if ((pd != NULL) && (pd->node)) {
+ if (os_get_prop_common(cdp, pd->node, "name",
+ 0, &namebuf, &namelen))
+ namebuf = "<unknown>";
+ debug_msg(DEBUG_UPLOAD, "Populated: %s = %p\n", namebuf,
+ pd->node);
+ return;
+ }
+
+ name = get_package_name(env, d);
+ debug_msg(DEBUG_UPLOAD, "Node %s: %p (%p)\n", name, d, pd);
+ if (d->parent) {
+ private_data_t *ppd = (private_data_t *) d->parent->private;
+ fc_phandle_t thisnode;
+
+ if (os_get_prop_common(cdp, ppd->node, "name",
+ 0, &namebuf, &namelen))
+ namebuf = "<unknown>";
+ debug_msg(DEBUG_UPLOAD, "Parent: %p (%p) %s = %p\n", d->parent,
+ ppd, namebuf, ppd->node);
+ for (thisnode = fc_nodeop(cdp, ppd->node, FC_CHILD_FCODE);
+ thisnode != NULL;
+ thisnode = fc_nodeop(cdp, thisnode, FC_PEER_FCODE)) {
+ int status;
+
+ namebuf = "";
+ namelen = 0;
+ status = os_get_prop_common(cdp, thisnode, "name",
+ 0, &namebuf, &namelen);
+ debug_msg(DEBUG_UPLOAD, "Lookup: %p name '%s'\n"
+ " status: %d", thisnode, namebuf, status);
+ if (status == 0 && strcmp(name, namebuf) == 0)
+ break;
+ }
+ if (thisnode) {
+ pd = MALLOC(sizeof (private_data_t));
+ pd->common = cdp;
+ pd->node = thisnode;
+ pd->upload = 0;
+ d->private = pd;
+ add_my_handle(env, pd->node, d);
+ install_property_vectors(env, d);
+ debug_msg(DEBUG_UPLOAD, "Found: %p\n", thisnode);
+ }
+ }
+}
+
+static void
+update_nodeids(fcode_env_t *env)
+{
+ /*
+ * We scan through the tree looking for nodes that don't have
+ * one of my structures attached, and for each of those nodes
+ * I attempt to match it with a real firmware node
+ */
+ recurse_tree(env, env->root_node, get_prom_nodeid);
+}
+
+static void
+build_nodes(fcode_env_t *env, common_data_t *cdp, fc_phandle_t h)
+{
+ char *name;
+ int len;
+ int n, allocd, depth;
+ fc_phandle_t p;
+ device_t *current, *attach;
+ private_data_t *pd;
+ private_data_t **node_array;
+
+ /*
+ * This is not nice; new_device calls the allocate_phandle
+ * routine without exception, we need to disable the allocation
+ * while we are building the tree to the attachment point
+ * which is why the init_done variable exists.
+ */
+ cdp->init_done = 0;
+ node_array = NULL;
+ depth = 0;
+ allocd = sizeof (private_data_t *);
+ do {
+ node_array = REALLOC(node_array, allocd*(depth+1));
+ pd = MALLOC(sizeof (private_data_t));
+ pd->node = h;
+ node_array[depth] = pd;
+ name = NULL;
+ (void) os_get_prop_common(cdp, pd->node, "name", 0, &name,
+ &len);
+ if (name)
+ debug_msg(DEBUG_UPLOAD, "Node: %p name: '%s'\n", h,
+ name);
+ else
+ log_message(MSG_ERROR, "Node: %p Unnamed node!!\n", h);
+ depth++;
+ h = fc_nodeop(cdp, h, FC_PARENT);
+ } while (h);
+
+ for (n = 0; n < (depth-1); n++) {
+ new_device(env);
+ }
+
+ env->attachment_pt = current = attach = env->current_device;
+
+ for (n = 0; n < depth; n++) {
+ pd = node_array[n];
+ pd->common = cdp;
+ current->private = pd;
+ add_my_handle(env, pd->node, current);
+ install_property_vectors(env, current);
+ current = current->parent;
+ }
+
+ for (current = attach; current != NULL; current = current->parent) {
+ install_node_data(env, current);
+ if (current->parent)
+ finish_device(env);
+ }
+
+ FREE(node_array);
+ cdp->init_done = 2;
+ update_nodeids(env);
+ cdp->init_done = 1;
+ cdp->first_node = 1;
+}
+
+void
+build_tree(fcode_env_t *env)
+{
+ common_data_t *cdp = env->private;
+ instance_t *ih;
+
+ root_node(env);
+ ih = open_instance_chain(env, env->current_device, 0);
+ MYSELF = ih;
+ build_nodes(env, cdp, cdp->attach);
+ close_instance_chain(env, ih, 0);
+ MYSELF = 0;
+ device_end(env);
+}
+
+/*
+ * Installs /openprom and /packages nodes and sub-nodes.
+ */
+void
+install_builtin_nodes(fcode_env_t *env)
+{
+ common_data_t *cdp = env->private;
+ int saved_first_node;
+ int saved_init_done;
+
+ if (cdp) {
+ saved_first_node = cdp->first_node;
+ saved_init_done = cdp->init_done;
+ cdp->first_node = 0;
+ cdp->init_done = 2;
+ install_openprom_nodes(env);
+ install_package_nodes(env);
+ cdp->first_node = saved_first_node;
+ cdp->init_done = saved_init_done;
+ }
+}
+
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ FORTH(0, "update-nodes", update_nodeids);
+ FORTH(0, "build-tree", build_tree);
+}
diff --git a/usr/src/lib/efcode/fcdriver/dma.c b/usr/src/lib/efcode/fcdriver/dma.c
new file mode 100644
index 0000000000..669a681905
--- /dev/null
+++ b/usr/src/lib/efcode/fcdriver/dma.c
@@ -0,0 +1,123 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+
+static void
+do_dma_alloc(fcode_env_t *env)
+{
+ size_t size;
+ void *p;
+
+ CHECK_DEPTH(env, 1, "dma-alloc");
+ size = (size_t) POP(DS);
+ p = valloc(size);
+ debug_msg(DEBUG_REG_ACCESS, "dma-alloc ( %x ) -> %p\n", (int)size, p);
+ throw_from_fclib(env, (p == 0), "dma-alloc failed");
+ PUSH(DS, (fstack_t) p);
+}
+
+static void
+do_dma_free(fcode_env_t *env)
+{
+ void *p;
+ size_t size;
+
+ CHECK_DEPTH(env, 2, "dma-free");
+ size = POP(DS);
+ p = (void *) POP(DS);
+ debug_msg(DEBUG_REG_ACCESS, "dma-free ( %p %x )\n", p, (int)size);
+
+ free(p);
+}
+
+static void
+do_dma_map_in(fcode_env_t *env)
+{
+ fc_cell_t data;
+ fstack_t va, len, cacheable;
+ private_data_t *pd = DEVICE_PRIVATE(env);
+ int error;
+
+ CHECK_DEPTH(env, 3, "dma-map-in");
+ cacheable = POP(DS);
+ len = POP(DS);
+ va = POP(DS);
+
+ error = fc_run_priv(pd->common, "dma-map-in", 3, 1,
+ fc_int2cell(cacheable), fc_size2cell(len), fc_ptr2cell(va),
+ &data);
+
+ throw_from_fclib(env, error, "dma-map-in failed");
+
+ PUSH(DS, (fstack_t)data);
+}
+
+static void
+do_dma_map_out(fcode_env_t *env)
+{
+ fstack_t va, dva, len;
+ private_data_t *pd = DEVICE_PRIVATE(env);
+ int error;
+
+ CHECK_DEPTH(env, 3, "dma-map-out");
+ len = POP(DS);
+ dva = POP(DS);
+ va = POP(DS);
+
+ error = fc_run_priv(pd->common, "dma-map-out", 3, 0, fc_size2cell(len),
+ fc_ptr2cell(dva), fc_ptr2cell(va));
+
+ throw_from_fclib(env, error, "dma-map-out failed");
+}
+
+static void
+do_dma_sync(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 3, "dma-sync");
+ /* 3drop */
+ DS -= 3;
+}
+
+void
+install_dma_methods(fcode_env_t *env)
+{
+ FORTH(0, "dma-alloc", do_dma_alloc);
+ FORTH(0, "dma-free", do_dma_free);
+ FORTH(0, "dma-map-in", do_dma_map_in);
+ FORTH(0, "dma-map-out", do_dma_map_out);
+ FORTH(0, "dma-sync", do_dma_sync);
+
+}
diff --git a/usr/src/lib/efcode/fcdriver/fcdebug.c b/usr/src/lib/efcode/fcdriver/fcdebug.c
new file mode 100644
index 0000000000..fee58574eb
--- /dev/null
+++ b/usr/src/lib/efcode/fcdriver/fcdebug.c
@@ -0,0 +1,116 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+static void
+dump_private(fcode_env_t *env)
+{
+ common_data_t *cdp;
+ private_data_t *p;
+
+ if (env->current_device) {
+ p = env->current_device->private;
+ if (p) {
+ cdp = p->common;
+ } else
+ cdp = NULL;
+ } else {
+ cdp = env->private;
+ p = NULL;
+ }
+
+ if (cdp == NULL) {
+ log_message(MSG_ERROR, "dump_private: NULL private ptr!\n");
+ return;
+ }
+
+ log_message(MSG_DEBUG, "Private Data:\n");
+ log_message(MSG_DEBUG, "Progname: %s\n", cdp->Progname);
+ log_message(MSG_DEBUG, "fcode_fd: %8p\n", cdp->fcode_fd);
+ log_message(MSG_DEBUG, "attach: %llx\n", cdp->attach);
+ log_message(MSG_DEBUG, "Params: (%8p)\n", &cdp->fc);
+ log_message(MSG_DEBUG, " size: %d\n", cdp->fc.fcode_size);
+ log_message(MSG_DEBUG, " unit: %s\n", cdp->fc.unit_address);
+ if (p != NULL) {
+ log_message(MSG_DEBUG, "Node: %p\n", p->node);
+ log_message(MSG_DEBUG, "Parent: %p\n", p->parent);
+ log_message(MSG_DEBUG, "upload: %d\n", p->upload);
+ log_message(MSG_DEBUG, "debug: %8x\n", p->debug);
+ }
+}
+
+static void
+trigger(fcode_env_t *env)
+{
+ common_data_t *cdp = (common_data_t *)env->private;
+
+ ASSERT(cdp);
+
+ cdp->fcode_fd = open("/dev/fcode", O_RDONLY);
+ if (cdp->fcode_fd >= 0) {
+ log_message(MSG_INFO, "Trigger...");
+ if (!fc_get_request(cdp))
+ log_message(MSG_ERROR, "fc_get_request failed\n");
+ else
+ log_message(MSG_INFO, "\n");
+ } else
+ forth_abort(env, "Can't open /dev/fcode\n");
+}
+
+static void
+do_trigger(fcode_env_t *env)
+{
+ trigger(env);
+ build_tree(env);
+ install_builtin_nodes(env);
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ FORTH(0, "dump-private", dump_private);
+ FORTH(0, "trigger", do_trigger);
+}
diff --git a/usr/src/lib/efcode/fcdriver/get_req.c b/usr/src/lib/efcode/fcdriver/get_req.c
new file mode 100644
index 0000000000..6a87b375d5
--- /dev/null
+++ b/usr/src/lib/efcode/fcdriver/get_req.c
@@ -0,0 +1,466 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+#include <errno.h>
+
+#include <sys/mman.h>
+#include <sys/pci.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+static char *pkg_my_args;
+static char fcode_dev[] = "/dev/fcode";
+
+static void
+dot_request(fcode_env_t *env)
+{
+ common_data_t *cdp = env->private;
+
+ log_message(MSG_INFO, "request: cfgadd: %x fc_size: %x unitadd: %s"
+ " attach: %x args: '%s'\n", cdp->fc.config_address,
+ cdp->fc.fcode_size, cdp->fc.unit_address, cdp->attach,
+ pkg_my_args ? pkg_my_args : "<null>");
+}
+
+/*
+ * Get next request from /dev/fcode.
+ */
+int
+fc_get_request(common_data_t *cdp)
+{
+ char c;
+ int nbytes;
+
+ if (cdp->fcode_fd < 0) {
+ log_message(MSG_FATAL, "fc_get_request: fcode_fd not open\n");
+ return (0);
+ }
+
+ if ((nbytes = read(cdp->fcode_fd, &c, sizeof (c))) < 0) {
+ log_perror(MSG_FATAL, "read(%s) failed", fcode_dev);
+ return (0);
+ }
+
+ if (ioctl(cdp->fcode_fd, FC_GET_PARAMETERS, &cdp->fc) < 0) {
+ log_perror(MSG_FATAL, "ioctl(FC_GET_PARAMETERS) failed");
+ return (0);
+ }
+
+ if ((cdp->attach = fc_get_ap(cdp)) == NULL)
+ return (0);
+
+ return (1);
+}
+
+static void
+get_my_args(fcode_env_t *env)
+{
+ common_data_t *cdp = env->private;
+ char buffer[BUFSIZ];
+
+ /*
+ * Don't get if already set.
+ */
+ if (pkg_my_args)
+ return;
+
+ if (ioctl(cdp->fcode_fd, FC_GET_MY_ARGS, buffer) < 0) {
+ return;
+ }
+ pkg_my_args = STRDUP(buffer);
+}
+
+static void
+set_my_args(fcode_env_t *env)
+{
+ if (pkg_my_args)
+ FREE(pkg_my_args);
+
+ parse_word(env);
+ pkg_my_args = pop_a_duped_string(env, NULL);
+}
+
+static void
+dot_my_args(fcode_env_t *env)
+{
+ if (pkg_my_args)
+ log_message(MSG_INFO, "%s\n", pkg_my_args);
+ else
+ log_message(MSG_INFO, "NULL\n");
+}
+
+void
+push_my_args(fcode_env_t *env)
+{
+ push_a_string(env, pkg_my_args);
+}
+
+void
+get_fcode_from_device(fcode_env_t *env)
+{
+ common_data_t *cdp = env->private;
+ char *p, *buf;
+ static char func_name[] = "get_fcode_from_device";
+ fc_fcode_info_t fcode_info;
+
+ if (!cdp->fc.fcode_size) {
+ debug_msg(DEBUG_FIND_FCODE, "%s: Fcode zero length\n",
+ func_name);
+ push_a_string(env, NULL);
+ return;
+ }
+ fcode_info.fcode_size = cdp->fc.fcode_size;
+ fcode_info.fcode_ptr = MALLOC(cdp->fc.fcode_size);
+ if (ioctl(cdp->fcode_fd, FC_GET_FCODE_DATA, &fcode_info) < 0) {
+ log_perror(MSG_FATAL, "ioctl(FC_GET_FCODE_DATA) failed");
+ push_a_string(env, NULL);
+ } else {
+ debug_msg(DEBUG_FIND_FCODE,
+ "%s: Fcode from device: len: 0x%x\n", func_name,
+ (int)cdp->fc.fcode_size);
+ PUSH(DS, (fstack_t)fcode_info.fcode_ptr);
+ PUSH(DS, (fstack_t)cdp->fc.fcode_size);
+ }
+}
+
+static void
+save_fcode_to_file(fcode_env_t *env)
+{
+ char *buf, *fname;
+ int len;
+ FILE *fd;
+
+ CHECK_DEPTH(env, 4, "save-fcode-to-file");
+ if ((fname = pop_a_string(env, NULL)) == NULL) {
+ log_message(MSG_DEBUG, "fname?\n");
+ return;
+ }
+ if ((buf = pop_a_string(env, &len)) == NULL) {
+ log_message(MSG_INFO, "buf?\n");
+ return;
+ }
+ if ((fd = fopen(fname, "w")) == NULL) {
+ log_perror(MSG_DEBUG, "Save_fcode_to_file: Can't open '%s'",
+ fname);
+ return;
+ }
+ log_message(MSG_INFO, "Fcode %p,%x to file '%s'\n", buf, len, fname);
+ fwrite(buf, len, sizeof (char), fd);
+ fclose(fd);
+}
+
+void
+exec_fcode_builtin_method(fcode_env_t *env)
+{
+ fstack_t d;
+ char *method;
+ extern void exec_parent_method(fcode_env_t *);
+ extern void exec_builtin_driver(fcode_env_t *);
+
+ method = (char *)DS[-1];
+ exec_parent_method(env);
+ d = POP(DS);
+ if (d) {
+ debug_msg(DEBUG_FIND_FCODE, "builtin-driver: %s -> %s found\n",
+ method, (char *)DS[-1]);
+ exec_builtin_driver(env);
+ debug_msg(DEBUG_FIND_FCODE, "builtin-driver-exec: %p %x\n",
+ (char *)DS[-1], (int)TOS);
+ } else {
+ debug_msg(DEBUG_FIND_FCODE, "builtin-driver: %s not found\n",
+ method);
+ PUSH(DS, FALSE);
+ }
+}
+
+void
+get_fcode_from_filesystem(fcode_env_t *env)
+{
+ fstack_t d;
+ char *method, *fc_name, *path;
+ extern void exec_parent_method(fcode_env_t *);
+ static char fname[] = "get-fcode-from-filesystem";
+
+ method = (char *)DS[-1];
+ exec_parent_method(env);
+ d = POP(DS);
+ if (d) {
+ fc_name = pop_a_string(env, NULL);
+ debug_msg(DEBUG_FIND_FCODE, "%s: %s -> %s found\n", fname,
+ method, fc_name);
+ if ((path = search_for_fcode_file(env, fc_name)) != NULL) {
+ debug_msg(DEBUG_FIND_FCODE, "%s: file: %s FOUND\n",
+ fname, path);
+ push_a_string(env, path);
+ load_file(env);
+ } else {
+ debug_msg(DEBUG_FIND_FCODE, "%s: file '%s' not found\n",
+ fname, fc_name);
+ PUSH(DS, FALSE);
+ }
+ } else {
+ debug_msg(DEBUG_FIND_FCODE, "%s: method '%s' not found\n",
+ fname, method);
+ PUSH(DS, FALSE);
+ }
+}
+
+/*
+ * Looks for "device-id" and "class-id" methods in parent, if there,
+ * executes them to get "builtin drivers" file name or method name, then
+ * executes the builtin-driver method. If both those fail, try getting the
+ * fcode from the device. Note that we sleaze resetting the data stack.
+ * This would be cleaner if we had a way to do the equivalent of "catch/throw"
+ * from within C code.
+ */
+void
+find_fcode(fcode_env_t *env)
+{
+ fstack_t *dp = env->ds;
+ static char func_name[] = "find_fcode";
+
+ my_unit(env);
+ push_a_string(env, "device-id");
+ get_fcode_from_filesystem(env);
+ if (TOS) {
+ debug_msg(DEBUG_FIND_FCODE, "%s: FS dev-id: len: 0x%x\n",
+ func_name, TOS);
+ return;
+ }
+
+ env->ds = dp;
+ my_unit(env);
+ push_a_string(env, "class-id");
+ get_fcode_from_filesystem(env);
+ if (TOS) {
+ debug_msg(DEBUG_FIND_FCODE, "%s: FS cls-id len: 0x%x\n",
+ func_name, TOS);
+ return;
+ }
+
+ env->ds = dp;
+ get_fcode_from_device(env);
+ if (TOS) {
+ debug_msg(DEBUG_FIND_FCODE, "%s: DEV fcode len: 0x%x\n",
+ func_name, TOS);
+ return;
+ }
+
+ env->ds = dp;
+ my_unit(env);
+ push_a_string(env, "device-id");
+ exec_fcode_builtin_method(env);
+ if (TOS) {
+ debug_msg(DEBUG_FIND_FCODE, "%s: dropin dev-id len: 0x%x\n",
+ func_name, TOS);
+ return;
+ }
+
+ env->ds = dp;
+ my_unit(env);
+ push_a_string(env, "class-id");
+ exec_fcode_builtin_method(env);
+ if (TOS) {
+ debug_msg(DEBUG_FIND_FCODE, "%s: dropin cls-id len: 0x%x\n",
+ func_name, TOS);
+ return;
+ }
+ debug_msg(DEBUG_FIND_FCODE, "%s: not found\n", func_name);
+}
+
+int
+open_fcode_dev(fcode_env_t *env)
+{
+ common_data_t *cdp = env->private;
+
+ if ((cdp->fcode_fd = open(fcode_dev, O_RDONLY)) < 0)
+ log_perror(MSG_ERROR, "Can't open '%s'", fcode_dev);
+ return (cdp->fcode_fd >= 0);
+}
+
+static void
+get_request(fcode_env_t *env)
+{
+ common_data_t *cdp = env->private;
+
+ if (cdp->fcode_fd >= 0)
+ close(cdp->fcode_fd);
+ if (!open_fcode_dev(env))
+ exit(1);
+ if (!fc_get_request(cdp)) {
+ log_message(MSG_FATAL, "fc_get_request failed\n");
+ exit(1);
+ }
+
+ get_my_args(env);
+
+ DEBUGF(UPLOAD, dot_request(env));
+}
+
+/*
+ * invoked from efdaemon, /dev/fcode event has been read and /dev/fcode opened
+ * file descriptor is fd 0.
+ */
+static void
+get_efdaemon_request(fcode_env_t *env)
+{
+ common_data_t *cdp = env->private;
+
+ cdp->fcode_fd = 0;
+ if (ioctl(cdp->fcode_fd, FC_GET_PARAMETERS, &cdp->fc) < 0) {
+ log_perror(MSG_FATAL, "ioctl(FC_GET_PARAMETERS) failed");
+ exit(1);
+ }
+
+ if ((cdp->attach = fc_get_ap(cdp)) == NULL)
+ exit(1);
+
+ get_my_args(env);
+
+ DEBUGF(UPLOAD, dot_request(env));
+}
+
+static void
+process_request(fcode_env_t *env)
+{
+ common_data_t *cdp = env->private;
+ fstack_t fcode_len;
+ char *path;
+
+ build_tree(env);
+ install_builtin_nodes(env);
+ push_my_args(env);
+ push_a_string(env, cdp->fc.unit_address);
+ if ((path = get_path(env, env->attachment_pt)) == NULL) {
+ log_message(MSG_FATAL, "Can't get_path of"
+ " attachment_pt %p\n", env->attachment_pt);
+ exit(1);
+ }
+ debug_msg(DEBUG_UPLOAD, "Attach Point: %s\n", path);
+
+ push_a_string(env, path);
+ begin_package(env);
+ find_fcode(env);
+ fcode_len = POP(DS);
+ if (!fcode_len) {
+ (void) POP(DS);
+ debug_msg(DEBUG_UPLOAD, "Zero length Fcode\n");
+ return;
+ }
+
+ debug_msg(DEBUG_UPLOAD, "byte-load fcode_len: %x\n",
+ fcode_len);
+
+ PUSH(DS, 1);
+ byte_load(env);
+ end_package(env);
+ upload_nodes(env);
+ validate_nodes(env);
+ debug_msg(DEBUG_UPLOAD, "Upload Done\n");
+}
+
+static void
+finish_request(fcode_env_t *env)
+{
+ common_data_t *cdp = env->private;
+
+ close(cdp->fcode_fd);
+}
+
+/*
+ * Non-daemon "do-request", for debugging
+ */
+static void
+do_request(fcode_env_t *env)
+{
+ get_request(env);
+ process_request(env);
+ finish_request(env);
+}
+
+/*
+ * This process one request from efdaemon, we know that /dev/fcode is already
+ * open and passed in fd0 (stdin). If it's not, we throw up our hands.
+ */
+void
+run_one_efdaemon_request(fcode_env_t *env)
+{
+ get_efdaemon_request(env);
+ process_request(env);
+ finish_request(env);
+ exit(0);
+}
+
+void
+probe_space(fcode_env_t *env)
+{
+ fc_cell_t cfg = 0;
+ int error;
+
+ error = fc_run_priv(env->private, FC_PROBE_SPACE, 0, 1, &cfg);
+ if (error)
+ throw_from_fclib(env, 1, "FC_PROBE_SPACE failed\n");
+ PUSH(DS, fc_cell2uint32_t(cfg));
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ FORTH(0, "get-fcode-from-device", get_fcode_from_device);
+ FORTH(0, "save-fcode-to-file", save_fcode_to_file);
+ FORTH(0, "get-my-args", get_my_args);
+ FORTH(0, "set-my-args", set_my_args);
+ FORTH(0, ".my-args", dot_my_args);
+ FORTH(0, ".request", dot_request);
+ FORTH(0, "get-request", get_request);
+ FORTH(0, "process-request", process_request);
+ FORTH(0, "finish-request", finish_request);
+ FORTH(0, "do-request", do_request);
+ FORTH(0, "find-fcode", find_fcode);
+ FORTH(0, "exec-fcode-builtin-method", exec_fcode_builtin_method);
+ FORTH(0, "run-one-efdaemon-request", run_one_efdaemon_request);
+ FORTH(0, "get-efdaemon-request", get_efdaemon_request);
+ FORTH(0, "probe-space", probe_space);
+}
diff --git a/usr/src/lib/efcode/fcdriver/ioctl.c b/usr/src/lib/efcode/fcdriver/ioctl.c
new file mode 100644
index 0000000000..218ceb88db
--- /dev/null
+++ b/usr/src/lib/efcode/fcdriver/ioctl.c
@@ -0,0 +1,110 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+#define FCC_MAX_CELLS 10
+
+int
+fc_run_priv(common_data_t *cdp, char *service, int nin, int nout, ...)
+{
+ va_list ap;
+ int i, error, no_err;
+ fc_cell_t fc_req[FCC_FIXED_CELLS+FCC_MAX_CELLS];
+ struct fc_client_interface *cip = (struct fc_client_interface *)fc_req;
+ fc_cell_t *fcp;
+ char *error_msg;
+
+ no_err = nin & FCRP_NOERROR;
+ nin &= ~FCRP_NOERROR;
+
+ bzero(fc_req, sizeof (fc_req));
+ if (nin + nout > FCC_MAX_CELLS) {
+ log_message(MSG_ERROR, "%s: too many ins (%d) and outs (%d)\n",
+ service, nin, nout);
+ nin = min(nin, FCC_MAX_CELLS);
+ nout = FCC_MAX_CELLS - nin;
+ }
+ va_start(ap, nout);
+ cip->svc_name = fc_ptr2cell(service);
+ cip->nargs = fc_int2cell(nin);
+ cip->nresults = fc_int2cell(nout);
+ for (i = 0; i < nin; i++)
+ fc_arg(cip, i) = va_arg(ap, fc_cell_t);
+ error = ioctl(cdp->fcode_fd, FC_RUN_PRIV, cip);
+ for (i = 0; i < nout; i++) {
+ fcp = va_arg(ap, fc_cell_t *);
+ *fcp = fc_result(cip, i);
+ }
+ va_end(ap);
+
+ if (error)
+ error_msg = strerror(errno);
+ else if (cip->priv_error) {
+ error_msg = "Priv violation";
+ error = 1;
+ } else if (cip->error) {
+ error_msg = "Error";
+ error = 1;
+ }
+ if ((error & !no_err) ||
+ (get_interpreter_debug_level() & DEBUG_REG_ACCESS)) {
+ if (error)
+ log_message(MSG_ERROR, "%s: FC_RUN_PRIV: %s: ",
+ cdp->Progname, error_msg);
+ log_message(MSG_ERROR, "%s ( ", service);
+ for (i = 0; i < nin; i++)
+ log_message(MSG_ERROR, "%llx ",
+ (uint64_t)fc_arg(cip, i));
+ log_message(MSG_ERROR, ")");
+ if (error)
+ ;
+ else if (nout) {
+ log_message(MSG_ERROR, " ->");
+ for (i = 0; i < nout; i++)
+ log_message(MSG_ERROR, " %llx",
+ (uint64_t)fc_result(cip, i));
+ } else
+ log_message(MSG_ERROR, " OK");
+ log_message(MSG_ERROR, "\n");
+ }
+ return (error);
+}
diff --git a/usr/src/lib/efcode/fcdriver/load_node.c b/usr/src/lib/efcode/fcdriver/load_node.c
new file mode 100644
index 0000000000..613a1f94f6
--- /dev/null
+++ b/usr/src/lib/efcode/fcdriver/load_node.c
@@ -0,0 +1,289 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/shm.h>
+#include <dlfcn.h>
+#include <sys/systeminfo.h>
+#include <sys/utsname.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+static char *default_search_path;
+static char search_proto[] =
+ "/usr/platform/%s/lib/efcode%s:"
+ "/usr/platform/%s/lib/efcode%s:"
+ "/usr/lib/efcode%s";
+
+/*
+ * Build the library/drop-in fcode search path. If there's no architecture
+ * passed, we build the search path (per the PSARC decision):
+ * /usr/platform/`uname -i`/lib/efcode
+ * /usr/platform/`uname -m`/lib/efcode
+ * /usr/lib/efcode
+ * If there is an architecture passed, we prepend the following search path to
+ * the above:
+ * /usr/platform/`uname -i`/lib/efcode/{architecture}
+ * /usr/platform/`uname -m`/lib/efcode/{architecture}
+ * /usr/lib/efcode/{architecture}
+ * This allows FCode drop-in searches to find FCode in the non-architecture
+ * directories.
+ */
+static void
+build_default_search_path(char *arch)
+{
+ char platform[100], *p;
+ struct stat statb;
+ struct utsname utsname;
+ int len;
+
+ sysinfo(SI_PLATFORM, platform, sizeof (platform));
+ uname(&utsname);
+ len = strlen(search_proto) + strlen(platform) + strlen(utsname.machine);
+ if (*arch != '\0') {
+ len += len + (3 * strlen(arch)) + 1;
+ }
+ default_search_path = MALLOC(len);
+ if (*arch != '\0') {
+ sprintf(default_search_path, search_proto, platform, arch,
+ utsname.machine, arch, arch);
+ p = default_search_path + strlen(default_search_path);
+ *p++ = ':';
+ } else
+ p = default_search_path;
+
+ sprintf(p, search_proto, platform, "", utsname.machine, "", "");
+}
+
+static void
+set_default_search_path(fcode_env_t *env)
+{
+ if (default_search_path)
+ FREE(default_search_path);
+
+ parse_word(env);
+ default_search_path = pop_a_duped_string(env, NULL);
+}
+
+static void
+get_default_search_path(fcode_env_t *env)
+{
+ push_a_string(env, default_search_path);
+}
+
+/*
+ * Complicated by fact that a library (e.g. a 32-bit library) can match the
+ * file name. But if we're running as 64-bit, dlopen on that library will
+ * fail.
+ */
+static char *
+search_path(char *name, char *search, int (*fn)(char *))
+{
+ char *p, *next_p;
+ char *tpath, *fpath;
+
+ fpath = STRDUP(search);
+ for (p = fpath; p != NULL; p = next_p) {
+ if ((next_p = strchr(p, ':')) != NULL)
+ *next_p++ = '\0';
+ tpath = MALLOC(strlen(p) + strlen(name) + 2);
+ sprintf(tpath, "%s/%s", p, name);
+ if ((*fn)(tpath)) {
+ FREE(fpath);
+ return (tpath);
+ }
+ FREE(tpath);
+ }
+ FREE(fpath);
+ return (NULL);
+}
+
+static int
+load_lib_file(char *path)
+{
+ struct stat buf;
+
+ debug_msg(DEBUG_FIND_FCODE, "load_lib_file: '%s' -> ", path);
+ if (stat(path, &buf)) {
+ debug_msg(DEBUG_FIND_FCODE, "stat failed\n");
+ return (0);
+ }
+ if (dlopen(path, RTLD_NOW) != NULL) {
+ debug_msg(DEBUG_FIND_FCODE, "OK\n");
+ return (1);
+ }
+ debug_msg(DEBUG_FIND_FCODE, "dlopen failed\n");
+ return (0);
+}
+
+static int
+is_fcode_file(char *path)
+{
+ struct stat statb;
+ int fd;
+ uchar_t header[8];
+ int status;
+ static char func_name[] = "is_fcode_file";
+ extern int check_fcode_header(char *, uchar_t *, int);
+
+ debug_msg(DEBUG_FIND_FCODE, "%s: '%s' -> ", func_name, path);
+ if ((fd = open(path, 0)) < 0) {
+ debug_msg(DEBUG_FIND_FCODE, "%s: '%s' can't open\n", func_name,
+ path);
+ return (0);
+ }
+ if (fstat(fd, &statb) != 0 || read(fd, header, sizeof (header)) < 0) {
+ debug_msg(DEBUG_FIND_FCODE, "%s: '%s' can't fstat/read\n",
+ func_name, path);
+ close(fd);
+ return (0);
+ }
+ status = check_fcode_header(path, header, statb.st_size);
+ debug_msg(DEBUG_FIND_FCODE, "%s: '%s' format %s\n", func_name, path,
+ status ? "OK" : "NOT OK");
+ close(fd);
+ return (status);
+}
+
+static char *
+find_lib_file(fcode_env_t *env, char *prefix, char *name, char *suffix,
+ int (*fn)(char *))
+{
+ char *search, *fname;
+ char *lib_name;
+ common_data_t *cdp = env->private;
+
+ if ((search = cdp->search_path) == NULL &&
+ (search = default_search_path) == NULL) {
+ log_message(MSG_ERROR, "find_lib_file: no search path\n");
+ return (NULL);
+ }
+
+ lib_name = MALLOC(strlen(name) + strlen(prefix) + strlen(suffix) + 1);
+ sprintf(lib_name, "%s%s%s", prefix, name, suffix);
+ fname = search_path(lib_name, search, fn);
+ FREE(lib_name);
+ return (fname);
+}
+
+char *
+search_for_fcode_file(fcode_env_t *env, char *basename)
+{
+ return (find_lib_file(env, "", basename, ".fc", is_fcode_file));
+}
+
+static void
+load_appropriate_file(fcode_env_t *env, char *name, device_t *d)
+{
+ char *fname;
+
+ if ((fname = find_lib_file(env, "lfc_", name, ".so", load_lib_file))
+ != NULL) {
+ debug_msg(DEBUG_FIND_FCODE, "Loading Library: %s\n", fname);
+ FREE(fname);
+ } else if ((fname = search_for_fcode_file(env, name)) != NULL) {
+ debug_msg(DEBUG_FIND_FCODE, "Loading Fcode: %s\n", fname);
+ run_fcode_from_file(env, fname, 0);
+ FREE(fname);
+ } else {
+ throw_from_fclib(env, 1,
+ "Can't find 'lfc_%s.so' or '%s.fc'\n", name, name);
+ }
+}
+
+void
+install_node_data(fcode_env_t *env, device_t *d)
+{
+ prop_t *p;
+ device_t *cd;
+ char libname[512];
+ static char func_name[] = "install_node_data";
+
+ if (d->parent) {
+ if ((p = lookup_package_property(env, "device_type",
+ d->parent)) == NULL) {
+ log_message(MSG_ERROR, "%s: no 'device_type' property"
+ " for '%s'\n", func_name, get_path(env, d->parent));
+ return;
+ }
+ /*
+ * Warning: lookup_package_property uses a static data area to
+ * build the property node returned, so we have to grab a copy
+ * of the data.
+ */
+ strcpy(libname, (char *)p->data);
+ strcat(libname, "_");
+ } else
+ libname[0] = '\0';
+
+ if ((p = lookup_package_property(env, "device_type", d)) == NULL) {
+ log_message(MSG_ERROR, "%s: no 'device_type' property for"
+ " '%s'\n", func_name, get_path(env, d));
+ return;
+ }
+
+ /*
+ * Warning: lookup_package_property uses a static data area to build
+ * the property node returned, so we have to grab a copy of the
+ * data.
+ */
+ strcat(libname, (char *)p->data);
+
+ debug_msg(DEBUG_FIND_FCODE, "%s: `%s` lname: '%s'\n", func_name,
+ get_path(env, d), libname);
+
+ load_appropriate_file(env, libname, d);
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+#if defined(__sparcv9)
+ build_default_search_path("/sparcv9");
+#else
+ build_default_search_path("");
+#endif
+ FORTH(0, "set-default-search-path", set_default_search_path);
+ FORTH(0, "get-default-search-path", get_default_search_path);
+}
diff --git a/usr/src/lib/efcode/fcdriver/misc.c b/usr/src/lib/efcode/fcdriver/misc.c
new file mode 100644
index 0000000000..4e62b11e03
--- /dev/null
+++ b/usr/src/lib/efcode/fcdriver/misc.c
@@ -0,0 +1,659 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+static fc_cell_t
+fc_reg_read(fcode_env_t *env, char *service, fstack_t virt, int *errp)
+{
+ fc_cell_t virtaddr, data;
+ int error, nin;
+
+ if (!is_mcookie(virt))
+ forth_abort(env, "fc_reg_read: bad mcookie: 0x%x\n", virt);
+
+ virtaddr = mcookie_to_addr(virt);
+
+ /* Supress fc_run_priv error msgs on peeks */
+ nin = ((errp == NULL) ? 1 : (1 | FCRP_NOERROR));
+
+ error = fc_run_priv(env->private, service, nin, 1, virtaddr, &data);
+ if (errp)
+ /* Don't report error on peeks */
+ *errp = error;
+ else if (error) {
+ log_message(MSG_ERROR, "fc_read_reg: ERROR: cookie: %llx"
+ " virt: %llx\n", (uint64_t)virt, (uint64_t)virtaddr);
+ data = 0;
+ }
+ return (data);
+}
+
+static void
+fc_reg_write(fcode_env_t *env, char *service, fstack_t virt, fc_cell_t data,
+ int *errp)
+{
+ fc_cell_t virtaddr;
+ int error, nin;
+
+ if (!is_mcookie(virt))
+ forth_abort(env, "fc_reg_write: bad mcookie: 0x%x\n", virt);
+
+ virtaddr = mcookie_to_addr(virt);
+
+ /* Supress fc_run_priv error msgs on pokes */
+ nin = ((errp == NULL) ? 2 : (2 | FCRP_NOERROR));
+
+ error = fc_run_priv(env->private, service, nin, 0, virtaddr, data);
+ if (errp)
+ /* Don't report error on pokes */
+ *errp = error;
+ else if (error) {
+ log_message(MSG_ERROR, "fc_write_reg: ERROR: cookie: %llx"
+ " virt: %llx\n", (uint64_t)virt, (uint64_t)virtaddr);
+ }
+}
+
+static int
+check_address_abuse(fcode_env_t *env, fstack_t addr, char *type,
+ int want_mcookie, void (*alt)(fcode_env_t *))
+{
+ if (is_mcookie(addr) != want_mcookie) {
+ debug_msg(DEBUG_ADDR_ABUSE, "Warning: %s to %s address: %llx\n",
+ type, want_mcookie ? "unmapped" : "mapped",
+ (uint64_t)addr);
+ (*alt)(env);
+ return (1);
+ }
+ return (0);
+}
+
+static void
+rlfetch(fcode_env_t *env)
+{
+ fstack_t p;
+
+ CHECK_DEPTH(env, 1, "rl@");
+ p = TOS;
+ if (!check_address_abuse(env, p, "rl@", 1, lfetch))
+ TOS = (lforth_t)fc_reg_read(env, "rl@", p, NULL);
+}
+
+static void
+rlstore(fcode_env_t *env)
+{
+ fstack_t p, d;
+
+ CHECK_DEPTH(env, 2, "rl!");
+ p = TOS;
+ if (!check_address_abuse(env, p, "rl!", 1, lstore)) {
+ p = POP(DS);
+ d = POP(DS);
+ fc_reg_write(env, "rl!", p, d, NULL);
+ }
+}
+
+static void
+rwfetch(fcode_env_t *env)
+{
+ fstack_t p;
+
+ CHECK_DEPTH(env, 1, "rw@");
+ p = TOS;
+ if (!check_address_abuse(env, p, "rw@", 1, wfetch))
+ TOS = (wforth_t)fc_reg_read(env, "rw@", p, NULL);
+}
+
+static void
+rwstore(fcode_env_t *env)
+{
+ fstack_t p, d;
+
+ CHECK_DEPTH(env, 2, "rw!");
+ p = TOS;
+ if (!check_address_abuse(env, p, "rw!", 1, wstore)) {
+ p = POP(DS);
+ d = POP(DS);
+ fc_reg_write(env, "rw!", p, d, NULL);
+ }
+}
+
+void
+rbfetch(fcode_env_t *env)
+{
+ fstack_t p;
+
+ CHECK_DEPTH(env, 1, "rb@");
+ p = TOS;
+ if (!check_address_abuse(env, p, "rb@", 1, cfetch)) {
+ TOS = (uchar_t)fc_reg_read(env, "rb@", p, NULL);
+ }
+}
+
+static void
+rbstore(fcode_env_t *env)
+{
+ fstack_t p, d;
+
+ CHECK_DEPTH(env, 2, "rb!");
+ p = TOS;
+ if (!check_address_abuse(env, p, "rb!", 1, cstore)) {
+ p = POP(DS);
+ d = POP(DS);
+ fc_reg_write(env, "rb!", p, d, NULL);
+ }
+}
+
+/*
+ * rx@ ( xa -- xv )
+ */
+static void
+rxfetch(fcode_env_t *env)
+{
+ fstack_t p;
+ xforth_t x;
+
+ CHECK_DEPTH(env, 1, "rx@");
+ p = TOS;
+ if (!check_address_abuse(env, p, "rx@", 1, xfetch)) {
+ p = POP(DS);
+ push_xforth(env, (xforth_t)fc_reg_read(env, "rx@", p, NULL));
+ }
+}
+
+/*
+ * rx! ( xv xa -- )
+ */
+static void
+rxstore(fcode_env_t *env)
+{
+ fstack_t p;
+ xforth_t d;
+
+ CHECK_DEPTH(env, 2, "rx!");
+ p = TOS;
+ if (!check_address_abuse(env, p, "rx!", 1, xstore)) {
+ p = POP(DS);
+ d = pop_xforth(env);
+ fc_reg_write(env, "rx!", p, d, NULL);
+ }
+}
+
+static void
+lpeek(fcode_env_t *env)
+{
+ fstack_t p;
+ lforth_t r;
+ int error;
+
+ CHECK_DEPTH(env, 1, "lpeek");
+ p = POP(DS);
+ r = (lforth_t)fc_reg_read(env, "rl@", p, &error);
+ if (error)
+ PUSH(DS, FALSE);
+ else {
+ PUSH(DS, r);
+ PUSH(DS, TRUE);
+ }
+}
+
+static void
+lpoke(fcode_env_t *env)
+{
+ fstack_t p, d;
+ int error;
+
+ CHECK_DEPTH(env, 2, "lpoke");
+ p = POP(DS);
+ d = POP(DS);
+ fc_reg_write(env, "rl!", p, d, &error);
+ PUSH(DS, error ? FALSE : TRUE);
+}
+
+static void
+wpeek(fcode_env_t *env)
+{
+ fstack_t p;
+ int error;
+ wforth_t r;
+
+ CHECK_DEPTH(env, 1, "wpeek");
+ p = POP(DS);
+ r = (wforth_t)fc_reg_read(env, "rw@", p, &error);
+ if (error)
+ PUSH(DS, FALSE);
+ else {
+ PUSH(DS, r);
+ PUSH(DS, TRUE);
+ }
+}
+
+static void
+wpoke(fcode_env_t *env)
+{
+ fstack_t p, d;
+ int error;
+
+ CHECK_DEPTH(env, 2, "wpoke");
+ p = POP(DS);
+ d = POP(DS);
+ fc_reg_write(env, "rw!", p, d, &error);
+ PUSH(DS, error ? FALSE : TRUE);
+}
+
+static void
+cpeek(fcode_env_t *env)
+{
+ fstack_t p;
+ uchar_t r;
+ int error;
+
+ CHECK_DEPTH(env, 1, "cpeek");
+ p = POP(DS);
+ r = (uchar_t)fc_reg_read(env, "rb@", p, &error);
+ if (error)
+ PUSH(DS, FALSE);
+ else {
+ PUSH(DS, r);
+ PUSH(DS, TRUE);
+ }
+}
+
+static void
+cpoke(fcode_env_t *env)
+{
+ fstack_t p, d;
+ int error;
+
+ CHECK_DEPTH(env, 2, "cpoke");
+ p = POP(DS);
+ d = POP(DS);
+ fc_reg_write(env, "rb!", p, d, &error);
+ PUSH(DS, error ? FALSE : TRUE);
+}
+
+/*
+ * fcdriver version of cfetch, replaces base 'c@'
+ */
+static void
+fcd_cfetch(fcode_env_t *env)
+{
+ fstack_t addr = TOS;
+
+ CHECK_DEPTH(env, 1, "c@");
+ if (!check_address_abuse(env, addr, "c@", 0, rbfetch))
+ cfetch(env);
+}
+
+/*
+ * fcdriver version of cstore, replaces base 'c!'
+ */
+static void
+fcd_cstore(fcode_env_t *env)
+{
+ fstack_t addr = TOS;
+
+ CHECK_DEPTH(env, 2, "c!");
+ if (!check_address_abuse(env, addr, "c!", 0, rbstore))
+ cstore(env);
+}
+
+/*
+ * fcdriver version of wfetch, replaces base 'w@'
+ */
+static void
+fcd_wfetch(fcode_env_t *env)
+{
+ fstack_t addr = TOS;
+
+ CHECK_DEPTH(env, 1, "w@");
+ if (!check_address_abuse(env, addr, "w@", 0, rwfetch))
+ wfetch(env);
+}
+
+/*
+ * fcdriver version of wstore, replaces base 'w!'
+ */
+static void
+fcd_wstore(fcode_env_t *env)
+{
+ fstack_t addr = TOS;
+
+ CHECK_DEPTH(env, 2, "w!");
+ if (!check_address_abuse(env, addr, "w!", 0, rwstore))
+ wstore(env);
+}
+
+/*
+ * fcdriver version of lfetch, replaces base 'l@'
+ */
+static void
+fcd_lfetch(fcode_env_t *env)
+{
+ fstack_t addr = TOS;
+
+ CHECK_DEPTH(env, 1, "l@");
+ if (!check_address_abuse(env, addr, "l@", 0, rlfetch))
+ lfetch(env);
+}
+
+/*
+ * fcdriver version of lstore, replaces base 'l!'
+ */
+static void
+fcd_lstore(fcode_env_t *env)
+{
+ fstack_t addr = TOS;
+
+ CHECK_DEPTH(env, 2, "l!");
+ if (!check_address_abuse(env, addr, "l!", 0, rlstore))
+ lstore(env);
+}
+
+/*
+ * fcdriver version of xfetch, replaces base 'x@'
+ */
+static void
+fcd_xfetch(fcode_env_t *env)
+{
+ fstack_t addr = TOS;
+
+ CHECK_DEPTH(env, 1, "x@");
+ if (!check_address_abuse(env, addr, "x@", 0, rxfetch))
+ xfetch(env);
+}
+
+/*
+ * fcdriver version of xstore, replaces base 'x!'
+ */
+static void
+fcd_xstore(fcode_env_t *env)
+{
+ fstack_t addr = TOS;
+
+ CHECK_DEPTH(env, 2, "x!");
+ if (!check_address_abuse(env, addr, "x!", 0, rxstore))
+ xstore(env);
+}
+
+/*
+ * fcdriver version of move, replaces base 'move'
+ */
+static void
+fcd_move(fcode_env_t *env)
+{
+ size_t len;
+ uchar_t *destaddr, *srcaddr;
+
+ CHECK_DEPTH(env, 3, "move");
+ len = POP(DS);
+ destaddr = ((uchar_t *)POP(DS));
+ srcaddr = ((uchar_t *)POP(DS));
+ for (; len > 0; len--, srcaddr++, destaddr++) {
+ PUSH(DS, (fstack_t)srcaddr);
+ fcd_cfetch(env);
+ PUSH(DS, (fstack_t)destaddr);
+ fcd_cstore(env);
+ }
+}
+
+static void
+fcd_comp(fcode_env_t *env)
+{
+ char *str1, *str2, byte1, byte2;
+ size_t len;
+
+ CHECK_DEPTH(env, 3, "comp");
+ len = (size_t)POP(DS);
+ str1 = (char *)POP(DS);
+ str2 = (char *)POP(DS);
+ for (; len > 0; len--, str1++, str2++) {
+ PUSH(DS, (fstack_t)str1);
+ fcd_cfetch(env);
+ byte1 = POP(DS);
+ PUSH(DS, (fstack_t)str2);
+ fcd_cfetch(env);
+ byte2 = POP(DS);
+ if (byte1 > byte2) {
+ PUSH(DS, -1);
+ return;
+ }
+ if (byte1 < byte2) {
+ PUSH(DS, 1);
+ return;
+ }
+ }
+ PUSH(DS, 0);
+}
+
+char *
+get_eeprom_value(fcode_env_t *env, char *name)
+{
+ FILE *fd;
+ char buf[80], *p;
+
+ sprintf(buf, "eeprom '%s'", name);
+ if ((fd = popen(buf, "r")) == NULL)
+ return (NULL);
+ fgets(buf, sizeof (buf), fd);
+ pclose(fd);
+ if ((p = strchr(buf, '\n')) != NULL)
+ *p = '\0';
+ if ((p = strchr(buf, '=')) != NULL)
+ return (p + 1);
+ return (NULL);
+}
+
+static void
+local_mac_address(fcode_env_t *env)
+{
+ char *mac_str;
+ int mac_value;
+
+ mac_str = get_eeprom_value(env, "local-mac-address?");
+ if (mac_str != NULL && strcmp(mac_str, "true") == 0)
+ mac_value = TRUE;
+ else
+ mac_value = FALSE;
+ PUSH(DS, mac_value);
+}
+
+/*
+ * Allow for programmatic over-ride of 'mac-address'
+ */
+#define MAC_ADDR_SIZE 6
+static char *mac_addr;
+static int mac_addr_is_valid;
+
+void
+set_mac_address(char *macaddr)
+{
+ mac_addr_is_valid = 1;
+ memcpy(mac_addr, macaddr, MAC_ADDR_SIZE);
+}
+
+void
+push_mac_address(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)mac_addr);
+ PUSH(DS, MAC_ADDR_SIZE);
+}
+
+/*
+ * Does driver call to get this.
+ */
+static void
+local_ether_addr(fcode_env_t *env)
+{
+ static fc_cell_t *mac_add;
+ int error;
+
+ mac_add = MALLOC(sizeof (fc_cell_t) * 2);
+ error = fc_run_priv(env->private, "local-ether-addr", 0, 2, &mac_add[0],
+ &mac_add[1]);
+ if (error) {
+ bzero(mac_add, sizeof (mac_add));
+ }
+
+ PUSH(DS, (fstack_t)&mac_add[0]);
+ PUSH(DS, 6);
+}
+
+/*
+ * 'mac-address' - complicated by 'local-mac-address' stuff.
+ */
+static void
+mac_address(fcode_env_t *env)
+{
+ fstack_t d;
+
+ if (mac_addr_is_valid) {
+ push_mac_address(env);
+ return;
+ }
+
+ /*
+ * From here, we essentially re-implement OBP's 'mac-address' word.
+ * on some platforms, this may need to be re-implemented.
+ */
+ local_mac_address(env);
+ d = POP(DS);
+ if (d) {
+ push_a_string(env, "local-mac-address");
+ get_inherited_prop(env);
+ d = POP(DS);
+ if (d == FALSE && TOS == 6)
+ return;
+ two_drop(env);
+ }
+ local_ether_addr(env);
+}
+
+/*
+ * Allow for the programmatic setting of diagnostic-mode?
+ */
+static int diag_mode_is_valid = 0;
+static int diag_mode = 0;
+
+void
+set_diagnostic_mode(fcode_env_t *env)
+{
+ fstack_t d = POP(DS);
+
+ diag_mode = d;
+ diag_mode_is_valid = 1;
+}
+
+void
+push_diagnostic_mode(fcode_env_t *env)
+{
+ PUSH(DS, (fstack_t)diag_mode);
+}
+
+/*
+ * 'diagnostic-mode?' - diagnostic-mode? is equivalent to NVRAM 'diag-switch?'
+ */
+static void
+diagnostic_mode(fcode_env_t *env)
+{
+ char *diag_str;
+ int diag_value;
+
+ if (!diag_mode_is_valid) {
+ diag_str = get_eeprom_value(env, "diag-switch?");
+ if (diag_str != NULL && strcmp(diag_str, "false") == 0)
+ diag_value = FALSE;
+ else
+ diag_value = TRUE;
+ PUSH(DS, diag_value);
+ set_diagnostic_mode(env);
+ }
+
+ push_diagnostic_mode(env);
+}
+
+/*
+ * May need to implement other memory-access Fcodes here (depending upon
+ * abuse), like fill, comp, +!, etc., etc.
+ */
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ mac_addr = MALLOC(MAC_ADDR_SIZE);
+
+ ASSERT(env);
+ NOTICE;
+
+ ANSI(0x06e, 0, "l@", fcd_lfetch);
+ ANSI(0x06f, 0, "w@", fcd_wfetch);
+ ANSI(0x071, 0, "c@", fcd_cfetch);
+ ANSI(0x073, 0, "l!", fcd_lstore);
+ ANSI(0x074, 0, "w!", fcd_wstore);
+ ANSI(0x075, 0, "c!", fcd_cstore);
+ ANSI(0x078, 0, "move", fcd_move);
+ ANSI(0x07a, 0, "comp", fcd_comp);
+
+ ANSI(0x120, 0, "diagnostic-mode?", diagnostic_mode);
+
+ ANSI(0x1a4, 0, "mac-address", mac_address);
+
+ P1275(0x220, 0, "cpeek", cpeek);
+ P1275(0x221, 0, "wpeek", wpeek);
+ P1275(0x222, 0, "lpeek", lpeek);
+ P1275(0x223, 0, "cpoke", cpoke);
+ P1275(0x224, 0, "wpoke", wpoke);
+ P1275(0x225, 0, "lpoke", lpoke);
+
+ P1275(0x230, 0, "rb@", rbfetch);
+ P1275(0x231, 0, "rb!", rbstore);
+ P1275(0x232, 0, "rw@", rwfetch);
+ P1275(0x233, 0, "rw!", rwstore);
+ P1275(0x234, 0, "rl@", rlfetch);
+ P1275(0x235, 0, "rl!", rlstore);
+
+ P1275(0x246, 0, "x@", fcd_xfetch);
+ P1275(0x247, 0, "x!", fcd_xstore);
+
+ P1275(0x22e, 0, "rx@", rxfetch);
+ P1275(0x22f, 0, "rx!", rxstore);
+ FORTH(0, "set-diagnostic-mode", set_diagnostic_mode);
+ FORTH(0, "local-mac-address?", local_mac_address);
+ FORTH(0, "local-ether-addr", local_ether_addr);
+}
diff --git a/usr/src/lib/efcode/fcdriver/phandle.c b/usr/src/lib/efcode/fcdriver/phandle.c
new file mode 100644
index 0000000000..79a202da4e
--- /dev/null
+++ b/usr/src/lib/efcode/fcdriver/phandle.c
@@ -0,0 +1,204 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+
+static int use_os_handle = 1;
+
+void
+do_use_os_handles(fcode_env_t *env)
+{
+ use_os_handle = 1;
+}
+
+void
+do_use_fake_handles(fcode_env_t *env)
+{
+ log_message(MSG_ERROR, "WARNING: using fake phandles, test only\n");
+ use_os_handle = 0;
+}
+
+static int
+match_nodeid(void *s, void *d)
+{
+ my_nodeid_t *src = s;
+ my_nodeid_t *dest = d;
+ return ((src->node) == (dest->node));
+}
+
+static int
+match_handle(void *s, void *d)
+{
+ my_nodeid_t *src = s;
+ my_nodeid_t *dest = d;
+ return ((src->my_handle) == (dest->my_handle));
+}
+
+/*
+ * Convert from an OS phandle to an interpreter phandle
+ */
+device_t *
+convert_phandle(fcode_env_t *env, fstack_t d)
+{
+ fc_resource_t *t;
+ common_data_t *cdp = env->private;
+ device_t *r;
+
+ if (use_os_handle) {
+ my_nodeid_t nh;
+ nh.my_handle = (fc_phandle_t) d;
+ t = find_resource(&cdp->nodeids, &nh, match_handle);
+ if (t == NULL) {
+ r = 0;
+ } else {
+ my_nodeid_t *p = (my_nodeid_t *) t->data;
+ r = (device_t *) p->node;
+ }
+ } else
+ r = (device_t *)d;
+ return (r);
+}
+
+/*
+ * Interpreter phandle to OS phandle
+ */
+fstack_t
+revert_phandle(fcode_env_t *env, device_t *d)
+{
+ fc_resource_t *t;
+ common_data_t *cdp = env->private;
+ fstack_t r;
+
+ if (use_os_handle) {
+ my_nodeid_t nh;
+ nh.node = d;
+ t = find_resource(&cdp->nodeids, &nh, match_nodeid);
+ if (t == NULL) {
+ r = 0;
+ } else {
+ my_nodeid_t *p = (my_nodeid_t *) t->data;
+ r = (fstack_t) p->my_handle;
+ }
+ } else
+ r = (fstack_t) d;
+ return (r);
+}
+
+void
+add_my_handle(fcode_env_t *env, fc_phandle_t mh, device_t *d)
+{
+ my_nodeid_t *nh;
+ common_data_t *cdp = env->private;
+
+ nh = MALLOC(sizeof (my_nodeid_t));
+ nh->my_handle = mh;
+ nh->node = d;
+ if (add_resource(&cdp->nodeids, nh, match_handle) == NULL) {
+ log_message(MSG_ERROR, "add_my_handle: add_resource failed\n");
+ }
+}
+
+void
+allocate_phandle(fcode_env_t *env)
+{
+ private_data_t *pd;
+ common_data_t *cdp;
+ int error;
+ char *service;
+ device_t *current;
+ fc_cell_t hcell;
+
+ if ((cdp = env->private) == NULL) {
+ log_message(MSG_ERROR, "allocate_phandle: NULL common\n");
+ return;
+ }
+
+ if (!cdp->init_done)
+ return;
+
+ current = MYSELF->device;
+ ASSERT(current);
+
+ if (cdp->first_node) {
+ service = FC_CONFIG_CHILD;
+ cdp->first_node = 0;
+ } else {
+ service = FC_ALLOC_PHANDLE;
+ }
+
+ pd = MALLOC(sizeof (private_data_t));
+ pd->common = cdp;
+ pd->parent = (fc_phandle_t) revert_phandle(env, current->parent);
+ pd->upload = (cdp->init_done == 1);
+ current->private = pd;
+
+ error = fc_run_priv(cdp, service, 0, 1, &hcell);
+
+ pd->node = fc_cell2phandle(hcell);
+
+ add_my_handle(env, pd->node, current);
+}
+
+fc_phandle_t
+fc_get_ap(common_data_t *cdp)
+{
+ fc_cell_t hcell;
+ int error;
+
+ error = fc_run_priv(cdp, FC_AP_PHANDLE, 0, 1, &hcell);
+
+ if (error)
+ exit(1);
+
+ return (fc_cell2phandle(hcell));
+}
+
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ env->convert_phandle = convert_phandle;
+ env->revert_phandle = revert_phandle;
+ env->allocate_phandle = allocate_phandle;
+ FORTH(0, "use-os-handles", do_use_os_handles);
+ FORTH(0, "use-fake-handles", do_use_fake_handles);
+}
diff --git a/usr/src/lib/efcode/fcdriver/property.c b/usr/src/lib/efcode/fcdriver/property.c
new file mode 100644
index 0000000000..5634d1407d
--- /dev/null
+++ b/usr/src/lib/efcode/fcdriver/property.c
@@ -0,0 +1,180 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+
+static char *prop_buf;
+
+static int
+getproplen(common_data_t *cdp, fc_phandle_t node, char *propname, int inherit)
+{
+ fc_cell_t len;
+ char *service;
+ int error;
+
+ service = inherit ? FC_GET_IN_PROPLEN : FC_GET_PKG_PROPLEN;
+
+ error = fc_run_priv(cdp, service, 2, 1, fc_phandle2cell(node),
+ fc_ptr2cell(propname), &len);
+ if (error)
+ return (-1);
+
+ return (fc_cell2int(len));
+}
+
+static int
+getprop(common_data_t *cdp, fc_phandle_t node, char *propname, char *buf,
+ int inherit)
+{
+ fc_cell_t len;
+ char *service;
+ int error;
+
+ service = inherit ? FC_GET_IN_PROP : FC_GET_PKG_PROP;
+
+ error = fc_run_priv(cdp, service, 3, 1, fc_phandle2cell(node),
+ fc_ptr2cell(buf), fc_ptr2cell(propname), &len);
+ if (error)
+ return (-1);
+
+ return (fc_cell2int(len));
+}
+
+int
+os_get_prop_common(common_data_t *cdp, fc_phandle_t node, char *name,
+ int inherit, char **buf, int *len)
+{
+ int i, j;
+ char *bp;
+
+ i = getproplen(cdp, node, name, inherit);
+ if (i <= 0) {
+ /*
+ * OK for properties to be undefined, suppress error message
+ * unless some debug is on.
+ */
+ if (get_interpreter_debug_level())
+ log_message(MSG_ERROR, "os_get_prop_common:"
+ " getproplen(%s) returned %d\n", name, i);
+ return (-1);
+ }
+ bp = MALLOC(i);
+
+ j = getprop(cdp, node, name, bp, inherit);
+ if (i != j) {
+ /*
+ * It's an error if getproplen succeeded but getprop didn't
+ * return a matching length.
+ */
+ log_message(MSG_ERROR, "os_get_prop_common: getprop(%s)"
+ " return %d, getproplen returned %d\n", name, j, i);
+ FREE(bp);
+ return (-2);
+ }
+ memcpy(prop_buf, bp, i);
+ *buf = prop_buf;
+ *len = i;
+ FREE(bp);
+ return (0);
+}
+
+static void
+os_get_prop(fcode_env_t *env, int inherit, device_t *dev)
+{
+ fc_phandle_t node;
+ char *name;
+ char *prop;
+ int len;
+ private_data_t *pd;
+
+ ASSERT(dev);
+
+ pd = dev->private;
+ ASSERT(pd);
+
+ name = pop_a_string(env, &len);
+
+ node = pd->node;
+ if (node == NULL) {
+ log_message(MSG_ERROR, "os_get_prop: NULL node: %s\n",
+ get_path(env, dev));
+ PUSH(DS, TRUE);
+ } else if (os_get_prop_common(pd->common, node, name, inherit, &prop,
+ &len)) {
+ PUSH(DS, TRUE);
+ } else {
+ PUSH(DS, (fstack_t)prop);
+ PUSH(DS, len);
+ PUSH(DS, FALSE);
+ }
+}
+
+static void
+os_get_package_prop(fcode_env_t *env)
+{
+ device_t *dev;
+
+ CONVERT_PHANDLE(env, dev, POP(DS));
+ os_get_prop(env, 0, dev);
+}
+
+static void
+os_get_inherited_prop(fcode_env_t *env)
+{
+ os_get_prop(env, 1, env->attachment_pt);
+}
+
+void
+install_property_vectors(fcode_env_t *env, device_t *d)
+{
+ d->vectors.get_package_prop = os_get_package_prop;
+ d->vectors.get_inherited_prop = os_get_inherited_prop;
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ prop_buf = MALLOC(4096);
+
+}
diff --git a/usr/src/lib/efcode/fcdriver/sparcv9/Makefile b/usr/src/lib/efcode/fcdriver/sparcv9/Makefile
new file mode 100644
index 0000000000..ec8b9d5c96
--- /dev/null
+++ b/usr/src/lib/efcode/fcdriver/sparcv9/Makefile
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+include $(SRC)/lib/Makefile.lib.64
+
+DYNFLAGS += $(FCODE64) $(FCPACKAGE64)
+
+install: all $(ROOTLIBS64)
diff --git a/usr/src/lib/efcode/fcdriver/upload.c b/usr/src/lib/efcode/fcdriver/upload.c
new file mode 100644
index 0000000000..14b8989295
--- /dev/null
+++ b/usr/src/lib/efcode/fcdriver/upload.c
@@ -0,0 +1,178 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+#include <fcntl.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+static void
+create_node(fcode_env_t *env, device_t *d)
+{
+ int error;
+ prop_t *p;
+ instance_t *ih;
+ char *service = FC_NEW_DEVICE;
+ private_data_t *pd, *ppd;
+ char *unit_str;
+
+ pd = (private_data_t *)d->private;
+ ppd = (private_data_t *)d->parent->private;
+
+ ih = MYSELF;
+ MYSELF = open_instance_chain(env, d, 0);
+ p = lookup_package_property(env, "name", d);
+ if (p == NULL) {
+ forth_abort(env, "create_node: '%s' name prop not found\n",
+ get_path(env, d));
+ }
+
+ debug_msg(DEBUG_UPLOAD, "Create Node: %p\n", pd->node);
+ debug_msg(DEBUG_UPLOAD, " Device Name: '%s'\n", p->data);
+ debug_msg(DEBUG_UPLOAD, " Parent : %p\n", ppd->node);
+
+ my_unit(env);
+ (void) call_my_parent(env, "encode-unit");
+ unit_str = pop_a_duped_string(env, NULL);
+ if (unit_str == NULL) {
+ unit_str = STRDUP("");
+ }
+
+ debug_msg(DEBUG_UPLOAD, " Unit Addr : '%s'\n", unit_str);
+
+ error = fc_run_priv(pd->common, FC_NEW_DEVICE, 4, 0,
+ fc_phandle2cell(pd->node), fc_phandle2cell(ppd->node),
+ fc_ptr2cell(unit_str), fc_ptr2cell(p->data));
+
+ FREE(unit_str);
+ close_instance_chain(env, MYSELF, 0);
+ MYSELF = ih;
+
+ if (error)
+ log_message(MSG_ERROR, "%s: parent: '%s' new: '%s'\n", service,
+ get_path(env, d->parent), p->data);
+}
+
+static void
+finish_node(fcode_env_t *env, device_t *d)
+{
+ private_data_t *pd;
+ int error;
+
+ pd = (private_data_t *)d->private;
+
+ debug_msg(DEBUG_UPLOAD, "Finish Node: %p\n", pd->node);
+
+ error = fc_run_priv(pd->common, FC_FINISH_DEVICE, 1, 0,
+ fc_phandle2cell(pd->node));
+ if (error)
+ log_message(MSG_ERROR, "%s: failed\n", FC_FINISH_DEVICE);
+}
+
+static void
+upload_properties(fcode_env_t *env, device_t *d)
+{
+ prop_t *p;
+ private_data_t *pd;
+ int error;
+
+ pd = (private_data_t *)d->private;
+ debug_msg(DEBUG_UPLOAD, "Upload Properties: node %p upload: %d\n",
+ pd->node, pd->upload);
+
+ if (!pd->upload)
+ return;
+
+ for (p = d->properties; p; p = p->next) {
+ DEBUGF(UPLOAD, print_property(env, p, " Upload: "));
+
+ error = fc_run_priv(pd->common, FC_CREATE_PROPERTY, 4, 0,
+ fc_phandle2cell(pd->node), fc_int2cell(p->size),
+ fc_ptr2cell(p->data), fc_ptr2cell(p->name));
+
+ if (error)
+ log_message(MSG_ERROR, "%s: '%s' failed\n",
+ FC_CREATE_PROPERTY, p->name);
+ }
+}
+
+static void
+upload_node(fcode_env_t *env, device_t *d)
+{
+ private_data_t *pd = (private_data_t *)d->private;
+
+ if (pd) {
+ debug_msg(DEBUG_UPLOAD, "Upload Node: dev: %p node: %p"
+ " upload: %d\n", d, pd->node, pd->upload);
+ if (pd->upload) {
+ create_node(env, d);
+ upload_properties(env, d);
+ finish_node(env, d);
+ }
+ } else
+ debug_msg(DEBUG_UPLOAD, "Upload Node: dev: %p NULL private\n",
+ d);
+}
+
+void
+upload_nodes(fcode_env_t *env)
+{
+ debug_msg(DEBUG_UPLOAD, "Upload Nodes: Recursing Tree\n");
+ recurse_tree(env, env->root_node, upload_node);
+}
+
+void
+validate_nodes(fcode_env_t *env)
+{
+ int error;
+ common_data_t *cdp = env->private;
+
+ error = ioctl(cdp->fcode_fd, FC_VALIDATE);
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ FORTH(0, "upload-nodes", upload_nodes);
+ FORTH(0, "validate-nodes", validate_nodes);
+}
diff --git a/usr/src/lib/efcode/fcode_test/Makefile b/usr/src/lib/efcode/fcode_test/Makefile
new file mode 100644
index 0000000000..e45ef0b706
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/Makefile
@@ -0,0 +1,56 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/efcode/fcode_test/Makefile
+#
+
+include ../../../Makefile.master
+
+TESTSRCS = test.fth calling.fth iftest.fth arithmetic.fth create.fth \
+ stack.fth bytemanipulate.fth loop.fth find.fth values.fth \
+ instance.fth catch.fth storage.fth case.fth access.fth misc.fth \
+ parse.fth
+
+PROGS = test.fcode test64.fcode
+
+TOKENIZE = $(ONBLD_TOOLS)/bin/sparc/tokenize
+
+.SUFFIXES: .fcode .fth $(SUFFIXES)
+
+install all: $(PROGS)
+
+.fth.fcode:
+ $(TOKENIZE) $<
+
+test.fcode: $(TESTSRCS)
+
+clean:
+ $(RM) $(PROGS)
+
+clobber: clean
+
+install_h:
diff --git a/usr/src/lib/efcode/fcode_test/access.fth b/usr/src/lib/efcode/fcode_test/access.fth
new file mode 100644
index 0000000000..9f441d83b4
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/access.fth
@@ -0,0 +1,70 @@
+\ #pragma ident "%Z%%M% %I% %E% SMI"
+\ Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ Use is subject to license terms.
+\
+\ CDDL HEADER START
+\
+\ The contents of this file are subject to the terms of the
+\ Common Development and Distribution License, Version 1.0 only
+\ (the "License"). You may not use this file except in compliance
+\ with the License.
+\
+\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ or http://www.opensolaris.org/os/licensing.
+\ See the License for the specific language governing permissions
+\ and limitations under the License.
+\
+\ When distributing Covered Code, include this CDDL HEADER in each
+\ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ If applicable, add the following below this CDDL HEADER, with the
+\ fields enclosed by brackets "[]" replaced with your own identifying
+\ information: Portions Copyright [yyyy] [name of copyright owner]
+\
+\ CDDL HEADER END
+\
+
+." Access test: "
+0 value word-test
+0 value char-test
+0 value end-test
+0 value end-test2
+variable var-test
+create access-test
+ h# 80004000 l,
+ here to word-test
+ h# 8000 w, h# 4000 w,
+ here to char-test
+ h# 1 c, h# 2 c, h# 3 c, h# 4 c,
+ here to end-test
+ h# a55aa55a ,
+ here to end-test2
+
+
+ " l,+" access-test la1+ word-test = .passed?
+ " w,+" word-test 2 wa+ char-test = .passed?
+ " c,+" char-test 4 ca+ end-test = .passed?
+ " ,+" end-test cell+ end-test2 = .passed?
+ " c@.1" char-test c@ h# 1 = .passed?
+ " c@.2" char-test char+ c@ h# 2 = .passed?
+ " c@.3" char-test 2 ca+ c@ h# 3 = .passed?
+ " c@.4" char-test 3 ca+ c@ h# 4 = .passed?
+ " w@.1" access-test w@ h# 8000 = .passed?
+ " w@.2" access-test wa1+ w@ h# 4000 = .passed?
+ " w@.3" word-test w@ h# 8000 = .passed?
+ " w@.4" word-test wa1+ w@ h# 4000 = .passed?
+ " w@.5" char-test w@ h# 0102 = .passed?
+ " w@.6" char-test wa1+ w@ h# 0304 = .passed?
+ " <w@" access-test <w@ h# ffff8000 = .passed?
+ " l@.1" access-test l@ h# 80004000 = .passed?
+ " l@.2" word-test l@ h# 80004000 = .passed?
+ " l@.3" char-test l@ h# 01020304 = .passed?
+ " @!.1" h# 5a5aa5a5 var-test ! var-test @ h# 5a5aa5a5 = .passed?
+ " c@c!.1" h# 55 var-test c! var-test c@ h# 55 = .passed?
+ " w@w!.1" h# aa55 var-test w! var-test w@ h# aa55 = .passed?
+ " l@l!.1" h# 5555aaaa var-test l! var-test l@ h# 5555aaaa = .passed?
+ " @!.1" h# aaaa5555 var-test ! var-test @ h# aaaa5555 = .passed?
+ " +!.1" 2 var-test ! 3 var-test +! var-test @ 5 = .passed?
+ " 2!.1" 1 2 access-test 2! access-test @ 2 =
+ access-test cell+ @ 1 = and .passed?
+ " 2@.1" access-test 2@ 2 = swap 1 = and .passed?
+cr
diff --git a/usr/src/lib/efcode/fcode_test/arithmetic.fth b/usr/src/lib/efcode/fcode_test/arithmetic.fth
new file mode 100644
index 0000000000..8a91e7d88d
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/arithmetic.fth
@@ -0,0 +1,174 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ purpose:
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+." Simple 0 Logic Tests: "
+ " 0 invert" 0 invert .passed?
+ " 0 0=" 0 0= .passed?
+ " -1 invert" -1 invert 0= .passed?
+ " 1 0<>" 1 0<> .passed?
+ " 1 0=" 1 0= invert .passed?
+ " 1 0<>" 1 0<> .passed?
+ " 0 0>=" 0 0>= .passed?
+ " 1 0>=" 1 0>= .passed?
+ " -1 0>=" -1 0>= invert .passed?
+ " 1 0>" 1 0> .passed?
+ " 0 0>" 0 0> invert .passed?
+ " -1 0<" -1 0< .passed?
+ " 0 0<" 0 0< invert .passed?
+ " 0 0<=" 0 0<= .passed?
+ " -1 0<=" -1 0<= .passed?
+ " 1 0<=" 1 0<= invert .passed?
+cr
+
+." Positive Arithmetic Comparision Tests: "
+ " 1 0 >" 1 0 > .passed?
+ " 1 1 >=" 1 1 >= .passed?
+ " 1 1 >" 1 1 > invert .passed?
+ " 0 1 <" 0 1 < .passed?
+ " 0 0 <=" 0 0 <= .passed?
+ " 1 0 <" 1 0 < invert .passed?
+ " 0 0 =" 0 0 = .passed?
+ " 0 1 =" 0 1 = invert .passed?
+ " 0 1 <>" 0 1 <> .passed?
+ " 1 1 <>" 1 1 <> invert .passed?
+cr
+
+." Signed Comparison Tests: "
+ " -1 1 >" -1 1 > invert .passed?
+ " -1 -2 >" -1 -2 > .passed?
+ " -1 0 <" -1 0 < .passed?
+ " -2 -1 <" -2 -1 < .passed?
+cr
+
+." Unsigned Comparison Tests: "
+ " -1 0 u>" -1 0 u> .passed?
+ " -1 0 u>=" 1 1 u>= .passed?
+ " 1 -1 <" 2 1 >= .passed?
+ " 0 1 >=" 0 1 >= invert .passed?
+ " 0 -1 u<" 0 -1 u< .passed?
+ " 0 -1 u<=" 0 -1 u<= .passed?
+ " 2 -2 u<=" 2 -2 u<= .passed?
+cr
+
+." Arithmetic Tests: "
+ " 1 1 +" 1 1 + 2 = .passed?
+ " 1 1 -" 1 1 - 0 = .passed?
+ " 1 negate " 1 negate 1+ 0= .passed?
+ " 0 1 -" 0 1 - -1 = .passed?
+ " -1 abs" -1 abs 1 = .passed?
+ " -1 2 min" -1 2 min 1+ 0= .passed?
+ " 2 -1 min" 2 -1 min 1+ 0= .passed?
+ " 3 2 max" 3 2 max 3 = .passed?
+ " 2 3 max" 2 3 max 3 = .passed?
+cr
+
+." Binary Logic: "
+ " 3 1 and" 3 1 and 1 = .passed?
+ " 2 1 and" 2 1 and 0= .passed?
+ " 1 1 or" 1 1 or 1 = .passed?
+ " 3 1 xor" 3 1 xor 2 = .passed?
+cr
+
+." Shifting: "
+ " (short) lshift" h# 11 8 lshift h# 1100 = .passed?
+ " (short) rshift" h# 1122 8 rshift h# 11 = .passed?
+ " (long) lshift" h# 1 d# 31 lshift 1- h# 7fffffff = .passed?
+ " (long) rshift" h# 80 d# 24 lshift d# 31 rshift 1 = .passed?
+ " >>a" -4 1 >>a -2 = .passed?
+cr
+
+." Sized Arithmetic Tests: "
+ " u2/" 0 0 0 h# 80 bljoin u2/ h# 4000.0000 = .passed?
+ " 2/" -4 2/ -2 = .passed?
+ " 2*" h# 4000.0000 dup 1 lshift swap 2* = .passed?
+ " /c" 1 /c = .passed?
+ " /w" 2 /w = .passed?
+ " /l" 4 /l = .passed?
+ " /n" 4 /n = 8 /n = or .passed?
+ " ca+" h# 4000 3 ca+ h# 4003 = .passed?
+ " wa+" h# 4000 3 wa+ h# 4006 = .passed?
+ " la+" h# 4000 3 la+ h# 400c = .passed?
+ " na+" h# 4000 3 na+ h# 4000 3 /n * + = .passed?
+ " char+" h# 4000 char+ h# 4001 = .passed?
+ " wa1+" h# 4000 wa1+ h# 4002 = .passed?
+ " la1+" h# 4000 la1+ h# 4004 = .passed?
+ " cell+" h# 4000 cell+ h# 4000 /n + = .passed?
+ " chars" 4 chars 4 = .passed?
+ " /w*" 8 /w* h# 10 = .passed?
+ " /l*" 4 /l* h# 10 = .passed?
+ " cells" 4 cells 4 /n * = .passed?
+cr
+
+." Division related Tests: "
+ " /mod (+ +)" 5 2 /mod 2 = swap 1 = and .passed?
+ " /mod (- -)" -5 -2 /mod 2 = swap -1 = and .passed?
+ " /mod (+ -)" 5 -2 /mod -3 = swap -1 = and .passed?
+ " /mod (- +)" -5 2 /mod -3 = swap 1 = and .passed?
+ " / (+ +)" 5 2 / 2 = .passed?
+ " / (- -)" -5 -2 / 2 = .passed?
+ " / (+ -)" 5 -2 / -3 = .passed?
+ " / (- +)" -5 2 / -3 = .passed?
+ " mod (+ +)" 5 2 mod 1 = .passed?
+ " mod (- -)" -5 -2 mod -1 = .passed?
+ " mod (+ -)" 5 -2 mod -1 = .passed?
+ " mod (- +)" -5 2 mod 1 = .passed?
+cr
+
+." Signed Multiply/Divide Tests:"
+ " * (+ +)" 2 3 * 6 = .passed?
+ " * (- +)" -3 3 * -9 = .passed?
+ " * (+ -)" 4 -2 * -8 = .passed?
+ " * (- -)" -4 -3 * 12 = .passed?
+cr
+
+." Unsigned Multiply/Divide Tests: "
+ " um*" 1 2 um* 0= swap 2 = and .passed?
+ " um/mod" 5 0 2 um/mod 2 = swap 1 = and .passed?
+ " u/mod" 5 2 u/mod 2 = swap 1 = and .passed?
+cr
+
+." Ranged Tests: "
+ " within (!0)" 2 1 3 within .passed?
+ " within (0 hi)" 3 1 3 within 0= .passed?
+ " within (!0 lo)" 1 1 3 within .passed?
+ " within (0 >)" 0 1 3 within 0= .passed?
+ " within (0 <)" 4 1 3 within 0= .passed?
+ " within (-ve)" 0 -5 5 within .passed?
+ " within (- -)" -7 -10 -5 within .passed?
+ " between (!0)" 2 1 3 between .passed?
+ " between (!0 lo)" 1 1 3 between .passed?
+ " between (!0 hi)" 3 1 3 between .passed?
+ " between (0 >)" 4 1 3 between 0= .passed?
+ " between (0 <)" 0 1 3 between 0= .passed?
+ " between (-ve)" 0 -5 5 between .passed?
+ " between (- -)" -7 -10 -5 between .passed?
+ " bounds" -1 3 bounds -1 = swap 2 = and .passed?
+cr
+
+." Double Arithmetic: "
+ " d+" 1 2 3 4 d+ 6 = swap 4 = and .passed?
+ " d-" 3 4 2 1 d- 3 = swap 1 = and .passed?
+cr
diff --git a/usr/src/lib/efcode/fcode_test/bytemanipulate.fth b/usr/src/lib/efcode/fcode_test/bytemanipulate.fth
new file mode 100644
index 0000000000..772e07f6f1
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/bytemanipulate.fth
@@ -0,0 +1,56 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ purpose:
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+." Byte Split tests: "
+ " lbsplit" h# 11223344 lbsplit
+ h# 11 = swap h# 22 = and swap
+ h# 33 = and swap h# 44 = and .passed?
+ " lwsplit" h# 11223344 lwsplit
+ h# 1122 = swap h# 3344 = and .passed?
+ " wbsplit" h# 31122 wbsplit
+ h# 11 = swap h# 22 = and .passed?
+ " wljoin" h# beef h# dead wljoin h# deadbeef = .passed?
+ " bljoin" h# 111 h# 222 h# 333 h# 444 bljoin
+ h# 44332211 = .passed?
+ " bwjoin" h# 111 h# 222 bwjoin h# 2211 = .passed?
+ " lbflip" h# 11223344 lbflip h# 44332211 = .passed?
+ " lwflip" h# 11223344 lwflip h# 33441122 = .passed?
+ " wbflip" h# 31122 wbflip h# 2211 = .passed?
+create flip-area
+ h# 01020304 l,
+ " wbflips" flip-area /l wbflips flip-area l@ h# 02010403 = .passed?
+ " lwflips" flip-area /l lwflips flip-area l@ h# 04030201 = .passed?
+ " lbflips" flip-area /l lbflips flip-area l@ h# 01020304 = .passed?
+cr
+
+." Memory ops: "
+ " comp +" " abcde" drop " abcd" drop 5 comp 1 = .passed?
+ " comp -" " abcd" drop " abcde" comp -1 = .passed?
+ " comp =" " abcdef" drop " abcdef" comp 0= .passed?
+ " alloc-mem" h# 100 dup alloc-mem ?dup
+ if 2swap -1 else drop false then .passed?
+ " free-mem" 2swap swap free-mem 1 .passed?
+cr
diff --git a/usr/src/lib/efcode/fcode_test/calling.fth b/usr/src/lib/efcode/fcode_test/calling.fth
new file mode 100644
index 0000000000..85eedc7f8b
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/calling.fth
@@ -0,0 +1,36 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ purpose:
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+: t1 ascii W emit ;
+: t2 ascii L emit ;
+: t3 t2 ascii D emit ;
+: t4 t1 ascii O emit ;
+: t5 t4 ascii R emit ;
+: t6 t5 t3 space ;
+: t7 ." hello " t6 ;
+: t8 t7 ." and everyone" ;
+
+cr ." > " t8 cr
diff --git a/usr/src/lib/efcode/fcode_test/case.fth b/usr/src/lib/efcode/fcode_test/case.fth
new file mode 100644
index 0000000000..58b7dcbc52
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/case.fth
@@ -0,0 +1,42 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ purpose:
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+." Case: "
+: case1 ( n -- str )
+ case
+ 0 of " zero" >r >r endof
+ 1 of " one" >r >r endof
+ 2 of " two" >r >r endof
+ dup <# u#s u#> >r >r
+ endcase
+ r> r>
+;
+ " case.1" 0 case1 drop " zero" comp invert .passed?
+ " case.2" 1 case1 drop " one" comp invert .passed?
+ " case.3" 2 case1 drop " two" comp invert .passed?
+ " case.4" 3 case1 drop " 3" comp invert .passed?
+ " case.5" 4 case1 drop " 4" comp invert .passed?
+cr
diff --git a/usr/src/lib/efcode/fcode_test/catch.fth b/usr/src/lib/efcode/fcode_test/catch.fth
new file mode 100644
index 0000000000..c3493bcf41
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/catch.fth
@@ -0,0 +1,33 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ purpose:
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+." catch/throw: "
+ : ttest ( n -- ) throw 0 ;
+ : ttest1 ( -- ) 0 ['] ttest catch 0= swap 0= and ;
+ : ttest2 ( -- ) 1 1 ['] ttest catch nip 1 = swap 1 = and ;
+ " 0 throw" ttest1 .passed?
+ " 1 throw" ttest2 .passed?
+cr
diff --git a/usr/src/lib/efcode/fcode_test/create.fth b/usr/src/lib/efcode/fcode_test/create.fth
new file mode 100644
index 0000000000..be83cd7d5a
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/create.fth
@@ -0,0 +1,40 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ purpose:
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+." Create Test: "
+create table
+ ascii p c,
+ ascii a c,
+ ascii s c,
+ ascii s c,
+ ascii e c,
+ ascii d c,
+
+here table - create table-len c,
+
+: table-test ( -- ) table table-len c@ ;
+ " create.1" " passed" drop table-test comp invert .passed?
+cr
diff --git a/usr/src/lib/efcode/fcode_test/find.fth b/usr/src/lib/efcode/fcode_test/find.fth
new file mode 100644
index 0000000000..443bb60fa3
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/find.fth
@@ -0,0 +1,35 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ Use is subject to license terms.
+\
+\ CDDL HEADER START
+\
+\ The contents of this file are subject to the terms of the
+\ Common Development and Distribution License, Version 1.0 only
+\ (the "License"). You may not use this file except in compliance
+\ with the License.
+\
+\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ or http://www.opensolaris.org/os/licensing.
+\ See the License for the specific language governing permissions
+\ and limitations under the License.
+\
+\ When distributing Covered Code, include this CDDL HEADER in each
+\ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ If applicable, add the following below this CDDL HEADER, with the
+\ fields enclosed by brackets "[]" replaced with your own identifying
+\ information: Portions Copyright [yyyy] [name of copyright owner]
+\
+\ CDDL HEADER END
+\
+
+." Execute test: "
+ : etest ['] 1 dup dup execute swap execute + swap execute + ;
+ " " etest 3 = .passed?
+ " evaluate.1" " 1 2 +" evaluate 3 = .passed?
+cr
+
+." $find testing: "
+" $find.1" 0 1 " drop" $find if execute then 0= .passed?
+" $find.2" " qwerty" $find if false else " qwerty" $= then .passed?
+cr
diff --git a/usr/src/lib/efcode/fcode_test/iftest.fth b/usr/src/lib/efcode/fcode_test/iftest.fth
new file mode 100644
index 0000000000..b087cff1d1
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/iftest.fth
@@ -0,0 +1,118 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ Use is subject to license terms.
+\
+\ CDDL HEADER START
+\
+\ The contents of this file are subject to the terms of the
+\ Common Development and Distribution License, Version 1.0 only
+\ (the "License"). You may not use this file except in compliance
+\ with the License.
+\
+\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ or http://www.opensolaris.org/os/licensing.
+\ See the License for the specific language governing permissions
+\ and limitations under the License.
+\
+\ When distributing Covered Code, include this CDDL HEADER in each
+\ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ If applicable, add the following below this CDDL HEADER, with the
+\ fields enclosed by brackets "[]" replaced with your own identifying
+\ information: Portions Copyright [yyyy] [name of copyright owner]
+\
+\ CDDL HEADER END
+\
+
+cr ." Simple interpreted IF THEN test: "
+1 if .passed then space
+0 if .failed then space
+cr
+
+." Simple interpreted IF ELSE THEN test: "
+0 if .failed else .passed then space
+1 if .passed else .failed then space
+cr
+
+." Nested interpreted IF test: "
+1 1 1 0 0 1 0 0
+if if .failed else .failed then space
+else if .failed else .passed then space
+then
+if if .failed else .passed then space
+else if .failed else .failed then space
+then
+if if .failed else .failed then space
+else if .passed else .failed then space
+then
+if if .passed else .failed then space
+else if .failed else .failed then space
+then
+cr
+
+." Compiled single IF tests:" space
+: if-true? if .passed space 0 exit then .failed space 0 ; 1 if-true?
+: if-false? if .failed space 1 exit then .passed space 1 ; if-false?
+: true? if .passed else .failed then space 0 ; true?
+: false? if .failed else .passed then space ; false?
+
+cr
+
+." Nested compiled IF test: "
+: if-test1 ( -- )
+ 0 1 0 if
+ .failed
+ else
+ if
+ dup if .failed then
+ if .failed else .passed then
+ else
+ .failed
+ then
+ then
+; if-test1 space
+
+: .passed? ( str,len flag )
+ if if then if then .passed space else cr type space .failed cr then
+;
+
+: if-test2 ( x x x -- )
+ if
+ if
+ if
+ 7
+ else
+ 6
+ then
+ else
+ if
+ 5
+ else
+ 4
+ then
+ then
+ else
+ if
+ if
+ 3
+ else
+ 2
+ then
+ else
+ if
+ 1
+ else
+ 0
+ then
+ then
+ then
+;
+
+ " if-test2.0" 0 0 0 if-test2 0 = .passed?
+ " if-test2.1" 1 0 0 if-test2 1 = .passed?
+ " if-test2.2" 0 1 0 if-test2 2 = .passed?
+ " if-test2.3" 1 1 0 if-test2 3 = .passed?
+ " if-test2.4" 0 0 1 if-test2 4 = .passed?
+ " if-test2.5" 1 0 1 if-test2 5 = .passed?
+ " if-test2.6" 0 1 1 if-test2 6 = .passed?
+ " if-test2.7" 1 1 1 if-test2 7 = .passed?
+cr
diff --git a/usr/src/lib/efcode/fcode_test/instance.fth b/usr/src/lib/efcode/fcode_test/instance.fth
new file mode 100644
index 0000000000..c37f08a5a1
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/instance.fth
@@ -0,0 +1,28 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ purpose:
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+3 instance value ivar-foo
+4 instance value ivar-bar
diff --git a/usr/src/lib/efcode/fcode_test/loop.fth b/usr/src/lib/efcode/fcode_test/loop.fth
new file mode 100644
index 0000000000..72f860ea9e
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/loop.fth
@@ -0,0 +1,97 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ Use is subject to license terms.
+\
+\ CDDL HEADER START
+\
+\ The contents of this file are subject to the terms of the
+\ Common Development and Distribution License, Version 1.0 only
+\ (the "License"). You may not use this file except in compliance
+\ with the License.
+\
+\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ or http://www.opensolaris.org/os/licensing.
+\ See the License for the specific language governing permissions
+\ and limitations under the License.
+\
+\ When distributing Covered Code, include this CDDL HEADER in each
+\ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ If applicable, add the following below this CDDL HEADER, with the
+\ fields enclosed by brackets "[]" replaced with your own identifying
+\ information: Portions Copyright [yyyy] [name of copyright owner]
+\
+\ CDDL HEADER END
+\
+
+." Interactive begin .. while .. repeat: "
+ " no loop (1) " 1 begin 0 while 1- repeat .passed?
+ " loop to 0 (1)" 9 begin dup while 1- repeat 0= .passed?
+cr
+." Compiled begin .. while .. repeat: "
+ : btest1 1 begin 0 while 1- repeat .passed? ;
+ : btest2 9 begin dup while 1- repeat 0= .passed? ;
+ " no loop (2) " btest1
+ " loop to 0 (2)" btest2
+cr
+." Interactive begin..until: "
+ " no loop (3)" 1 begin dup until .passed?
+ " loop to 0 (3)" 9 begin 1- dup 0= until 0= .passed?
+cr
+." Compiled begin..until: "
+ : btest3 1 begin dup until .passed? ;
+ : btest4 9 begin 1- dup 0= until 0= .passed? ;
+ " no loop (4)" btest3
+ " loop to 0 (4)" btest4
+cr
+." Interactive do .. loop: "
+ " loop (1)" 0 h# 10 0 do drop i loop h# f = .passed?
+ " no loop (1)" 1 0 0 ?do 1- loop .passed?
+ " leave (1)" h# 10 0 do i 5 = if 1 leave drop 0 then loop .passed?
+cr
+." Compiled do .. loop: "
+ : loop1 do drop i loop h# f = .passed? ;
+ : loop2 ?do 1- loop .passed? ;
+ : loop3 do i 3 = if drop i leave 0 then loop ;
+ : loop7 do i 4 = if drop i unloop exit then loop ;
+ " loop (2)" 0 h# 10 0 loop1
+ " no loop (2)" 1 0 0 loop2
+ " leave (2)" 3 4 0 loop3 3 = .passed?
+ " unloop" 5 6 0 loop7 4 = .passed?
+cr
+." Interactive do .. +loop: "
+ " loop by 2" 0 h# 10 0 do drop i 2 +loop h# e = .passed?
+ " loop down by 2" 0 -2 h# 10 do drop i -2 +loop h# -2 = .passed?
+cr
+." Compiled do .. +loop: "
+ : loop4 0 h# 10 0 do drop i 2 +loop h# e = .passed? ;
+ : loop5 0 -2 h# 10 do drop i -2 +loop -2 = .passed? ;
+ " loop (4)" loop4
+ " loop (5)" loop5
+cr
+." Nested loops: "
+ : loop6 0 h# 4 0 do 8 0 do 1 j 3 lshift i + lshift xor loop loop ;
+ " i,j sum" loop6 lwsplit over = swap h# ffff = and .passed?
+cr
+." Negative Limit Loops: "
+ " loop.7" h# 10 -37 8 bounds do drop i loop -30 = .passed?
+ " loop.8" h# 10 -37 -30 do drop i -1 +loop -37 = .passed?
+cr
+." Compiled begin...again: "
+ : loop9 begin true exit again false ; loop9 " loop9" rot .passed?
+ 0 value in-count
+ 0 value out-count
+ : loop10
+ begin
+ out-count 1+ to out-count
+ begin
+ in-count 10 >= if
+ exit
+ then in-count 1+ to in-count
+ again
+ -1 to in-count
+ exit
+ again
+ -2 to in-count
+ ;
+ " loop.10" loop10 in-count 10 = out-count 1 = and .passed?
+cr
diff --git a/usr/src/lib/efcode/fcode_test/misc.fth b/usr/src/lib/efcode/fcode_test/misc.fth
new file mode 100644
index 0000000000..20dee7aabd
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/misc.fth
@@ -0,0 +1,188 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ purpose:
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+." Buffer: "
+ h# 20 buffer: my-unit-str
+ " abcd" my-unit-str pack drop
+ " pack.1" my-unit-str c@ 4 = .passed?
+ " pack.2" my-unit-str 1 + c@ ascii a = .passed?
+ " pack.3" my-unit-str 2 + c@ ascii b = .passed?
+ " pack.4" my-unit-str 3 + c@ ascii c = .passed?
+ " pack.5" my-unit-str 4 + c@ ascii d = .passed?
+ " count.1" my-unit-str count " abcd" $= .passed?
+cr
+
+." Formatting: "
+ " fmt.1" 1 h# 23 <# #s #> " 2300000001" $= .passed?
+ " fmt.2" 1 h# 23 <# # # #> " 01" $= .passed?
+ " fmt.3" h# 123 <# u#s u#> " 123" $= .passed?
+ " fmt.4" h# 123 <# u# ascii X hold u# u#> " 2X3" $= .passed?
+ d# 10 base !
+ " fmt.5" d# -123 <# dup abs u#s swap sign u#> " -123" $= .passed?
+ " fmt.6" d# 123 <# dup abs u#s swap sign u#> " 123" $= .passed?
+ " fmt.7" " -123" $number invert swap d# -123 = and .passed?
+ d# 16 base !
+ " fmt.8" " 32a" $number invert swap h# 32a = and .passed?
+ " fmt.9" " xyzzy" $number .passed?
+ : dnumber ( n -- str len )
+ base @ >r d# 10 base !
+ <# dup abs u#s swap sign u#>
+ r> base !
+ ;
+ " fmt.10" d# 12345678 dnumber " 12345678" $= .passed?
+ " fmt.11" d# -87654321 dnumber " -87654321" $= .passed?
+ " fmt.12" #out @ space #out @ 1 - = .passed?
+ " fmt.13" #line @ cr #out @ #line @ rot 1 + = swap 0= and .passed?
+ " fmt.14" #line @ (cr #out @ #line @ rot = swap 0= and .passed?
+ " fmt.15" bs h# 8 = .passed?
+ " fmt.16" bell h# 7 = .passed?
+ " fmt.17" bl h# 20 = .passed?
+ " fmt.18" ascii 5 d# 10 digit swap 5 = and .passed?
+ " fmt.19" ascii x d# 16 digit invert swap ascii x = and .passed?
+cr
+
+." (is-user-word): "
+ : xyzzy 1 2 3 ;
+ " xx" ' xyzzy (is-user-word)
+ " xx" $find if .passed space execute else .failed then
+ " iuw.1" 2 pick 3 = .passed?
+ " iuw.2" 3 pick 2 = .passed?
+ " iuw.3" 4 pick 1 = .passed?
+ drop drop drop
+cr
+
+." Move/Fill/Upper/Lower:"
+ " xyzzy" my-unit-str swap move
+ " move.1" my-unit-str " xyzzy" comp 0= .passed?
+ my-unit-str 9 ascii A fill
+ my-unit-str 6 ascii X fill
+ " fill.1" my-unit-str " XXXXXXAAA" comp 0= .passed?
+ 9 0 do my-unit-str i + dup c@ lcc swap c! loop
+ " lcc.1" my-unit-str " xxxxxxaaa" comp 0= .passed?
+ 9 0 do my-unit-str i + dup c@ upc swap c! loop
+ " upc.1" my-unit-str " XXXXXXAAA" comp 0= .passed?
+cr
+
+." >body/body>: "
+external
+ : xx 1 2 3 ;
+headers
+ " >body" ' xx >body ' xx /n + = .passed?
+ " body>" ' xx dup >body body> = .passed?
+cr
+
+." Fcode-revision: "
+ " Fcode-revision" fcode-revision h# 30000 = .passed?
+cr
+
+." Defer/Behavior: "
+ defer defer-word
+ ' xx to defer-word
+ " defer.1" defer-word 3 = swap 2 = and swap 1 = and .passed?
+ " behavior.1" ' defer-word behavior ' xx = .passed?
+cr
+
+." Aligned: "
+ variable alvar
+ " align.1" alvar aligned alvar = .passed?
+ " align.2" alvar /c - aligned alvar = .passed?
+ " align.3" alvar char+ aligned alvar la1+ = .passed?
+cr
+
+." Field: "
+struct
+ /n field >x1
+ /l field >x2
+ /w field >x3
+ /c field >x4
+constant /field-test
+ " field.1" /field-test /n /l /w /c + + + = .passed?
+ " field.2" 0 >x1 0 = .passed?
+ " field.3" 0 >x2 /n = .passed?
+ " field.4" 0 >x3 /n /l + = .passed?
+ " field.5" 0 >x4 /n /l /w + + = .passed?
+cr
+
+
+." Properties: "
+ 0 value root-phandle
+ " use-fake-handles" $find if execute else 2drop then
+ " /" " (cd)" $find if execute else 2drop then
+ " /" find-package if to root-phandle then
+ 1 encode-int " int-prop" property
+ 1 2 encode-phys " phys-prop" property
+ 1 2 3 reg
+ " XYZZY" model
+ 1 encode-int 2 encode-int encode+ " 2int-prop" property
+ " abcd" encode-string " string-prop" property
+ " wxyz" encode-bytes " bytes-prop" property
+ " prop.1" " bytes-prop" root-phandle get-package-property if
+ .failed
+ else
+ " wxyz" $= .passed?
+ then
+ " prop.2" " string-prop" root-phandle get-package-property if
+ .failed
+ else
+ decode-string " abcd" $= nip nip .passed?
+ then
+ " prop.3" " int-prop" root-phandle get-package-property if
+ .failed
+ else
+ decode-int 1 = nip nip .passed?
+ then
+ " prop.4" " phys-prop" root-phandle get-package-property if
+ .failed
+ else
+ decode-phys 2 = swap 1 = and nip nip .passed?
+ then
+ " prop.5" 0 0 root-phandle next-property if
+ " bytes-prop" $= .passed?
+ else
+ .failed
+ then
+ " prop.6" " string-prop" root-phandle next-property if
+ " 2int-prop" $= .passed?
+ else
+ .failed
+ then
+cr
+ " .properties" $find if execute else 2drop then
+cr
+
+." Timing/Alarm: "
+ " ms.1" get-msecs h# 100 ms get-msecs swap - h# 80 h# 150 between .passed?
+\ 0 value alarm-happened
+\ : alarm-word 1 to alarm-happened ." OK " ;
+\ ' alarm-word 10 alarm
+\ 0
+\ begin
+\ 1 + dup 1000000 > alarm-happened 0<> or
+\ until
+\ drop
+\ 0 0 alarm
+\ " alarm.1" alarm-happened .passed?
+cr
diff --git a/usr/src/lib/efcode/fcode_test/parse.fth b/usr/src/lib/efcode/fcode_test/parse.fth
new file mode 100644
index 0000000000..121cfdb3a1
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/parse.fth
@@ -0,0 +1,56 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ purpose:
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+ ." parse:"
+ : $= ( str1 len1 str2 len2 -- true/false )
+ 2 pick <> if
+ 3drop false
+ else
+ swap dup 0= if
+ 3drop true
+ else
+ true swap 0 do
+ 2 pick i + c@
+ 2 pick i + c@
+ = and
+ loop nip nip
+ then
+ then
+ ;
+ : parse-test
+ " $= test.1" " abcd" " abcd" $= .passed?
+ " $= test.2" " abdc" " abcd" $= invert .passed?
+ " $= test.3" " abc" " abcd" $= invert .passed?
+ " 9600,8,n,1,-"
+ ascii , left-parse-string " 9600" $= " left-parse.1" rot .passed?
+ ascii , left-parse-string " 8" $= " left-parse.2" rot .passed?
+ ascii , left-parse-string " n" $= " left-parse.3" rot .passed?
+ ascii , left-parse-string " 1" $= " left-parse.4" rot .passed?
+ ascii , left-parse-string " -" $= " left-parse.5" rot .passed?
+ 2drop
+ ;
+ parse-test
+ cr
diff --git a/usr/src/lib/efcode/fcode_test/stack.fth b/usr/src/lib/efcode/fcode_test/stack.fth
new file mode 100644
index 0000000000..b0f4c2eb07
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/stack.fth
@@ -0,0 +1,56 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ purpose:
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+." Stack Manipulation: "
+ " drop" 1 0 drop .passed?
+ " swap" 1 2 1 swap drop = .passed?
+ " nip" 1 0 1 nip - 0= .passed?
+ " over" 1 2 over 1 = nip nip .passed?
+ " dup" 1 dup = .passed?
+ " tuck" 2 1 tuck nip = .passed?
+ " rot" 3 2 1 rot 3 = nip nip .passed?
+ " -rot" 3 2 1 -rot 2 = nip nip .passed?
+ " 2rot" 1 2 3 4 5 6 2rot 2 = swap 1 = and swap 6 = and swap
+ 5 = and swap 4 = and swap 3 = and .passed?
+ " 2dup" 1 -1 2dup + 0= nip nip .passed?
+ " ?dup" 0 1 ?dup = nip .passed?
+ " 2swap" 1 1 0 0 2swap and nip nip .passed?
+ " 2drop" 1 1 0 0 2drop and .passed?
+ " 2over" 1 2 0 0 2over 2swap 2drop rot = -rot = = .passed?
+ " roll" 1 2 3 4 3 roll 1 = nip nip nip .passed?
+ " depth" 0 0 depth 4 = nip nip .passed?
+cr
+
+." Return Stack: "
+: test-rs
+ " >r" 3 1 >r 2 >r 3 = .passed?
+ " r@" 3 r@ 2 = nip .passed?
+ " r>" 3 r> 2 = r> 1 = and nip .passed?
+; test-rs
+: bail-test ( -- ) r> drop ;
+: bail ( -- ) 1 bail-test drop 0 ;
+ " Manipulate" bail .passed?
+cr
diff --git a/usr/src/lib/efcode/fcode_test/storage.fth b/usr/src/lib/efcode/fcode_test/storage.fth
new file mode 100644
index 0000000000..1ffa4f79fb
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/storage.fth
@@ -0,0 +1,46 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ purpose:
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+." Runtime storage access: "
+ variable var-1 var-1 off
+ 4 constant const-1
+ 5 value val-1
+ " variable (off) (get)" var-1 @ 0= .passed?
+ " variable (on) (set)" var-1 on var-1 @ -1 = .passed?
+ " variable (set)" 2 var-1 ! var-1 @ 2 = .passed?
+ " constant.1" const-1 4 = .passed?
+ " value (get)" val-1 5 = .passed?
+ " value (set)" 2 to val-1 val-1 2 = .passed?
+cr
+
+." Compile time storage access: "
+ " variable (get)" : vtest1 var-1 @ = .passed? ; 2 vtest1
+ " variable (set)" : vtest2 1 var-1 ! 1 vtest1 ; vtest2
+ " constant.2" : ctest const-1 const-1 + 8 = .passed? ; ctest
+ " value (get)" : vtest3 val-1 = .passed? ; 2 vtest3
+ " value (set)" : vtest4 1 to val-1 1 vtest3 ; vtest4
+cr
+
diff --git a/usr/src/lib/efcode/fcode_test/test.fth b/usr/src/lib/efcode/fcode_test/test.fth
new file mode 100644
index 0000000000..86e27b33f7
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/test.fth
@@ -0,0 +1,70 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ Use is subject to license terms.
+\
+\ CDDL HEADER START
+\
+\ The contents of this file are subject to the terms of the
+\ Common Development and Distribution License, Version 1.0 only
+\ (the "License"). You may not use this file except in compliance
+\ with the License.
+\
+\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ or http://www.opensolaris.org/os/licensing.
+\ See the License for the specific language governing permissions
+\ and limitations under the License.
+\
+\ When distributing Covered Code, include this CDDL HEADER in each
+\ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ If applicable, add the following below this CDDL HEADER, with the
+\ fields enclosed by brackets "[]" replaced with your own identifying
+\ information: Portions Copyright [yyyy] [name of copyright owner]
+\
+\ CDDL HEADER END
+\
+
+fcode-version1
+
+alias headerless headers
+
+ fload calling.fth
+ noop
+ : .noop noop noop ;
+
+ : .failed ." failed!" ;
+
+ : .passed ." OK" ;
+
+ fload iftest.fth
+
+ : .chkstk depth if ." Stack Changed: " .s cr then ;
+
+ .chkstk
+ fload arithmetic.fth
+ .chkstk
+ fload stack.fth
+ .chkstk
+ fload create.fth
+ .chkstk
+ fload bytemanipulate.fth
+ .chkstk
+ fload loop.fth
+ .chkstk
+ fload storage.fth
+ .chkstk
+ fload access.fth
+ .chkstk
+ fload case.fth
+ .chkstk
+ fload catch.fth
+ .chkstk
+ fload parse.fth
+ .chkstk
+ fload find.fth
+ .chkstk
+ fload misc.fth
+ .chkstk
+ cr ." End of Tests" cr
+
+end0
+
diff --git a/usr/src/lib/efcode/fcode_test/test64.fth b/usr/src/lib/efcode/fcode_test/test64.fth
new file mode 100644
index 0000000000..56088018a5
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/test64.fth
@@ -0,0 +1,126 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ purpose:
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+fcode-version1
+." 64-bit Fcode operation tests" cr
+
+ : .failed ." failed!" ;
+
+ : .passed ." OK" ;
+
+ : .chkstk depth if ." Stack Changed: " .s cr then ;
+
+ : .passed? ( str,len flag )
+ if if then if then .passed space else cr type space .failed cr then
+ ;
+
+\ comparisons only 32-bit...
+: xl= ( xv lh ll -- flag )
+ swap rot xlsplit rot = -rot = and
+;
+
+: x= ( xv1 xv2 -- flag )
+ xlsplit rot xlsplit rot = -rot = and
+;
+create test-64
+ h# 01020304 l,
+ h# 05060708 l,
+ h# 81121314 l,
+ h# 85161718 l,
+ h# ffffffff l,
+ h# 80000000 l,
+
+." 64-bit access tests: "
+ " /x.1" /x 8 = .passed?
+ " xa1+.1" test-64 xa1+ test-64 /x + = .passed?
+ " xa+.1" test-64 2 xa+ test-64 /x 2 * + = .passed?
+ " x@.1" test-64 x@ h# 01020304 h# 05060708 xl= .passed?
+ " x@.2" test-64 xa1+ x@ h# 81121314 h# 85161718 xl= .passed?
+ " <l@.1" test-64 2 xa+ dup la1+ <l@ swap x@ x= .passed?
+ " bxjoin.1" 8 7 6 5 4 3 2 1 bxjoin test-64 x@ x= .passed?
+ " wxjoin.1" h# 0708 h# 0506 h# 0304 h# 0102 wxjoin test-64 x@ x= .passed?
+ " lxjoin.1" h# 05060708 h# 01020304 lxjoin test-64 x@ x= .passed?
+ " x!.1" h# 85161718 h# 81121314 lxjoin test-64 x!
+ test-64 x@ h# 81121314 h# 85161718 xl= .passed?
+ " x!.2" h# 05060708 h# 01020304 lxjoin test-64 x!
+ test-64 x@ h# 01020304 h# 05060708 xl= .passed?
+cr
+." 64-bit flips: "
+ " xbflip.1" test-64 x@ xbflip h# 08070605 h# 04030201 xl= .passed?
+ " xwflip.1" test-64 x@ xwflip h# 07080506 h# 03040102 xl= .passed?
+ " xlflip.1" test-64 x@ xlflip h# 05060708 h# 01020304 xl= .passed?
+ " xbsplit.1" test-64 x@ xbsplit bxjoin test-64 x@ x= .passed?
+ " xwsplit.1" test-64 x@ xwsplit wxjoin test-64 x@ x= .passed?
+ " xlsplit.1" test-64 x@ xlsplit lxjoin test-64 x@ x= .passed?
+ " xbflips.1" test-64 /x xbflips test-64 x@
+ h# 08070605 h# 04030201 xl= .passed?
+ " xbflips.2" test-64 /x xbflips test-64 x@
+ h# 01020304 h# 05060708 xl= .passed?
+ " xwflips.1" test-64 /x xwflips test-64 x@
+ h# 07080506 h# 03040102 xl= .passed?
+ " xwflips.2" test-64 /x xwflips test-64 x@
+ h# 01020304 h# 05060708 xl= .passed?
+ " xlflips.1" test-64 /x xlflips test-64 x@
+ h# 05060708 h# 01020304 xl= .passed?
+ " xlflips.2" test-64 /x xlflips test-64 x@
+ h# 01020304 h# 05060708 xl= .passed?
+cr
+
+
+0 value commatest-64-end
+create commatest-64
+ h# 01020304 h# 05060708 swap lxjoin x,
+ h# 81121314 h# 85161718 swap lxjoin x,
+ h# ffffffff h# 80000000 swap lxjoin x,
+ here to commatest-64-end
+
+." 64-bit xcomma: "
+ " x,.1" commatest-64 3 xa+ commatest-64-end = .passed?
+ " x,.2" test-64 x@ commatest-64 x@ x= .passed?
+ " x,.3" test-64 xa1+ x@ commatest-64 xa1+ x@ x= .passed?
+ " x,.4" test-64 2 xa+ x@ commatest-64 2 xa+ x@ x= .passed?
+cr
+
+." 64-bit constant/value/variable: "
+1 2 lxjoin constant const-64
+1 2 lxjoin value value-64
+variable var-64
+ " const.1" const-64 2 1 xl= .passed?
+ " value.1" value-64 2 1 xl= .passed?
+ " value.2" 3 4 lxjoin to value-64 value-64 4 3 xl= .passed?
+ " var.1" const-64 var-64 ! var-64 @ 2 1 xl= .passed?
+cr
+
+." 64-bit comparisions: "
+ \ FCode comparators are 32-bit only, upper 32-bits are ignored.
+ " 64comp.1" 1 2 lxjoin 1 = .passed?
+ " 64comp.2" 1 2 lxjoin 2 < .passed?
+ " 64comp.3" 2 1 2 lxjoin > .passed?
+ " 64comp.4" 0 2 lxjoin 0= .passed?
+ " 64comp.5" 1 2 lxjoin 0> .passed?
+cr
+
+end0
diff --git a/usr/src/lib/efcode/fcode_test/values.fth b/usr/src/lib/efcode/fcode_test/values.fth
new file mode 100644
index 0000000000..296f0e0387
--- /dev/null
+++ b/usr/src/lib/efcode/fcode_test/values.fth
@@ -0,0 +1,29 @@
+\ #ident "%Z%%M% %I% %E% SMI"
+\ purpose:
+\ copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+\ copyright: Use is subject to license terms.
+\ copyright:
+\ copyright: CDDL HEADER START
+\ copyright:
+\ copyright: The contents of this file are subject to the terms of the
+\ copyright: Common Development and Distribution License, Version 1.0 only
+\ copyright: (the "License"). You may not use this file except in compliance
+\ copyright: with the License.
+\ copyright:
+\ copyright: You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+\ copyright: or http://www.opensolaris.org/os/licensing.
+\ copyright: See the License for the specific language governing permissions
+\ copyright: and limitations under the License.
+\ copyright:
+\ copyright: When distributing Covered Code, include this CDDL HEADER in each
+\ copyright: file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+\ copyright: If applicable, add the following below this CDDL HEADER, with the
+\ copyright: fields enclosed by brackets "[]" replaced with your own identifying
+\ copyright: information: Portions Copyright [yyyy] [name of copyright owner]
+\ copyright:
+\ copyright: CDDL HEADER END
+\ copyright:
+
+external
+1 value var-foo
+2 value var-bar
diff --git a/usr/src/lib/efcode/gp2/Makefile b/usr/src/lib/efcode/gp2/Makefile
new file mode 100644
index 0000000000..29132d88a1
--- /dev/null
+++ b/usr/src/lib/efcode/gp2/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.subdirs
diff --git a/usr/src/lib/efcode/gp2/Makefile.com b/usr/src/lib/efcode/gp2/Makefile.com
new file mode 100644
index 0000000000..87d58209a9
--- /dev/null
+++ b/usr/src/lib/efcode/gp2/Makefile.com
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+OBJECTS = gp2.o
+LIBRARY = lfc_gptwo.a
+SYMLINKS = lfc_gptwo_gptwo.so
+
+include ../../Makefile.efcode
diff --git a/usr/src/lib/efcode/gp2/gp2.c b/usr/src/lib/efcode/gp2/gp2.c
new file mode 100644
index 0000000000..8832230f76
--- /dev/null
+++ b/usr/src/lib/efcode/gp2/gp2.c
@@ -0,0 +1,341 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+fstack_t
+mem_map_in(fcode_env_t *env, fstack_t hi, fstack_t lo, fstack_t len)
+{
+ private_data_t *pdp = DEVICE_PRIVATE(env);
+ fc_cell_t virt;
+ fstack_t mcookie = NULL;
+ char *service = "map-in";
+ int error;
+ int offset = 0;
+
+ /*
+ * The calculation of the offset, lo and len are left here
+ * due to historical precedence.
+ */
+
+ offset = lo & PAGEOFFSET;
+ lo &= PAGEMASK;
+ len = (len + offset + PAGEOFFSET) & PAGEMASK;
+
+ error = fc_run_priv(pdp->common, service, 3, 1, fc_size2cell(len),
+ fc_uint32_t2cell(hi), fc_uint32_t2cell(lo), &virt);
+
+ if (error)
+ throw_from_fclib(env, 1, "gp2:%s: failed\n", service);
+
+ mcookie = mapping_to_mcookie(virt, len, NULL, NULL);
+
+ if (mcookie == NULL)
+ throw_from_fclib(env, 1, "gp2:%s: mapping_to_mcookie failed\n",
+ service);
+
+ mcookie += offset;
+
+ debug_msg(DEBUG_REG_ACCESS, "gp2:%s: %llx -> %x\n", service,
+ (uint64_t)virt, (uint32_t)mcookie);
+
+ return (mcookie);
+}
+
+static void
+mem_map_out(fcode_env_t *env, fstack_t mcookie, fstack_t len)
+{
+ private_data_t *pdp = DEVICE_PRIVATE(env);
+ fc_cell_t virt;
+ char *service = "map-out";
+ int error;
+ int offset;
+
+ /*
+ * The calculation of the offset, lo and len are left here
+ * due to historical precedence.
+ */
+
+ offset = mcookie & PAGEOFFSET;
+ mcookie &= PAGEMASK;
+ len = (len + offset + PAGEOFFSET) & PAGEMASK;
+
+ if (!is_mcookie(mcookie)) {
+ log_message(MSG_ERROR, "gp2:%s: %x not an mcookie!\n",
+ service, (int)mcookie);
+ virt = mcookie;
+ } else {
+ virt = mcookie_to_addr(mcookie);
+ debug_msg(DEBUG_REG_ACCESS, "gp2:%s: %x -> %llx\n", service,
+ (int)mcookie, (uint64_t)virt);
+ delete_mapping(mcookie);
+ }
+
+ error = fc_run_priv(pdp->common, service, 2, 0, fc_size2cell(len),
+ virt);
+ if (error)
+ log_message(MSG_ERROR, "gp2:%s: failed\n", service);
+}
+
+static void
+do_get_portid(fcode_env_t *env)
+{
+ fstack_t phi, plo, portid;
+ private_data_t *pdp = DEVICE_PRIVATE(env);
+
+ CHECK_DEPTH(env, 2, "gp2:get-portid");
+ phi = POP(DS);
+ plo = POP(DS);
+
+ portid = ((plo & 0xff800000) >> 23) | ((phi & 1) << 9);
+ debug_msg(DEBUG_REG_ACCESS, "gp2:get-portid ( %x %x ) -> %x\n",
+ (int)phi, (int)plo, (int)portid);
+ PUSH(DS, portid);
+}
+
+static void
+do_map_in(fcode_env_t *env)
+{
+ fstack_t phi, pmid, plo, len, addr;
+
+ CHECK_DEPTH(env, 3, "gp2:map-in");
+ len = POP(DS);
+ phi = POP(DS);
+ plo = POP(DS);
+ addr = mem_map_in(env, phi, plo, len);
+ PUSH(DS, addr);
+}
+
+static void
+do_map_out(fcode_env_t *env)
+{
+ fstack_t addr, len;
+
+ CHECK_DEPTH(env, 2, "gp2:map-out");
+ len = POP(DS);
+ addr = POP(DS);
+ mem_map_out(env, addr, len);
+}
+
+static void
+do_encode_unit(fcode_env_t *env)
+{
+ char enc_buf[64];
+ fstack_t hi, mid, lo;
+ int id, off;
+
+ CHECK_DEPTH(env, 2, "gp2:encode-unit");
+ hi = POP(DS);
+ lo = POP(DS);
+
+ hi = (hi & 0x00000001); /* get high order agent id bit */
+ id = (hi << 9) | (lo >> 23); /* build extended agent id */
+ off = lo & 0x7fffff; /* build config offset */
+
+ if (off) {
+ sprintf(enc_buf, "%x,%x", id, off);
+ } else {
+ sprintf(enc_buf, "%x", id);
+ }
+ debug_msg(DEBUG_REG_ACCESS, "gp2:encode_unit ( %x %x ) -> '%s'\n",
+ (int)hi, (int)lo, enc_buf);
+ push_a_string(env, STRDUP(enc_buf));
+}
+
+static void
+do_decode_unit(fcode_env_t *env)
+{
+ uint32_t lo, hi;
+ int agent, offset;
+ char *buf;
+
+ CHECK_DEPTH(env, 2, "gp2:decode-unit");
+ buf = pop_a_string(env, NULL);
+ if (sscanf(buf, "%x,%x", &agent, &offset) != 2) {
+ if (sscanf(buf, "%x", &agent) != 1) {
+ throw_from_fclib(env, 1, "gp2:decode_unit:%s", buf);
+ }
+ offset = 0;
+ }
+ lo = offset | (agent << 23);
+ hi = (agent >> 9) | 0x400;
+ debug_msg(DEBUG_REG_ACCESS, "gp2:decode_unit ( '%s' ) -> %x %x\n", buf,
+ hi, lo);
+ PUSH(DS, lo);
+ PUSH(DS, hi);
+}
+
+static void
+do_claim_addr(fcode_env_t *env)
+{
+ fstack_t portid, bar, align, type, size_hi, size_lo;
+ fc_cell_t lo, hi;
+ private_data_t *pdp = DEVICE_PRIVATE(env);
+ char *service = "claim-address";
+ int error;
+
+ CHECK_DEPTH(env, 6, "gp2:claim-address");
+ portid = POP(DS);
+ bar = POP(DS);
+ align = POP(DS);
+ type = POP(DS);
+ size_hi = POP(DS);
+ size_lo = POP(DS);
+
+ error = fc_run_priv(pdp->common, service, 6, 2,
+ fc_int2cell(portid), fc_int2cell(bar), fc_int2cell(align),
+ fc_int2cell(type), fc_int2cell(size_hi), fc_int2cell(size_lo),
+ &lo, &hi);
+
+ if (error)
+ throw_from_fclib(env, 1, "gp2:%s: failed\n", service);
+
+ debug_msg(DEBUG_REG_ACCESS,
+ "gp2:%s ( %x %x %x %x %x %x ) -> %x %x\n", service, (int)portid,
+ (int)bar, (int)align, (int)type, (int)size_hi, (int)size_lo,
+ (uint32_t)hi, (uint32_t)lo);
+
+ PUSH(DS, (uint32_t)lo);
+ PUSH(DS, (uint32_t)hi);
+}
+
+static void
+do_master_interrupt(fcode_env_t *env)
+{
+ int portid;
+ token_t xt;
+
+ CHECK_DEPTH(env, 2, "gp2:master-interrput");
+ portid = POP(DS);
+ xt = POP(DS);
+ PUSH(DS, FALSE);
+ debug_msg(DEBUG_REG_ACCESS, "gp2:master-interrupt ( %x %x ) -> %x\n",
+ portid, xt, (int)FALSE);
+}
+
+static void
+do_register_vectory_entry(fcode_env_t *env)
+{
+ int ign, ino, level;
+
+ CHECK_DEPTH(env, 3, "gp2:register-vector-entry");
+ ign = POP(DS);
+ ino = POP(DS);
+ level = POP(DS);
+ PUSH(DS, FALSE);
+ debug_msg(DEBUG_REG_ACCESS, "gp2:register-vector-entry ( %x %x %x ) ->"
+ " %x\n", ign, ino, level, (int)FALSE);
+}
+
+static void
+do_get_interrupt_target(fcode_env_t *env)
+{
+ int mid = 0;
+
+ PUSH(DS, mid);
+ debug_msg(DEBUG_REG_ACCESS, "gp2:get-interrupt-target ( ) -> %x\n",
+ mid);
+}
+
+static void
+do_device_id(fcode_env_t *env)
+{
+ fstack_t phi, plo, addr;
+ fc_cell_t virtaddr;
+ private_data_t *pdp = DEVICE_PRIVATE(env);
+ uint64_t wci_id_reg;
+ int rc, parid;
+
+ CHECK_DEPTH(env, 2, "gp2:device-id");
+ phi = POP(DS);
+ plo = POP(DS);
+
+ PUSH(DS, plo);
+ PUSH(DS, phi);
+ PUSH(DS, 0x100);
+
+ do_map_in(env);
+
+ addr = POP(DS);
+
+ virtaddr = mcookie_to_addr(addr);
+
+ /* Try to read the wci_id register */
+ rc = fc_run_priv(pdp->common, "rx@", 1, 1, virtaddr + 0xe0,
+ &wci_id_reg);
+
+ mem_map_out(env, addr, 0x100);
+
+ /*
+ * Get the part id from the jtag ID register
+ */
+ parid = ((wci_id_reg >> 12) & 0xffff);
+
+ if (!rc && parid == 0x4478) {
+ debug_msg(DEBUG_FIND_FCODE, "gp2: do_device_id: gp2-wci\n");
+ push_a_string(env, "SUNW,wci");
+ } else {
+ debug_msg(DEBUG_FIND_FCODE, "gp2: do_device_id: gp2-pci\n");
+ push_a_string(env, "gp2-pci");
+ }
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ ASSERT(env->current_device);
+ NOTICE;
+
+ create_int_prop(env, "#address-cells", 2);
+
+ FORTH(0, "map-in", do_map_in);
+ FORTH(0, "get-portid", do_get_portid);
+ FORTH(0, "map-out", do_map_out);
+ FORTH(0, "decode-unit", do_decode_unit);
+ FORTH(0, "encode-unit", do_encode_unit);
+ FORTH(0, "claim-address", do_claim_addr);
+ FORTH(0, "master-interrupt", do_master_interrupt);
+ FORTH(0, "register-vector-entry", do_register_vectory_entry);
+ FORTH(0, "get-interrupt-target", do_get_interrupt_target);
+ FORTH(0, "device-id", do_device_id);
+
+ install_dma_methods(env);
+
+}
diff --git a/usr/src/lib/efcode/gp2/sparcv9/Makefile b/usr/src/lib/efcode/gp2/sparcv9/Makefile
new file mode 100644
index 0000000000..6656b54ad3
--- /dev/null
+++ b/usr/src/lib/efcode/gp2/sparcv9/Makefile
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+include $(SRC)/lib/Makefile.lib.64
+
+DYNFLAGS += $(FCODE64) $(FCDRIVER64)
+
+install: all $(ROOTLIBS64) $(ROOTSYMLINKS64)
diff --git a/usr/src/lib/efcode/include/fcdriver/fcdriver.h b/usr/src/lib/efcode/include/fcdriver/fcdriver.h
new file mode 100644
index 0000000000..d40ca79cd4
--- /dev/null
+++ b/usr/src/lib/efcode/include/fcdriver/fcdriver.h
@@ -0,0 +1,75 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _FCDRIVER_FCDRIVER_H
+#define _FCDRIVER_FCDRIVER_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/fcode.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct NODEIDs {
+ fc_phandle_t my_handle;
+ device_t *node;
+} my_nodeid_t;
+
+typedef struct MY_GLOBAL_DATA {
+ int fcode_fd;
+ char *path;
+ char *Progname;
+ struct fc_parameters fc;
+ fc_phandle_t attach;
+ fc_resource_t *nodeids;
+ char *search_path;
+ int init_done;
+ int first_node;
+} common_data_t;
+
+typedef struct MY_PRIVATE_DATA {
+ common_data_t *common;
+ fc_phandle_t node;
+ fc_phandle_t parent;
+ struct fc_parameters fc;
+ void *debug;
+ int upload;
+} private_data_t;
+
+#ifdef FCODE_INTERNAL
+#include <fcdriver/proto.h>
+#endif
+
+void upload_nodes(fcode_env_t *);
+void validate_nodes(fcode_env_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FCDRIVER_FCDRIVER_H */
diff --git a/usr/src/lib/efcode/include/fcdriver/proto.h b/usr/src/lib/efcode/include/fcdriver/proto.h
new file mode 100644
index 0000000000..2cab34e4d2
--- /dev/null
+++ b/usr/src/lib/efcode/include/fcdriver/proto.h
@@ -0,0 +1,61 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _FCDRIVER_PROTO_H
+#define _FCDRIVER_PROTO_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CURRENT_DEVICE(e) (e)->current_device
+#define COMMON_PRIVATE(e) (common_data_t *)((e)->private)
+#define DEVICE_PRIVATE(e) (private_data_t *)(MYSELF->device->private)
+
+void install_pci_methods(fcode_env_t *);
+void install_property_vectors(fcode_env_t *, device_t *);
+void install_node_data(fcode_env_t *, device_t *);
+void build_tree(fcode_env_t *);
+void install_dma_methods(fcode_env_t *);
+void add_my_handle(fcode_env_t *, fc_phandle_t, device_t *);
+void recurse_tree(fcode_env_t *, device_t *,
+ void (*)(fcode_env_t *, device_t *));
+
+int do_run_priv(common_data_t *, struct fc_client_interface *, int);
+int fc_run_priv(common_data_t *, char *, int, int, ...);
+int os_get_prop_common(common_data_t *, fc_phandle_t, char *, int, char **,
+ int *);
+fc_phandle_t fc_get_ap(common_data_t *);
+int fc_get_request(common_data_t *);
+void set_debug_level(common_data_t *, uint32_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FCDRIVER_PROTO_H */
diff --git a/usr/src/lib/efcode/include/fcode/debug.h b/usr/src/lib/efcode/include/fcode/debug.h
new file mode 100644
index 0000000000..450844618c
--- /dev/null
+++ b/usr/src/lib/efcode/include/fcode/debug.h
@@ -0,0 +1,75 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _FCODE_DEBUG_H
+#define _FCODE_DEBUG_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEBUG_CONTEXT 0x00000001
+#define DEBUG_BYTELOAD_DS 0x00000002
+#define DEBUG_BYTELOAD_RS 0x00000004
+#define DEBUG_BYTELOAD_TOKENS 0x00000008
+#define DEBUG_NEW_TOKEN 0x00000010
+#define DEBUG_EXEC_TRACE 0x00000020
+#define DEBUG_EXEC_SHOW_VITALS 0x00000040
+#define DEBUG_EXEC_DUMP_DS 0x00000080
+#define DEBUG_EXEC_DUMP_RS 0x00000100
+#define DEBUG_COMMA 0x00000200
+#define DEBUG_HEADER 0x00000400
+#define DEBUG_EXIT_WORDS 0x00000800
+#define DEBUG_EXIT_DUMP 0x00001000
+#define DEBUG_DUMP_TOKENS 0x00002000
+#define DEBUG_COLON 0x00004000
+#define DEBUG_NEXT_VITALS 0x00008000
+#define DEBUG_UPLOAD 0x00010000
+#define DEBUG_VOC_FIND 0x00020000
+#define DEBUG_DUMP_DICT_TOKENS 0x00040000
+#define DEBUG_TOKEN_USAGE 0x00080000
+#define DEBUG_DUMP_TOKEN_TABLE 0x00100000
+#define DEBUG_SHOW_STACK 0x00200000
+#define DEBUG_SHOW_RS 0x00400000
+#define DEBUG_TRACING 0x00800000
+#define DEBUG_TRACE_STACK 0x01000000
+#define DEBUG_CALL_METHOD 0x02000000
+#define DEBUG_ACTIONS 0x04000000
+#define DEBUG_STEPPING 0x08000000
+#define DEBUG_REG_ACCESS 0x10000000
+#define DEBUG_ADDR_ABUSE 0x20000000
+#define DEBUG_FIND_FCODE 0x40000000
+
+#define DEBUG_ANY 0xffffffff
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FCODE_DEBUG_H */
diff --git a/usr/src/lib/efcode/include/fcode/engine.h b/usr/src/lib/efcode/include/fcode/engine.h
new file mode 100644
index 0000000000..06e5ef2767
--- /dev/null
+++ b/usr/src/lib/efcode/include/fcode/engine.h
@@ -0,0 +1,331 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _FCODE_ENGINE_H
+#define _FCODE_ENGINE_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_ORDER 32
+#define CONVERT_HANDLES
+
+#ifdef BIGSTACK
+typedef long long fstack_t;
+typedef unsigned long long ufstack_t;
+#else
+typedef long fstack_t;
+typedef unsigned long ufstack_t;
+#endif
+typedef long *acf_t; /* pointer to execution token */
+typedef long token_t; /* sizeof a forth token */
+
+/* x@, x! type */
+typedef uint64_t u_xforth_t;
+typedef int64_t s_xforth_t;
+typedef uint64_t xforth_t;
+
+/* l@, l! type */
+typedef uint32_t u_lforth_t;
+typedef int32_t s_lforth_t;
+typedef uint32_t lforth_t;
+
+/* w@, w! type */
+typedef uint16_t u_wforth_t;
+typedef int16_t s_wforth_t;
+typedef uint16_t wforth_t;
+
+/* Double type */
+typedef uint64_t u_dforth_t;
+typedef int64_t s_dforth_t;
+typedef uint64_t dforth_t;
+
+/* Variable/Value/Constant type */
+typedef token_t variable_t;
+
+typedef struct PROPERTY {
+ char *name;
+ uchar_t *data;
+ int size;
+ struct PROPERTY *next;
+} prop_t;
+
+typedef struct RESOURCE {
+ struct RESOURCE *next;
+ void *data;
+} fc_resource_t;
+
+#define INIT_DATA 0
+#define UINIT_DATA 1
+
+typedef struct FCODE_ENV fcode_env_t;
+
+typedef struct DEVICE_VECTOR {
+ /*
+ * If there is private data associated with a node this vector
+ * table contains the routines that will be called to augment the
+ * device.
+ * These two routines allow the interpreter to use a different
+ *
+ * Interface Note:
+ * Any routine installed here is assumed to have the standard forth
+ * call state. It must be a void function call taking a forth execution
+ * environment, returning any data on the stack. In general the
+ * vector call should have the same semantics as the original routine
+ * it is replacing. (see get_prop as an example).
+ *
+ * The caller has the responsibility of converting the resulting data
+ * back to a form it requires.
+ *
+ */
+ void (*get_package_prop)(fcode_env_t *);
+ void (*get_inherited_prop)(fcode_env_t *);
+} device_vector_t;
+
+typedef struct DEVICE device_t;
+
+#define MAX_MY_ADDR 4
+
+struct DEVICE {
+ device_t *parent;
+ device_t *child;
+ device_t *peer;
+ prop_t *properties;
+ token_t *vocabulary;
+ fstack_t parent_adr_cells;
+ fstack_t my_space;
+ fstack_t my_addr[MAX_MY_ADDR];
+ fstack_t frame_buffer_adr;
+ int data_size[2];
+ token_t *init_data; /* initialised instance data */
+ void *private; /* app private data */
+ device_vector_t vectors;
+};
+
+typedef struct INSTANCE {
+ struct INSTANCE *parent;
+ device_t *device;
+ /*
+ * These are copies of the same structures from the device definition
+ * however changes here will be thrown away when the instance is
+ * destroyed.
+ */
+ char *my_args;
+ int my_args_len;
+ fstack_t my_space;
+ fstack_t my_addr[MAX_MY_ADDR];
+ fstack_t frame_buffer_adr;
+ token_t *data[2];
+} instance_t;
+
+typedef struct FCODE_TOKEN {
+ ulong_t flags;
+ char *name;
+ acf_t apf; /* pointer to acf in dictionary */
+#ifdef DEBUG
+ int usage;
+#endif
+} fcode_token;
+
+typedef struct {
+ char *buffer;
+ char *scanptr;
+ int maxlen;
+ int separator;
+} input_typ;
+
+typedef struct ERROR_FRAME {
+ struct ERROR_FRAME *next;
+ fstack_t *ds;
+ fstack_t *rs;
+ instance_t *myself;
+ token_t *ip;
+ fstack_t code;
+} error_frame;
+
+struct FCODE_ENV {
+ fcode_token *table; /* token table */
+ uchar_t *base; /* dictionary base */
+ uchar_t *here; /* current dp */
+ char *name; /* last name */
+ long level; /* level */
+ token_t *ip; /* instruction pointer */
+ token_t *wa; /* word address */
+ fstack_t *ds0; /* base of dats stack */
+ fstack_t *rs0; /* base of return stack */
+ fstack_t *ds; /* data stack base */
+ fstack_t *rs; /* return stack base */
+ variable_t num_base; /* current base */
+ token_t *current; /* current voc */
+ long order_depth;
+ token_t **order; /* Voc. search order */
+ token_t *lastlink; /* last forth def */
+ token_t *forth_voc_link; /* Storage location for 'forth' voc */
+ int last_token; /* last defined token */
+ device_t *root_node; /* root node */
+ device_t *attachment_pt;
+ device_t *current_device; /* */
+ instance_t *my_self; /* pointer to my data */
+ int offset_incr; /* size of FCODE token offsets */
+ error_frame *catch_frame;
+ uchar_t *fcode_buffer; /* pointer to fcode buffer */
+ uchar_t *fcode_ptr; /* pointer into fcode buffer */
+ uchar_t *last_fcode_ptr; /* pointer to last fcode fetched */
+ fstack_t last_fcode; /* last fcode# executed */
+ fstack_t last_error; /* last throw code executed */
+ int fcode_incr; /* space between bytecodes */
+ int interpretting;
+ variable_t state; /* compile or run? */
+ int fcode_debug;
+ int diagnostic_mode;
+ fstack_t instance_mode;
+ int interactive; /* DEBUG, interact variable */
+ int num_actions;
+ int action_count;
+ token_t *action_ptr;
+ int strict_fcode;
+ fstack_t control; /* control VM behaviour */
+ input_typ *input; /* input buffer pointer */
+ variable_t span;
+ char *picturebufpos; /* pictured string buffer position */
+ char *picturebuf; /* pictured string buffer */
+ int picturebuflen; /* pictured string buffer length */
+ variable_t output_column; /* output column# (#out) */
+ variable_t output_line; /* output line# (#line) */
+#ifdef CONVERT_HANDLES
+ device_t *(*convert_phandle)(fcode_env_t *, fstack_t);
+ fstack_t (*revert_phandle)(fcode_env_t *, device_t *);
+ void (*allocate_phandle)(fcode_env_t *);
+#endif
+ fc_resource_t *propbufs;
+ void *private; /* private data ptr for app use. */
+};
+
+#define MAX_FCODE 0xfff /* max no. of Fcode entries in table */
+
+
+typedef unsigned char flag_t;
+
+#define DS (env->ds)
+#define RS (env->rs)
+#define TOS *DS
+#define IP (env->ip)
+#define WA (env->wa)
+#define DEPTH (DS-env->ds0)
+#define CURRENT (env->current)
+#define ORDER (env->order)
+#define BASE (env->base)
+#define HERE (env->here)
+#define CONTEXT env->order[env->order_depth]
+#define MYSELF (env->my_self)
+
+#ifdef FCODE_INTERNAL
+#include <fcode/proto.h>
+#endif
+#include <fcode/public.h>
+
+#define SIGN_SHIFT ((8*(sizeof (fstack_t)))-1)
+#define SIGN_BIT (((ufstack_t)1)<<SIGN_SHIFT)
+
+/*
+ * Note that sizeof (token_t) MUST equal sizeof (token_t *). If it doesn't,
+ * many things will break.
+ */
+#define _ALIGN(x, y) (((long)(x)) & ~(sizeof (y)-1))
+#define TOKEN_ROUNDUP(x) _ALIGN((x + ((sizeof (token_t)-1))), token_t)
+
+#define min(x, y) ((x) < (y) ? (x) : (y))
+#define max(x, y) ((x) > (y) ? (x) : (y))
+
+/* values for flag_t */
+#define ANSI_WORD 0x01
+#define P1275_WORD 0x02
+#define FLAG_NONAME 0x04
+#define IMMEDIATE 0x08
+#define FLAG_VALUE 0x10
+#define FLAG_DEBUG 0x20
+#define DEFINER (FLAG_NONAME|IMMEDIATE)
+
+#define FORTH(fl, nm, fnc) define_word(env, fl, nm, fnc);
+
+#define LINK_TO_ACF(x) (((token_t *)(x))+1)
+#define LINK_TO_FLAGS(x) (((flag_t *)(x))-1)
+#define ACF_TO_LINK(x) (((token_t *)(x))-1)
+#define ACF_TO_BODY(x) (((acf_t)(x))+1)
+#define BODY_TO_LINK(x) (((acf_t)(x))-1)
+#define BODY_TO_FLAGS(x) (((flag_t *)(BODY_TO_LINK(x))) - 1)
+#define EXPOSE_ACF *((acf_t)env->current) = \
+ (token_t)(env->lastlink)
+
+#define COMPILE_TOKEN(x) PUSH(DS, (fstack_t)(x)); compile_comma(env);
+#define CHECK_DEPTH(env, x, w) if ((x) > (env->ds - env->ds0)) \
+ forth_abort(env, "%s: stack underflow\n", w);
+#define CHECK_RETURN_DEPTH(env, x, w) if ((x) > (env->rs - env->rs0)) \
+ forth_abort(env, "%s: return stack underflow\n", w);
+
+#define FCRP_NOERROR 0x80000000 /* fc_run_priv: no err msg. */
+
+#ifdef CONVERT_HANDLES
+#define CONVERT_PHANDLE(e, x, y) x = env->convert_phandle(e, y)
+#define REVERT_PHANDLE(e, x, y) x = env->revert_phandle(e, y)
+#define ALLOCATE_PHANDLE(e) env->allocate_phandle(e)
+#else
+#define CONVERT_PHANDLE(e, x, y) x = (device_t *)(y)
+#define REVERT_PHANDLE(e, x, y) x = (fstack_t)(y)
+#define ALLOCATE_PHANDLE(e)
+#endif
+
+extern fcode_env_t *env;
+extern int dict_size;
+extern int in_forth_abort;
+extern int stack_size;
+extern token_t value_defines[][3];
+extern void (*bbranch_ptrs[3])(fcode_env_t *);
+extern void (*blit_ptr)(fcode_env_t *);
+extern void (*create_ptr)(fcode_env_t *);
+extern void (*do_bdo_ptr)(fcode_env_t *);
+extern void (*do_bqdo_ptr)(fcode_env_t *);
+extern void (*do_leave_ptr)(fcode_env_t *);
+extern void (*do_loop_ptr)(fcode_env_t *);
+extern void (*do_ploop_ptr)(fcode_env_t *);
+extern void (*does_ptr)(fcode_env_t *);
+extern void (*quote_ptr)(fcode_env_t *);
+extern void (*quote_ptr)(fcode_env_t *);
+extern void (*semi_ptr)(fcode_env_t *);
+extern void (*tlit_ptr)(fcode_env_t *);
+extern void (*to_ptr)(fcode_env_t *);
+extern void (*to_ptr)(fcode_env_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FCODE_ENGINE_H */
diff --git a/usr/src/lib/efcode/include/fcode/log.h b/usr/src/lib/efcode/include/fcode/log.h
new file mode 100644
index 0000000000..866739fb1c
--- /dev/null
+++ b/usr/src/lib/efcode/include/fcode/log.h
@@ -0,0 +1,60 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _FCODE_LOG_H
+#define _FCODE_LOG_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Internal Message Levels */
+#define MSG_FATAL 0x01 /* Fatal Error -> LOG_ERR */
+#define MSG_ERROR 0x02 /* Error -> LOG_ERR */
+#define MSG_WARN 0x04 /* Warning -> LOG_WARN */
+#define MSG_NOTE 0x08 /* Notice -> LOG_NOTICE */
+#define MSG_INFO 0x10 /* Informational -> LOG_INFO */
+#define MSG_DEBUG 0x20 /* Debug -> LOG_DEBUG */
+#define MSG_FC_DEBUG 0x40 /* Fcode (Noisy) Debug -> LOG_DEBUG */
+#define MSG_EMIT 0x80 /* Fcode Emit -> LOG_DEBUG */
+
+void log_message(int, char *, ...);
+void log_perror(int, char *, ...);
+void debug_msg(int, char *, ...);
+void open_syslog_log(char *, int);
+void open_error_log(char *, int);
+void log_emit(char);
+void set_daemon_log_flag(int);
+void set_min_syslog_level(int);
+int parse_msg_flags(char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FCODE_LOG_H */
diff --git a/usr/src/lib/efcode/include/fcode/private.h b/usr/src/lib/efcode/include/fcode/private.h
new file mode 100644
index 0000000000..1a5834483b
--- /dev/null
+++ b/usr/src/lib/efcode/include/fcode/private.h
@@ -0,0 +1,147 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _FCODE_PRIVATE_H
+#define _FCODE_PRIVATE_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef DEBUG
+#include <fcode/debug.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+long get_interpreter_debug_level(void);
+void set_interpreter_debug_level(long lvl);
+
+#define DPRINTF(x, y) if (get_interpreter_debug_level() & (DEBUG_##x))\
+ printf y
+#define DEBUGF(x, y) if (get_interpreter_debug_level() & (DEBUG_##x))\
+ { y; }
+#else
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DPRINTF(x, y)
+#define DEBUGF(x, y)
+#endif
+
+#define PUSH(sp, n) *(++sp) = (n)
+#define POP(sp) *(sp--)
+
+#define ERROR(x) printf x
+
+#define MALLOC(x) safe_malloc((x), __FILE__, __LINE__)
+#define REALLOC(x, n) safe_realloc((x), (n), __FILE__, __LINE__)
+#define STRDUP(x) safe_strdup((x), __FILE__, __LINE__)
+#define FREE(x) safe_free((x), __FILE__, __LINE__)
+
+#include <fcode/engine.h>
+
+extern fcode_env_t *initial_env;
+extern int fcode_impl_count;
+
+#define SET_TOKEN(t, f, n, a) \
+ env->table[t].flags = f; \
+ env->table[t].name = n; \
+ env->table[t].apf = a;
+
+#define FCODE(token, fl, nm, fnc) \
+ fcode_impl_count++; \
+ env->table[token].flags = fl; \
+ do_code(env, token, nm, fnc);
+
+#define ANSI(tk, t, nm, fnc) FCODE(tk, (ANSI_WORD|P1275_WORD|t), nm, fnc)
+#define P1275(tk, t, nm, fnc) FCODE(tk, (P1275_WORD|t), nm, fnc)
+
+#ifdef DEBUG
+#define ASSERT(x) if (!(x)) printf("%s:%d: ASSERT FAILED!!\n",\
+ __FILE__, __LINE__);
+#ifdef NOTICE
+#undef NOTICE
+#define NOTICE printf("%s:%d: _init called\n", __FILE__, __LINE__)
+#else
+#define NOTICE
+#endif
+#else
+#define ASSERT(x)
+#define NOTICE
+#endif
+
+void fc_abort(fcode_env_t *, char *type);
+
+#define TODO fc_abort(env, "TODO")
+#define FATAL ERROR(("%s:%d: MANGLED FCODE!! Fatal Error\n",\
+ __FILE__, __LINE__)))
+
+#ifndef USE_INTERRUPTS
+#define CHECK_INTERRUPT
+#define COMPLETE_INTERRUPT
+#else
+#define CHECK_INTERRUPT check_interrupt()
+#define COMPLETE_INTERRUPT complete_interrupt()
+#endif
+
+/* dforth_t manimpulations */
+#define MAKE_DFORTH(hi, lo) ((((u_dforth_t)(hi) << 32)) | \
+ (((u_dforth_t)(lo)) & 0xffffffff))
+#define DFORTH_LO(df) (((u_dforth_t)(df)) & 0xffffffff)
+#define DFORTH_HI(df) ((((u_dforth_t)(df)) >> 32) & 0xffffffff)
+
+#define TRUE (-1)
+#define FALSE (0)
+
+
+instance_t *open_instance_chain(fcode_env_t *, device_t *, int);
+void close_instance_chain(fcode_env_t *, instance_t *, int);
+void activate_device(fcode_env_t *, device_t *);
+void deactivate_device(fcode_env_t *, device_t *);
+
+void install_handlers(fcode_env_t *);
+void set_defer_actions(fcode_env_t *, int);
+void throw_from_fclib(fcode_env_t *, fstack_t, char *, ...);
+int get_default_intprop(fcode_env_t *, char *, device_t *, int);
+uint_t get_number_of_parent_address_cells(fcode_env_t *);
+char *get_package_name(fcode_env_t *, device_t *);
+
+token_t *get_instance_address(fcode_env_t *);
+fc_resource_t *find_resource(fc_resource_t **, void *,
+ int (c)(void *, void *));
+void *add_resource(fc_resource_t **, void *, int (c)(void *, void *));
+void free_resource(fc_resource_t **, void *, int (c)(void *, void *));
+void set_temporary_compile(fcode_env_t *);
+void temporary_execute(fcode_env_t *);
+prop_t *lookup_package_property(fcode_env_t *, char *, device_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FCODE_PRIVATE_H */
diff --git a/usr/src/lib/efcode/include/fcode/proto.h b/usr/src/lib/efcode/include/fcode/proto.h
new file mode 100644
index 0000000000..84a7490cf4
--- /dev/null
+++ b/usr/src/lib/efcode/include/fcode/proto.h
@@ -0,0 +1,448 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _FCODE_PROTO_H
+#define _FCODE_PROTO_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FNPROTO(x) void x(fcode_env_t *)
+
+FNPROTO(bdo);
+FNPROTO(bqdo);
+
+FNPROTO(literal);
+void branch_common(fcode_env_t *, short, fstack_t, int);
+FNPROTO(zero);
+FNPROTO(bloop);
+FNPROTO(bplusloop);
+FNPROTO(loop_i);
+FNPROTO(loop_j);
+FNPROTO(bleave);
+FNPROTO(execute);
+FNPROTO(add);
+FNPROTO(subtract);
+FNPROTO(multiply);
+FNPROTO(slash_mod);
+FNPROTO(uslash_mod);
+FNPROTO(divide);
+FNPROTO(mod);
+FNPROTO(and);
+FNPROTO(or);
+FNPROTO(xor);
+FNPROTO(invert);
+FNPROTO(lshift);
+FNPROTO(rshift);
+FNPROTO(rshifta);
+FNPROTO(negate);
+FNPROTO(f_abs);
+FNPROTO(f_min);
+FNPROTO(f_max);
+FNPROTO(to_r);
+FNPROTO(from_r);
+FNPROTO(rfetch);
+FNPROTO(f_exit);
+FNPROTO(zero_equals);
+FNPROTO(zero_not_equals);
+FNPROTO(zero_less);
+FNPROTO(zero_less_equals);
+FNPROTO(zero_greater);
+FNPROTO(zero_greater_equals);
+FNPROTO(less);
+FNPROTO(greater);
+FNPROTO(equals);
+FNPROTO(not_equals);
+FNPROTO(unsign_greater);
+FNPROTO(unsign_less_equals);
+FNPROTO(unsign_less);
+FNPROTO(unsign_greater_equals);
+FNPROTO(greater_equals);
+FNPROTO(less_equals);
+FNPROTO(between);
+FNPROTO(within);
+FNPROTO(drop);
+FNPROTO(f_dup);
+FNPROTO(over);
+FNPROTO(swap);
+FNPROTO(rot);
+FNPROTO(minus_rot);
+FNPROTO(tuck);
+FNPROTO(nip);
+FNPROTO(pick);
+FNPROTO(roll);
+FNPROTO(qdup);
+FNPROTO(depth);
+FNPROTO(two_drop);
+FNPROTO(two_dup);
+FNPROTO(two_over);
+FNPROTO(two_swap);
+FNPROTO(two_rot);
+FNPROTO(two_slash);
+FNPROTO(utwo_slash);
+FNPROTO(two_times);
+FNPROTO(slash_c);
+FNPROTO(slash_w);
+FNPROTO(slash_l);
+FNPROTO(slash_n);
+FNPROTO(ca_plus);
+FNPROTO(wa_plus);
+FNPROTO(la_plus);
+FNPROTO(na_plus);
+FNPROTO(c1_plus);
+FNPROTO(w1_plus);
+FNPROTO(l1_plus);
+FNPROTO(cell_plus);
+FNPROTO(do_chars);
+FNPROTO(slash_w_times);
+FNPROTO(slash_l_times);
+FNPROTO(cells);
+FNPROTO(do_off);
+FNPROTO(do_on);
+FNPROTO(fetch);
+FNPROTO(lfetch);
+FNPROTO(wfetch);
+FNPROTO(swfetch);
+FNPROTO(cfetch);
+FNPROTO(store);
+FNPROTO(lstore);
+FNPROTO(wstore);
+FNPROTO(cstore);
+
+FNPROTO(noop);
+FNPROTO(lwsplit);
+FNPROTO(wljoin);
+FNPROTO(lbsplit);
+FNPROTO(bljoin);
+FNPROTO(wbflip);
+FNPROTO(upper_case);
+FNPROTO(lower_case);
+FNPROTO(pack_str);
+FNPROTO(count_str);
+FNPROTO(to_body);
+FNPROTO(to_acf);
+FNPROTO(bcase);
+FNPROTO(bendcase);
+
+FNPROTO(span);
+
+FNPROTO(expect);
+
+FNPROTO(emit);
+FNPROTO(type);
+
+FNPROTO(fc_crlf);
+
+FNPROTO(base);
+FNPROTO(dollar_number);
+FNPROTO(digit);
+
+FNPROTO(do_constant);
+FNPROTO(do_defer);
+FNPROTO(do_crash);
+FNPROTO(do_field);
+FNPROTO(idefer_exec);
+
+FNPROTO(set_args);
+
+void make_common_access(fcode_env_t *, char *, int, int, int,
+ void (*acf_i)(fcode_env_t *), void (*acf_s)(fcode_env_t *),
+ void (*set_a)(fcode_env_t *, int));
+
+FNPROTO(do_create);
+
+FNPROTO(instance);
+FNPROTO(semi);
+
+FNPROTO(dollar_find);
+acf_t voc_find(fcode_env_t *env);
+
+FNPROTO(evaluate);
+
+FNPROTO(ccomma);
+FNPROTO(wcomma);
+FNPROTO(lcomma);
+FNPROTO(comma);
+FNPROTO(state);
+FNPROTO(compile_comma);
+
+FNPROTO(here);
+FNPROTO(aligned);
+FNPROTO(wbsplit);
+FNPROTO(bwjoin);
+FNPROTO(bmark);
+FNPROTO(bresolve);
+
+FNPROTO(f_error);
+FNPROTO(fc_unimplemented);
+FNPROTO(fc_obsolete);
+FNPROTO(fc_historical);
+
+FNPROTO(myspace);
+FNPROTO(property);
+FNPROTO(encode_int);
+FNPROTO(encode_plus);
+FNPROTO(encode_phys);
+FNPROTO(encode_string);
+FNPROTO(encode_bytes);
+FNPROTO(model_prop);
+FNPROTO(device_type);
+FNPROTO(new_device);
+
+FNPROTO(finish_device);
+
+FNPROTO(device_name);
+
+FNPROTO(lwflip);
+FNPROTO(lbflip);
+
+FNPROTO(child_node);
+FNPROTO(peer_node);
+
+FNPROTO(byte_load);
+
+uchar_t next_bytecode(fcode_env_t *);
+ushort_t get_short(fcode_env_t *);
+uint_t get_int(fcode_env_t *);
+
+char *get_name(long *);
+FNPROTO(words);
+void header(fcode_env_t *, char *, int, flag_t);
+void do_code(fcode_env_t *, int, char *, FNPROTO((*)));
+void push_string(fcode_env_t *, char *, int);
+
+FNPROTO(verify_usage);
+FNPROTO(dump_dictionary);
+void print_stack_element(fcode_env_t *, fstack_t);
+void dump_data_stack(fcode_env_t *, int);
+void dump_return_stack(fcode_env_t *, int);
+char *acf_lookup(fcode_env_t *, acf_t);
+char *acf_to_name(fcode_env_t *, acf_t);
+int within_dictionary(fcode_env_t *, void *);
+char *acf_backup_search(fcode_env_t *, acf_t);
+void dump_forth_environment(fcode_env_t *);
+void forth_abort(fcode_env_t *, char *, ...);
+void forth_perror(fcode_env_t *, char *, ...);
+void return_to_interact(fcode_env_t *);
+char *get_path(fcode_env_t *, device_t *);
+char *search_for_fcode_file(fcode_env_t *, char *);
+int current_debug_state(fcode_env_t *);
+int debug_flags_to_mask(char *);
+int do_exec_debug(fcode_env_t *, void *);
+int name_is_debugged(fcode_env_t *, char *);
+prop_t *find_property(device_t *, char *);
+void buffer_init(fcode_env_t *env);
+void check_for_debug_entry(fcode_env_t *);
+void check_for_debug_exit(fcode_env_t *);
+void check_semi_debug_exit(fcode_env_t *);
+void check_vitals(fcode_env_t *);
+void clear_debug_state(fcode_env_t *, int);
+void debug_set_level(fcode_env_t *, int);
+void define_actions(fcode_env_t *env, int n, token_t *array);
+void do_alias(fcode_env_t *);
+void do_bbranch(fcode_env_t *env);
+void do_bdo(fcode_env_t *);
+void do_bleave(fcode_env_t *env);
+void do_bloop(fcode_env_t *env);
+void do_bofbranch(fcode_env_t *env);
+void do_bploop(fcode_env_t *env);
+void do_bqbranch(fcode_env_t *env);
+void do_bqdo(fcode_env_t *env);
+void do_creator(fcode_env_t *env);
+void do_default_action(fcode_env_t *env);
+void do_emit(fcode_env_t *, uchar_t);
+void do_literal(fcode_env_t *);
+void dump_comma(fcode_env_t *, char *);
+void dump_words(fcode_env_t *);
+void fevaluate(fcode_env_t *);
+void ibuffer_init(fcode_env_t *env);
+void install_builtin_nodes(fcode_env_t *);
+void install_does(fcode_env_t *);
+void install_openprom_nodes(fcode_env_t *);
+void install_package_nodes(fcode_env_t *);
+void internal_env_addr(fcode_env_t *env);
+void internal_env_fetch(fcode_env_t *env);
+void internal_env_store(fcode_env_t *env);
+void key(fcode_env_t *);
+void keyquestion(fcode_env_t *);
+void make_a_node(fcode_env_t *, char *, int);
+void output_data_stack(fcode_env_t *, int);
+void output_return_stack(fcode_env_t *, int, int);
+void output_step_message(fcode_env_t *);
+void output_vitals(fcode_env_t *);
+void print_property(fcode_env_t *, prop_t *, char *);
+void read_line(fcode_env_t *);
+void run_daemon(fcode_env_t *);
+void run_fcode_from_file(fcode_env_t *, char *, int);
+void tick_literal(fcode_env_t *);
+void unbug(fcode_env_t *);
+void xbflip(fcode_env_t *);
+void xfetch(fcode_env_t *);
+void xlflip(fcode_env_t *);
+void xstore(fcode_env_t *);
+void expose_acf(fcode_env_t *, char *);
+
+FNPROTO(do_semi);
+FNPROTO(do_colon);
+FNPROTO(do_next);
+void do_run(fcode_env_t *, int);
+
+void *safe_malloc(size_t, char *, int);
+void *safe_realloc(void *, size_t, char *, int);
+char *safe_strdup(char *, char *, int);
+void safe_free(void *, char *, int);
+
+FNPROTO(do_forth);
+FNPROTO(do_current);
+FNPROTO(do_context);
+FNPROTO(do_definitions);
+FNPROTO(do_interact);
+FNPROTO(do_resume);
+FNPROTO(do_vocab);
+FNPROTO(create);
+FNPROTO(colon);
+FNPROTO(does);
+FNPROTO(recursive);
+FNPROTO(do_if);
+FNPROTO(do_else);
+FNPROTO(do_then);
+FNPROTO(parse_word);
+FNPROTO(do_quote);
+FNPROTO(run_quote);
+
+FNPROTO(do_order);
+FNPROTO(do_also);
+FNPROTO(do_previous);
+
+FNPROTO(find_package);
+FNPROTO(open_package);
+FNPROTO(close_package);
+FNPROTO(find_method);
+FNPROTO(dollar_call_parent);
+FNPROTO(my_parent);
+FNPROTO(my_unit);
+FNPROTO(ihandle_to_phandle);
+FNPROTO(dollar_call_method);
+FNPROTO(dollar_open_package);
+
+FNPROTO(call_environment_method);
+
+FNPROTO(f_abort);
+FNPROTO(catch);
+FNPROTO(throw);
+
+FNPROTO(get_my_property);
+FNPROTO(decode_int);
+FNPROTO(decode_string);
+FNPROTO(get_inherited_prop);
+FNPROTO(delete_property);
+FNPROTO(get_package_property);
+void get_environment_property(fcode_env_t *env, int);
+
+FNPROTO(root_node);
+FNPROTO(current_device);
+FNPROTO(dot_properties);
+FNPROTO(pwd);
+FNPROTO(do_ls);
+FNPROTO(do_cd);
+FNPROTO(do_select_dev);
+FNPROTO(do_unselect_dev);
+FNPROTO(device_end);
+FNPROTO(value);
+FNPROTO(buffer_colon);
+FNPROTO(variable);
+FNPROTO(constant);
+FNPROTO(actions);
+FNPROTO(use_actions);
+FNPROTO(action_colon);
+FNPROTO(perform_action);
+FNPROTO(do_tick);
+FNPROTO(bracket_tick);
+FNPROTO(defer);
+FNPROTO(bye);
+FNPROTO(dump_device);
+FNPROTO(dump_instance);
+FNPROTO(compile_string);
+FNPROTO(parse_two_int);
+
+token_t *alloc_instance_data(fcode_env_t *, int, int, int *);
+FNPROTO(fetch_instance_data);
+FNPROTO(set_instance_data);
+FNPROTO(address_instance_data);
+FNPROTO(instance_variable);
+FNPROTO(decode_phys);
+
+void install_actions(fcode_env_t *env, token_t *table);
+void set_value_actions(fcode_env_t *env, int);
+void set_internal_value_actions(fcode_env_t *env);
+void set_buffer_actions(fcode_env_t *env, int);
+
+void system_message(fcode_env_t *env, char *msg);
+
+void check_interrupt(void);
+void complete_interrupt(void);
+
+FNPROTO(do_set_action);
+void push_a_string(fcode_env_t *, char *);
+char *pop_a_string(fcode_env_t *, int *);
+char *pop_a_duped_string(fcode_env_t *, int *);
+char *parse_a_string(fcode_env_t *, int *);
+void push_double(fcode_env_t *, dforth_t);
+dforth_t pop_double(fcode_env_t *);
+dforth_t peek_double(fcode_env_t *);
+void push_xforth(fcode_env_t *, xforth_t);
+xforth_t pop_xforth(fcode_env_t *);
+xforth_t peek_xforth(fcode_env_t *);
+void create_prop(fcode_env_t *, char *);
+void create_int_prop(fcode_env_t *, char *, int);
+void create_string_prop(fcode_env_t *, char *, char *);
+void make_builtin_hooks(fcode_env_t *, char *);
+fstack_t mapping_to_mcookie(uint64_t, size_t, uint64_t, size_t);
+void delete_mapping(fstack_t);
+int is_mcookie(fstack_t);
+uint64_t mcookie_to_addr(fstack_t);
+fstack_t mcookie_to_rlen(fstack_t);
+fstack_t mcookie_to_rvirt(fstack_t);
+void set_here(fcode_env_t *, uchar_t *, char *);
+int call_my_parent(fcode_env_t *, char *);
+FILE *get_dump_fd(fcode_env_t *);
+
+void load_file(fcode_env_t *);
+void token_roundup(fcode_env_t *, char *);
+
+#ifdef DEBUG
+void do_fclib_trace(fcode_env_t *, void *);
+int do_fclib_step(fcode_env_t *);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FCODE_PROTO_H */
diff --git a/usr/src/lib/efcode/include/fcode/public.h b/usr/src/lib/efcode/include/fcode/public.h
new file mode 100644
index 0000000000..98ec6b2219
--- /dev/null
+++ b/usr/src/lib/efcode/include/fcode/public.h
@@ -0,0 +1,59 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _FCODE_PUBLIC_H
+#define _FCODE_PUBLIC_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * these are the public interfaces to the fcode interpretter
+ */
+
+void define_word(fcode_env_t *, int, char *, void (*)(fcode_env_t *));
+void push_ds(fcode_env_t *, fstack_t);
+void push_rs(fcode_env_t *, fstack_t);
+fstack_t pop_ds(fcode_env_t *);
+fstack_t pop_rs(fcode_env_t *);
+
+void run_fcode(fcode_env_t *, uchar_t *, int);
+void destroy_environment(fcode_env_t *);
+void begin_package(fcode_env_t *);
+void end_package(fcode_env_t *);
+fcode_env_t *clone_environment(fcode_env_t *, void *);
+
+void set_interpreter_debug_level(long);
+long get_interpreter_debug_level(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FCODE_PUBLIC_H */
diff --git a/usr/src/lib/efcode/interpreter/Makefile b/usr/src/lib/efcode/interpreter/Makefile
new file mode 100644
index 0000000000..b8c56e1542
--- /dev/null
+++ b/usr/src/lib/efcode/interpreter/Makefile
@@ -0,0 +1,55 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/cmd/Makefile.cmd.64
+
+PROG = interpreter
+
+EFCODEDIR64 = $(ROOT)/usr/lib/efcode/$(MACH64)
+ROOTCMDDIR = $(EFCODEDIR64)
+
+CPPFLAGS += -DDEBUG -DFCODE_INTERNAL
+CPPFLAGS += -I ../include -I $(ROOT)/usr/platform/sun4u/include
+LDFLAGS += -R/usr/lib/efcode/$(MACH64) -M mapfile64
+
+LIBS = fcode.so fcdriver.so
+$(PROG) := LDLIBS += -L/usr/lib/efcode/$(MACH64) $(LIBS:%=$(EFCODEDIR64)/%)
+
+all: $(PROG)
+
+clean:
+ -$(RM) $(PROG)
+
+install: all .WAIT $(ROOTCMD)
+
+lint: lint_PROG
+
+.KEEP_STATE:
+
+include $(SRC)/cmd/Makefile.targ
diff --git a/usr/src/lib/efcode/interpreter/interpreter.c b/usr/src/lib/efcode/interpreter/interpreter.c
new file mode 100644
index 0000000000..73383e5704
--- /dev/null
+++ b/usr/src/lib/efcode/interpreter/interpreter.c
@@ -0,0 +1,198 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Embedded Fcode Interpreter
+ *
+ * Process cmd line args and invoke Fcode engine.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <stropts.h>
+#include <ctype.h>
+
+#include <fcode/engine.h>
+#include <fcode/log.h>
+#include <fcode/debug.h>
+
+#include <fcdriver/fcdriver.h>
+
+#define MSG_ERRLOG_DEFAULT (MSG_FATAL|MSG_ERROR|MSG_WARN|MSG_INFO|\
+ MSG_DEBUG|MSG_FC_DEBUG)
+#define MSG_SYSLOG_DEFAULT (MSG_FATAL|MSG_ERROR|MSG_WARN)
+#define DEBUG_FC_LIST (DEBUG_COMMA|DEBUG_EXEC_TRACE|\
+ DEBUG_EXEC_DUMP_RS|DEBUG_EXEC_DUMP_RS|\
+ DEBUG_EXEC_SHOW_VITALS|DEBUG_TRACING|\
+ DEBUG_BYTELOAD_DS|DEBUG_BYTELOAD_RS|\
+ DEBUG_BYTELOAD_TOKENS|DEBUG_SHOW_RS|\
+ DEBUG_SHOW_STACK)
+
+common_data_t common;
+
+void *fc_env;
+
+void
+usage(char *argv[])
+{
+ log_message(MSG_ERROR, "Usage: %s <flags>\n", argv[0]);
+ log_message(MSG_ERROR,
+ " -D fcode_debug = true\n");
+ log_message(MSG_ERROR,
+ " -d <level> set debug level\n");
+ log_message(MSG_ERROR,
+ " -f <file> interpret fcode/source <file>\n");
+ log_message(MSG_ERROR,
+ " -i go 'interactive'\n");
+ log_message(MSG_ERROR,
+ " -s <string> interpret <string> as forth\n");
+ log_message(MSG_ERROR,
+ " -a FCODE image has a.out header\n");
+ log_message(MSG_ERROR,
+ " -e [<msglvl>:]<errorlog> Set error log file\n");
+ log_message(MSG_ERROR,
+ " -l <msglvl> Set syslog message level\n");
+ log_message(MSG_ERROR,
+ " -k Toggle OBP page kludge\n");
+}
+
+fcode_env_t *env;
+
+int
+main(int argc, char *argv[])
+{
+ extern char *optarg;
+ extern int optind, opterr, optopt;
+ int c, aout = 0;
+ char *fcode_file = NULL;
+ char *forthstr = NULL;
+ int debug = 0;
+ int syslog_flags = MSG_SYSLOG_DEFAULT;
+ int lflag = 0;
+ int error_log_flags;
+ char *errlog = NULL;
+ extern void run_one_efdaemon_request(fcode_env_t *);
+
+ common.Progname = argv[0];
+ common.search_path = getenv("FC_SEARCH_PATH");
+ common.fcode_fd = -1;
+ env = fc_env = clone_environment(NULL, &common);
+
+ while ((c = getopt(argc, argv, "ad:e:f:l:iDs:k")) != EOF) {
+ switch (c) {
+ case 'a':
+ aout = 1;
+ break;
+
+ case 'd':
+ debug = debug_flags_to_mask(optarg);
+ set_interpreter_debug_level(debug);
+ if (debug)
+ env->fcode_debug = 1;
+ break;
+
+ case 'e':
+ if ((errlog = strchr(optarg, ':')) != NULL) {
+ *errlog++ = '\0';
+ error_log_flags = parse_msg_flags(optarg);
+ } else {
+ errlog = optarg;
+ error_log_flags = MSG_ERRLOG_DEFAULT;
+ }
+ open_error_log(errlog, error_log_flags);
+ break;
+
+ case 'l':
+ syslog_flags = parse_msg_flags(optarg);
+ lflag++;
+ break;
+
+ case 'D':
+ env->fcode_debug = 1;
+ break;
+
+ case 'f':
+ fcode_file = optarg;
+ break;
+
+ case 'i':
+ forthstr = "interact";
+ env->fcode_debug = 1;
+ break;
+
+ case 's':
+ forthstr = optarg;
+ break;
+
+ case '?':
+ usage(argv);
+ exit(1);
+ }
+ }
+
+ if (forthstr) {
+ run_fcode(env, (uchar_t *)forthstr, strlen(forthstr));
+ } else if (fcode_file) {
+ run_fcode_from_file(env, fcode_file, aout);
+ } else {
+ if ((debug & DEBUG_FC_LIST) != 0 &&
+ ((error_log_flags | syslog_flags) & MSG_FC_DEBUG) == 0) {
+ log_message(MSG_WARN, "Warning, verbose debug flag(s)"
+ " on, but syslog/errlog not enabled for verbose"
+ " debug\n");
+ if (errlog)
+ error_log_flags |= MSG_FC_DEBUG;
+ else
+ syslog_flags |= MSG_FC_DEBUG;
+ }
+ if ((debug & ~DEBUG_FC_LIST) != 0 &&
+ ((error_log_flags | syslog_flags) & MSG_DEBUG) == 0) {
+ log_message(MSG_WARN, "Warning, debug flag(s) on, but"
+ " syslog/errlog not enabled for debug\n");
+ if (errlog)
+ error_log_flags |= MSG_DEBUG;
+ else
+ syslog_flags |= MSG_DEBUG;
+ }
+
+ if (errlog == NULL || lflag) {
+ if (syslog_flags & MSG_FC_DEBUG)
+ log_message(MSG_WARN, "Warning, verbose debug"
+ " not recommended for syslog\n");
+ open_syslog_log("interpreter", syslog_flags);
+ }
+ run_one_efdaemon_request(env);
+ }
+
+ return (0);
+}
diff --git a/usr/src/lib/efcode/interpreter/mapfile64 b/usr/src/lib/efcode/interpreter/mapfile64
new file mode 100644
index 0000000000..1e1367557c
--- /dev/null
+++ b/usr/src/lib/efcode/interpreter/mapfile64
@@ -0,0 +1,32 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# identical to /usr/lib/ld/sparcv9/map.below4G
+# We need this because malloc may return addresses which are bigger than
+# 32 bits, but the Fcode interpreter assumes addresses can fit in 32 bits.
+# This forces addresses to be in 32 bits.
+#
+text = V0x80000000;
diff --git a/usr/src/lib/efcode/packages/Makefile b/usr/src/lib/efcode/packages/Makefile
new file mode 100644
index 0000000000..29132d88a1
--- /dev/null
+++ b/usr/src/lib/efcode/packages/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.subdirs
diff --git a/usr/src/lib/efcode/packages/Makefile.com b/usr/src/lib/efcode/packages/Makefile.com
new file mode 100644
index 0000000000..d481808477
--- /dev/null
+++ b/usr/src/lib/efcode/packages/Makefile.com
@@ -0,0 +1,39 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+OBJECTS = populate.o parse.o memalloc.o
+LIBRARY = fcpackage.a
+
+include ../../Makefile.efcode
+
+#
+# Unfortunately, there's a circular dependency between fcdriver and fcpackage,
+# and we have to compile one of them first. Since no one other than fcdriver
+# directly links with fcpackage, this is the simplest way out.
+#
+ZDEFS =
diff --git a/usr/src/lib/efcode/packages/memalloc.c b/usr/src/lib/efcode/packages/memalloc.c
new file mode 100644
index 0000000000..3bb4a928ff
--- /dev/null
+++ b/usr/src/lib/efcode/packages/memalloc.c
@@ -0,0 +1,131 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+static void schizo_vtop(fcode_env_t *, fc_cell_t, fstack_t *, fstack_t *);
+
+/*
+ * claim under /openprom/client-services is only used by schizo Fcode, we
+ * call "schizo,claim-memory" service.
+ */
+void
+claim(fcode_env_t *env)
+{
+ size_t size;
+ void *hint;
+ int align;
+ fc_cell_t vaddr;
+ int error;
+
+ CHECK_DEPTH(env, 3, "schizo,claim-memory");
+ hint = (void *)POP(DS);
+ size = POP(DS);
+ align = POP(DS);
+ error = fc_run_priv(env->private, "schizo,claim-memory", 3, 1,
+ fc_int2cell(align), fc_size2cell(size), fc_ptr2cell(hint), &vaddr);
+ if (error)
+ throw_from_fclib(env, 1, "client-services/claim failed\n");
+ vaddr = mapping_to_mcookie(vaddr, size, NULL, NULL);
+ PUSH(DS, (fstack_t)vaddr);
+}
+
+void
+release(fcode_env_t *env)
+{
+ size_t size;
+ void *addr;
+ int error;
+
+ CHECK_DEPTH(env, 2, "schizo,release-memory");
+ addr = (void *)POP(DS);
+ size = POP(DS);
+ error = fc_run_priv(env->private, "schizo,release-memory", 2, 0,
+ fc_size2cell(size), fc_ptr2cell(addr));
+ if (error)
+ throw_from_fclib(env, 1, "client-services/release failed\n");
+ delete_mapping((fstack_t)addr);
+}
+
+static void
+fc_vtop(fcode_env_t *env)
+{
+ void *vaddr;
+ fc_cell_t physlo, physhi;
+ int error;
+
+ CHECK_DEPTH(env, 1, "schizo,vtop");
+ vaddr = (void *)POP(DS);
+ error = fc_run_priv(env->private, "schizo,vtop", 1, 2,
+ fc_ptr2cell(vaddr), &physlo, &physhi);
+ if (error)
+ throw_from_fclib(env, 1, "fc_vtop: '>physical' failed\n");
+
+ PUSH(DS, physlo);
+ PUSH(DS, physhi);
+}
+
+void
+install_openprom_nodes(fcode_env_t *env)
+{
+ MYSELF = open_instance_chain(env, env->root_node, 0);
+ if (MYSELF != NULL) {
+ make_a_node(env, "openprom", 0);
+ make_a_node(env, "client-services", 0);
+ FORTH(0, "claim", claim);
+ FORTH(0, "release", release);
+ finish_device(env);
+ finish_device(env);
+ close_instance_chain(env, MYSELF, 0);
+ device_end(env);
+ MYSELF = 0;
+ }
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ FORTH(0, "install-openprom-nodes", install_openprom_nodes);
+ FORTH(0, "claim", claim);
+ FORTH(0, "release", release);
+ P1275(0x106, 0, ">physical", fc_vtop);
+}
diff --git a/usr/src/lib/efcode/packages/parse.c b/usr/src/lib/efcode/packages/parse.c
new file mode 100644
index 0000000000..b75dd73ee5
--- /dev/null
+++ b/usr/src/lib/efcode/packages/parse.c
@@ -0,0 +1,135 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+void
+byte_loadfile(fcode_env_t *env)
+{
+ int len;
+
+ load_file(env);
+ len = (int) POP(DS);
+ if (len) {
+ void *ptr = (void *) TOS;
+ PUSH(DS, 1);
+ byte_load(env);
+ FREE(ptr);
+ } else {
+ drop(env);
+ }
+}
+
+void
+define_hook(fcode_env_t *env, char *name, int len, char *fcimage)
+{
+ static void (*byteload_ptr)(fcode_env_t *env) = byte_loadfile;
+
+ header(env, name, len, 0);
+ COMPILE_TOKEN(&do_colon);
+ env->state |= 1;
+ PUSH(DS, (fstack_t) fcimage);
+ PUSH(DS, strlen(fcimage));
+ compile_string(env);
+ COMPILE_TOKEN(&byteload_ptr);
+ semi(env);
+}
+
+/*
+ * simple parser for builtin-driver matching.
+ *
+ * Consists of alias:target<CR>
+ * where alias is:
+ * <Key>[;<key>[;<key>]]
+ *
+ * and target is:
+ * <path to fcode image>
+ */
+
+#define PARSE_LINE 256
+
+static void
+line_error(char *where, int line, char *msg)
+{
+ log_message(MSG_ERROR, "%s:%d: %s\n", where, line, msg);
+}
+
+void
+make_builtin_hooks(fcode_env_t *env, char *where)
+{
+ FILE *fd;
+ int lnum = 0, len;
+ char *buffer, *line, *target, *next;
+
+ if (where == NULL)
+ where = "/fcode/aliases";
+
+ if ((fd = fopen(where, "r")) == NULL) {
+ return;
+ }
+
+ buffer = MALLOC(PARSE_LINE+1);
+
+ while ((line = fgets(buffer, PARSE_LINE, fd)) != NULL) {
+ lnum++;
+ if ((next = strpbrk(line, " \t#\n")) != NULL)
+ *next = '\0';
+ if (strlen(line) == 0)
+ continue;
+ if ((target = strchr(line, ':')) == NULL) {
+ line_error(where, lnum, "Badly formed line");
+ continue;
+ }
+ *target++ = 0;
+ if (strlen(line) == 0) {
+ line_error(where, lnum, "Badly formed alias");
+ continue;
+ }
+ if (strlen(target) == 0) {
+ line_error(where, lnum, "Badly formed target");
+ continue;
+ }
+ for (; line; line = next) {
+ if ((next = strchr(line, ';')) != NULL)
+ *next++ = '\0';
+ if (strlen(line) == 0)
+ line_error(where, lnum, "Null key in alias");
+ else
+ define_hook(env, line, strlen(line), target);
+ }
+ }
+ FREE(buffer);
+ fclose(fd);
+}
diff --git a/usr/src/lib/efcode/packages/populate.c b/usr/src/lib/efcode/packages/populate.c
new file mode 100644
index 0000000000..6d9cc7501e
--- /dev/null
+++ b/usr/src/lib/efcode/packages/populate.c
@@ -0,0 +1,310 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <strings.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+static device_t *builtin_driver_device;
+
+static int
+is_device_builtin_package(fcode_env_t *env, device_t *d)
+{
+ return (d == builtin_driver_device);
+}
+
+static char *dropin_name;
+
+/*
+ * do-builtin-dropin ( -- )
+ * Convoluted name just in case someone has "do-dropin" word in Fcode.
+ * Somewhat different from do-dropin in OBP, as we just load the Fcode, we
+ * don't do a byte-load.
+ */
+static void
+do_builtin_dropin(fcode_env_t *env)
+{
+ fc_cell_t len, result;
+ char *buf;
+ int error;
+ static char func_name[] = "do-builtin-dropin";
+ extern int check_fcode_header(char *, uchar_t *, int);
+
+ if (dropin_name == NULL) {
+ log_message(MSG_ERROR, "%s: dropin_name not set\n", func_name);
+ return;
+ }
+ debug_msg(DEBUG_FIND_FCODE, "%s: '%s'\n", func_name, dropin_name);
+ error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1,
+ fc_ptr2cell(dropin_name), &len);
+ if (error)
+ return;
+ if (len == 0) {
+ log_message(MSG_WARN, "%s: '%s' zero length Fcode\n",
+ func_name, dropin_name);
+ return;
+ }
+ buf = MALLOC(len);
+ error = fc_run_priv(env->private, "sunos,get-fcode", 3, 1,
+ fc_ptr2cell(dropin_name), fc_ptr2cell(buf), len, &result);
+ if (error) {
+ FREE(buf);
+ return;
+ }
+
+ if (check_fcode_header(dropin_name, (uchar_t *)buf, len) == 0)
+ log_message(MSG_WARN, "%s: '%s' fcode header NOT OK\n",
+ func_name, dropin_name);
+
+ debug_msg(DEBUG_FIND_FCODE,
+ "%s: '%s' doing byte-load len: %x\n", func_name, dropin_name,
+ (int)len);
+ PUSH(DS, (fstack_t)buf);
+ PUSH(DS, 1);
+ byte_load(env);
+}
+
+static void
+do_builtin_file(fcode_env_t *env)
+{
+ char *fname;
+ static char func_name[] = "do-builtin-file";
+ fstack_t d;
+
+ if (dropin_name == NULL) {
+ log_message(MSG_ERROR, "%s: dropin_name not set\n", func_name);
+ return;
+ }
+ debug_msg(DEBUG_FIND_FCODE, "%s: '%s'\n", func_name, dropin_name);
+ push_a_string(env, dropin_name);
+ load_file(env);
+ d = POP(DS);
+ if (d) {
+ debug_msg(DEBUG_FIND_FCODE, "%s: byte-load '%s'\n", func_name,
+ dropin_name);
+ PUSH(DS, 1);
+ byte_load(env);
+ } else
+ debug_msg(DEBUG_FIND_FCODE, "%s: load_file '%s' FAIL\n",
+ func_name, dropin_name);
+}
+
+/*
+ * We need to lookup the builtin name via an FC_RUN_PRIV call to make sure
+ * the builtin exists. If it exists, then we need to leave the xt of
+ * do-builtin-dropin on the stack and remember the name for do-dropin. This is
+ * extremely convoluted because we can't a priori populate
+ * SUNW,builtin-drivers.
+ */
+static void
+builtin_driver_method_hook(fcode_env_t *env)
+{
+ device_t *device;
+ char *method, *path;
+ fc_cell_t len;
+ fstack_t d;
+ int error;
+ static char func_name[] = "builtin-driver-method-hook";
+
+ d = POP(DS);
+ CONVERT_PHANDLE(env, device, d);
+ if (!is_device_builtin_package(env, device)) {
+ PUSH(DS, d);
+ PUSH(DS, FALSE);
+ return;
+ }
+
+ method = pop_a_string(env, NULL);
+
+ /*
+ * Check for file in filesystem. If it exists, we'll just try to do
+ * a do-dropin-file.
+ */
+ if ((path = search_for_fcode_file(env, method)) != NULL) {
+ debug_msg(DEBUG_FIND_FCODE, "%s: '%s' file: '%s'\n", func_name,
+ method, path);
+ if (dropin_name) {
+ FREE(dropin_name);
+ }
+ dropin_name = STRDUP(path);
+ push_a_string(env, "do-builtin-file");
+ dollar_find(env);
+ return;
+ }
+
+ error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1,
+ fc_ptr2cell(method), &len);
+ if (error || len == 0) {
+ if (len == 0)
+ debug_msg(DEBUG_FIND_FCODE, "%s: '%s' NOT FOUND\n",
+ func_name, method);
+ push_a_string(env, method);
+ PUSH(DS, d);
+ PUSH(DS, FALSE);
+ } else {
+ debug_msg(DEBUG_FIND_FCODE, "%s: '%s' FOUND len: %x\n",
+ func_name, method, (int)len);
+ if (dropin_name) {
+ FREE(dropin_name);
+ }
+ dropin_name = STRDUP(method);
+ push_a_string(env, "do-builtin-dropin");
+ dollar_find(env);
+ }
+}
+
+void
+make_a_node(fcode_env_t *env, char *name, int finish)
+{
+ new_device(env);
+ push_a_string(env, name);
+ device_name(env);
+ if (finish)
+ finish_device(env);
+}
+
+void
+install_package_nodes(fcode_env_t *env)
+{
+ MYSELF = open_instance_chain(env, env->root_node, 0);
+ if (MYSELF != NULL) {
+ make_a_node(env, "packages", 0);
+ make_a_node(env, "disk-label", 0);
+ finish_device(env);
+ make_a_node(env, "SUNW,builtin-drivers", 0);
+ builtin_driver_device = env->current_device;
+ finish_device(env);
+ finish_device(env);
+ close_instance_chain(env, MYSELF, 0);
+ device_end(env);
+ MYSELF = 0;
+ }
+}
+
+/*
+ * find-builtin-driver ( str len -- xt true | false )
+ */
+void
+find_builtin_driver(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 2, "find-builtin-driver");
+ push_a_string(env, "SUNW,builtin-drivers");
+ find_package(env);
+ d = POP(DS);
+ if (d) {
+ find_method(env);
+ } else {
+ two_drop(env);
+ PUSH(DS, FALSE);
+ }
+}
+
+void
+exec_builtin_driver(fcode_env_t *env)
+{
+ fstack_t d;
+ char *method, *path, *buf;
+ fc_cell_t len, result;
+ int error;
+ static char func_name[] = "exec-builtin-driver";
+ extern int check_fcode_header(char *, uchar_t *, int);
+
+ CHECK_DEPTH(env, 2, func_name);
+ method = pop_a_string(env, NULL);
+
+ /*
+ * Check for file in filesystem. If it exists, we'll just try to do
+ * a do-dropin-file.
+ */
+ if ((path = search_for_fcode_file(env, method)) != NULL) {
+ push_a_string(env, path);
+ load_file(env);
+ return;
+ }
+
+ error = fc_run_priv(env->private, "sunos,get-fcode-size", 1, 1,
+ fc_ptr2cell(method), &len);
+ if (error || len == 0) {
+ if (len == 0)
+ debug_msg(DEBUG_FIND_FCODE, "%s: '%s' NOT FOUND\n",
+ func_name, method);
+ PUSH(DS, 0);
+ return;
+ }
+ debug_msg(DEBUG_FIND_FCODE, "%s: '%s' FOUND len: %x\n",
+ func_name, method, (int)len);
+ buf = MALLOC(len);
+ error = fc_run_priv(env->private, "sunos,get-fcode", 3, 1,
+ fc_ptr2cell(method), fc_ptr2cell(buf), len, &result);
+ if (error) {
+ FREE(buf);
+ PUSH(DS, 0);
+ return;
+ }
+
+ if (check_fcode_header(dropin_name, (uchar_t *)buf, len) == 0)
+ log_message(MSG_WARN, "%s: '%s' fcode header NOT OK\n",
+ func_name, method);
+
+ debug_msg(DEBUG_FIND_FCODE, "%s: '%s' dropin Fcode: 0x%p/0x%x\n",
+ func_name, method, buf, (int)len);
+ PUSH(DS, (fstack_t)buf);
+ PUSH(DS, len);
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ extern void set_find_method_hook(fcode_env_t *,
+ void (*)(fcode_env_t *));
+ fcode_env_t *env = initial_env;
+ fstack_t d;
+
+ ASSERT(env);
+ NOTICE;
+
+ set_find_method_hook(env, builtin_driver_method_hook);
+
+ FORTH(0, "install-package-nodes", install_package_nodes);
+ FORTH(0, "find-builtin-driver", find_builtin_driver);
+ FORTH(0, "exec-builtin-driver", exec_builtin_driver);
+ FORTH(0, "builtin-driver-method-hook",
+ builtin_driver_method_hook);
+ FORTH(0, "do-builtin-dropin", do_builtin_dropin);
+ FORTH(0, "do-builtin-file", do_builtin_file);
+}
diff --git a/usr/src/lib/efcode/packages/sparcv9/Makefile b/usr/src/lib/efcode/packages/sparcv9/Makefile
new file mode 100644
index 0000000000..1c13ef5f37
--- /dev/null
+++ b/usr/src/lib/efcode/packages/sparcv9/Makefile
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+include $(SRC)/lib/Makefile.lib.64
+
+DYNFLAGS += $(FCODE64)
+
+install: all $(ROOTLIBS64)
diff --git a/usr/src/lib/efcode/pci/Makefile b/usr/src/lib/efcode/pci/Makefile
new file mode 100644
index 0000000000..29132d88a1
--- /dev/null
+++ b/usr/src/lib/efcode/pci/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.subdirs
diff --git a/usr/src/lib/efcode/pci/Makefile.com b/usr/src/lib/efcode/pci/Makefile.com
new file mode 100644
index 0000000000..759b03e7e9
--- /dev/null
+++ b/usr/src/lib/efcode/pci/Makefile.com
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+OBJECTS = pci.o
+LIBRARY = lfc_upa_pci.a
+
+SYMLINKS = lfc_pci_pci.so lfc_gptwo_pci.so
+
+include ../../Makefile.efcode
diff --git a/usr/src/lib/efcode/pci/pci.c b/usr/src/lib/efcode/pci/pci.c
new file mode 100644
index 0000000000..53aa22cdf9
--- /dev/null
+++ b/usr/src/lib/efcode/pci/pci.c
@@ -0,0 +1,345 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#include <fcdriver/fcdriver.h>
+
+static fstack_t
+mem_map_in(fcode_env_t *env, fstack_t hi, fstack_t mid, fstack_t lo,
+ fstack_t requested_len)
+{
+ private_data_t *cdp = DEVICE_PRIVATE(env);
+ int error;
+ fc_cell_t requested_virt, adjusted_virt;
+ char *service = "map-in";
+ fstack_t mcookie = NULL;
+ int pa_offset = 0, va_offset = 0;
+ fstack_t adjusted_len = 0;
+
+ pa_offset = lo & PAGEOFFSET;
+ lo &= PAGEMASK;
+
+ /* adjust the requested_len to a multiple of a pagesize */
+ requested_len = (requested_len + pa_offset + PAGEOFFSET) & PAGEMASK;
+
+ error = fc_run_priv(cdp->common, service, 4, 1,
+ fc_size2cell(requested_len), fc_uint32_t2cell(hi),
+ fc_uint32_t2cell(mid), fc_uint32_t2cell(lo), &requested_virt);
+
+ if (error)
+ throw_from_fclib(env, 1, "pci:%s: failed\n", service);
+
+ /*
+ * Check the requested_virt address and ensure that
+ * it starts at a page boundary.
+ */
+
+ va_offset = requested_virt & PAGEOFFSET;
+
+ if (va_offset != 0) {
+
+ /*
+ * Align the virtual address to a page boundary
+ * before mapping it to a mcookie. Recalcuate the
+ * length and round it up to the next multiple of a pagesize.
+ */
+
+ adjusted_virt = requested_virt & PAGEMASK;
+ adjusted_len = (requested_len + va_offset + PAGEOFFSET)
+ & PAGEMASK;
+ }
+
+ mcookie = mapping_to_mcookie(requested_virt, requested_len,
+ adjusted_virt, adjusted_len);
+
+ if (mcookie == NULL)
+ throw_from_fclib(env, 1, "pci-mapin-> pci:%s:"
+ " mapping_to_mcookie failed\n", service);
+ /*
+ * Recalculate the address of the mcookie.
+ */
+
+ mcookie += va_offset + pa_offset;
+
+ debug_msg(DEBUG_REG_ACCESS, "pci:map-in: %llx -> %x\n",
+ (uint64_t)requested_virt, (uint32_t)mcookie);
+
+ return (mcookie);
+}
+
+static void
+mem_map_out(fcode_env_t *env, fstack_t mcookie, fstack_t requested_len)
+{
+ private_data_t *cdp = DEVICE_PRIVATE(env);
+ char *service = "map-out";
+ fc_cell_t requested_virt;
+ int error;
+
+ if (!is_mcookie(mcookie)) {
+ log_message(MSG_ERROR, "pci:%s: %x not mcookie!\n", service,
+ (uint32_t)mcookie);
+ requested_virt = mcookie;
+ } else {
+ requested_virt = mcookie_to_rvirt(mcookie);
+ requested_len = mcookie_to_rlen(mcookie);
+ delete_mapping(mcookie);
+ debug_msg(DEBUG_REG_ACCESS, "pci:%s: %x -> %llx\n", service,
+ (uint32_t)mcookie, (uint64_t)requested_virt);
+ }
+
+ error = fc_run_priv(cdp->common, service, 2, 0,
+ fc_size2cell(requested_len), requested_virt);
+
+ if (error)
+ log_message(MSG_ERROR, "pci:%s: failed\n", service);
+}
+
+static void
+pci_config_fetch(fcode_env_t *env, char *service)
+{
+ uint32_t cfgadd;
+ fc_cell_t value;
+ private_data_t *h = DEVICE_PRIVATE(env);
+ int error;
+
+ ASSERT(h);
+ CHECK_DEPTH(env, 1, service);
+ cfgadd = POP(DS);
+ error = fc_run_priv(h->common, service, 1, 1, fc_uint32_t2cell(cfgadd),
+ &value);
+
+ if (error)
+ throw_from_fclib(env, 1, "pci:%s ( %x ) FAIL\n", service,
+ cfgadd);
+
+ PUSH(DS, value);
+}
+
+static void
+pci_config_store(fcode_env_t *env, char *service)
+{
+ uint32_t cfgadd;
+ fc_cell_t value;
+ private_data_t *h = DEVICE_PRIVATE(env);
+ int error;
+
+ ASSERT(h);
+ CHECK_DEPTH(env, 2, service);
+ cfgadd = POP(DS);
+ value = POP(DS);
+ error = fc_run_priv(h->common, service, 2, 0, fc_uint32_t2cell(cfgadd),
+ fc_uint32_t2cell(value));
+
+ if (error)
+ throw_from_fclib(env, 1, "pci:%s ( %x %x ) FAIL\n", service,
+ cfgadd, value);
+}
+
+static void
+config_lfetch(fcode_env_t *env)
+{
+ pci_config_fetch(env, "config-l@");
+}
+
+static void
+config_lstore(fcode_env_t *env)
+{
+ pci_config_store(env, "config-l!");
+}
+
+static void
+config_wfetch(fcode_env_t *env)
+{
+ pci_config_fetch(env, "config-w@");
+}
+
+static void
+config_wstore(fcode_env_t *env)
+{
+ pci_config_store(env, "config-w!");
+}
+
+static void
+config_bfetch(fcode_env_t *env)
+{
+ pci_config_fetch(env, "config-b@");
+}
+
+static void
+config_bstore(fcode_env_t *env)
+{
+ pci_config_store(env, "config-b!");
+}
+
+static void
+do_map_in(fcode_env_t *env)
+{
+ fstack_t phi, pmid, plo, len, addr;
+
+ CHECK_DEPTH(env, 4, "pci:map-in");
+ len = POP(DS);
+ phi = POP(DS);
+ pmid = POP(DS);
+ plo = POP(DS);
+ addr = mem_map_in(env, phi, pmid, plo, len);
+ PUSH(DS, addr);
+}
+
+static void
+do_map_out(fcode_env_t *env)
+{
+ fstack_t addr, len;
+
+ CHECK_DEPTH(env, 2, "pci:map-out");
+ len = POP(DS);
+ addr = POP(DS);
+ mem_map_out(env, addr, len);
+}
+
+static void
+do_encode_unit(fcode_env_t *env)
+{
+ char enc_buf[64];
+ uint32_t hi;
+ int dev, fn;
+
+ CHECK_DEPTH(env, 3, "pci:encode-unit");
+ hi = POP(DS);
+ (void) POP(DS);
+ (void) POP(DS);
+
+ fn = ((hi >> 8) & 0x7);
+ dev = ((hi >> 11) & 0x1f);
+
+ if (fn) {
+ sprintf(enc_buf, "%x,%x", dev, fn);
+ } else {
+ sprintf(enc_buf, "%x", dev);
+ }
+ debug_msg(DEBUG_REG_ACCESS, "pci:encode-unit ( %x ) -> %s\n",
+ hi, enc_buf);
+ push_a_string(env, STRDUP(enc_buf));
+}
+
+static void
+do_decode_unit(fcode_env_t *env)
+{
+ int lo, hi, unit;
+ char *buf;
+
+ CHECK_DEPTH(env, 2, "pci:decode-unit");
+ buf = pop_a_string(env, NULL);
+ if (sscanf(buf, "%x,%x", &hi, &lo) != 2) {
+ throw_from_fclib(env, 1, "pci:decode-unit: '%s'", buf);
+ }
+ unit = ((hi & 0x1f) << 11);
+ unit |= ((lo & 0x7) << 8);
+ debug_msg(DEBUG_REG_ACCESS, "pci:decode-unit ( '%s' ) -> 0 0 %x\n",
+ buf, unit);
+ PUSH(DS, 0);
+ PUSH(DS, 0);
+ PUSH(DS, unit);
+}
+
+static void
+do_device_id(fcode_env_t *env)
+{
+ uint32_t cfgadd;
+ uint16_t ven_id, dev_id;
+ char buf[40];
+
+ CHECK_DEPTH(env, 3, "pci:device-id");
+ cfgadd = POP(DS);
+ (void) POP(DS);
+ (void) POP(DS);
+ PUSH(DS, cfgadd + PCI_CONF_VENID);
+ config_wfetch(env);
+ ven_id = POP(DS);
+ PUSH(DS, cfgadd + PCI_CONF_DEVID);
+ config_wfetch(env);
+ dev_id = POP(DS);
+ sprintf(buf, "pci%x,%x", ven_id, dev_id);
+ push_a_string(env, STRDUP(buf));
+}
+
+static void
+do_class_id(fcode_env_t *env)
+{
+ uint32_t cfgadd;
+ uint8_t basclass, subclass, progclass;
+ char buf[40];
+
+ CHECK_DEPTH(env, 3, "pci:class-id");
+ cfgadd = POP(DS);
+ (void) POP(DS);
+ (void) POP(DS);
+ PUSH(DS, cfgadd + PCI_CONF_BASCLASS);
+ config_bfetch(env);
+ basclass = POP(DS);
+ PUSH(DS, cfgadd + PCI_CONF_SUBCLASS);
+ config_bfetch(env);
+ subclass = POP(DS);
+ PUSH(DS, cfgadd + PCI_CONF_PROGCLASS);
+ config_bfetch(env);
+ progclass = POP(DS);
+ sprintf(buf, "pciclass%02x%02x%02x", basclass, subclass, progclass);
+ push_a_string(env, STRDUP(buf));
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ ASSERT(env->current_device);
+ NOTICE;
+
+ FORTH(0, "config-l@", config_lfetch);
+ FORTH(0, "config-l!", config_lstore);
+ FORTH(0, "config-w@", config_wfetch);
+ FORTH(0, "config-w!", config_wstore);
+ FORTH(0, "config-b@", config_bfetch);
+ FORTH(0, "config-b!", config_bstore);
+ FORTH(0, "map-in", do_map_in);
+ FORTH(0, "map-out", do_map_out);
+ FORTH(0, "decode-unit", do_decode_unit);
+ FORTH(0, "encode-unit", do_encode_unit);
+ FORTH(0, "device-id", do_device_id);
+ FORTH(0, "class-id", do_class_id);
+
+ install_dma_methods(env);
+}
diff --git a/usr/src/lib/efcode/pci/sparcv9/Makefile b/usr/src/lib/efcode/pci/sparcv9/Makefile
new file mode 100644
index 0000000000..6656b54ad3
--- /dev/null
+++ b/usr/src/lib/efcode/pci/sparcv9/Makefile
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+include $(SRC)/lib/Makefile.lib.64
+
+DYNFLAGS += $(FCODE64) $(FCDRIVER64)
+
+install: all $(ROOTLIBS64) $(ROOTSYMLINKS64)
diff --git a/usr/src/lib/efcode/upa/Makefile b/usr/src/lib/efcode/upa/Makefile
new file mode 100644
index 0000000000..29132d88a1
--- /dev/null
+++ b/usr/src/lib/efcode/upa/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.subdirs
diff --git a/usr/src/lib/efcode/upa/Makefile.com b/usr/src/lib/efcode/upa/Makefile.com
new file mode 100644
index 0000000000..c3edf9eb42
--- /dev/null
+++ b/usr/src/lib/efcode/upa/Makefile.com
@@ -0,0 +1,32 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+OBJECTS = upa.o
+LIBRARY = lfc_upa.a
+
+include ../../Makefile.efcode
diff --git a/usr/src/lib/efcode/upa/sparcv9/Makefile b/usr/src/lib/efcode/upa/sparcv9/Makefile
new file mode 100644
index 0000000000..c545bf4255
--- /dev/null
+++ b/usr/src/lib/efcode/upa/sparcv9/Makefile
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+include $(SRC)/lib/Makefile.lib.64
+
+DYNFLAGS += $(FCODE64)
+
+install: all $(ROOTLIBS64) $(ROOTSYMLINKS64)
diff --git a/usr/src/lib/efcode/upa/upa.c b/usr/src/lib/efcode/upa/upa.c
new file mode 100644
index 0000000000..251dd5183d
--- /dev/null
+++ b/usr/src/lib/efcode/upa/upa.c
@@ -0,0 +1,74 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include <fcode/private.h>
+
+static void
+do_decode_unit(fcode_env_t *env)
+{
+ CHECK_DEPTH(env, 2, "upa:decode-unit");
+ parse_two_int(env);
+ if ((TOS & 0x1c0) == 0) {
+ TOS = ((TOS << 1) | 0x1c0);
+ }
+}
+
+static void
+do_encode_unit(fcode_env_t *env)
+{
+ static char buf[8];
+ fstack_t hi, mid, lo;
+ int dev, fn, len;
+
+ CHECK_DEPTH(env, 2, "upa:encode-unit");
+ hi = POP(DS);
+ lo = POP(DS);
+ hi = ((hi >> 1) & 0x1f);
+ sprintf(buf, "%x,%x", hi, lo);
+ push_a_string(env, buf);
+}
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+
+ ASSERT(env);
+ NOTICE;
+
+ create_int_prop(env, "#address-cells", 2);
+ create_int_prop(env, "#size-cells", 2);
+
+ FORTH(0, "decode-unit", do_decode_unit);
+ FORTH(0, "encode-unit", do_encode_unit);
+
+}