diff --git a/src/interpret.c b/src/interpret.c
index 8864e95f20347eed183c924ce32966cd9e3a849a..cf20f0dc505b09e049a9bba212bb1595d05a7b40 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: interpret.c,v 1.217 2001/07/09 11:37:20 grubba Exp $");
+RCSID("$Id: interpret.c,v 1.218 2001/07/09 14:19:15 grubba Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -66,6 +66,7 @@ RCSID("$Id: interpret.c,v 1.217 2001/07/09 11:37:20 grubba Exp $");
 
 #ifdef HAVE_COMPUTED_GOTO
 PIKE_OPCODE_T *fcode_to_opcode = NULL;
+struct op_2_f *opcode_to_fcode = NULL;
 #endif /* HAVE_COMPUTED_GOTO */
 
 PMOD_EXPORT const char *Pike_check_stack_errmsg =
@@ -691,7 +692,7 @@ void dump_backlog(void)
       fprintf(stderr,"%s:%ld: %s",
 	      file,
 	      (long)line,
-	      low_get_f_name(backlog[e].instruction, backlog[e].program));
+	      get_opcode_name(backlog[e].instruction));
 #else /* !HAVE_COMPUTED_GOTO */
       if(backlog[e].instruction < 0 || backlog[e].instruction+F_OFFSET > F_MAX_OPCODE)
       {
@@ -741,6 +742,14 @@ static int o_catch(PIKE_OPCODE_T *pc);
 #define EVAL_INSTR_RET_CHECK(x)
 #endif
 
+#ifdef HAVE_COMPUTED_GOTO
+int lookup_sort_fun(const void *a, const void *b)
+{
+  return (int)(((ptrdiff_t)((struct op_2_f *)a)->opcode) -
+	       ((ptrdiff_t)((struct op_2_f *)b)->opcode));
+}
+#endif /* HAVE_COMPUTED_GOTO */
+
 /* NOTE: Due to the implementation of computed goto,
  *       interpreter.h may only be included once.
  */
@@ -1241,7 +1250,7 @@ int low_mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2)
       {
 	int num_args;
 	int num_locals;
-	unsigned char *pc;
+	PIKE_OPCODE_T *pc;
 
 #ifdef PIKE_DEBUG
 	if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_FREE)
@@ -1250,9 +1259,14 @@ int low_mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2)
 
 	debug_malloc_touch(Pike_fp);
 	pc=new_frame->context.prog->program + function->func.offset;
-	
-	num_locals=EXTRACT_UCHAR(pc++);
-	num_args=EXTRACT_UCHAR(pc++);
+
+#ifdef HAVE_COMPUTED_GOTO
+	num_locals = (int)(ptrdiff_t)((pc++)[0]);
+	num_args = (int)(ptrdiff_t)((pc++)[0]);
+#else /* !HAVE_COMPUTED_GOTO */
+	num_locals = EXTRACT_UCHAR(pc++);
+	num_args = EXTRACT_UCHAR(pc++);
+#endif /* HAVE_COMPUTED_GOTO */
 
 #ifdef PIKE_DEBUG
 	if(num_locals < num_args)
@@ -1294,7 +1308,7 @@ int low_mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2)
 	new_frame->save_mark_sp=Pike_mark_sp;
 	new_frame->mark_sp_base=Pike_mark_sp;
 	check_threads_etc();
-	new_frame->pc=pc;
+	new_frame->pc = pc;
 	return 1;
       }
       }
diff --git a/src/interpreter.h b/src/interpreter.h
index 71e784a0aff8d87c219fbb2e099a334e8876cd6e..141e240eccb1cdef9ba27895e77d853c515d5f48 100644
--- a/src/interpreter.h
+++ b/src/interpreter.h
@@ -135,7 +135,7 @@ static int eval_instruction(PIKE_OPCODE_T *pc)
 	      file,(long)linep,
 	      DO_NOT_WARN((long)(pc-Pike_fp->context.prog->program-1)),
 #ifdef HAVE_COMPUTED_GOTO
-	      get_f_name(instr),
+	      get_opcode_name(instr),
 #else /* !HAVE_COMPUTED_GOTO */
 	      get_f_name(instr + F_OFFSET),
 #endif /* HAVE_COMPUTED_GOTO */
@@ -144,7 +144,8 @@ static int eval_instruction(PIKE_OPCODE_T *pc)
     }
 
 #ifdef HAVE_COMPUTED_GOTO
