diff --git a/sourcepawn/include/sp_vm_api.h b/sourcepawn/include/sp_vm_api.h
index 8c6e7589..c07248d8 100644
--- a/sourcepawn/include/sp_vm_api.h
+++ b/sourcepawn/include/sp_vm_api.h
@@ -59,7 +59,7 @@ namespace SourcePawn
 		virtual void FreeBaseContext(IPluginContext *ctx) =0;
 
 		/**
-		 * Allocates memory.
+		 * Allocates large blocks of temporary memory.
 		 * 
 		 * @param size		Size of memory to allocate.
 		 * @return			Pointer to memory, NULL if allocation failed.
@@ -72,6 +72,21 @@ namespace SourcePawn
 		 * @param mem		Memory address to free.
 		 */
 		virtual void BaseFree(void *memory) =0;
+
+		/**
+		 * Allocates executable memory.
+		 *
+		 * @param size		Size of memory to allocate.
+		 * @return			Pointer to memory, NULL if allocation failed.
+		 */
+		virtual void *ExecAlloc(size_t size) =0;
+
+		/**
+		 * Frees executable memory.
+		 *
+		 * @param mem		Address to free.
+		 */
+		virtual void ExecFree(void *address) =0;
 	};
 
 	class ICompilation
@@ -107,14 +122,14 @@ namespace SourcePawn
 		virtual bool SetCompilationOption(ICompilation *co, const char *key, const char *val) =0;
 
 		/**
-		 * Finalizes a compilation into a new IContext.
+		 * Finalizes a compilation into a new sp_context_t.
 		 * Note: This will free the ICompilation pointer.
 		 *
 		 * @param co		Compilation pointer.
 		 * @param err		Filled with error code on exit.
 		 * @return			New plugin context.
 		 */
-		virtual IPluginContext *CompileToContext(ICompilation *co, int *err) =0;
+		virtual sp_context_t *CompileToContext(ICompilation *co, int *err) =0;
 
 		/**
 		 * Aborts a compilation and frees the ICompilation pointer.
@@ -128,7 +143,7 @@ namespace SourcePawn
 		 *
 		 * @param ctx		Context structure pointer.
 		 */
-		virtual void FreeContextVars(sp_context_t *ctx) =0;
+		virtual void FreeContext(sp_context_t *ctx) =0;
 
 		/**
 		 * Calls the "execute" function on a context.
diff --git a/sourcepawn/include/sp_vm_types.h b/sourcepawn/include/sp_vm_types.h
index 95434180..e81802d1 100644
--- a/sourcepawn/include/sp_vm_types.h
+++ b/sourcepawn/include/sp_vm_types.h
@@ -201,7 +201,7 @@ typedef int (*SPVM_DEBUGBREAK)(SourcePawn::IPluginContext *, uint32_t, uint32_t)
 typedef struct sp_context_s
 {
 	/* general/parent information */
-	void			*base;		/* base of generated code and memory */
+	void			*codebase;	/* base of generated code and memory */
 	sp_plugin_t		*plugin;	/* pointer back to parent information */
 	SourcePawn::IPluginContext *context;	/* pointer to IPluginContext */
 	SourcePawn::IVirtualMachine *vmbase;	/* pointer to IVirtualMachine */
diff --git a/sourcepawn/vm/jit/x86/jit_x86.cpp b/sourcepawn/vm/jit/x86/jit_x86.cpp
index 57da1767..1835acea 100644
--- a/sourcepawn/vm/jit/x86/jit_x86.cpp
+++ b/sourcepawn/vm/jit/x86/jit_x86.cpp
@@ -5,6 +5,10 @@
 #include "opcode_helpers.h"
 #include "x86_macros.h"
 
+#if defined USE_UNGEN_OPCODES
+#include "ungen_opcodes.h"
+#endif
+
 inline void WriteOp_Move_Pri(JitWriter *jit)
 {
 	//mov eax, edx
@@ -231,6 +235,27 @@ inline void WriteOp_Proc(JitWriter *jit)
 	IA32_Sub_Rm_Reg(jit, AMX_INFO_FRM, AMX_REG_DAT, MOD_MEM_REG);
 }
 
+inline void WriteOp_Lidx_B(JitWriter *jit)
+{
+	cell_t val = jit->read_cell();
+	//shl eax, <val>
+	//add eax, edx
+	//mov eax, [edi+eax]
+	IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
+	IA32_Add_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
+	Write_Check_VerifyAddr(jit, AMX_REG_PRI, false);
+	IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
+}
+
+inline void WriteOp_Idxaddr_B(JitWriter *jit)
+{
+	//shl eax, <val>
+	//add eax, edx
+	cell_t val = jit->read_cell();
+	IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
+	IA32_Add_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
+}
+
 inline void WriteOp_Shl(JitWriter *jit)
 {
 	//mov ecx, edx
@@ -293,18 +318,6 @@ inline void WriteOp_SMul(JitWriter *jit)
 	IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG);
 }
 
-#ifdef UNSUPPORTED
-inline void WriteOp_UMul(JitWriter *jit)
-{
-	//mov ecx, edx
-	//mul edx
-	//mov edx, ecx
-	IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
-	IA32_Mul_Rm(jit, AMX_REG_ALT, MOD_REG);
-	IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG);
-}
-#endif
-
 inline void WriteOp_Not(JitWriter *jit)
 {
 	//test eax, eax
@@ -401,54 +414,6 @@ inline void WriteOp_Neq(JitWriter *jit)
 	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_NE);
 }
 
-#ifdef UNSUPPORTED
-inline void WriteOp_Less(JitWriter *jit)
-{
-	//cmp eax, edx	; PRI < ALT ? (unsigned)
-	//mov eax, 0
-	//setb al
-	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
-	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_B);
-}
-#endif
-
-#ifdef UNSUPPORTED
-inline void WriteOp_Leq(JitWriter *jit)
-{
-	//cmp eax, edx	; PRI <= ALT ? (unsigned)
-	//mov eax, 0
-	//setbe al
-	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
-	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_BE);
-}
-#endif
-
-#ifdef UNSUPPORTED
-inline void WriteOp_Grtr(JitWriter *jit)
-{
-	//cmp eax, edx	; PRI > ALT ? (unsigned)
-	//mov eax, 0
-	//seta al
-	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
-	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_A);
-}
-#endif
-
-#ifdef UNSUPPORTED
-inline void WriteOp_Geq(JitWriter *jit)
-{
-	//cmp eax, edx	; PRI >= ALT ? (unsigned)
-	//mov eax, 0
-	//setae al
-	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
-	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_AE);
-}
-#endif
-
 inline void WriteOp_Sless(JitWriter *jit)
 {
 	//cmp eax, edx	; PRI < ALT ? (signed)
@@ -633,7 +598,6 @@ inline void WriteOp_Load_S_Alt(JitWriter *jit)
 		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
 }
 
-#ifdef UNSUPPORTED
 inline void WriteOp_Lref_Pri(JitWriter *jit)
 {
 	//mov eax, [edi+<val>]
@@ -645,9 +609,7 @@ inline void WriteOp_Lref_Pri(JitWriter *jit)
 		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val);
 	IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
 }
-#endif
 
-#ifdef UNSUPPORTED
 inline void WriteOp_Lref_Alt(JitWriter *jit)
 {
 	//mov edx, [edi+<val>]
@@ -659,9 +621,7 @@ inline void WriteOp_Lref_Alt(JitWriter *jit)
 		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val);
 	IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
 }
-#endif
 
-#ifdef UNSUPPORTED
 inline void WriteOp_Lref_S_Pri(JitWriter *jit)
 {
 	//mov eax, [ebx+<val>]
@@ -673,9 +633,7 @@ inline void WriteOp_Lref_S_Pri(JitWriter *jit)
 		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val);
 	IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
 }
-#endif
 
-#ifdef UNSUPPORTED
 inline void WriteOp_Lref_S_Alt(JitWriter *jit)
 {
 	//mov edx, [ebx+<val>]
@@ -687,7 +645,6 @@ inline void WriteOp_Lref_S_Alt(JitWriter *jit)
 		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
 	IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
 }
-#endif
 
 inline void WriteOp_Const_Pri(JitWriter *jit)
 {
@@ -773,18 +730,6 @@ inline void WriteOp_Idxaddr(JitWriter *jit)
 	IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
 }
 
