diff -bru tcl8.4a3-orig/generic/tclCompile.c tcl8.4a3/generic/tclCompile.c
--- tcl8.4a3-orig/generic/tclCompile.c	Thu May 17 04:13:02 2001
+++ tcl8.4a3/generic/tclCompile.c	Sun Jan  6 21:12:37 2002
@@ -48,8 +48,11 @@
  * from global variables; the bytecode interpreter at runtime uses the
  * existence of a procedure call frame to distinguish these.
  */
-
+#ifdef USEROPCODE
+InstructionDesc instructionTable[255] = {
+#else
 InstructionDesc instructionTable[] = {
+#endif
    /* Name	      Bytes #Opnds Operand types	Stack top, next	  */
     {"done",		  1,   0,   {OPERAND_NONE}},
 	/* Finish ByteCode execution and return stktop (top stack item) */
diff -bru tcl8.4a3-orig/generic/tclCompile.h tcl8.4a3/generic/tclCompile.h
--- tcl8.4a3-orig/generic/tclCompile.h	Thu May 17 04:13:02 2001
+++ tcl8.4a3/generic/tclCompile.h	Sun Jan  6 21:14:17 2002
@@ -22,6 +22,8 @@
 # define TCL_STORAGE_CLASS DLLEXPORT
 #endif
 
+#define USEROPCODE 1
+
 /*
  *------------------------------------------------------------------------
  * Variables related to compilation. These are used in tclCompile.c,
@@ -524,6 +526,10 @@
 /* The last opcode */
 #define LAST_INST_OPCODE        	93
 
+#ifdef USEROPCODE
+#define MAXUSEROPCODES 255-LAST_INST_OPCODE
+#endif
+
 /*
  * Table describing the Tcl bytecode instructions: their name (for
  * displaying code), total number of code bytes required (including
@@ -1004,5 +1010,9 @@
 
 # undef TCL_STORAGE_CLASS
 # define TCL_STORAGE_CLASS DLLIMPORT
+
+#ifdef USEROPCODE
+int TclRegisterUserOpcode(InstructionDesc *, Tcl_ObjCmdProc, ClientData);
+#endif
 
 #endif /* _TCLCOMPILATION */
diff -bru tcl8.4a3-orig/generic/tclExecute.c tcl8.4a3/generic/tclExecute.c
--- tcl8.4a3-orig/generic/tclExecute.c	Wed Jul  4 01:39:10 2001
+++ tcl8.4a3/generic/tclExecute.c	Sun Jan  6 21:28:02 2002
@@ -276,6 +276,39 @@
 static int		VerifyExprObjType _ANSI_ARGS_((Tcl_Interp *interp,
 			    Tcl_Obj *objPtr));
 
+#ifdef USEROPCODE
+static int numberUserOpcodes = 0;
+static const int maxUserOpcodes = MAXUSEROPCODES;
+typedef struct UserOpcode 
+{
+  Tcl_ObjCmdProc *proc;
+  ClientData cd;
+} UserOpcode;
+UserOpcode userOpcodes[MAXUSEROPCODES];
+
+int 
+TclRegisterUserOpcode(InstructionDesc *instDesc, Tcl_ObjCmdProc proc,
+		      ClientData cd) {
+  int opcode;
+  if (numberUserOpcodes < MAXUSEROPCODES-1) {
+    /*
+    fprintf(stderr, "userOpCode[%d].proc = %p byte = %d '%s'\n", 
+	    numberUserOpcodes, proc, 
+	    LAST_INST_OPCODE + numberUserOpcodes + 1, 
+	    instDesc->name);
+    */
+    userOpcodes[numberUserOpcodes].proc = proc;
+    userOpcodes[numberUserOpcodes].cd = cd;
+    numberUserOpcodes ++;
+    opcode = LAST_INST_OPCODE + numberUserOpcodes;
+    instructionTable[opcode] = *instDesc;
+  } else {
+    opcode = 0;
+  }
+  return opcode;
+}
+#endif
+
 /*
  * Table describing the built-in math functions. Entries in this table are
  * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
@@ -3372,7 +3405,43 @@
 	    ADJUST_PC(1);
 
 	default:
+#ifdef USEROPCODE
+	{
+	  InstructionDesc *inst = &instructionTable[*pc];
+	  UserOpcode *u = &userOpcodes[*pc - LAST_INST_OPCODE - 1];
+	  Tcl_Obj **objv = NULL;
+	  int objc = 0, i;
+
+	  if (*pc > numberUserOpcodes + LAST_INST_OPCODE) {
+	    panic("TclExecuteByteCode: unrecognized opCode %u", *pc);
+	  }
+	  
+	  if (inst->numOperands == 0) {
+	  } else if (inst->numOperands == 1 && 
+		     inst->opTypes[0] == OPERAND_UINT1) {
+	    objc = TclGetUInt1AtPtr(pc+1);
+	    objv = &stackPtr[stackTop - objc + 1];
+	  } else {
+	    panic("UserOpcodes: this operands are not expected\n");
+	  }
+
+	  DECACHE_STACK_INFO();
+	  result = (u->proc)(u->cd, interp, objc, objv);
+	  CACHE_STACK_INFO();
+	  
+	  for (i = 0;  i < objc;  i++) {
+	    Tcl_Obj *valuePtr = stackPtr[stackTop];
+	    TclDecrRefCount(valuePtr);
+	    stackTop--;
+	  }
+
+	  PUSH_OBJECT(Tcl_GetObjResult(interp));
+	  ADJUST_PC(inst->numBytes);
+	}
+#else
+	default:
 	    panic("TclExecuteByteCode: unrecognized opCode %u", *pc);
+#endif
 	} /* end of switch on opCode */
 
 	/*
@@ -3571,7 +3640,12 @@
 		(unsigned int) pc);
 	panic("TclExecuteByteCode execution failure: bad pc");
     }
-    if ((unsigned int) opCode > LAST_INST_OPCODE) {
+#ifdef USEROPCODE
+    if ((unsigned int) opCode > (LAST_INST_OPCODE + numberUserOpcodes))
+#else
+    if ((unsigned int) opCode > LAST_INST_OPCODE) 
+#endif
+    {
 	fprintf(stderr, "\nBad opcode %d at pc %u in TclExecuteByteCode\n",
 		(unsigned int) opCode, relativePc);
 	panic("TclExecuteByteCode execution failure: bad opcode");
