sourcepawn/vm/jit/x86/opcode_helpers.cpp
author David Anderson <dvander@alliedmods.net>
Wed Sep 20 07:07:49 2006 +0000 (2006-09-20)
changeset 74 935d64738275
parent 73 9d08f3f63830
child 75 55682fa202ea
permissions -rw-r--r--
Wrote the JIT execution function
Solidified some more code
     1 #include <limits.h>
     2 #include <string.h>
     3 #include "jit_x86.h"
     4 #include "opcode_helpers.h"
     5 #include "x86_macros.h"
     6 
     7 int OpAdvTable[OP_NUM_OPCODES];
     8 
     9 jitoffs_t Write_Execute_Function(JitWriter *jit, bool never_inline)
    10 {
    11 	/** 
    12 	 * The state expected by our plugin is:
    13 	 * #define AMX_REG_PRI		REG_EAX		(done)
    14 	   #define AMX_REG_ALT		REG_EDX		(done)
    15 	   #define AMX_REG_STK		REG_EBP		(done)
    16 	   #define AMX_REG_DAT		REG_EDI		(done)
    17 	   #define AMX_REG_TMP		REG_ECX		(nothing)
    18 	   #define AMX_REG_INFO		REG_ESI		(done)
    19 	   #define AMX_REG_FRM		REG_EBX		(done)
    20 	   #define AMX_INFO_FRM		AMX_REG_INFO	(done)
    21 	   #define AMX_INFO_HEAP	4			(done)
    22 	   #define AMX_INFO_RETVAL	8			(done)
    23 	   #define AMX_INFO_CONTEXT	12			(done)
    24 	 *
    25 	 * The variables we're passed in:
    26 	 *  sp_context_t *ctx, uint32_t code_idx, cell_t *result
    27 	 */
    28 
    29 	/**
    30 	 * !NOTE!
    31 	 * Currently, we do not accept ctx->frm as the new frame pointer.
    32 	 * Instead, we copy the frame from the stack pointer.
    33 	 * This is because we do not support resuming or sleeping!
    34 	 */
    35 
    36 	//push ebp
    37 	//mov ebp, esp
    38 	IA32_Push_Reg(jit, REG_EBP);
    39 	IA32_Mov_Reg_Rm(jit, REG_EBP, REG_ESP, MOD_REG);
    40 
    41 	//push esi
    42 	//push edi
    43 	//push ebx
    44 	IA32_Push_Reg(jit, REG_ESI);
    45 	IA32_Push_Reg(jit, REG_EDI);
    46 	IA32_Push_Reg(jit, REG_EBX);
    47 
    48 	//sub esp, 4*4	- allocate info array
    49 	//mov esi, esp	- save info pointer
    50 	IA32_Sub_Rm_Imm8(jit, REG_ESP, 4*4, MOD_REG);
    51 	IA32_Mov_Reg_Rm(jit, AMX_REG_INFO, REG_ESP, MOD_REG);
    52 
    53 	//mov eax, [ebp+16]	- get result pointer
    54 	//mov [esi+8], eax	- store into info pointer
    55 	IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 16);
    56 	IA32_Mov_Rm_Reg_Disp8(jit, REG_ESI, REG_EAX, AMX_INFO_RETVAL);
    57 
    58 	//mov eax, [ebp+8]		- get context
    59 	//mov [esi+12], eax		- store context into info pointer
    60 	//mov ecx, [eax+<offs>]	- get heap pointer
    61 	//mov [esi+4], ecx		- store heap into info pointer
    62 	//mov edi, [eax+<offs>]	- get data pointer
    63 	IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 8);
    64 	IA32_Mov_Rm_Reg_Disp8(jit, REG_ESI, REG_EAX, AMX_INFO_CONTEXT);
    65 	IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, hp));
    66 	IA32_Mov_Rm_Reg_Disp8(jit, REG_ESI, REG_ECX, AMX_INFO_HEAP);
    67 	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_DAT, REG_EAX, offsetof(sp_context_t, data));
    68 
    69 	//mov ebp, [eax+<offs>]	- get stack pointer
    70 	//add ebp, edi			- relocate to data section
    71 	//mov ebx, ebp			- copy sp to frm
    72 	//mov ecx, [ebp+12]		- get code index
    73 	//add ecx, [eax+<offs>] - add code base to index
    74 	//mov edx, [eax+<offs>]	- get alt
    75 	//mov eax, [eax+<offs>] - get pri
    76 	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_STK, REG_EAX, offsetof(sp_context_t, sp));
    77 	IA32_Add_Rm_Reg(jit, REG_EBP, AMX_REG_STK, AMX_REG_DAT);
    78 	IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG);
    79 	IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EBP, 12);
    80 	IA32_Add_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, base));
    81 	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, REG_EAX, offsetof(sp_context_t, alt));
    82 	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, REG_EAX, offsetof(sp_context_t, pri));
    83 
    84 	/* by now, everything is set up, so we can call into the plugin */
    85 
    86 	//call ecx
    87 	IA32_Call_Rm(jit, REG_ECX);
    88 
    89 	/* if the code flow gets to here, there was a normal return */
    90 	//mov ebp, [esi+8]		- get retval pointer
    91 	//mov [ebp], eax		- store retval from PRI
    92 	//mov eax, SP_ERR_NONE	- set no error
    93 	IA32_Mov_Reg_Rm_Disp8(jit, REG_EBP, AMX_REG_INFO, AMX_INFO_RETVAL);
    94 	IA32_Mov_Rm_Reg(jit, REG_EBP, AMX_REG_PRI, MOD_MEM_REG);
    95 	IA32_Mov_Reg_Imm32(jit, REG_EAX, SP_ERR_NONE);
    96 
    97 	/* where error checking/return functions should go to */
    98 	jitoffs_t offs_return;
    99 	if (never_inline)
   100 	{
   101 		/* We have to write code assume we're breaking out of a call */
   102 		//jmp [past the next instruction]
   103 		//add esp, 4
   104 		jitoffs_t offs = IA32_Jump_Imm8(jit, 0);
   105 		offs_return = jit->jit_curpos();
   106 		IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
   107 		IA32_Send_Jump8_Here(jit, offs);
   108 	} else {
   109 		offs_return = jit->jit_curpos();
   110 	}
   111 
   112 	/* _FOR NOW_ ... 
   113 	 * We are _not_ going to restore anything that was on the stack.
   114 	 * This is a tiny, useless optimization based on the fact that 
   115 	 * BaseContext::Execute() automatically restores our values anyway.
   116 	 */
   117 
   118 	//add esp, 4*4
   119 	//pop ebx
   120 	//pop edi
   121 	//pop esi
   122 	//pop ebp
   123 	//ret
   124 	IA32_Add_Rm_Imm8(jit, REG_ESP, 4*4, MOD_REG);
   125 	IA32_Pop_Reg(jit, REG_EBX);
   126 	IA32_Pop_Reg(jit, REG_EDI);
   127 	IA32_Pop_Reg(jit, REG_ESI);
   128 	IA32_Pop_Reg(jit, REG_EBP);
   129 	IA32_Return(jit);
   130 
   131 	return offs_return;
   132 }
   133 
   134 void Macro_PushN_Addr(JitWriter *jit, int i)
   135 {
   136 	//push eax
   137 	//mov eax, frm
   138 	//loop i times:
   139 	// lea ecx, [eax+<val>]
   140 	// mov [ebp-4*i], ecx
   141 	//sub ebp, 4*N
   142 	//pop eax
   143 
   144 	cell_t val;
   145 	int n = 1;
   146 	IA32_Push_Reg(jit, AMX_REG_PRI);
   147 	IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_INFO_FRM, MOD_MEM_REG);
   148 	do
   149 	{
   150 		val = jit->read_cell();
   151 		if (val < SCHAR_MAX && val > SCHAR_MIN)
   152 			IA32_Lea_DispRegImm8(jit, AMX_REG_TMP, AMX_REG_PRI, (jit_int8_t)val);
   153 		else
   154 			IA32_Lea_DispRegImm32(jit, AMX_REG_TMP, AMX_REG_PRI, val);
   155 		IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4*n);
   156 	} while (n++ < i);
   157 	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
   158 	IA32_Pop_Reg(jit, AMX_REG_PRI);
   159 }
   160 
   161 void Macro_PushN_S(JitWriter *jit, int i)
   162 {
   163 	//loop i times:
   164 	// mov ecx, [ebx+<val>]
   165 	// mov [ebp-4*i], ecx
   166 	//sub ebp, 4*N
   167 
   168 	cell_t val;
   169 	int n = 1;
   170 	do 
   171 	{
   172 		val = jit->read_cell();
   173 		if (val < SCHAR_MAX && val > SCHAR_MIN)
   174 			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
   175 		else
   176 			IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
   177 		IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4*n);
   178 	} while (n++ < i);
   179 	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
   180 }
   181 
   182 void Macro_PushN_C(JitWriter *jit, int i)
   183 {
   184 	//loop i times:
   185 	// mov [ebp-4*i], <val>
   186 	//sub ebp, 4*N
   187 
   188 	int n = 1;
   189 	do 
   190 	{
   191 		IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, jit->read_cell(), -4*n);
   192 	} while (n++ < i);
   193 	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
   194 }
   195 
   196 void Macro_PushN(JitWriter *jit, int i)
   197 {
   198 	//loop i times:
   199 	// mov ecx, [edi+<val>]
   200 	// mov [ebp-4*i], ecx
   201 	//sub ebp, 4*N
   202 
   203 	cell_t val;
   204 	int n = 1;
   205 	do 
   206 	{
   207 		val = jit->read_cell();
   208 		if (val < SCHAR_MAX && val > SCHAR_MIN)
   209 			IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
   210 		else
   211 			IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
   212 		IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4*n);
   213 	} while (n++ < i);
   214 	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
   215 }
   216 
   217 JITX86::JITX86()
   218 {
   219 	memset(OpAdvTable, -1, sizeof(OpAdvTable));
   220 
   221 	/* instructions with 5 parameters */
   222 	OpAdvTable[OP_PUSH5_C] = sizeof(cell_t)*5;
   223 	OpAdvTable[OP_PUSH5] = sizeof(cell_t)*5;
   224 	OpAdvTable[OP_PUSH5_S] = sizeof(cell_t)*5;
   225 	OpAdvTable[OP_PUSH5_ADR] = sizeof(cell_t)*5;
   226 
   227 	/* instructions with 4 parameters */
   228 	OpAdvTable[OP_PUSH4_C] = sizeof(cell_t)*4;
   229 	OpAdvTable[OP_PUSH4] = sizeof(cell_t)*4;
   230 	OpAdvTable[OP_PUSH4_S] = sizeof(cell_t)*4;
   231 	OpAdvTable[OP_PUSH4_ADR] = sizeof(cell_t)*4;
   232 
   233 	/* instructions with 3 parameters */
   234 	OpAdvTable[OP_PUSH3_C] = sizeof(cell_t)*3;
   235 	OpAdvTable[OP_PUSH3] = sizeof(cell_t)*3;
   236 	OpAdvTable[OP_PUSH3_S] = sizeof(cell_t)*3;
   237 	OpAdvTable[OP_PUSH3_ADR] = sizeof(cell_t)*3;
   238 
   239 	/* instructions with 2 parameters */
   240 	OpAdvTable[OP_PUSH2_C] = sizeof(cell_t)*2;
   241 	OpAdvTable[OP_PUSH2] = sizeof(cell_t)*2;
   242 	OpAdvTable[OP_PUSH2_S] = sizeof(cell_t)*2;
   243 	OpAdvTable[OP_PUSH2_ADR] = sizeof(cell_t)*2;
   244 	OpAdvTable[OP_LOAD_BOTH] = sizeof(cell_t)*2;
   245 	OpAdvTable[OP_LOAD_S_BOTH] = sizeof(cell_t)*2;
   246 	OpAdvTable[OP_CONST] = sizeof(cell_t)*2;
   247 	OpAdvTable[OP_CONST_S] = sizeof(cell_t)*2;
   248 	OpAdvTable[OP_SYSREQ_N] = sizeof(cell_t)*2;
   249 
   250 	/* instructions with 1 parameter */
   251 	OpAdvTable[OP_LOAD_PRI] = sizeof(cell_t);
   252 	OpAdvTable[OP_LOAD_ALT] = sizeof(cell_t);
   253 	OpAdvTable[OP_LOAD_S_PRI] = sizeof(cell_t);
   254 	OpAdvTable[OP_LOAD_S_ALT] = sizeof(cell_t);
   255 	OpAdvTable[OP_LREF_PRI] = sizeof(cell_t);
   256 	OpAdvTable[OP_LREF_ALT] = sizeof(cell_t);
   257 	OpAdvTable[OP_LREF_S_PRI] = sizeof(cell_t);
   258 	OpAdvTable[OP_LREF_S_ALT] = sizeof(cell_t);
   259 	OpAdvTable[OP_LODB_I] = sizeof(cell_t);
   260 	OpAdvTable[OP_CONST_PRI] = sizeof(cell_t);
   261 	OpAdvTable[OP_CONST_ALT] = sizeof(cell_t);
   262 	OpAdvTable[OP_ADDR_PRI] = sizeof(cell_t);
   263 	OpAdvTable[OP_ADDR_ALT] = sizeof(cell_t);
   264 	OpAdvTable[OP_STOR_PRI] = sizeof(cell_t);
   265 	OpAdvTable[OP_STOR_ALT] = sizeof(cell_t);
   266 	OpAdvTable[OP_STOR_S_PRI] = sizeof(cell_t);
   267 	OpAdvTable[OP_STOR_S_ALT] = sizeof(cell_t);
   268 	OpAdvTable[OP_SREF_PRI] = sizeof(cell_t);
   269 	OpAdvTable[OP_SREF_ALT] = sizeof(cell_t);
   270 	OpAdvTable[OP_SREF_S_PRI] = sizeof(cell_t);
   271 	OpAdvTable[OP_SREF_S_ALT] = sizeof(cell_t);
   272 	OpAdvTable[OP_STRB_I] = sizeof(cell_t);
   273 	OpAdvTable[OP_LIDX_B] = sizeof(cell_t);
   274 	OpAdvTable[OP_IDXADDR_B] = sizeof(cell_t);
   275 	OpAdvTable[OP_ALIGN_PRI] = sizeof(cell_t);
   276 	OpAdvTable[OP_ALIGN_ALT] = sizeof(cell_t);
   277 	OpAdvTable[OP_LCTRL] = sizeof(cell_t);
   278 	OpAdvTable[OP_SCTRL] = sizeof(cell_t);
   279 	OpAdvTable[OP_PUSH_C] = sizeof(cell_t);
   280 	OpAdvTable[OP_PUSH] = sizeof(cell_t);
   281 	OpAdvTable[OP_PUSH_S] = sizeof(cell_t);
   282 	OpAdvTable[OP_STACK] = sizeof(cell_t);
   283 	OpAdvTable[OP_HEAP] = sizeof(cell_t);
   284 	OpAdvTable[OP_JREL] = sizeof(cell_t);
   285 	OpAdvTable[OP_SHL_C_PRI] = sizeof(cell_t);
   286 	OpAdvTable[OP_SHL_C_ALT] = sizeof(cell_t);
   287 	OpAdvTable[OP_SHR_C_PRI] = sizeof(cell_t);
   288 	OpAdvTable[OP_SHR_C_ALT] = sizeof(cell_t);
   289 	OpAdvTable[OP_ADD_C] = sizeof(cell_t);
   290 	OpAdvTable[OP_SMUL_C] = sizeof(cell_t);
   291 	OpAdvTable[OP_ZERO] = sizeof(cell_t);
   292 	OpAdvTable[OP_ZERO_S] = sizeof(cell_t);
   293 	OpAdvTable[OP_EQ_C_PRI] = sizeof(cell_t);
   294 	OpAdvTable[OP_EQ_C_ALT] = sizeof(cell_t);
   295 	OpAdvTable[OP_INC] = sizeof(cell_t);
   296 	OpAdvTable[OP_INC_S] = sizeof(cell_t);
   297 	OpAdvTable[OP_DEC] = sizeof(cell_t);
   298 	OpAdvTable[OP_DEC_S] = sizeof(cell_t);
   299 	OpAdvTable[OP_MOVS] = sizeof(cell_t);
   300 	OpAdvTable[OP_CMPS] = sizeof(cell_t);
   301 	OpAdvTable[OP_FILL] = sizeof(cell_t);
   302 	OpAdvTable[OP_HALT] = sizeof(cell_t);
   303 	OpAdvTable[OP_BOUNDS] = sizeof(cell_t);
   304 	OpAdvTable[OP_PUSH_ADR] = sizeof(cell_t);
   305 	OpAdvTable[OP_PUSH_HEAP_C] = sizeof(cell_t);
   306 	OpAdvTable[OP_SYSREQ_C] = sizeof(cell_t);
   307 
   308 	/* instructions with 0 parameters */
   309 	OpAdvTable[OP_LOAD_I] = 0;
   310 	OpAdvTable[OP_STOR_I] = 0;
   311 	OpAdvTable[OP_LIDX] = 0;
   312 	OpAdvTable[OP_IDXADDR] = 0;
   313 	OpAdvTable[OP_MOVE_PRI] = 0;
   314 	OpAdvTable[OP_MOVE_ALT] = 0;
   315 	OpAdvTable[OP_XCHG] = 0;
   316 	OpAdvTable[OP_PUSH_PRI] = 0;
   317 	OpAdvTable[OP_PUSH_ALT] = 0;
   318 	OpAdvTable[OP_POP_PRI] = 0;
   319 	OpAdvTable[OP_POP_ALT] = 0;
   320 	OpAdvTable[OP_PROC] = 0;
   321 	OpAdvTable[OP_RET] = 0;
   322 	OpAdvTable[OP_RETN] = 0;
   323 	OpAdvTable[OP_CALL_PRI] = 0;
   324 	OpAdvTable[OP_SHL] = 0;
   325 	OpAdvTable[OP_SHR] = 0;
   326 	OpAdvTable[OP_SSHR] = 0;
   327 	OpAdvTable[OP_SMUL] = 0;
   328 	OpAdvTable[OP_SDIV] = 0;
   329 	OpAdvTable[OP_SDIV_ALT] = 0;
   330 	OpAdvTable[OP_UMUL] = 0;
   331 	OpAdvTable[OP_UDIV] = 0;
   332 	OpAdvTable[OP_UDIV_ALT] = 0;
   333 	OpAdvTable[OP_ADD] = 0;
   334 	OpAdvTable[OP_SUB] = 0;
   335 	OpAdvTable[OP_SUB_ALT] = 0;
   336 	OpAdvTable[OP_AND] = 0;
   337 	OpAdvTable[OP_OR] = 0;
   338 	OpAdvTable[OP_XOR] = 0;
   339 	OpAdvTable[OP_NOT] = 0;
   340 	OpAdvTable[OP_NEG] = 0;
   341 	OpAdvTable[OP_INVERT] = 0;
   342 	OpAdvTable[OP_ZERO_PRI] = 0;
   343 	OpAdvTable[OP_ZERO_ALT] = 0;
   344 	OpAdvTable[OP_SIGN_PRI] = 0;
   345 	OpAdvTable[OP_SIGN_ALT] = 0;
   346 	OpAdvTable[OP_EQ] = 0;
   347 	OpAdvTable[OP_NEQ] = 0;
   348 	OpAdvTable[OP_LESS] = 0;
   349 	OpAdvTable[OP_LEQ] = 0;
   350 	OpAdvTable[OP_GRTR] = 0;
   351 	OpAdvTable[OP_GEQ] = 0;
   352 	OpAdvTable[OP_SLESS] = 0;
   353 	OpAdvTable[OP_SLEQ] = 0;
   354 	OpAdvTable[OP_SGRTR] = 0;
   355 	OpAdvTable[OP_SGEQ] = 0;
   356 	OpAdvTable[OP_INC_PRI] = 0;
   357 	OpAdvTable[OP_INC_ALT] = 0;
   358 	OpAdvTable[OP_INC_I] = 0;
   359 	OpAdvTable[OP_DEC_PRI] = 0;
   360 	OpAdvTable[OP_DEC_ALT] = 0;
   361 	OpAdvTable[OP_DEC_I] = 0;
   362 	OpAdvTable[OP_JUMP_PRI] = 0;
   363 	OpAdvTable[OP_SWAP_PRI] = 0;
   364 	OpAdvTable[OP_SWAP_ALT] = 0;
   365 	OpAdvTable[OP_NOP] = 0;
   366 	OpAdvTable[OP_BREAK] = 0;
   367 	OpAdvTable[OP_HEAP_PRI] = 0;
   368 	OpAdvTable[OP_POP_HEAP_PRI] = 0;
   369 	OpAdvTable[OP_SYSREQ_PRI] = 0;
   370 
   371 	/* opcodes that need relocation */
   372 	OpAdvTable[OP_CALL] = -2;
   373 	OpAdvTable[OP_JUMP] = -2;
   374 	OpAdvTable[OP_JZER] = -2;
   375 	OpAdvTable[OP_JNZ] = -2;
   376 	OpAdvTable[OP_JEQ] = -2;
   377 	OpAdvTable[OP_JNEQ] = -2;
   378 	OpAdvTable[OP_JLESS] = -2;
   379 	OpAdvTable[OP_JLEQ] = -2;
   380 	OpAdvTable[OP_JGRTR] = -2;
   381 	OpAdvTable[OP_JGEQ] = -2;
   382 	OpAdvTable[OP_JSLESS] = -2;
   383 	OpAdvTable[OP_JSLEQ] = -2;
   384 	OpAdvTable[OP_JSGRTR] = -2;
   385 	OpAdvTable[OP_JSGEQ] = -2;
   386 	OpAdvTable[OP_SWITCH] = -2;
   387 
   388 	/* opcodes that are totally invalid */
   389 	OpAdvTable[OP_FILE] = -3;
   390 	OpAdvTable[OP_SYMBOL] = -3;
   391 	OpAdvTable[OP_LINE] = -3;
   392 	OpAdvTable[OP_SRANGE] = -3;
   393 	OpAdvTable[OP_SYMTAG] = -3;
   394 	OpAdvTable[OP_SYSREQ_D] = -3;
   395 	OpAdvTable[OP_SYSREQ_ND] = -3;
   396 	OpAdvTable[OP_PUSH_R] = -3;
   397 }
   398