-#ifdef UNSUPPORTED
-inline void WriteOp_Idxaddr_B(JitWriter *jit)
-{
-	//shl eax, <val>
-	//add eax, edx
-	cell_t val = jit->read_cell();
-	IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
-	IA32_Add_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-}
-#endif
-
-#ifdef UNSUPPORTED
 inline void WriteOp_Sref_Pri(JitWriter *jit)
 {
 	//mov ecx, [edi+<val>]
@@ -796,9 +741,7 @@ inline void WriteOp_Sref_Pri(JitWriter *jit)
 		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
 	IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
 }
-#endif
 
-#ifdef UNSUPPORTED
 inline void WriteOp_Sref_Alt(JitWriter *jit)
 {
 	//mov ecx, [edi+<val>]
@@ -810,9 +753,7 @@ inline void WriteOp_Sref_Alt(JitWriter *jit)
 		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
 	IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
 }
-#endif
 
-#ifdef UNSUPPORTED
 inline void WriteOp_Sref_S_Pri(JitWriter *jit)
 {
 	//mov ecx, [ebx+<val>]
@@ -824,9 +765,7 @@ inline void WriteOp_Sref_S_Pri(JitWriter *jit)
 		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
 	IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
 }
-#endif
 
-#ifdef UNSUPPORTED
 inline void WriteOp_Sref_S_Alt(JitWriter *jit)
 {
 	//mov ecx, [ebx+<val>]
@@ -838,31 +777,6 @@ inline void WriteOp_Sref_S_Alt(JitWriter *jit)
 		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
 	IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
 }
-#endif
-
-#ifdef UNSUPPORTED
-inline void WriteOp_Align_Pri(JitWriter *jit)
-{
-	//xor eax, <cellsize - val>
-	cell_t val = sizeof(cell_t) - jit->read_cell();
-	if (val < SCHAR_MAX && val > SCHAR_MIN)
-		IA32_Xor_Rm_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val);
-	else
-		IA32_Xor_Eax_Imm32(jit, val);
-}
-#endif
-
-#ifdef UNSUPPORTED
-inline void WriteOp_Align_Alt(JitWriter *jit)
-{
-	//xor edx, <cellsize - val>
-	cell_t val = sizeof(cell_t) - jit->read_cell();
-	if (val < SCHAR_MAX && val > SCHAR_MIN)
-		IA32_Xor_Rm_Imm8(jit, AMX_REG_ALT, MOD_REG, (jit_int8_t)val);
-	else
-		IA32_Xor_Rm_Imm32(jit, AMX_REG_ALT, MOD_REG, val);
-}
-#endif
 
 inline void WriteOp_Pop_Pri(JitWriter *jit)
 {
@@ -963,39 +877,6 @@ inline void WriteOp_Movs(JitWriter *jit)
 	IA32_Pop_Reg(jit, REG_ESI);
 }
 
-#ifdef UNSUPPORTED
-inline void WriteOp_Cmps(JitWriter *jit)
-{
-	//push edi
-	//push esi
-	//lea esi, [edi+edx]
-	//lea edi, [edi+eax]
-	IA32_Push_Reg(jit, REG_EDI);
-	IA32_Push_Reg(jit, REG_ESI);
-	IA32_Lea_Reg_DispRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
-	IA32_Lea_Reg_DispRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
-
-	//xor eax, eax
-	//repe cmpsb
-	//je :cmps1
-	IA32_Xor_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG);
-	IA32_Cmpsb(jit);
-	jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_E, 0);
-	
-	//sbb eax, eax
-	//sbb eax, -1
-	IA32_Sbb_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG);
-	IA32_Sbb_Eax_Imm32(jit, -1);//:TODO: use imm8 here
-	
-	//:cmps1
-	//pop esi
-	//pop edi
-	IA32_Send_Jump8_Here(jit, jmp);
-	IA32_Pop_Reg(jit, REG_ESI);
-	IA32_Pop_Reg(jit, REG_EDI);
-}
-#endif
-
 inline void WriteOp_Fill(JitWriter *jit)
 {
 	//add edi, edx
@@ -1099,32 +980,6 @@ inline void WriteOp_Load_I(JitWriter *jit)
 	IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
 }
 
-#ifdef UNSUPPORTED
-inline void WriteOp_Lodb_I(JitWriter *jit)
-{
-	Write_Check_VerifyAddr(jit, AMX_REG_PRI, false);
-
-	//mov eax, [edi+eax]
-	IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
-
-	//and eax, <bitmask>
-	cell_t val = jit->read_cell();
-	switch(val)
-	{
-	case 1:
-		{
-			IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x000000FF);//:TODO: replace with AND EAX, imm32
-			break;
-		}
-	case 2:
-		{
-			IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x0000FFFF);//:TODO: replace with AND EAX, imm32
-			break;
-		}
-	}
-}
-#endif
-
 inline void WriteOp_Stor_I(JitWriter *jit)
 {
 	//mov [edi+edx], eax
@@ -1132,33 +987,6 @@ inline void WriteOp_Stor_I(JitWriter *jit)
 	IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
 }
 
-#ifdef UNSUPPORTED
-inline void WriteOp_Strb_I(JitWriter *jit)
-{
-	Write_Check_VerifyAddr(jit, AMX_REG_ALT, false);
-	//mov [edi+edx], eax
-	cell_t val = jit->read_cell();
-	switch (val)
-	{
-	case 1:
-		{
-			IA32_Mov_Rm8_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
-			break;
-		}
-	case 2:
-		{
-			IA32_Mov_Rm16_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
-			break;
-		}
-	case 4:
-		{
-			IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
-			break;
-		}
-	}
-}
-#endif
-
 inline void WriteOp_Lidx(JitWriter *jit)
 {
 	//lea eax, [edx+4*eax]
@@ -1168,119 +996,6 @@ inline void WriteOp_Lidx(JitWriter *jit)
 	IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
 }
 
-#ifdef UNSUPPORTED
-inline void WriteOp_Lidx_B(JitWriter *jit)
-{
-	cell_t val = jit->read_cell();
-	//shl eax, <val>
-	//add eax, edx
-	//mov eax, [edi+eax]
-	IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
-	IA32_Add_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-	Write_Check_VerifyAddr(jit, AMX_REG_PRI, false);
-	IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
-}
-#endif
-
-#ifdef UNSUPPORTED
-inline void WriteOp_Lctrl(JitWriter *jit)
-{
-	cell_t val = jit->read_cell();
-	switch (val)
-	{
-	case 0:
-		{
-			//mov ecx, [esi+ctx]
-			//mov eax, [ecx+<offs>]
-			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
-			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, base));
-			break;
-		}
-	case 1:
-		{
-			//mov eax, edi
-			IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG);
-			break;
-		}
-	case 2:
-		{
-			//mov eax, [esi+hea]
-			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_INFO, AMX_INFO_HEAP);
-			break;
-		}
-	case 3:
-		{
-			//mov ecx, [esi+ctx]
-			//mov eax, [ecx+ctx.memory]
-			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
-			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, memory));
-			break;
-		}
-	case 4:
-		{
-			//mov eax, ebp
-			//sub eax, edi	- unrelocate
-			IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_REG);
-			IA32_Sub_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG);
-			break;
-		}
-	case 5:
-		{
-			//mov eax, [esi+frm]
-			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_INFO, AMX_INFO_FRM);
-			break;
-		}
-	case 6:
-		{
-			//mov eax, [cip]
-			jitoffs_t imm32 = IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
-			jitoffs_t save = jit->jit_curpos();
-			jit->setpos(imm32);
-			jit->write_int32((uint32_t)(jit->outbase + save));
-			jit->setpos(save);
-			break;
-		}
-	}
-}
-#endif
-
-#ifdef UNSUPPORTED
-inline void WriteOp_Sctrl(JitWriter *jit)
-{
-	cell_t val = jit->read_cell();
-	switch (val)
-	{
-	case 2:
-		{
-			//mov [esi+hea], eax
-			IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_INFO_HEAP, AMX_REG_PRI);
-			break;
-		}
-	case 4:
-		{
-			//lea ebp, [edi+eax]
-			IA32_Lea_Reg_DispRegMult(jit, AMX_REG_STK, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
-			break;
-		}
-	case 5:
-		{
-			//mov ebx, eax	- overwrite frm
-			//mov frm, eax	- overwrite stacked frame
-			//add ebx, edi	- relocate local frm //:TODO: use LEA here!!!
-			IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_PRI, MOD_REG);
-			IA32_Mov_Rm_Reg(jit, AMX_INFO_FRM, AMX_REG_PRI, MOD_MEM_REG);
-			IA32_Add_Rm_Reg(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
-			break;
-		}
-	case 6:
-		{
-			IA32_Jump_Reg(jit, AMX_REG_PRI);
-			break;
-		}
-	}
-}
-#endif
-
 inline void WriteOp_Stack(JitWriter *jit)
 {
 	//mov edx, ebp
@@ -1337,50 +1052,6 @@ inline void WriteOp_SDiv_Alt(JitWriter *jit)
 	IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG);
 }
 