-    ADD_RUNNED(instr);
+    if (instr) 
+      ADD_RUNNED(instr);
 #else /* !HAVE_COMPUTED_GOTO */
     if(instr + F_OFFSET < F_MAX_OPCODE) 
       ADD_RUNNED(instr + F_OFFSET);
@@ -383,6 +384,44 @@ static int eval_instruction(PIKE_OPCODE_T *pc)
       LABEL(F_RETURN_LOCAL),
       LABEL(F_RETURN_IF_TRUE),
 
+#include "interpret_protos.h"
+    };
+
+    static struct op_2_f lookup[] = {
+#undef LABEL
+#define LABEL(OP)	{ &&PIKE_CONCAT(LABEL_, OP), OP }
+#undef NULL_LABEL
+#define NULL_LABEL(OP)	{ NULL, OP }
+
+      NULL_LABEL(F_OFFSET),
+
+      NULL_LABEL(F_PREFIX_256),
+      NULL_LABEL(F_PREFIX_512),
+      NULL_LABEL(F_PREFIX_768),
+      NULL_LABEL(F_PREFIX_1024),
+      NULL_LABEL(F_PREFIX_CHARX256),
+      NULL_LABEL(F_PREFIX_WORDX256),
+      NULL_LABEL(F_PREFIX_24BITX256),
+
+      NULL_LABEL(F_PREFIX2_256),
+      NULL_LABEL(F_PREFIX2_512),
+      NULL_LABEL(F_PREFIX2_768),
+      NULL_LABEL(F_PREFIX2_1024),
+      NULL_LABEL(F_PREFIX2_CHARX256),
+      NULL_LABEL(F_PREFIX2_WORDX256),
+      NULL_LABEL(F_PREFIX2_24BITX256),
+
+      LABEL(F_INDEX),
+      LABEL(F_POS_INT_INDEX),
+      LABEL(F_NEG_INT_INDEX),
+
+      LABEL(F_RETURN),
+      LABEL(F_DUMB_RETURN),
+      LABEL(F_RETURN_0),
+      LABEL(F_RETURN_1),
+      LABEL(F_RETURN_LOCAL),
+      LABEL(F_RETURN_IF_TRUE),
+
 #include "interpret_protos.h"
     };
 
@@ -393,6 +432,11 @@ static int eval_instruction(PIKE_OPCODE_T *pc)
 	    DO_NOT_WARN((long)((F_MAX_OPCODE-F_OFFSET)*sizeof(void *))));
 #endif /* PIKE_DEBUG */
     fcode_to_opcode = table;
+    opcode_to_fcode = lookup;
+
+    qsort(lookup, F_MAX_OPCODE-F_OFFSET, sizeof(struct op_2_f),
+	  lookup_sort_fun);
+
     return 0;
   }
 #endif /* HAVE_COMPUTED_GOTO */
diff --git a/src/lex.c b/src/lex.c
index 598d36493d2441d6454dd53ce985487e998dfa70..59cb097e300a3ef7298a49e023db428b8d963cc1 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: lex.c,v 1.95 2001/07/09 11:37:21 grubba Exp $");
+RCSID("$Id: lex.c,v 1.96 2001/07/09 14:19:16 grubba Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -85,7 +85,9 @@ void add_runned(PIKE_OPCODE_T instr)
     tmp=tmp[0]->next + last_instruction[e];
     last_instruction[e]=last_instruction[e+1];
   }
+#ifndef HAVE_COMPUTED_GOTO
   ((char **)(tmp))[0]++;
+#endif /* !HAVE_COMPUTED_GOTO */
   last_instruction[e]=instr;
 }
 
@@ -323,6 +325,34 @@ char *get_f_name(int n)
   }
 }
 
