|
dvander@367
|
1 |
/** |
|
ds@653
|
2 |
* vim: set ts=4 : |
|
ds@1330
|
3 |
* ============================================================================= |
|
ds@1330
|
4 |
* SourcePawn JIT |
|
ds@1330
|
5 |
* Copyright (C)2004-2007 AlliedModders LLC. All rights reserved. |
|
ds@1330
|
6 |
* ============================================================================= |
|
dvander@367
|
7 |
* |
|
ds@1330
|
8 |
* This file is not open source and may not be copied without explicit wriiten |
|
ds@1330
|
9 |
* permission of AlliedModders LLC. This file may not be redistributed in whole |
|
ds@1330
|
10 |
* or significant part. |
|
dvander@367
|
11 |
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php |
|
dvander@367
|
12 |
* |
|
dvander@367
|
13 |
* Version: $Id$ |
|
dvander@367
|
14 |
*/ |
|
dvander@367
|
15 |
|
|
dvander@157
|
16 |
#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_ |
|
dvander@157
|
17 |
#define _INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_ |
|
dvander@157
|
18 |
|
|
dvander@157
|
19 |
inline void WriteOp_UMul(JitWriter *jit) |
|
dvander@157
|
20 |
{ |
|
dvander@157
|
21 |
//mov ecx, edx |
|
dvander@157
|
22 |
//mul edx |
|
dvander@157
|
23 |
//mov edx, ecx |
|
dvander@157
|
24 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
25 |
IA32_Mul_Rm(jit, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
26 |
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG); |
|
dvander@157
|
27 |
} |
|
dvander@157
|
28 |
|
|
dvander@157
|
29 |
inline void WriteOp_Less(JitWriter *jit) |
|
dvander@157
|
30 |
{ |
|
dvander@157
|
31 |
//cmp eax, edx ; PRI < ALT ? (unsigned) |
|
dvander@157
|
32 |
//mov eax, 0 |
|
dvander@157
|
33 |
//setb al |
|
dvander@157
|
34 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
35 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
dvander@157
|
36 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_B); |
|
dvander@157
|
37 |
} |
|
dvander@157
|
38 |
|
|
dvander@157
|
39 |
inline void WriteOp_Leq(JitWriter *jit) |
|
dvander@157
|
40 |
{ |
|
dvander@157
|
41 |
//cmp eax, edx ; PRI <= ALT ? (unsigned) |
|
dvander@157
|
42 |
//mov eax, 0 |
|
dvander@157
|
43 |
//setbe al |
|
dvander@157
|
44 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
45 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
dvander@157
|
46 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_BE); |
|
dvander@157
|
47 |
} |
|
dvander@157
|
48 |
|
|
dvander@157
|
49 |
inline void WriteOp_Grtr(JitWriter *jit) |
|
dvander@157
|
50 |
{ |
|
dvander@157
|
51 |
//cmp eax, edx ; PRI > ALT ? (unsigned) |
|
dvander@157
|
52 |
//mov eax, 0 |
|
dvander@157
|
53 |
//seta al |
|
dvander@157
|
54 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
55 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
dvander@157
|
56 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_A); |
|
dvander@157
|
57 |
} |
|
dvander@157
|
58 |
|
|
dvander@157
|
59 |
inline void WriteOp_Geq(JitWriter *jit) |
|
dvander@157
|
60 |
{ |
|
dvander@157
|
61 |
//cmp eax, edx ; PRI >= ALT ? (unsigned) |
|
dvander@157
|
62 |
//mov eax, 0 |
|
dvander@157
|
63 |
//setae al |
|
dvander@157
|
64 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
65 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
dvander@157
|
66 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_AE); |
|
dvander@157
|
67 |
} |
|
dvander@157
|
68 |
|
|
dvander@157
|
69 |
inline void WriteOp_Align_Pri(JitWriter *jit) |
|
dvander@157
|
70 |
{ |
|
dvander@157
|
71 |
//xor eax, <cellsize - val> |
|
dvander@157
|
72 |
cell_t val = sizeof(cell_t) - jit->read_cell(); |
|
dvander@157
|
73 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
74 |
{ |
|
dvander@157
|
75 |
IA32_Xor_Rm_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val); |
|
dvander@157
|
76 |
} else { |
|
dvander@157
|
77 |
IA32_Xor_Eax_Imm32(jit, val); |
|
dvander@157
|
78 |
} |
|
dvander@157
|
79 |
} |
|
dvander@157
|
80 |
|
|
dvander@157
|
81 |
inline void WriteOp_Align_Alt(JitWriter *jit) |
|
dvander@157
|
82 |
{ |
|
dvander@157
|
83 |
//xor edx, <cellsize - val> |
|
dvander@157
|
84 |
cell_t val = sizeof(cell_t) - jit->read_cell(); |
|
dvander@157
|
85 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
86 |
{ |
|
dvander@157
|
87 |
IA32_Xor_Rm_Imm8(jit, AMX_REG_ALT, MOD_REG, (jit_int8_t)val); |
|
dvander@157
|
88 |
} else { |
|
dvander@157
|
89 |
IA32_Xor_Rm_Imm32(jit, AMX_REG_ALT, MOD_REG, val); |
|
dvander@157
|
90 |
} |
|
dvander@157
|
91 |
} |
|
dvander@157
|
92 |
|
|
dvander@157
|
93 |
inline void WriteOp_Cmps(JitWriter *jit) |
|
dvander@157
|
94 |
{ |
|
dvander@157
|
95 |
//push edi |
|
dvander@157
|
96 |
//push esi |
|
dvander@157
|
97 |
//lea esi, [ebp+edx] |
|
dvander@157
|
98 |
//lea edi, [ebp+eax] |
|
dvander@157
|
99 |
//mov ecx, <val> |
|
dvander@157
|
100 |
unsigned int val = jit->read_cell(); |
|
dvander@157
|
101 |
|
|
dvander@157
|
102 |
IA32_Push_Reg(jit, REG_EDI); |
|
dvander@157
|
103 |
IA32_Push_Reg(jit, REG_ESI); |
|
dvander@157
|
104 |
IA32_Lea_Reg_DispEBPRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE); |
|
dvander@157
|
105 |
IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
dvander@157
|
106 |
IA32_Mov_Reg_Imm32(jit, REG_ECX, val); |
|
dvander@157
|
107 |
|
|
dvander@157
|
108 |
//xor eax, eax |
|
dvander@157
|
109 |
//repe cmpsb |
|
dvander@157
|
110 |
//je :cmps1 |
|
dvander@157
|
111 |
IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
112 |
IA32_Rep(jit); |
|
dvander@157
|
113 |
IA32_Cmpsb(jit); |
|
dvander@157
|
114 |
jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_E, 0); |
|
dvander@157
|
115 |
|
|
dvander@157
|
116 |
//sbb eax, eax |
|
dvander@157
|
117 |
//sbb eax, -1 |
|
dvander@157
|
118 |
IA32_Sbb_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
119 |
IA32_Sbb_Rm_Imm8(jit, AMX_REG_PRI, -1, MOD_REG); |
|
dvander@157
|
120 |
|
|
dvander@157
|
121 |
//:cmps1 |
|
dvander@157
|
122 |
//pop esi |
|
dvander@157
|
123 |
//pop edi |
|
dvander@157
|
124 |
IA32_Send_Jump8_Here(jit, jmp); |
|
dvander@157
|
125 |
IA32_Pop_Reg(jit, REG_ESI); |
|
dvander@157
|
126 |
IA32_Pop_Reg(jit, REG_EDI); |
|
dvander@157
|
127 |
} |
|
dvander@157
|
128 |
|
|
dvander@157
|
129 |
inline void WriteOp_Lctrl(JitWriter *jit) |
|
dvander@157
|
130 |
{ |
|
dvander@157
|
131 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
132 |
switch (val) |
|
dvander@157
|
133 |
{ |
|
dvander@157
|
134 |
case 0: |
|
dvander@157
|
135 |
{ |
|
dvander@157
|
136 |
//mov ecx, [esi+ctx] |
|
dvander@157
|
137 |
//mov eax, [ecx+ctx.codebase] |
|
dvander@157
|
138 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); |
|
dvander@157
|
139 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, codebase)); |
|
dvander@157
|
140 |
break; |
|
dvander@157
|
141 |
} |
|
dvander@157
|
142 |
case 1: |
|
dvander@157
|
143 |
{ |
|
dvander@157
|
144 |
//mov eax, ebp |
|
dvander@157
|
145 |
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG); |
|
dvander@157
|
146 |
break; |
|
dvander@157
|
147 |
} |
|
dvander@157
|
148 |
case 2: |
|
dvander@157
|
149 |
{ |
|
dvander@157
|
150 |
//mov eax, [esi+hea] |
|
dvander@157
|
151 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_INFO, AMX_INFO_HEAP); |
|
dvander@157
|
152 |
break; |
|
dvander@157
|
153 |
} |
|
dvander@157
|
154 |
case 3: |
|
dvander@157
|
155 |
{ |
|
dvander@157
|
156 |
//mov ecx, [esi+ctx] |
|
dvander@157
|
157 |
//mov eax, [ecx+ctx.memory] |
|
dvander@157
|
158 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); |
|
dvander@157
|
159 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, memory)); |
|
dvander@157
|
160 |
break; |
|
dvander@157
|
161 |
} |
|
dvander@157
|
162 |
case 4: |
|
dvander@157
|
163 |
{ |
|
dvander@157
|
164 |
//mov eax, edi |
|
dvander@157
|
165 |
//sub eax, ebp - unrelocate |
|
dvander@157
|
166 |
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_REG); |
|
dvander@157
|
167 |
IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG); |
|
dvander@157
|
168 |
break; |
|
dvander@157
|
169 |
} |
|
dvander@157
|
170 |
case 5: |
|
dvander@157
|
171 |
{ |
|
dvander@157
|
172 |
//mov eax, [esi+frm] |
|
dvander@157
|
173 |
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG); |
|
dvander@157
|
174 |
break; |
|
dvander@157
|
175 |
} |
|
dvander@157
|
176 |
case 6: |
|
dvander@157
|
177 |
{ |
|
dvander@157
|
178 |
//mov eax, [cip] |
|
dvander@157
|
179 |
jitoffs_t imm32 = IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
dvander@157
|
180 |
jitoffs_t save = jit->get_outputpos(); |
|
dvander@157
|
181 |
jit->set_outputpos(imm32); |
|
dvander@157
|
182 |
jit->write_int32((uint32_t)(jit->outbase + save)); |
|
dvander@157
|
183 |
jit->set_outputpos(save); |
|
dvander@157
|
184 |
break; |
|
dvander@157
|
185 |
} |
|
dvander@157
|
186 |
} |
|
dvander@157
|
187 |
} |
|
dvander@157
|
188 |
|
|
dvander@157
|
189 |
inline void WriteOp_Sctrl(JitWriter *jit) |
|
dvander@157
|
190 |
{ |
|
dvander@157
|
191 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
192 |
switch (val) |
|
dvander@157
|
193 |
{ |
|
dvander@157
|
194 |
case 2: |
|
dvander@157
|
195 |
{ |
|
dvander@157
|
196 |
//mov [esi+hea], eax |
|
dvander@157
|
197 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_PRI, AMX_INFO_HEAP); |
|
dvander@157
|
198 |
break; |
|
dvander@157
|
199 |
} |
|
dvander@157
|
200 |
case 4: |
|
dvander@157
|
201 |
{ |
|
dvander@157
|
202 |
//lea edi, [ebp+eax] |
|
dvander@157
|
203 |
IA32_Lea_Reg_DispEBPRegMult(jit, AMX_REG_STK, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
dvander@157
|
204 |
break; |
|
dvander@157
|
205 |
} |
|
dvander@157
|
206 |
case 5: |
|
dvander@157
|
207 |
{ |
|
dvander@157
|
208 |
//lea ebx, [ebp+eax] - overwrite frm |
|
dvander@157
|
209 |
//mov [esi+frm], eax - overwrite stacked frame |
|
dvander@157
|
210 |
IA32_Lea_Reg_DispEBPRegMult(jit, AMX_REG_FRM, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
dvander@157
|
211 |
IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_PRI, MOD_MEM_REG); |
|
dvander@157
|
212 |
break; |
|
dvander@157
|
213 |
} |
|
dvander@157
|
214 |
case 6: |
|
dvander@157
|
215 |
{ |
|
dvander@157
|
216 |
IA32_Jump_Reg(jit, AMX_REG_PRI); |
|
dvander@157
|
217 |
break; |
|
dvander@157
|
218 |
} |
|
dvander@157
|
219 |
} |
|
dvander@157
|
220 |
} |
|
dvander@157
|
221 |
|
|
dvander@157
|
222 |
inline void WriteOp_UDiv(JitWriter *jit) |
|
dvander@157
|
223 |
{ |
|
dvander@157
|
224 |
//mov ecx, edx |
|
dvander@157
|
225 |
//xor edx, edx |
|
dvander@157
|
226 |
//div ecx |
|
dvander@157
|
227 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
228 |
IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
229 |
Write_Check_DivZero(jit, AMX_REG_TMP); |
|
dvander@157
|
230 |
IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG); |
|
dvander@157
|
231 |
} |
|
dvander@157
|
232 |
|
|
dvander@157
|
233 |
inline void WriteOp_UDiv_Alt(JitWriter *jit) |
|
dvander@157
|
234 |
{ |
|
dvander@157
|
235 |
//mov ecx, eax |
|
dvander@157
|
236 |
//mov eax, edx |
|
dvander@157
|
237 |
//xor edx, edx |
|
dvander@157
|
238 |
//div ecx |
|
dvander@157
|
239 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
240 |
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
241 |
IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
242 |
Write_Check_DivZero(jit, AMX_REG_TMP); |
|
dvander@157
|
243 |
IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG); |
|
dvander@157
|
244 |
} |
|
dvander@157
|
245 |
|
|
dvander@157
|
246 |
inline void WriteOp_Ret(JitWriter *jit) |
|
dvander@157
|
247 |
{ |
|
dvander@157
|
248 |
//mov ebx, [edi] - get old FRM |
|
dvander@157
|
249 |
//add edi, 4 - pop stack |
|
dvander@157
|
250 |
//mov [esi+frm], ebx - restore |
|
dvander@157
|
251 |
//add ebx, ebp - relocate |
|
dvander@157
|
252 |
//ret |
|
dvander@157
|
253 |
IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_MEM_REG); |
|
dvander@157
|
254 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
dvander@157
|
255 |
IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_FRM, MOD_MEM_REG); |
|
dvander@157
|
256 |
IA32_Add_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG); |
|
dvander@157
|
257 |
IA32_Return(jit); |
|
dvander@157
|
258 |
} |
|
dvander@157
|
259 |
|
|
dvander@157
|
260 |
inline void WriteOp_JRel(JitWriter *jit) |
|
dvander@157
|
261 |
{ |
|
dvander@157
|
262 |
//jmp <offs> ;relative jump |
|
dvander@157
|
263 |
cell_t cip_offs = jit->read_cell(); |
|
dvander@157
|
264 |
|
|
dvander@157
|
265 |
/* Note that since code size calculation has to be done in the same |
|
dvander@157
|
266 |
* phase as building relocation information, we cannot know the jump size |
|
dvander@157
|
267 |
* beforehand. Thus, we always write full 32bit jumps for safety. |
|
dvander@157
|
268 |
*/ |
|
dvander@157
|
269 |
jitoffs_t jmp = IA32_Jump_Imm32(jit, 0); |
|
dvander@157
|
270 |
IA32_Write_Jump32(jit, jmp, RelocLookup(jit, cip_offs)); |
|
dvander@157
|
271 |
} |
|
dvander@157
|
272 |
|
|
dvander@157
|
273 |
inline void WriteOp_Jless(JitWriter *jit) |
|
dvander@157
|
274 |
{ |
|
dvander@157
|
275 |
//cmp eax, edx |
|
dvander@157
|
276 |
//jb <target> |
|
dvander@157
|
277 |
cell_t target = jit->read_cell(); |
|
dvander@157
|
278 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
279 |
IA32_Jump_Cond_Imm32(jit, CC_B, RelocLookup(jit, target, false)); |
|
dvander@157
|
280 |
} |
|
dvander@157
|
281 |
|
|
dvander@157
|
282 |
inline void WriteOp_Jleq(JitWriter *jit) |
|
dvander@157
|
283 |
{ |
|
dvander@157
|
284 |
//cmp eax, edx |
|
dvander@157
|
285 |
//jbe <target> |
|
dvander@157
|
286 |
cell_t target = jit->read_cell(); |
|
dvander@157
|
287 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
288 |
IA32_Jump_Cond_Imm32(jit, CC_BE, RelocLookup(jit, target, false)); |
|
dvander@157
|
289 |
} |
|
dvander@157
|
290 |
|
|
dvander@157
|
291 |
inline void WriteOp_Jgrtr(JitWriter *jit) |
|
dvander@157
|
292 |
{ |
|
dvander@157
|
293 |
//cmp eax, edx |
|
dvander@157
|
294 |
//ja <target> |
|
dvander@157
|
295 |
cell_t target = jit->read_cell(); |
|
dvander@157
|
296 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
297 |
IA32_Jump_Cond_Imm32(jit, CC_A, RelocLookup(jit, target, false)); |
|
dvander@157
|
298 |
} |
|
dvander@157
|
299 |
|
|
dvander@157
|
300 |
inline void WriteOp_Jgeq(JitWriter *jit) |
|
dvander@157
|
301 |
{ |
|
dvander@157
|
302 |
//cmp eax, edx |
|
dvander@157
|
303 |
//jae <target> |
|
dvander@157
|
304 |
cell_t target = jit->read_cell(); |
|
dvander@157
|
305 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
306 |
IA32_Jump_Cond_Imm32(jit, CC_AE, RelocLookup(jit, target, false)); |
|
dvander@157
|
307 |
} |
|
dvander@157
|
308 |
|
|
dvander@157
|
309 |
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_ |