-#ifdef UNSUPPORTED
-inline void WriteOp_UDiv(JitWriter *jit)
-{
-	//mov ecx, edx
-	//xor edx, edx
-	//div ecx
-	IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
-	IA32_Xor_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
-	Write_Check_DivZero(jit, AMX_REG_TMP);
-	IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG);
-}
-#endif
-
-#ifdef UNSUPPORTED
-inline void WriteOp_UDiv_Alt(JitWriter *jit)
-{
-	//mov ecx, eax
-	//mov eax, edx
-	//xor edx, edx
-	//div ecx
-	IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
-	IA32_Mov_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-	IA32_Xor_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
-	Write_Check_DivZero(jit, AMX_REG_TMP);
-	IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG);
-}
-#endif
-
-#ifdef UNSUPPORTED
-inline void WriteOp_Ret(JitWriter *jit)
-{
-	//mov ebx, [ebp]		- get old FRM
-	//add ebp, 4			- pop stack
-	//mov [esi+frm], ebx	- restore
-	//add ebx, edi			- relocate
-	//ret
-	IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_MEM_REG);
-	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
-	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_INFO, AMX_REG_FRM, AMX_INFO_FRM);//:TODO: this is wrong!
-	IA32_Add_Rm_Reg(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
-	IA32_Return(jit);
-}
-#endif
-
 inline void WriteOp_Retn(JitWriter *jit)
 {
 	//mov ebx, [ebp]		- get old frm
@@ -1449,21 +1120,6 @@ inline void WriteOp_Break(JitWriter *jit)
 	}
 }
 
-#ifdef UNSUPPORTED
-inline void WriteOp_JRel(JitWriter *jit)
-{
-	//jmp <offs>	;relative jump
-	cell_t cip_offs = jit->read_cell();
-
-	/* Note that since code size calculation has to be done in the same
-	 * phase as building relocation information, we cannot know the jump size
-	 * beforehand.  Thus, we always write full 32bit jumps for safety.
-	 */
-	jitoffs_t jmp = IA32_Jump_Imm32(jit, 0);
-	IA32_Write_Jump32(jit, jmp, RelocLookup(jit, cip_offs));
-}
-#endif
-
 inline void WriteOp_Jump(JitWriter *jit)
 {
 	//jmp <offs>
@@ -1508,50 +1164,6 @@ inline void WriteOp_Jneq(JitWriter *jit)
 	IA32_Jump_Cond_Imm32(jit, CC_NE, RelocLookup(jit, target, false));
 }
 
-#ifdef UNSUPPORTED
-inline void WriteOp_Jless(JitWriter *jit)
-{
-	//cmp eax, edx
-	//jb <target>
-	cell_t target = jit->read_cell();
-	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-	IA32_Jump_Cond_Imm32(jit, CC_B, RelocLookup(jit, target, false));
-}
-#endif
-
-#ifdef UNSUPPORTED
-inline void WriteOp_Jleq(JitWriter *jit)
-{
-	//cmp eax, edx
-	//jbe <target>
-	cell_t target = jit->read_cell();
-	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-	IA32_Jump_Cond_Imm32(jit, CC_BE, RelocLookup(jit, target, false));
-}
-#endif
-
-#ifdef UNSUPPORTED
-inline void WriteOp_Jgrtr(JitWriter *jit)
-{
-	//cmp eax, edx
-	//ja <target>
-	cell_t target = jit->read_cell();
-	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-	IA32_Jump_Cond_Imm32(jit, CC_A, RelocLookup(jit, target, false));
-}
-#endif
-
-#ifdef UNSUPPORTED
-inline void WriteOp_Jgeq(JitWriter *jit)
-{
-	//cmp eax, edx
-	//jae <target>
-	cell_t target = jit->read_cell();
-	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-	IA32_Jump_Cond_Imm32(jit, CC_AE, RelocLookup(jit, target, false));
-}
-#endif
-
 inline void WriteOp_Jsless(JitWriter *jit)
 {
 	//cmp eax, edx
@@ -1617,7 +1229,7 @@ jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
 	}
 }
 
-IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err)
+sp_context_t *JITX86::CompileToContext(ICompilation *co, int *err)
 {
 	CompData *data = (CompData *)co;
 	sp_plugin_t *plugin = data->plugin;
@@ -1750,7 +1362,7 @@ jit_rewind:
 
 		/* the total codesize is now known! */
 		uint32_t mem = writer.jit_curpos();
-		writer.outbase = new char[mem];
+		writer.outbase = (jitcode_t)engine->ExecAlloc(mem);
 		writer.outptr = writer.outbase;
 		/* go back for third pass */
 		goto jit_rewind;
@@ -1768,29 +1380,31 @@ jit_rewind:
 		}
 	}
 
-	/*******
-	* Context Setup
-	*******/
+	/*************
+	 * FOURTH PASS - Context Setup
+	 *************/
+
 	sp_context_t *ctx = new sp_context_t;
 	memset(ctx, 0, sizeof(sp_context_t));
 
-	ctx->base = plugin->base;
+	/* setup  basics */
+	ctx->codebase = writer.outbase;
 	ctx->plugin = plugin;
-	ctx->context = engine->CreateBaseContext(ctx);
 	ctx->vmbase = this;
 	ctx->flags = (data->debug ? SPFLAG_PLUGIN_DEBUG : 0);
 
+	/* setup memory */
 	ctx->data = new uint8_t[plugin->memory];
 	memcpy(ctx->data, plugin->data, plugin->data_size);
 	ctx->memory = plugin->memory;
 	ctx->heapbase = plugin->data_size;
-
 	ctx->hp = ctx->heapbase;
 	ctx->sp = ctx->memory - sizeof(cell_t);
 
 	const char *strbase = plugin->info.stringbase;
 	uint32_t max, iter;
 
+	/* relocate public info */
 	if ((max = plugin->info.publics_num))
 	{
 		ctx->publics = new sp_public_t[max];
@@ -1801,6 +1415,7 @@ jit_rewind:
 		}
 	}
 
+	/* relocate pubvar info */
 	if ((max = plugin->info.pubvars_num))
 	{
 		uint8_t *dat = ctx->data;
@@ -1812,21 +1427,26 @@ jit_rewind:
 		}
 	}
 
+	/* relocate native info */
 	if ((max = plugin->info.natives_num))
 	{
 		ctx->natives = new sp_native_t[max];
 		for (iter=0; iter<max; iter++)
 		{
 			ctx->natives[iter].name = strbase + plugin->info.natives[iter].name;
-			//ctx->natives[iter].pfn = SP_NoExecNative; :TODO:
+			ctx->natives[iter].pfn = NULL;
 			ctx->natives[iter].status = SP_NATIVE_NONE;
 		}
 	}
 
-	strbase = plugin->debug.stringbase;
-
-	if (plugin->flags & SP_FLAG_DEBUG)
+	/**
+	 * If we're debugging, make sure we copy the necessary info.
+	 */
+	if (data->debug)
 	{
+		strbase = plugin->debug.stringbase;
+		
+		/* relocate files */
 		max = plugin->debug.files_num;
 		ctx->files = new sp_debug_file_t[max];
 		for (iter=0; iter<max; iter++)
@@ -1835,6 +1455,7 @@ jit_rewind:
 			ctx->files[iter].name = strbase + plugin->debug.files[iter].name;
 		}
 
+		/* relocate lines */
 		max = plugin->debug.lines_num;
 		ctx->lines = new sp_debug_line_t[max];
 		for (iter=0; iter<max; iter++)
@@ -1843,6 +1464,7 @@ jit_rewind:
 			ctx->lines[iter].line = plugin->debug.lines[iter].line;
 		}
 
