From 0503ac73b7e4c9ca254f1b4c43660915e63a476f Mon Sep 17 00:00:00 2001
From: David Anderson <dvander@alliedmods.net>
Date: Wed, 20 Sep 2006 15:51:05 +0000
Subject: [PATCH] implemented some more opcode

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%4081
---
 sourcepawn/vm/jit/jit_helpers.h          |   8 ++
 sourcepawn/vm/jit/x86/jit_x86.cpp        | 117 ++++++++++++++++++++++-
 sourcepawn/vm/jit/x86/jit_x86.h          |   4 +-
 sourcepawn/vm/jit/x86/opcode_helpers.cpp |   5 +
 sourcepawn/vm/jit/x86/opcode_helpers.h   |  12 +--
 sourcepawn/vm/jit/x86/x86_macros.h       |  40 ++++++++
 6 files changed, 178 insertions(+), 8 deletions(-)

diff --git a/sourcepawn/vm/jit/jit_helpers.h b/sourcepawn/vm/jit/jit_helpers.h
index 5b74ce65..e7d79084 100644
--- a/sourcepawn/vm/jit/jit_helpers.h
+++ b/sourcepawn/vm/jit/jit_helpers.h
@@ -63,6 +63,14 @@ public:
 		}
 		outptr += sizeof(jit_int32_t);
 	}
+	inline void write_uint32(jit_uint32_t c)
+	{
+		if (outptr)
+		{
+			*(jit_uint32_t *)outptr = c;
+		}
+		outptr += sizeof(jit_uint32_t);
+	}
 	inline jitoffs_t jit_curpos()
 	{
 		return (outptr - outbase);
diff --git a/sourcepawn/vm/jit/x86/jit_x86.cpp b/sourcepawn/vm/jit/x86/jit_x86.cpp
index e7cc2885..ba292178 100644
--- a/sourcepawn/vm/jit/x86/jit_x86.cpp
+++ b/sourcepawn/vm/jit/x86/jit_x86.cpp
@@ -755,6 +755,15 @@ inline void WriteOp_Idxaddr(JitWriter *jit)
 	IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
 }
 
+inline void WriteOp_Idxaddr_B(JitWriter *jit)
+{
+	cell_t val = jit->read_cell();
+	//shl eax, <val>
+	//add eax, edx
+	IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG);
+	IA32_Add_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
+}
+
 inline void WriteOp_Sref_Pri(JitWriter *jit)
 {
 	//mov ecx, [edi+<val>]
@@ -1003,10 +1012,86 @@ inline void WriteOp_Const_S(JitWriter *jit)
 inline void WriteOp_Load_I(JitWriter *jit)
 {
 	//mov eax, [edi+eax]
-	Write_Check_VerifyAddr(jit, REG_EAX, false);
+	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_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);
+			break;
+		}
+	case 2:
+		{
+			IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x0000FFFF);
+			break;
+		}
+	}
+}
+
+inline void WriteOp_Stor_I(JitWriter *jit)
+{
+	//mov [edi+edx], eax
+	Write_Check_VerifyAddr(jit, AMX_REG_ALT, false);
+	IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
+}
+
+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 3:
+		{
+			IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
+			break;
+		}
+	}
+}
+
+inline void WriteOp_Lidx(JitWriter *jit)
+{
+	//lea eax, [edx+4*eax]
+	//mov eax, [edi+eax]
+	IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
+	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_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, 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);
+}
 
 /*************************************************
  *************************************************
@@ -1667,6 +1752,36 @@ IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err)
 				WriteOp_Load_I(jit);
 				break;
 			}
+		case OP_LODB_I:
+			{
+				WriteOp_Lodb_I(jit);
+				break;
+			}
+		case OP_STOR_I:
+			{
+				WriteOp_Stor_I(jit);
+				break;
+			}
+		case OP_STRB_I:
+			{
+				WriteOp_Strb_I(jit);
+				break;
+			}
+		case OP_LIDX:
+			{
+				WriteOp_Lidx(jit);
+				break;
+			}
+		case OP_LIDX_B:
+			{
+				WriteOp_Lidx_B(jit);
+				break;
+			}
+		case OP_IDXADDR_B:
+			{
+				WriteOp_Idxaddr_B(jit);
+				break;
+			}
 		default:
 			{
 				AbortCompilation(co);
diff --git a/sourcepawn/vm/jit/x86/jit_x86.h b/sourcepawn/vm/jit/x86/jit_x86.h
index 0eb22f8f..5e53ee33 100644
--- a/sourcepawn/vm/jit/x86/jit_x86.h
+++ b/sourcepawn/vm/jit/x86/jit_x86.h
@@ -13,7 +13,8 @@ using namespace SourcePawn;
 class CompData : public ICompilation
 {
 public:
-	CompData() : plugin(NULL), debug(false), inline_level(3)
+	CompData() : plugin(NULL), 
+		debug(false), inline_level(3), checks(true)
 	{
 	};
 public:
@@ -22,6 +23,7 @@ public:
 	jitoffs_t jit_verify_addr_eax;
 	jitoffs_t jit_verify_addr_edx;
 	int inline_level;
+	bool checks;
 	bool debug;
 };
 
diff --git a/sourcepawn/vm/jit/x86/opcode_helpers.cpp b/sourcepawn/vm/jit/x86/opcode_helpers.cpp
index 0b5180f9..df8bde71 100644
--- a/sourcepawn/vm/jit/x86/opcode_helpers.cpp
+++ b/sourcepawn/vm/jit/x86/opcode_helpers.cpp
@@ -147,6 +147,11 @@ void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg, bool firstcall)
 	 * The old JIT did not.
 	 */
 