+#ifdef HAVE_COMPUTED_GOTO
+char *get_opcode_name(PIKE_OPCODE_T n)
+{
+  int fcode;
+  int low = 0;
+  int high = F_MAX_OPCODE - F_OFFSET;
+  static char buf[64];
+
+  if (!n) {
+    return "<NULL opcode!>";
+  }
+
+  while (low < high) {
+    int mid = (low+high)/2;
+    if (opcode_to_fcode[mid].opcode < n) {
+      low = mid + 1;
+    } else if (opcode_to_fcode[mid].opcode > n) {
+      high = mid;
+    } else {
+      return get_f_name(opcode_to_fcode[mid].fcode);
+    }
+  }
+
+  sprintf(buf, "<Unknown opcode 0x%p>", n);
+  return buf;
+}
+#endif /* HAVE_COMPUTED_GOTO */
+
 char *get_token_name(int n)
 {
   static char buf[30];
diff --git a/src/lex.h b/src/lex.h
index 661a722faf35a96de0a7a690742d01fa0f815d68..96a47efe29cdaa6db6aaf43c609e157c35f359ac 100644
--- a/src/lex.h
+++ b/src/lex.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: lex.h,v 1.17 2001/07/09 11:37:20 grubba Exp $
+ * $Id: lex.h,v 1.18 2001/07/09 14:19:16 grubba Exp $
  */
 #ifndef LEX_H
 #define LEX_H
@@ -90,6 +90,11 @@ struct reserved;
 void init_lex(void);
 char *low_get_f_name(int n,struct program *p);
 char *get_f_name(int n);
+#ifdef HAVE_COMPUTED_GOTO
+char *get_opcode_name(PIKE_OPCODE_T n);
+#else /* !HAVE_COMPUTED_GOTO */
+#define get_opcode_name(n)	get_f_name(n)
+#endif /* HAVE_COMPUTED_GOTO */
 char *get_token_name(int n);
 
 int yylex0(YYSTYPE *);
diff --git a/src/peep.c b/src/peep.c
index 767ea3f7fed9d6abb34ca7c1119c32ccd0a1a32a..d005636506bbdb64b9bc8ff0af6406695a291cfc 100644
--- a/src/peep.c
+++ b/src/peep.c
@@ -17,7 +17,7 @@
 #include "builtin_functions.h"
 #include "constants.h"
 
-RCSID("$Id: peep.c,v 1.52 2001/07/09 12:50:18 grubba Exp $");
+RCSID("$Id: peep.c,v 1.53 2001/07/09 14:19:16 grubba Exp $");
 
 static void asm_opt(void);
 
@@ -360,7 +360,9 @@ void assemble(void)
     case F_START_FUNCTION:
       break;
     case F_ALIGN:
+#ifndef HAVE_COMPUTED_GOTO
       while(PC % c->arg) add_to_program(0);
+#endif /* HAVE_COMPUTED_GOTO */
       break;
 
     case F_BYTE:
@@ -447,9 +449,16 @@ void assemble(void)
 	fatal("Hyperspace error: unknown jump point %ld at %d (pc=%x).\n",
 	      PTRDIFF_T_TO_LONG(e), labels[e], jumps[e]);
 #endif
+#ifdef HAVE_COMPUTED_GOTO
+      tmp = (int)(ptrdiff_t)(Pike_compiler->new_program->program[jumps[e]]);
+      Pike_compiler->new_program->program[jumps[e]] =
+	(PIKE_OPCODE_T)(ptrdiff_t)(tmp2 - jumps[e]);
+      jumps[e] = tmp;
+#else /* !HAVE_COMPUTED_GOTO */
       tmp=read_int(jumps[e]);
       upd_int(jumps[e], tmp2 - jumps[e]);
       jumps[e]=tmp;
+#endif /* HAVE_COMPUTED_GOTO */
     }
   }
 
diff --git a/src/program.h b/src/program.h
index 78414a2ab1031f18cda29afde14c431a8118cc91..8baa09cbfaa0dae1eedb59e7eb2de22258c80973 100644
--- a/src/program.h
+++ b/src/program.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: program.h,v 1.135 2001/07/09 11:37:19 grubba Exp $
+ * $Id: program.h,v 1.136 2001/07/09 14:19:16 grubba Exp $
  */
 #ifndef PROGRAM_H
 #define PROGRAM_H
@@ -30,6 +30,10 @@ PMOD_PROTO extern struct program_state * Pike_compiler;
 #ifdef HAVE_COMPUTED_GOTO
 #define PIKE_OPCODE_T	void *
 extern PIKE_OPCODE_T *fcode_to_opcode;
+extern struct op_2_f {
+  PIKE_OPCODE_T opcode;
+  INT32 fcode;
+} *opcode_to_fcode;
 #else /* !HAVE_COMPUTED_GOTO */
 #ifdef SHORT_PIKE_OPCODE
 #define PIKE_OPCODE_T	unsigned INT16