+		/* relocate arrays */
 		sp_fdbg_symbol_t *sym;
 		sp_fdbg_arraydim_t *arr;
 		uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
@@ -1872,9 +1494,13 @@ jit_rewind:
 		}
 	}
 
+	/* clean up relocation+compilation memory */
+	engine->BaseFree(data->rebase);
+	delete data;
+
 	*err = SP_ERR_NONE;
 
-	return ctx->context;
+	return ctx;
 }
 
 const char *JITX86::GetVMName()
@@ -1882,6 +1508,26 @@ const char *JITX86::GetVMName()
 	return "JIT (x86)";
 }
 
+int JITX86::ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result)
+{
+	typedef int (*CONTEXT_EXECUTE)(sp_context_t *, uint32_t, cell_t *);
+	CONTEXT_EXECUTE fn = (CONTEXT_EXECUTE)ctx->codebase;
+	return fn(ctx, code_idx, result);
+}
+
+void JITX86::FreeContext(sp_context_t *ctx)
+{
+	engine->ExecFree(ctx->codebase);
+	delete [] ctx->data;
+	delete [] ctx->files;
+	delete [] ctx->lines;
+	delete [] ctx->natives;
+	delete [] ctx->publics;
+	delete [] ctx->pubvars;
+	delete [] ctx->symbols;
+	delete ctx;
+}
+
 ICompilation *JITX86::StartCompilation(sp_plugin_t *plugin)
 {
 	CompData *data = new CompData;
diff --git a/sourcepawn/vm/jit/x86/jit_x86.h b/sourcepawn/vm/jit/x86/jit_x86.h
index 01febc4f..a3a08322 100644
--- a/sourcepawn/vm/jit/x86/jit_x86.h
+++ b/sourcepawn/vm/jit/x86/jit_x86.h
@@ -42,9 +42,9 @@ public:
 	const char *GetVMName() =0;
 	ICompilation *StartCompilation(sp_plugin_t *plugin);
 	bool SetCompilationOption(ICompilation *co, const char *key, const char *val) ;
-	IPluginContext *CompileToContext(ICompilation *co, int *err);
+	sp_context_t *CompileToContext(ICompilation *co, int *err);
 	void AbortCompilation(ICompilation *co);
-	void FreeContextVars(sp_context_t *ctx);
+	void FreeContext(sp_context_t *ctx);
 	int ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result);
 };
 
diff --git a/sourcepawn/vm/jit/x86/msvc8/jit-x86.vcproj b/sourcepawn/vm/jit/x86/msvc8/jit-x86.vcproj
index 1f3f4973..f7e0b79c 100644
--- a/sourcepawn/vm/jit/x86/msvc8/jit-x86.vcproj
+++ b/sourcepawn/vm/jit/x86/msvc8/jit-x86.vcproj
@@ -213,6 +213,10 @@
 				RelativePath="..\opcode_helpers.h"
 				>
 			</File>
+			<File
+				RelativePath="..\ungen_opcodes.h"
+				>
+			</File>
 			<File
 				RelativePath="..\x86_macros.h"
 				>
@@ -227,6 +231,10 @@
 				RelativePath="..\opcode_switch.inc"
 				>
 			</File>
+			<File
+				RelativePath="..\ungen_opcode_switch.inc"
+				>
+			</File>
 		</Filter>
 		<Filter
 			Name="SDK"
diff --git a/sourcepawn/vm/jit/x86/opcode_helpers.cpp b/sourcepawn/vm/jit/x86/opcode_helpers.cpp
index f6c2d3ff..809567bf 100644
--- a/sourcepawn/vm/jit/x86/opcode_helpers.cpp
+++ b/sourcepawn/vm/jit/x86/opcode_helpers.cpp
@@ -6,7 +6,7 @@
 
 int OpAdvTable[OP_NUM_OPCODES];
 
-jitoffs_t Write_Execute_Function(JitWriter *jit, bool never_inline)
+jitoffs_t Write_Execute_Function(JitWriter *jit)
 {
 	/** 
 	 * The variables we're passed in:
@@ -79,7 +79,7 @@ jitoffs_t Write_Execute_Function(JitWriter *jit, bool never_inline)
 	//mov edx, [eax+<offs>]	- get alt
 	//mov eax, [eax+<offs>] - get pri
 	IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EBP, 12);
-	IA32_Add_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, base));
+	IA32_Add_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, codebase));
 	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, REG_EAX, offsetof(sp_context_t, alt));
 	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, REG_EAX, offsetof(sp_context_t, pri));
 
@@ -503,7 +503,6 @@ JITX86::JITX86()
 	OpAdvTable[OP_LREF_ALT] = sizeof(cell_t);
 	OpAdvTable[OP_LREF_S_PRI] = sizeof(cell_t);
 	OpAdvTable[OP_LREF_S_ALT] = sizeof(cell_t);
-	OpAdvTable[OP_LODB_I] = sizeof(cell_t);
 	OpAdvTable[OP_CONST_PRI] = sizeof(cell_t);
 	OpAdvTable[OP_CONST_ALT] = sizeof(cell_t);
 	OpAdvTable[OP_ADDR_PRI] = sizeof(cell_t);
@@ -516,19 +515,13 @@ JITX86::JITX86()
 	OpAdvTable[OP_SREF_ALT] = sizeof(cell_t);
 	OpAdvTable[OP_SREF_S_PRI] = sizeof(cell_t);
 	OpAdvTable[OP_SREF_S_ALT] = sizeof(cell_t);
-	OpAdvTable[OP_STRB_I] = sizeof(cell_t);
 	OpAdvTable[OP_LIDX_B] = sizeof(cell_t);
 	OpAdvTable[OP_IDXADDR_B] = sizeof(cell_t);
-	OpAdvTable[OP_ALIGN_PRI] = sizeof(cell_t);
-	OpAdvTable[OP_ALIGN_ALT] = sizeof(cell_t);
-	OpAdvTable[OP_LCTRL] = sizeof(cell_t);
-	OpAdvTable[OP_SCTRL] = sizeof(cell_t);
 	OpAdvTable[OP_PUSH_C] = sizeof(cell_t);
 	OpAdvTable[OP_PUSH] = sizeof(cell_t);
 	OpAdvTable[OP_PUSH_S] = sizeof(cell_t);
 	OpAdvTable[OP_STACK] = sizeof(cell_t);
 	OpAdvTable[OP_HEAP] = sizeof(cell_t);
-	OpAdvTable[OP_JREL] = sizeof(cell_t);
 	OpAdvTable[OP_SHL_C_PRI] = sizeof(cell_t);
 	OpAdvTable[OP_SHL_C_ALT] = sizeof(cell_t);
 	OpAdvTable[OP_SHR_C_PRI] = sizeof(cell_t);
@@ -544,7 +537,6 @@ JITX86::JITX86()
 	OpAdvTable[OP_DEC] = sizeof(cell_t);
 	OpAdvTable[OP_DEC_S] = sizeof(cell_t);
 	OpAdvTable[OP_MOVS] = sizeof(cell_t);
-	OpAdvTable[OP_CMPS] = sizeof(cell_t);
 	OpAdvTable[OP_FILL] = sizeof(cell_t);
 	OpAdvTable[OP_HALT] = sizeof(cell_t);
 	OpAdvTable[OP_BOUNDS] = sizeof(cell_t);
@@ -574,9 +566,6 @@ JITX86::JITX86()
 	OpAdvTable[OP_SMUL] = 0;
 	OpAdvTable[OP_SDIV] = 0;
 	OpAdvTable[OP_SDIV_ALT] = 0;
-	OpAdvTable[OP_UMUL] = 0;
-	OpAdvTable[OP_UDIV] = 0;
-	OpAdvTable[OP_UDIV_ALT] = 0;
 	OpAdvTable[OP_ADD] = 0;
 	OpAdvTable[OP_SUB] = 0;
 	OpAdvTable[OP_SUB_ALT] = 0;
@@ -592,10 +581,6 @@ JITX86::JITX86()
 	OpAdvTable[OP_SIGN_ALT] = 0;
 	OpAdvTable[OP_EQ] = 0;
 	OpAdvTable[OP_NEQ] = 0;
-	OpAdvTable[OP_LESS] = 0;
-	OpAdvTable[OP_LEQ] = 0;
-	OpAdvTable[OP_GRTR] = 0;
-	OpAdvTable[OP_GEQ] = 0;
 	OpAdvTable[OP_SLESS] = 0;
 	OpAdvTable[OP_SLEQ] = 0;
 	OpAdvTable[OP_SGRTR] = 0;
@@ -622,10 +607,6 @@ JITX86::JITX86()
 	OpAdvTable[OP_JNZ] = -2;
 	OpAdvTable[OP_JEQ] = -2;
 	OpAdvTable[OP_JNEQ] = -2;
-	OpAdvTable[OP_JLESS] = -2;
-	OpAdvTable[OP_JLEQ] = -2;
-	OpAdvTable[OP_JGRTR] = -2;
-	OpAdvTable[OP_JGEQ] = -2;
 	OpAdvTable[OP_JSLESS] = -2;
 	OpAdvTable[OP_JSLEQ] = -2;
 	OpAdvTable[OP_JSGRTR] = -2;
@@ -633,6 +614,7 @@ JITX86::JITX86()
 	OpAdvTable[OP_SWITCH] = -2;
 
 	/* opcodes that are totally invalid */
+	/* :TODO: make an alternate table if USE_UNGEN_OPCODES is on? */
 	OpAdvTable[OP_FILE] = -3;
 	OpAdvTable[OP_SYMBOL] = -3;
 	OpAdvTable[OP_LINE] = -3;
@@ -641,4 +623,24 @@ JITX86::JITX86()
 	OpAdvTable[OP_SYSREQ_D] = -3;
 	OpAdvTable[OP_SYSREQ_ND] = -3;
 	OpAdvTable[OP_PUSH_R] = -3;
+	OpAdvTable[OP_LODB_I] = -3;
+	OpAdvTable[OP_STRB_I] = -3;
+	OpAdvTable[OP_LCTRL] = -3;
+	OpAdvTable[OP_SCTRL] = -3;
+	OpAdvTable[OP_ALIGN_PRI] = -3;
+	OpAdvTable[OP_ALIGN_ALT] = -3;
+	OpAdvTable[OP_JREL] = -3;
+	OpAdvTable[OP_CMPS] = -3;
+	OpAdvTable[OP_UMUL] = -3;
+	OpAdvTable[OP_UDIV] = -3;
+	OpAdvTable[OP_UDIV_ALT] = -3;
+	OpAdvTable[OP_LESS] = -3;
+	OpAdvTable[OP_LEQ] = -3;
+	OpAdvTable[OP_GRTR] = -3;
+	OpAdvTable[OP_GEQ] = -3;
+	OpAdvTable[OP_JLESS] = -3;
+	OpAdvTable[OP_JLEQ] = -3;
+	OpAdvTable[OP_JGRTR] = -3;
+	OpAdvTable[OP_JGEQ] = -3;
+
 }
