3 * ================================================================
4 * SourcePawn (C)2004-2007 AlliedModders LLC. All rights reserved.
5 * ================================================================
7 * This file is not open source and may not be copied without explicit
8 * written permission of AlliedModders LLC. This file may not be redistributed
9 * in whole or significant part.
10 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
15 #ifndef _INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_
16 #define _INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_
18 inline void WriteOp_UMul(JitWriter *jit)
23 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
24 IA32_Mul_Rm(jit, AMX_REG_ALT, MOD_REG);
25 IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG);
28 inline void WriteOp_Less(JitWriter *jit)
30 //cmp eax, edx ; PRI < ALT ? (unsigned)
33 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
34 IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
35 IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_B);
38 inline void WriteOp_Leq(JitWriter *jit)
40 //cmp eax, edx ; PRI <= ALT ? (unsigned)
43 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
44 IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
45 IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_BE);
48 inline void WriteOp_Grtr(JitWriter *jit)
50 //cmp eax, edx ; PRI > ALT ? (unsigned)
53 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
54 IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
55 IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_A);
58 inline void WriteOp_Geq(JitWriter *jit)
60 //cmp eax, edx ; PRI >= ALT ? (unsigned)
63 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
64 IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
65 IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_AE);
68 inline void WriteOp_Align_Pri(JitWriter *jit)
70 //xor eax, <cellsize - val>
71 cell_t val = sizeof(cell_t) - jit->read_cell();
72 if (val < SCHAR_MAX && val > SCHAR_MIN)
74 IA32_Xor_Rm_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val);
76 IA32_Xor_Eax_Imm32(jit, val);
80 inline void WriteOp_Align_Alt(JitWriter *jit)
82 //xor edx, <cellsize - val>
83 cell_t val = sizeof(cell_t) - jit->read_cell();
84 if (val < SCHAR_MAX && val > SCHAR_MIN)
86 IA32_Xor_Rm_Imm8(jit, AMX_REG_ALT, MOD_REG, (jit_int8_t)val);
88 IA32_Xor_Rm_Imm32(jit, AMX_REG_ALT, MOD_REG, val);
92 inline void WriteOp_Cmps(JitWriter *jit)
99 unsigned int val = jit->read_cell();
101 IA32_Push_Reg(jit, REG_EDI);
102 IA32_Push_Reg(jit, REG_ESI);
103 IA32_Lea_Reg_DispEBPRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
104 IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
105 IA32_Mov_Reg_Imm32(jit, REG_ECX, val);
110 IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
113 jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_E, 0);
117 IA32_Sbb_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
118 IA32_Sbb_Rm_Imm8(jit, AMX_REG_PRI, -1, MOD_REG);
123 IA32_Send_Jump8_Here(jit, jmp);
124 IA32_Pop_Reg(jit, REG_ESI);
125 IA32_Pop_Reg(jit, REG_EDI);
128 inline void WriteOp_Lctrl(JitWriter *jit)
130 cell_t val = jit->read_cell();
136 //mov eax, [ecx+ctx.codebase]
137 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
138 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, codebase));
144 IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG);
150 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_INFO, AMX_INFO_HEAP);
156 //mov eax, [ecx+ctx.memory]
157 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
158 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, memory));
164 //sub eax, ebp - unrelocate
165 IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_REG);
166 IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG);
172 IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG);
178 jitoffs_t imm32 = IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
179 jitoffs_t save = jit->get_outputpos();
180 jit->set_outputpos(imm32);
181 jit->write_int32((uint32_t)(jit->outbase + save));
182 jit->set_outputpos(save);
188 inline void WriteOp_Sctrl(JitWriter *jit)
190 cell_t val = jit->read_cell();
196 IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_PRI, AMX_INFO_HEAP);
202 IA32_Lea_Reg_DispEBPRegMult(jit, AMX_REG_STK, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
207 //lea ebx, [ebp+eax] - overwrite frm
208 //mov [esi+frm], eax - overwrite stacked frame
209 IA32_Lea_Reg_DispEBPRegMult(jit, AMX_REG_FRM, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
210 IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_PRI, MOD_MEM_REG);
215 IA32_Jump_Reg(jit, AMX_REG_PRI);
221 inline void WriteOp_UDiv(JitWriter *jit)
226 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
227 IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
228 Write_Check_DivZero(jit, AMX_REG_TMP);
229 IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG);
232 inline void WriteOp_UDiv_Alt(JitWriter *jit)
238 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
239 IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
240 IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
241 Write_Check_DivZero(jit, AMX_REG_TMP);
242 IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG);
245 inline void WriteOp_Ret(JitWriter *jit)
247 //mov ebx, [edi] - get old FRM
248 //add edi, 4 - pop stack
249 //mov [esi+frm], ebx - restore
250 //add ebx, ebp - relocate
252 IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_MEM_REG);
253 IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
254 IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_FRM, MOD_MEM_REG);
255 IA32_Add_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
259 inline void WriteOp_JRel(JitWriter *jit)
261 //jmp <offs> ;relative jump
262 cell_t cip_offs = jit->read_cell();
264 /* Note that since code size calculation has to be done in the same
265 * phase as building relocation information, we cannot know the jump size
266 * beforehand. Thus, we always write full 32bit jumps for safety.
268 jitoffs_t jmp = IA32_Jump_Imm32(jit, 0);
269 IA32_Write_Jump32(jit, jmp, RelocLookup(jit, cip_offs));
272 inline void WriteOp_Jless(JitWriter *jit)
276 cell_t target = jit->read_cell();
277 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
278 IA32_Jump_Cond_Imm32(jit, CC_B, RelocLookup(jit, target, false));
281 inline void WriteOp_Jleq(JitWriter *jit)
285 cell_t target = jit->read_cell();
286 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
287 IA32_Jump_Cond_Imm32(jit, CC_BE, RelocLookup(jit, target, false));
290 inline void WriteOp_Jgrtr(JitWriter *jit)
294 cell_t target = jit->read_cell();
295 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
296 IA32_Jump_Cond_Imm32(jit, CC_A, RelocLookup(jit, target, false));
299 inline void WriteOp_Jgeq(JitWriter *jit)
303 cell_t target = jit->read_cell();
304 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
305 IA32_Jump_Cond_Imm32(jit, CC_AE, RelocLookup(jit, target, false));
308 #endif //_INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_