+	if (!data->checks)
+	{
+		return;
+	}
+
 	bool call = false;
 	if (!(data->inline_level & JIT_INLINE_ERRORCHECKS))
 	{
diff --git a/sourcepawn/vm/jit/x86/opcode_helpers.h b/sourcepawn/vm/jit/x86/opcode_helpers.h
index 7cb8efd5..3fbc6801 100644
--- a/sourcepawn/vm/jit/x86/opcode_helpers.h
+++ b/sourcepawn/vm/jit/x86/opcode_helpers.h
@@ -42,7 +42,7 @@ typedef enum
 	OP_LREF_S_PRI,			//DONE
 	OP_LREF_S_ALT,			//DONE
 	OP_LOAD_I,				//DONE
-	OP_LODB_I,
+	OP_LODB_I,				//DONE
 	OP_CONST_PRI,			//DONE
 	OP_CONST_ALT,			//DONE
 	OP_ADDR_PRI,			//DONE
@@ -55,12 +55,12 @@ typedef enum
 	OP_SREF_ALT,			//DONE
 	OP_SREF_S_PRI,			//DONE
 	OP_SREF_S_ALT,			//DONE
-	OP_STOR_I,
-	OP_STRB_I,
-	OP_LIDX,
-	OP_LIDX_B,
+	OP_STOR_I,				//DONE
+	OP_STRB_I,				//DONE
+	OP_LIDX,				//DONE
+	OP_LIDX_B,				//DONE
 	OP_IDXADDR,				//DONE
-	OP_IDXADDR_B,
+	OP_IDXADDR_B,			//DONE
 	OP_ALIGN_PRI,			//DONE
 	OP_ALIGN_ALT,			//DONE
 	OP_LCTRL,
diff --git a/sourcepawn/vm/jit/x86/x86_macros.h b/sourcepawn/vm/jit/x86/x86_macros.h
index 067e6620..d12b86df 100644
--- a/sourcepawn/vm/jit/x86/x86_macros.h
+++ b/sourcepawn/vm/jit/x86/x86_macros.h
@@ -25,6 +25,8 @@
 #define REG_ESI		6
 #define REG_EDI		7
 
+#define IA32_16BIT_PREFIX	0x66
+
 //condition codes (for example, Jcc opcodes)
 #define CC_B	0x2
 #define CC_NAE	CC_B
@@ -65,6 +67,7 @@
 #define IA32_CALL_IMM32			0xE8	// relative call, <imm32>
 #define IA32_CALL_RM			0xFF	// encoding is /2
 #define IA32_MOV_REG_IMM		0xB8	// encoding is +r <imm32>
+#define	IA32_MOV_RM8_REG		0x88	// encoding is /r
 #define	IA32_MOV_RM_REG			0x89	// encoding is /r
 #define	IA32_MOV_REG_MEM		0x8B	// encoding is /r
 #define IA32_MOV_RM_IMM32		0xC7	// encoding is /0
@@ -83,6 +86,8 @@
 #define IA32_DEC_RM				0xFF	// encoding is /1
 #define IA32_OR_RM_REG			0x09	// encoding is /r
 #define IA32_AND_RM_REG			0x21	// encoding is /r
+#define IA32_AND_EAX_IMM32		0x25	// encoding is <imm32>
+#define IA32_AND_RM_IMM32		0x81	// encoding is /4
 #define IA32_NOT_RM				0xF7	// encoding is /2
 #define IA32_DIV_RM				0xF7	// encoding is /6
 #define IA32_MUL_RM				0xF7	// encoding is /4
@@ -238,6 +243,18 @@ inline void IA32_And_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, j
 	jit->write_ubyte(ia32_modrm(mode, src, dest));
 }
 
+inline void IA32_And_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_uint32_t c)
+{
+	if (reg == REG_EAX)
+	{
+		jit->write_ubyte(IA32_AND_EAX_IMM32);
+	} else {
+		jit->write_ubyte(IA32_AND_RM_IMM32);
+		jit->write_ubyte(ia32_modrm(MOD_REG, 4, reg));
+	}
+	jit->write_uint32(c);
+}
+
 inline void IA32_Not_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode)
 {
 	jit->write_ubyte(IA32_NOT_RM);
@@ -606,6 +623,29 @@ inline void IA32_Mov_Rm_Reg_Disp_Reg(JitWriter *jit,
 	jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base));
 }
 
+inline void IA32_Mov_Rm8_Reg_Disp_Reg(JitWriter *jit, 
+									 jit_uint8_t dest_base, 
+									 jit_uint8_t dest_index,
+									 jit_uint8_t dest_scale,
+									 jit_uint8_t src)
+{
+	jit->write_ubyte(IA32_MOV_RM8_REG);
+	jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src, REG_SIB));
+	jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base));
+}
+
+inline void IA32_Mov_Rm16_Reg_Disp_Reg(JitWriter *jit, 
+									  jit_uint8_t dest_base, 
+									  jit_uint8_t dest_index,
+									  jit_uint8_t dest_scale,
+									  jit_uint8_t src)
+{
+	jit->write_ubyte(IA32_16BIT_PREFIX);
+	jit->write_ubyte(IA32_MOV_RM_REG);
+	jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src, REG_SIB));
+	jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base));
+}
+
 /**
  * Moving from IMMEDIATE to REGISTER
  */