diff --git a/sourcepawn/vm/jit/x86/opcode_helpers.h b/sourcepawn/vm/jit/x86/opcode_helpers.h
index d5b024c5..20388dd2 100644
--- a/sourcepawn/vm/jit/x86/opcode_helpers.h
+++ b/sourcepawn/vm/jit/x86/opcode_helpers.h
@@ -63,12 +63,12 @@ typedef enum
 	OP_LOAD_ALT,			//DONE
 	OP_LOAD_S_PRI,			//DONE
 	OP_LOAD_S_ALT,			//DONE
-	OP_LREF_PRI,			//UNSUPPORTED
-	OP_LREF_ALT,			//UNSUPPORTED
-	OP_LREF_S_PRI,			//UNSUPPORTED
-	OP_LREF_S_ALT,			//UNSUPPORTED
+	OP_LREF_PRI,			// !GEN :TODO: we will need this for dynarrays
+	OP_LREF_ALT,			// !GEN :TODO: we will need this for dynarrays
+	OP_LREF_S_PRI,			//DONE 
+	OP_LREF_S_ALT,			//DONE
 	OP_LOAD_I,				//DONE
-	OP_LODB_I,				//UNSUPPORTED
+	OP_LODB_I,				// !GEN :TODO: - only used for pack access - drop support in compiler first
 	OP_CONST_PRI,			//DONE
 	OP_CONST_ALT,			//DONE
 	OP_ADDR_PRI,			//DONE
@@ -77,26 +77,26 @@ typedef enum
 	OP_STOR_ALT,			//DONE
 	OP_STOR_S_PRI,			//DONE
 	OP_STOR_S_ALT,			//DONE
-	OP_SREF_PRI,			//UNSUPPORTED
-	OP_SREF_ALT,			//UNSUPPORTED
-	OP_SREF_S_PRI,			//UNSUPPORTED
-	OP_SREF_S_ALT,			//UNSUPPORTED
+	OP_SREF_PRI,			//DONE
+	OP_SREF_ALT,			//DONE
+	OP_SREF_S_PRI,			// !GEN :TODO: we will need this for dynarrays
+	OP_SREF_S_ALT,			// !GEN :TODO: we will need this for dynarrays
 	OP_STOR_I,				//DONE
-	OP_STRB_I,				//UNSUPPORTED
+	OP_STRB_I,				// !GEN :TODO: - only used for pack access, drop support in compiler first
 	OP_LIDX,				//DONE
-	OP_LIDX_B,				//UNSUPPORTED
+	OP_LIDX_B,				//DONE
 	OP_IDXADDR,				//DONE
-	OP_IDXADDR_B,			//UNSUPPORTED
-	OP_ALIGN_PRI,			//UNSUPPORTED
-	OP_ALIGN_ALT,			//UNSUPPORTED
-	OP_LCTRL,				//UNSUPPORTED
-	OP_SCTRL,				//UNSUPPORTED
+	OP_IDXADDR_B,			//DONE
+	OP_ALIGN_PRI,			// !GEN :TODO: - only used for pack access, drop support in compiler first
+	OP_ALIGN_ALT,			// !GEN :TODO: - only used for pack access, drop support in compiler first
+	OP_LCTRL,				// !GEN
+	OP_SCTRL,				// !GEN
 	OP_MOVE_PRI,			//DONE
 	OP_MOVE_ALT,			//DONE
 	OP_XCHG,				//DONE
 	OP_PUSH_PRI,			//DONE
 	OP_PUSH_ALT,			//DONE
-	OP_PUSH_R,				//DEPRECATED
+	OP_PUSH_R,				// !GEN DEPRECATED
 	OP_PUSH_C,				//DONE
 	OP_PUSH,				//DONE
 	OP_PUSH_S,				//DONE
@@ -105,20 +105,20 @@ typedef enum
 	OP_STACK,				//DONE
 	OP_HEAP,				//DONE
 	OP_PROC,				//DONE
-	OP_RET,					//UNSUPPORTED
+	OP_RET,					// !GEN
 	OP_RETN,				//DONE
 	OP_CALL,
-	OP_CALL_PRI,
+	OP_CALL_PRI,			// !GEN
 	OP_JUMP,				//DONE
-	OP_JREL,				//UNSUPPORTED
+	OP_JREL,				// !GEN
 	OP_JZER,				//DONE
 	OP_JNZ,					//DONE
 	OP_JEQ,					//DONE
 	OP_JNEQ,				//DONE
-	OP_JLESS,				//UNSUPPORTED
-	OP_JLEQ,				//UNSUPPORTED
-	OP_JGRTR,				//UNSUPPORTED
-	OP_JGEQ,				//UNSUPPORTED
+	OP_JLESS,				// !GEN
+	OP_JLEQ,				// !GEN
+	OP_JGRTR,				// !GEN
+	OP_JGEQ,				// !GEN
 	OP_JSLESS,				//DONE
 	OP_JSLEQ,				//DONE
 	OP_JSGRTR,				//DONE
@@ -133,9 +133,9 @@ typedef enum
 	OP_SMUL,				//DONE
 	OP_SDIV,				//DONE
 	OP_SDIV_ALT,			//DONE
-	OP_UMUL,				//UNSUPPORTED
-	OP_UDIV,				//UNSUPPORTED
-	OP_UDIV_ALT,			//UNSUPPORTED
+	OP_UMUL,				// !GEN
+	OP_UDIV,				// !GEN
+	OP_UDIV_ALT,			// !GEN
 	OP_ADD,					//DONE
 	OP_SUB,					//DONE
 	OP_SUB_ALT,				//DONE
@@ -155,10 +155,10 @@ typedef enum
 	OP_SIGN_ALT,			//DONE
 	OP_EQ,					//DONE
 	OP_NEQ,					//DONE
