/* * 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 #include #include #include #include #include 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 = ""; 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("e_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: %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, ""); } 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, ""); } 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(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); }