4 #include "opcode_helpers.h"
5 #include "x86_macros.h"
7 int OpAdvTable[OP_NUM_OPCODES];
9 jitoffs_t Write_Execute_Function(JitWriter *jit, bool never_inline)
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)
25 * The variables we're passed in:
26 * sp_context_t *ctx, uint32_t code_idx, cell_t *result
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!
38 IA32_Push_Reg(jit, REG_EBP);
39 IA32_Mov_Reg_Rm(jit, REG_EBP, REG_ESP, MOD_REG);
44 IA32_Push_Reg(jit, REG_ESI);
45 IA32_Push_Reg(jit, REG_EDI);
46 IA32_Push_Reg(jit, REG_EBX);
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);
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);
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));
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));
84 /* by now, everything is set up, so we can call into the plugin */
87 IA32_Call_Rm(jit, REG_ECX);
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);
97 /* where error checking/return functions should go to */
98 jitoffs_t offs_return;
101 /* We have to write code assume we're breaking out of a call */
102 //jmp [past the next instruction]
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);
109 offs_return = jit->jit_curpos();
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.
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);
134 void Macro_PushN_Addr(JitWriter *jit, int i)
139 // lea ecx, [eax+<val>]
140 // mov [ebp-4*i], ecx
146 IA32_Push_Reg(jit, AMX_REG_PRI);
147 IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_INFO_FRM, MOD_MEM_REG);
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);
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);
157 IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
158 IA32_Pop_Reg(jit, AMX_REG_PRI);
161 void Macro_PushN_S(JitWriter *jit, int i)
164 // mov ecx, [ebx+<val>]
165 // mov [ebp-4*i], ecx
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);
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);
179 IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
182 void Macro_PushN_C(JitWriter *jit, int i)
185 // mov [ebp-4*i], <val>
191 IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, jit->read_cell(), -4*n);
193 IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
196 void Macro_PushN(JitWriter *jit, int i)
199 // mov ecx, [edi+<val>]
200 // mov [ebp-4*i], ecx
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);
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);
214 IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG);
219 memset(OpAdvTable, -1, sizeof(OpAdvTable));
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;
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;
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;
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;
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);
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;
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;
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;