-	OP_LESS,				//UNSUPPORTED
-	OP_LEQ,					//UNSUPPORTED
-	OP_GRTR,				//UNSUPPORTED
-	OP_GEQ,					//UNSUPPORTED
+	OP_LESS,				// !GEN
+	OP_LEQ,					// !GEN
+	OP_GRTR,				// !GEN
+	OP_GEQ,					// !GEN
 	OP_SLESS,				//DONE
 	OP_SLEQ,				//DONE
 	OP_SGRTR,				//DONE
@@ -176,17 +176,17 @@ typedef enum
 	OP_DEC_S,				//DONE
 	OP_DEC_I,				//DONE
 	OP_MOVS,				//DONE
-	OP_CMPS,				//UNSUPPORTED
+	OP_CMPS,				// !GEN
 	OP_FILL,				//DONE
 	OP_HALT,				//DONE
 	OP_BOUNDS,				//DONE
-	OP_SYSREQ_PRI,
-	OP_SYSREQ_C,
-	OP_FILE,				//DEPRECATED
-	OP_LINE,				//DEPRECATED
-	OP_SYMBOL,				//DEPRECATED
-	OP_SRANGE,				//DEPRECATED
-	OP_JUMP_PRI,
+	OP_SYSREQ_PRI,			// !GEN
+	OP_SYSREQ_C,			
+	OP_FILE,				// !GEN DEPRECATED
+	OP_LINE,				// !GEN DEPRECATED
+	OP_SYMBOL,				// !GEN DEPRECATED
+	OP_SRANGE,				// !GEN DEPRECATED
+	OP_JUMP_PRI,			// !GEN
 	OP_SWITCH,
 	OP_CASETBL,
 	OP_SWAP_PRI,			//DONE
@@ -194,7 +194,7 @@ typedef enum
 	OP_PUSH_ADR,			//DONE
 	OP_NOP,					//DONE
 	OP_SYSREQ_N,
-	OP_SYMTAG,				//DEPRECATED
+	OP_SYMTAG,				// !GEN DEPRECATED
 	OP_BREAK,				//DONE
 	OP_PUSH2_C,				//DONE
 	OP_PUSH2,				//DONE
@@ -217,8 +217,8 @@ typedef enum
 	OP_CONST,				//DONE
 	OP_CONST_S,				//DONE
 	/* ----- */
-	OP_SYSREQ_D,			//UNSUPPORTED
-	OP_SYSREQ_ND,			//UNSUPPORTED
+	OP_SYSREQ_D,			// !GEN UNSUPPORT
+	OP_SYSREQ_ND,			// !GEN UNSUPPORT
 	/* ----- */
 	OP_HEAP_PRI,			//DONE
 	OP_PUSH_HEAP_C,			//DONE
diff --git a/sourcepawn/vm/jit/x86/opcode_switch.inc b/sourcepawn/vm/jit/x86/opcode_switch.inc
index e34bfb93..4ea20788 100644
--- a/sourcepawn/vm/jit/x86/opcode_switch.inc
+++ b/sourcepawn/vm/jit/x86/opcode_switch.inc
@@ -158,13 +158,6 @@
 				WriteOp_SMul(jit);
 				break;
 			}
-#ifdef UNSUPPORTED
-		case OP_UMUL:
-			{
-				WriteOp_UMul(jit);
-				break;
-			}
-#endif
 		case OP_ADD:
 			{
 				WriteOp_Add(jit);
@@ -245,34 +238,6 @@
 				WriteOp_Neq(jit);
 				break;
 			}
-#ifdef UNSUPPORTED
-		case OP_LESS:
-			{
-				WriteOp_Less(jit);
-				break;
-			}
-#endif
-#ifdef UNSUPPORTED
-		case OP_LEQ:
-			{
-				WriteOp_Leq(jit);
-				break;
-			}
-#endif
-#ifdef UNSUPPORTED
-		case OP_GRTR:
-			{
-				WriteOp_Grtr(jit);
-				break;
-			}
-#endif
-#ifdef UNSUPPORTED
-		case OP_GEQ:
-			{
-				WriteOp_Geq(jit);
-				break;
-			}
-#endif
 		case OP_SLESS:
 			{
 				WriteOp_Sless(jit);
@@ -373,34 +338,26 @@
 				WriteOp_Load_S_Alt(jit);
 				break;
 			}
-#ifdef UNSUPPORTED
 		case OP_LREF_PRI:
 			{
 				WriteOp_Lref_Pri(jit);
 				break;
 			}
-#endif
-#ifdef UNSUPPORTED
 		case OP_LREF_ALT:
 			{
 				WriteOp_Lref_Alt(jit);
 				break;
 			}
-#endif
-#ifdef UNSUPPORTED
 		case OP_LREF_S_PRI:
 			{
 				WriteOp_Lref_Pri(jit);
 				break;
 			}
-#endif
-#ifdef UNSUPPORTED
 		case OP_LREF_S_ALT:
 			{
 				WriteOp_Lref_Alt(jit);
 				break;
 			}
-#endif
 		case OP_CONST_PRI:
 			{
 				WriteOp_Const_Pri(jit);
@@ -446,48 +403,26 @@
 				WriteOp_Idxaddr(jit);
 				break;
 			}
-#ifdef UNSUPPORTED
 		case OP_SREF_PRI:
 			{
 				WriteOp_Sref_Pri(jit);
 				break;
 			}
-#endif
-#ifdef UNSUPPORTED
 		case OP_SREF_ALT:
 			{
 				WriteOp_Sref_Alt(jit);
 				break;
 			}
-#endif
-#ifdef UNSUPPORTED
 		case OP_SREF_S_PRI:
 			{
 				WriteOp_Sref_S_Pri(jit);
 				break;
 			}
-#endif
-#ifdef UNSUPPORTED
 		case OP_SREF_S_ALT:
 			{
 				WriteOp_Sref_S_Alt(jit);
 				break;
 			}
-#endif
-#ifdef UNSUPPORTED
-		case OP_ALIGN_PRI:
-			{
-				WriteOp_Align_Pri(jit);
-				break;
-			}
-#endif
-#ifdef UNSUPPORTED
-		case OP_ALIGN_ALT:
-			{
-				WriteOp_Align_Alt(jit);
-				break;
-			}
-#endif
 		case OP_POP_PRI:
 			{
 				WriteOp_Pop_Pri(jit);
@@ -588,58 +523,26 @@
 				WriteOp_Load_I(jit);
 				break;
 			}
-#ifdef UNSUPPORTED
-		case OP_LODB_I:
-			{
-				WriteOp_Lodb_I(jit);
-				break;
-			}
-#endif
 		case OP_STOR_I:
 			{
 				WriteOp_Stor_I(jit);
 				break;
 			}
-#ifdef UNSUPPORTED
-		case OP_STRB_I:
-			{
-				WriteOp_Strb_I(jit);
-				break;
-			}
-#endif
 		case OP_LIDX:
 			{
 				WriteOp_Lidx(jit);
 				break;
 			}
-#ifdef UNSUPPORTED
 		case OP_LIDX_B:
 			{
 				WriteOp_Lidx_B(jit);
 				break;
 			}
-#endif
-#ifdef UNSUPPORTED
 		case OP_IDXADDR_B:
 			{
 				WriteOp_Idxaddr_B(jit);
 				break;
 			}
-#endif
-#ifdef UNSUPPORTED
-		case OP_LCTRL:
-			{
-				WriteOp_Lctrl(jit);
-				break;
-			}
-#endif
-#ifdef UNSUPPORTED
-		case OP_SCTRL:
-			{
-				WriteOp_Sctrl(jit);
-				break;
-			}
-#endif
 		case OP_STACK:
 			{
 				WriteOp_Stack(jit);
@@ -660,39 +563,11 @@
 				WriteOp_SDiv_Alt(jit);
 				break;
 			}
-#ifdef UNSUPPORTED
-		case OP_UDIV:
-			{
-				WriteOp_UDiv(jit);
-				break;
-			}
-#endif
-#ifdef UNSUPPORTED
-		case OP_UDIV_ALT:
-			{
-				WriteOp_UDiv_Alt(jit);
-				break;
-			}
-#endif
-#ifdef UNSUPPORTED
-		case OP_RET:
-			{
-				WriteOp_Ret(jit);
-				break;
-			}
-#endif
 		case OP_RETN:
 			{
 				WriteOp_Retn(jit);
 				break;
 			}
