OpenSolaris_b135/lib/efcode/engine/fcode.c

Compare this file to the similar file:
Show the results in this format:

/*
 * 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);
}