-#ifdef UNSUPPORTED
-		case OP_CMPS:
-			{
-				WriteOp_Cmps(jit);
-				break;
-			}
-#endif
 		case OP_BOUNDS:
 			{
 				WriteOp_Bounds(jit);
@@ -708,13 +583,6 @@
 				WriteOp_Break(jit);
 				break;
 			}
-#ifdef UNSUPPORTED
-		case OP_JREL:
-			{
-				WriteOp_JRel(jit);
-				break;
-			}
-#endif
 		case OP_JUMP:
 			{
 				WriteOp_Jump(jit);
@@ -740,34 +608,6 @@
 				WriteOp_Jneq(jit);
 				break;
 			}
-#ifdef UNSUPPORTED
-		case OP_JLESS:
-			{
-				WriteOp_Jless(jit);
-				break;
-			}
-#endif
-#ifdef UNSUPPORTED
-		case OP_JLEQ:
-			{
-				WriteOp_Jeq(jit);
-				break;
-			}
-#endif
-#ifdef UNSUPPORTED
-		case OP_JGRTR:
-			{
-				WriteOp_Jgrtr(jit);
-				break;
-			}
-#endif
-#ifdef UNSUPPORTED
-		case OP_JGEQ:
-			{
-				WriteOp_Jgeq(jit);
-				break;
-			}
-#endif
 		case OP_JSLESS:
 			{
 				WriteOp_Jsless(jit);
@@ -778,6 +618,9 @@
 				WriteOp_Jsleq(jit);
 				break;
 			}
+#if defined USE_UNGEN_OPCODES
+		#include "ungen_opcode_switch.inc"
+#endif
 		default:
 			{
 				assert(0);
diff --git a/sourcepawn/vm/jit/x86/ungen_opcode_switch.inc b/sourcepawn/vm/jit/x86/ungen_opcode_switch.inc
new file mode 100644
index 00000000..0f9ba552
--- /dev/null
+++ b/sourcepawn/vm/jit/x86/ungen_opcode_switch.inc
@@ -0,0 +1,100 @@
+		case OP_UMUL:
+			{
+				WriteOp_UMul(jit);
+				break;
+			}
+		case OP_LESS:
+			{
+				WriteOp_Less(jit);
+				break;
+			}
+		case OP_LEQ:
+			{
+				WriteOp_Leq(jit);
+				break;
+			}
+		case OP_GRTR:
+			{
+				WriteOp_Grtr(jit);
+				break;
+			}
+		case OP_GEQ:
+			{
+				WriteOp_Geq(jit);
+				break;
+			}
+		case OP_ALIGN_PRI:
+			{
+				WriteOp_Align_Pri(jit);
+				break;
+			}
+		case OP_ALIGN_ALT:
+			{
+				WriteOp_Align_Alt(jit);
+				break;
+			}
+		case OP_LODB_I:
+			{
+				WriteOp_Lodb_I(jit);
+				break;
+			}
+		case OP_STRB_I:
+			{
+				WriteOp_Strb_I(jit);
+				break;
+			}
+		case OP_LCTRL:
+			{
+				WriteOp_Lctrl(jit);
+				break;
+			}
+		case OP_SCTRL:
+			{
+				WriteOp_Sctrl(jit);
+				break;
+			}
+		case OP_UDIV:
+			{
+				WriteOp_UDiv(jit);
+				break;
+			}
+		case OP_UDIV_ALT:
+			{
+				WriteOp_UDiv_Alt(jit);
+				break;
+			}
+		case OP_RET:
+			{
+				WriteOp_Ret(jit);
+				break;
+			}
+		case OP_CMPS:
+			{
+				WriteOp_Cmps(jit);
+				break;
+			}
+		case OP_JREL:
+			{
+				WriteOp_JRel(jit);
+				break;
+			}
+		case OP_JLESS:
+			{
+				WriteOp_Jless(jit);
+				break;
+			}
+		case OP_JLEQ:
+			{
+				WriteOp_Jeq(jit);
+				break;
+			}
+		case OP_JGRTR:
+			{
+				WriteOp_Jgrtr(jit);
+				break;
+			}
+		case OP_JGEQ:
+			{
+				WriteOp_Jgeq(jit);
+				break;
+			}
\ No newline at end of file
diff --git a/sourcepawn/vm/jit/x86/ungen_opcodes.h b/sourcepawn/vm/jit/x86/ungen_opcodes.h
new file mode 100644
index 00000000..3072db28
--- /dev/null
+++ b/sourcepawn/vm/jit/x86/ungen_opcodes.h
@@ -0,0 +1,336 @@
+#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_
+#define _INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_
+
+inline void WriteOp_UMul(JitWriter *jit)
+{
+	//mov ecx, edx
+	//mul edx
+	//mov edx, ecx
+	IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
+	IA32_Mul_Rm(jit, AMX_REG_ALT, MOD_REG);
+	IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG);
+}
+
+inline void WriteOp_Less(JitWriter *jit)
+{
+	//cmp eax, edx	; PRI < ALT ? (unsigned)
+	//mov eax, 0
+	//setb al
+	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
+	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
+	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_B);
+}
+
+inline void WriteOp_Leq(JitWriter *jit)
+{
+	//cmp eax, edx	; PRI <= ALT ? (unsigned)
+	//mov eax, 0
+	//setbe al
+	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
+	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
+	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_BE);
+}
+
+inline void WriteOp_Grtr(JitWriter *jit)
+{
+	//cmp eax, edx	; PRI > ALT ? (unsigned)
+	//mov eax, 0
+	//seta al
+	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
+	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
+	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_A);
+}
+
+inline void WriteOp_Geq(JitWriter *jit)
+{
+	//cmp eax, edx	; PRI >= ALT ? (unsigned)
+	//mov eax, 0
+	//setae al
+	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
+	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
+	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_AE);
+}
+
+inline void WriteOp_Align_Pri(JitWriter *jit)
+{
+	//xor eax, <cellsize - val>
+	cell_t val = sizeof(cell_t) - jit->read_cell();
+	if (val < SCHAR_MAX && val > SCHAR_MIN)
+		IA32_Xor_Rm_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val);
+	else
+		IA32_Xor_Eax_Imm32(jit, val);
+}
+
+inline void WriteOp_Align_Alt(JitWriter *jit)
+{
+	//xor edx, <cellsize - val>
+	cell_t val = sizeof(cell_t) - jit->read_cell();
+	if (val < SCHAR_MAX && val > SCHAR_MIN)
+		IA32_Xor_Rm_Imm8(jit, AMX_REG_ALT, MOD_REG, (jit_int8_t)val);
+	else
+		IA32_Xor_Rm_Imm32(jit, AMX_REG_ALT, MOD_REG, val);
+}
+
+inline void WriteOp_Cmps(JitWriter *jit)
+{
+	//push edi
+	//push esi
+	//lea esi, [edi+edx]
+	//lea edi, [edi+eax]
+	IA32_Push_Reg(jit, REG_EDI);
+	IA32_Push_Reg(jit, REG_ESI);
+	IA32_Lea_Reg_DispRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
+	IA32_Lea_Reg_DispRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
+
+	//xor eax, eax
+	//repe cmpsb
+	//je :cmps1
+	IA32_Xor_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG);
+	IA32_Cmpsb(jit);
+	jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_E, 0);
+
+	//sbb eax, eax
+	//sbb eax, -1
+	IA32_Sbb_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG);
+	IA32_Sbb_Eax_Imm32(jit, -1);//:TODO: use imm8 here
+
+	//:cmps1
+	//pop esi
+	//pop edi
+	IA32_Send_Jump8_Here(jit, jmp);
+	IA32_Pop_Reg(jit, REG_ESI);
+	IA32_Pop_Reg(jit, REG_EDI);
+}
+
+inline void WriteOp_Lodb_I(JitWriter *jit)
+{
+	Write_Check_VerifyAddr(jit, AMX_REG_PRI, false);
+
+	//mov eax, [edi+eax]
+	IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
+
+	//and eax, <bitmask>
+	cell_t val = jit->read_cell();
+	switch(val)
+	{
+	case 1:
+		{
+			IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x000000FF);//:TODO: replace with AND EAX, imm32
+			break;
+		}
+	case 2:
+		{
+			IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x0000FFFF);//:TODO: replace with AND EAX, imm32
+			break;
+		}
+	}
+}
+
+inline void WriteOp_Strb_I(JitWriter *jit)
+{
+	Write_Check_VerifyAddr(jit, AMX_REG_ALT, false);
+	//mov [edi+edx], eax
+	cell_t val = jit->read_cell();
+	switch (val)
+	{
+	case 1:
+		{
+			IA32_Mov_Rm8_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
+			break;
+		}
+	case 2:
+		{
+			IA32_Mov_Rm16_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
+			break;
+		}
+	case 4:
+		{
+			IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
+			break;
+		}
+	}
+}
+
+inline void WriteOp_Lctrl(JitWriter *jit)
+{
+	cell_t val = jit->read_cell();
+	switch (val)
+	{
+	case 0:
+		{
+			//mov ecx, [esi+ctx]
+			//mov eax, [ecx+<offs>]
+			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
+			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, base));
+			break;
+		}
+	case 1:
+		{
+			//mov eax, edi
+			IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG);
+			break;
+		}
+	case 2:
+		{
+			//mov eax, [esi+hea]
+			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_INFO, AMX_INFO_HEAP);
+			break;
+		}
+	case 3:
+		{
+			//mov ecx, [esi+ctx]
+			//mov eax, [ecx+ctx.memory]
+			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
+			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, memory));
+			break;
+		}
+	case 4:
+		{
+			//mov eax, ebp
+			//sub eax, edi	- unrelocate
+			IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_REG);
+			IA32_Sub_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG);
+			break;
+		}
+	case 5:
+		{
+			//mov eax, [esi+frm]
+			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_INFO, AMX_INFO_FRM);
+			break;
+		}
+	case 6:
+		{
+			//mov eax, [cip]
+			jitoffs_t imm32 = IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
+			jitoffs_t save = jit->jit_curpos();
+			jit->setpos(imm32);
+			jit->write_int32((uint32_t)(jit->outbase + save));
+			jit->setpos(save);
+			break;
+		}
+	}
+}
+
+inline void WriteOp_Sctrl(JitWriter *jit)
+{
+	cell_t val = jit->read_cell();
+	switch (val)
+	{
+	case 2:
+		{
+			//mov [esi+hea], eax
+			IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_INFO_HEAP, AMX_REG_PRI);
+			break;
+		}
+	case 4:
+		{
+			//lea ebp, [edi+eax]
+			IA32_Lea_Reg_DispRegMult(jit, AMX_REG_STK, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
+			break;
+		}
+	case 5:
+		{
+			//mov ebx, eax	- overwrite frm
+			//mov frm, eax	- overwrite stacked frame
+			//add ebx, edi	- relocate local frm //:TODO: use LEA here!!!
+			IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_PRI, MOD_REG);
+			IA32_Mov_Rm_Reg(jit, AMX_INFO_FRM, AMX_REG_PRI, MOD_MEM_REG);
+			IA32_Add_Rm_Reg(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
+			break;
+		}
+	case 6:
+		{
+			IA32_Jump_Reg(jit, AMX_REG_PRI);
+			break;
+		}
+	}
+}
+
+inline void WriteOp_UDiv(JitWriter *jit)
+{
+	//mov ecx, edx
+	//xor edx, edx
+	//div ecx
+	IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
+	IA32_Xor_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
+	Write_Check_DivZero(jit, AMX_REG_TMP);
+	IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG);
+}
+
+inline void WriteOp_UDiv_Alt(JitWriter *jit)
+{
+	//mov ecx, eax
+	//mov eax, edx
+	//xor edx, edx
+	//div ecx
+	IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
+	IA32_Mov_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
+	IA32_Xor_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
+	Write_Check_DivZero(jit, AMX_REG_TMP);
+	IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG);
+}
+
+inline void WriteOp_Ret(JitWriter *jit)
+{
+	//mov ebx, [ebp]		- get old FRM
+	//add ebp, 4			- pop stack
+	//mov [esi+frm], ebx	- restore
+	//add ebx, edi			- relocate
+	//ret
+	IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_MEM_REG);
+	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
+	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_INFO, AMX_REG_FRM, AMX_INFO_FRM);//:TODO: this is wrong!
+	IA32_Add_Rm_Reg(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
+	IA32_Return(jit);
+}
+
+inline void WriteOp_JRel(JitWriter *jit)
+{
+	//jmp <offs>	;relative jump
+	cell_t cip_offs = jit->read_cell();
+
+	/* Note that since code size calculation has to be done in the same
+	* phase as building relocation information, we cannot know the jump size
+	* beforehand.  Thus, we always write full 32bit jumps for safety.
+	*/
+	jitoffs_t jmp = IA32_Jump_Imm32(jit, 0);
+	IA32_Write_Jump32(jit, jmp, RelocLookup(jit, cip_offs));
+}
+
+inline void WriteOp_Jless(JitWriter *jit)
+{
+	//cmp eax, edx
+	//jb <target>
+	cell_t target = jit->read_cell();
+	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
+	IA32_Jump_Cond_Imm32(jit, CC_B, RelocLookup(jit, target, false));
+}
+
+inline void WriteOp_Jleq(JitWriter *jit)
+{
+	//cmp eax, edx
+	//jbe <target>
+	cell_t target = jit->read_cell();
+	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
+	IA32_Jump_Cond_Imm32(jit, CC_BE, RelocLookup(jit, target, false));
+}
+
+inline void WriteOp_Jgrtr(JitWriter *jit)
+{
+	//cmp eax, edx
+	//ja <target>
+	cell_t target = jit->read_cell();
+	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
+	IA32_Jump_Cond_Imm32(jit, CC_A, RelocLookup(jit, target, false));
+}
+
+inline void WriteOp_Jgeq(JitWriter *jit)
+{
+	//cmp eax, edx
+	//jae <target>
+	cell_t target = jit->read_cell();
+	IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
+	IA32_Jump_Cond_Imm32(jit, CC_AE, RelocLookup(jit, target, false));
+}
+
+#endif //_INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_
diff --git a/sourcepawn/vm/sp_vm_engine.cpp b/sourcepawn/vm/sp_vm_engine.cpp
index 5bae6220..fa3d2a79 100644
--- a/sourcepawn/vm/sp_vm_engine.cpp
+++ b/sourcepawn/vm/sp_vm_engine.cpp
@@ -6,8 +6,39 @@
 #include "zlib/zlib.h"
 #include "sp_vm_basecontext.h"
 
+#if defined WIN32
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+#else if defined __GNUC__
+ #include <sys/mman.h>
+#endif
+
 using namespace SourcePawn;
 
+void *SourcePawnEngine::ExecAlloc(size_t size)
+{
+#if defined WIN32
+	return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+#else if defined __GNUC__
+	void *base = memalign(sysconf(_SC_PAGESIZE), size);
+	if (mprotect(base, size, PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
+	{
+		free(base);
+		return NULL;
+	}
+	return base;
+#endif
+}
+
+void SourcePawnEngine::ExecFree(void *address)
+{
+#if defined WIN32
+	VirtualFree(address, 0, MEM_RELEASE);
+#else if defined __GNUC__
+	free(address);
+#endif
+}
+
 void *SourcePawnEngine::BaseAlloc(size_t size)
 {
 	return malloc(size);
@@ -28,7 +59,7 @@ void SourcePawnEngine::FreeBaseContext(IPluginContext *ctx)
 	sp_context_t *_ctx = ctx->GetContext();
 	IVirtualMachine *vm = ctx->GetVirtualMachine();
 	
-	vm->FreeContextVars(_ctx);
+	vm->FreeContext(_ctx);
 
 	delete ctx;
 }
diff --git a/sourcepawn/vm/sp_vm_engine.h b/sourcepawn/vm/sp_vm_engine.h
index 13b18557..66b38e6c 100644
--- a/sourcepawn/vm/sp_vm_engine.h
+++ b/sourcepawn/vm/sp_vm_engine.h
@@ -67,6 +67,22 @@ namespace SourcePawn
 		 * @param mem		Memory address to free.
 		 */
 		void BaseFree(void *memory);
+
+
+		/**
+		* Allocates executable memory.
+		*
+		* @param size		Size of memory to allocate.
+		* @return			Pointer to memory, NULL if allocation failed.
+		*/
+		void *ExecAlloc(size_t size);
+
+		/**
+		* Frees executable memory.
+		*
+		* @param mem		Address to free.
+		*/
+		void ExecFree(void *address);
 	};
 };