|
ds@1952
|
1 |
/** |
|
ds@1952
|
2 |
* vim: set ts=4 : |
|
ds@1952
|
3 |
* ============================================================================= |
|
dvander@2114
|
4 |
* SourceMod |
|
dvander@2114
|
5 |
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. |
|
ds@1952
|
6 |
* ============================================================================= |
|
ds@1952
|
7 |
* |
|
dvander@2114
|
8 |
* This program is free software; you can redistribute it and/or modify it under |
|
dvander@2114
|
9 |
* the terms of the GNU General Public License, version 3.0, as published by the |
|
dvander@2114
|
10 |
* Free Software Foundation. |
|
dvander@2114
|
11 |
* |
|
dvander@2114
|
12 |
* This program is distributed in the hope that it will be useful, but WITHOUT |
|
dvander@2114
|
13 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
dvander@2114
|
14 |
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
|
dvander@2114
|
15 |
* details. |
|
dvander@2114
|
16 |
* |
|
dvander@2114
|
17 |
* You should have received a copy of the GNU General Public License along with |
|
dvander@2114
|
18 |
* this program. If not, see <http://www.gnu.org/licenses/>. |
|
dvander@2114
|
19 |
* |
|
dvander@2114
|
20 |
* As a special exception, AlliedModders LLC gives you permission to link the |
|
dvander@2114
|
21 |
* code of this program (as well as its derivative works) to "Half-Life 2," the |
|
dvander@2114
|
22 |
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software |
|
dvander@2114
|
23 |
* by the Valve Corporation. You must obey the GNU General Public License in |
|
dvander@2114
|
24 |
* all respects for all other code used. Additionally, AlliedModders LLC grants |
|
dvander@2114
|
25 |
* this exception to all derivative works. AlliedModders LLC defines further |
|
dvander@2114
|
26 |
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), |
|
dvander@2114
|
27 |
* or <http://www.sourcemod.net/license.php>. |
|
ds@1952
|
28 |
* |
|
ds@1952
|
29 |
* Version: $Id$ |
|
ds@1952
|
30 |
*/ |
|
ds@1952
|
31 |
|
|
ds@1952
|
32 |
#include <string.h> |
|
ds@1952
|
33 |
#include <stdlib.h> |
|
ds@1952
|
34 |
#include <assert.h> |
|
ds@1952
|
35 |
#include "jit_x86.h" |
|
ds@1952
|
36 |
#include "opcode_helpers.h" |
|
ds@1952
|
37 |
#include <x86_macros.h> |
|
dvander@2193
|
38 |
#include "../jit_version.h" |
|
dvander@2193
|
39 |
#include "../sp_vm_engine.h" |
|
dvander@2193
|
40 |
#include "../engine2.h" |
|
dvander@2193
|
41 |
#include "../BaseRuntime.h" |
|
dvander@2193
|
42 |
#include "../sp_vm_basecontext.h" |
|
ds@1952
|
43 |
|
|
dvander@2226
|
44 |
using namespace Knight; |
|
dvander@2226
|
45 |
|
|
ds@1952
|
46 |
#if defined USE_UNGEN_OPCODES |
|
ds@1952
|
47 |
#include "ungen_opcodes.h" |
|
ds@1952
|
48 |
#endif |
|
ds@1952
|
49 |
|
|
dvander@2226
|
50 |
JITX86 g_Jit; |
|
dvander@2226
|
51 |
KeCodeCache *g_pCodeCache = NULL; |
|
dvander@2193
|
52 |
ISourcePawnEngine *engine = &g_engine1; |
|
dvander@2193
|
53 |
|
|
dvander@2193
|
54 |
inline sp_plugin_t *GETPLUGIN(sp_context_t *ctx) |
|
dvander@2193
|
55 |
{ |
|
dvander@2193
|
56 |
return (sp_plugin_t *)(ctx->vm[JITVARS_PLUGIN]); |
|
dvander@2193
|
57 |
} |
|
dvander@2193
|
58 |
|
|
ds@1952
|
59 |
inline void WriteOp_Move_Pri(JitWriter *jit) |
|
ds@1952
|
60 |
{ |
|
ds@1952
|
61 |
//mov eax, edx |
|
ds@1952
|
62 |
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
63 |
} |
|
ds@1952
|
64 |
|
|
ds@1952
|
65 |
inline void WriteOp_Move_Alt(JitWriter *jit) |
|
ds@1952
|
66 |
{ |
|
ds@1952
|
67 |
//mov edx, eax |
|
ds@1952
|
68 |
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
69 |
} |
|
ds@1952
|
70 |
|
|
ds@1952
|
71 |
inline void WriteOp_Xchg(JitWriter *jit) |
|
ds@1952
|
72 |
{ |
|
ds@1952
|
73 |
//xchg eax, edx |
|
ds@1952
|
74 |
IA32_Xchg_Eax_Reg(jit, AMX_REG_ALT); |
|
ds@1952
|
75 |
} |
|
ds@1952
|
76 |
|
|
ds@1952
|
77 |
inline void WriteOp_Push(JitWriter *jit) |
|
ds@1952
|
78 |
{ |
|
ds@1952
|
79 |
//push stack, DAT offset based |
|
ds@1952
|
80 |
//sub edi, 4 |
|
ds@1952
|
81 |
//mov ecx, [ebp+<val>] |
|
ds@1952
|
82 |
//mov [edi], ecx |
|
ds@1952
|
83 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
84 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
85 |
//optimize encoding a bit... |
|
faluco@2029
|
86 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
87 |
{ |
|
ds@1952
|
88 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val); |
|
ds@1952
|
89 |
} else { |
|
ds@1952
|
90 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val); |
|
ds@1952
|
91 |
} |
|
ds@1952
|
92 |
IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG); |
|
ds@1952
|
93 |
} |
|
ds@1952
|
94 |
|
|
ds@1952
|
95 |
inline void WriteOp_Push_C(JitWriter *jit) |
|
ds@1952
|
96 |
{ |
|
ds@1952
|
97 |
//push stack |
|
ds@1952
|
98 |
//mov [edi-4], <val> |
|
ds@1952
|
99 |
//sub edi, 4 |
|
ds@1952
|
100 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
101 |
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, val, -4); |
|
ds@1952
|
102 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
103 |
} |
|
ds@1952
|
104 |
|
|
ds@1952
|
105 |
inline void WriteOp_Zero(JitWriter *jit) |
|
ds@1952
|
106 |
{ |
|
ds@1952
|
107 |
//mov [ebp+<val>], 0 |
|
ds@1952
|
108 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
109 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
110 |
{ |
|
ds@1952
|
111 |
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, 0, (jit_int8_t)val); |
|
ds@1952
|
112 |
} else { |
|
ds@1952
|
113 |
IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, 0, val); |
|
ds@1952
|
114 |
} |
|
ds@1952
|
115 |
} |
|
ds@1952
|
116 |
|
|
ds@1952
|
117 |
inline void WriteOp_Zero_S(JitWriter *jit) |
|
ds@1952
|
118 |
{ |
|
ds@1952
|
119 |
//mov [ebx+<val>], 0 |
|
ds@1952
|
120 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
121 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
122 |
{ |
|
ds@1952
|
123 |
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, 0, (jit_int8_t)val); |
|
ds@1952
|
124 |
} else { |
|
ds@1952
|
125 |
IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, 0, val); |
|
ds@1952
|
126 |
} |
|
ds@1952
|
127 |
} |
|
ds@1952
|
128 |
|
|
ds@1952
|
129 |
inline void WriteOp_Push_S(JitWriter *jit) |
|
ds@1952
|
130 |
{ |
|
ds@1952
|
131 |
//push stack, FRM offset based |
|
ds@1952
|
132 |
//sub edi, 4 |
|
ds@1952
|
133 |
//mov ecx, [ebx+<val>] |
|
ds@1952
|
134 |
//mov [edi], ecx |
|
ds@1952
|
135 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
136 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
137 |
//optimize encoding a bit... |
|
faluco@2029
|
138 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
139 |
{ |
|
ds@1952
|
140 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val); |
|
ds@1952
|
141 |
} else { |
|
ds@1952
|
142 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val); |
|
ds@1952
|
143 |
} |
|
ds@1952
|
144 |
IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG); |
|
ds@1952
|
145 |
} |
|
ds@1952
|
146 |
|
|
ds@1952
|
147 |
inline void WriteOp_Push_Pri(JitWriter *jit) |
|
ds@1952
|
148 |
{ |
|
ds@1952
|
149 |
//mov [edi-4], eax |
|
ds@1952
|
150 |
//sub edi, 4 |
|
ds@1952
|
151 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_PRI, -4); |
|
ds@1952
|
152 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
153 |
} |
|
ds@1952
|
154 |
|
|
ds@1952
|
155 |
inline void WriteOp_Push_Alt(JitWriter *jit) |
|
ds@1952
|
156 |
{ |
|
ds@1952
|
157 |
//mov [edi-4], edx |
|
ds@1952
|
158 |
//sub edi, 4 |
|
ds@1952
|
159 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_ALT, -4); |
|
ds@1952
|
160 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
161 |
} |
|
ds@1952
|
162 |
|
|
ds@1952
|
163 |
inline void WriteOp_Push2_C(JitWriter *jit) |
|
ds@1952
|
164 |
{ |
|
ds@1952
|
165 |
Macro_PushN_C(jit, 2); |
|
ds@1952
|
166 |
} |
|
ds@1952
|
167 |
|
|
ds@1952
|
168 |
inline void WriteOp_Push3_C(JitWriter *jit) |
|
ds@1952
|
169 |
{ |
|
ds@1952
|
170 |
Macro_PushN_C(jit, 3); |
|
ds@1952
|
171 |
} |
|
ds@1952
|
172 |
|
|
ds@1952
|
173 |
inline void WriteOp_Push4_C(JitWriter *jit) |
|
ds@1952
|
174 |
{ |
|
ds@1952
|
175 |
Macro_PushN_C(jit, 4); |
|
ds@1952
|
176 |
} |
|
ds@1952
|
177 |
|
|
ds@1952
|
178 |
inline void WriteOp_Push5_C(JitWriter *jit) |
|
ds@1952
|
179 |
{ |
|
ds@1952
|
180 |
Macro_PushN_C(jit, 5); |
|
ds@1952
|
181 |
} |
|
ds@1952
|
182 |
|
|
ds@1952
|
183 |
inline void WriteOp_Push2_Adr(JitWriter *jit) |
|
ds@1952
|
184 |
{ |
|
ds@1952
|
185 |
Macro_PushN_Addr(jit, 2); |
|
ds@1952
|
186 |
} |
|
ds@1952
|
187 |
|
|
ds@1952
|
188 |
inline void WriteOp_Push3_Adr(JitWriter *jit) |
|
ds@1952
|
189 |
{ |
|
ds@1952
|
190 |
Macro_PushN_Addr(jit, 3); |
|
ds@1952
|
191 |
} |
|
ds@1952
|
192 |
|
|
ds@1952
|
193 |
inline void WriteOp_Push4_Adr(JitWriter *jit) |
|
ds@1952
|
194 |
{ |
|
ds@1952
|
195 |
Macro_PushN_Addr(jit, 4); |
|
ds@1952
|
196 |
} |
|
ds@1952
|
197 |
|
|
ds@1952
|
198 |
inline void WriteOp_Push5_Adr(JitWriter *jit) |
|
ds@1952
|
199 |
{ |
|
ds@1952
|
200 |
Macro_PushN_Addr(jit, 5); |
|
ds@1952
|
201 |
} |
|
ds@1952
|
202 |
|
|
ds@1952
|
203 |
inline void WriteOp_Push2_S(JitWriter *jit) |
|
ds@1952
|
204 |
{ |
|
ds@1952
|
205 |
Macro_PushN_S(jit, 2); |
|
ds@1952
|
206 |
} |
|
ds@1952
|
207 |
|
|
ds@1952
|
208 |
inline void WriteOp_Push3_S(JitWriter *jit) |
|
ds@1952
|
209 |
{ |
|
ds@1952
|
210 |
Macro_PushN_S(jit, 3); |
|
ds@1952
|
211 |
} |
|
ds@1952
|
212 |
|
|
ds@1952
|
213 |
inline void WriteOp_Push4_S(JitWriter *jit) |
|
ds@1952
|
214 |
{ |
|
ds@1952
|
215 |
Macro_PushN_S(jit, 4); |
|
ds@1952
|
216 |
} |
|
ds@1952
|
217 |
|
|
ds@1952
|
218 |
inline void WriteOp_Push5_S(JitWriter *jit) |
|
ds@1952
|
219 |
{ |
|
ds@1952
|
220 |
Macro_PushN_S(jit, 5); |
|
ds@1952
|
221 |
} |
|
ds@1952
|
222 |
|
|
ds@1952
|
223 |
inline void WriteOp_Push5(JitWriter *jit) |
|
ds@1952
|
224 |
{ |
|
ds@1952
|
225 |
Macro_PushN(jit, 5); |
|
ds@1952
|
226 |
} |
|
ds@1952
|
227 |
|
|
ds@1952
|
228 |
inline void WriteOp_Push4(JitWriter *jit) |
|
ds@1952
|
229 |
{ |
|
ds@1952
|
230 |
Macro_PushN(jit, 4); |
|
ds@1952
|
231 |
} |
|
ds@1952
|
232 |
|
|
ds@1952
|
233 |
inline void WriteOp_Push3(JitWriter *jit) |
|
ds@1952
|
234 |
{ |
|
ds@1952
|
235 |
Macro_PushN(jit, 3); |
|
ds@1952
|
236 |
} |
|
ds@1952
|
237 |
|
|
ds@1952
|
238 |
inline void WriteOp_Push2(JitWriter *jit) |
|
ds@1952
|
239 |
{ |
|
ds@1952
|
240 |
Macro_PushN(jit, 2); |
|
ds@1952
|
241 |
} |
|
ds@1952
|
242 |
|
|
ds@1952
|
243 |
inline void WriteOp_Zero_Pri(JitWriter *jit) |
|
ds@1952
|
244 |
{ |
|
ds@1952
|
245 |
//xor eax, eax |
|
ds@1952
|
246 |
IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
247 |
} |
|
ds@1952
|
248 |
|
|
ds@1952
|
249 |
inline void WriteOp_Zero_Alt(JitWriter *jit) |
|
ds@1952
|
250 |
{ |
|
ds@1952
|
251 |
//xor edx, edx |
|
ds@1952
|
252 |
IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
253 |
} |
|
ds@1952
|
254 |
|
|
ds@1952
|
255 |
inline void WriteOp_Add(JitWriter *jit) |
|
ds@1952
|
256 |
{ |
|
ds@1952
|
257 |
//add eax, edx |
|
ds@1952
|
258 |
IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
259 |
} |
|
ds@1952
|
260 |
|
|
ds@1952
|
261 |
inline void WriteOp_Sub(JitWriter *jit) |
|
ds@1952
|
262 |
{ |
|
ds@1952
|
263 |
//sub eax, edx |
|
ds@1952
|
264 |
IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
265 |
} |
|
ds@1952
|
266 |
|
|
ds@1952
|
267 |
inline void WriteOp_Sub_Alt(JitWriter *jit) |
|
ds@1952
|
268 |
{ |
|
ds@1952
|
269 |
//neg eax |
|
ds@1952
|
270 |
//add eax, edx |
|
ds@1952
|
271 |
IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
272 |
IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
273 |
} |
|
ds@1952
|
274 |
|
|
ds@1952
|
275 |
inline void WriteOp_Proc(JitWriter *jit) |
|
ds@1952
|
276 |
{ |
|
dvander@2226
|
277 |
#if 0 /* :TODO: We no longer use this */ |
|
ds@1952
|
278 |
/* Specialized code to align this taking in account the function magic number */ |
|
ds@1952
|
279 |
jitoffs_t cur_offs = jit->get_outputpos(); |
|
ds@1952
|
280 |
jitoffs_t offset = ((cur_offs & 0xFFFFFFF8) + 8) - cur_offs; |
|
ds@1952
|
281 |
if (!((offset + cur_offs) & 8)) |
|
ds@1952
|
282 |
{ |
|
ds@1952
|
283 |
offset += 8; |
|
ds@1952
|
284 |
} |
|
ds@1952
|
285 |
if (offset) |
|
ds@1952
|
286 |
{ |
|
ds@1952
|
287 |
for (jit_uint32_t i=0; i<offset; i++) |
|
ds@1952
|
288 |
{ |
|
ds@1952
|
289 |
jit->write_ubyte(IA32_INT3); |
|
ds@1952
|
290 |
} |
|
ds@1952
|
291 |
} |
|
ds@1952
|
292 |
|
|
ds@1952
|
293 |
/* Write the info struct about this function */ |
|
ds@1952
|
294 |
jit->write_uint32(JIT_FUNCMAGIC); |
|
ds@1952
|
295 |
jit->write_uint32(co->func_idx); |
|
ds@1952
|
296 |
|
|
ds@1952
|
297 |
/* Now we have to backpatch our reloction offset! */ |
|
ds@1952
|
298 |
{ |
|
ds@1952
|
299 |
jitoffs_t offs = jit->get_inputpos() - sizeof(cell_t); |
|
dvander@2226
|
300 |
uint8_t *rebase = ((CompData *)jit->data)->rebase; |
|
dvander@2226
|
301 |
*(jitoffs_t *)(rebase + offs) = jit->get_outputpos(); |
|
ds@1952
|
302 |
} |
|
ds@1952
|
303 |
|
|
ds@1952
|
304 |
/* Lastly, if we're writing, keep track of the function count */ |
|
ds@1952
|
305 |
if (jit->outbase) |
|
ds@1952
|
306 |
{ |
|
ds@1952
|
307 |
co->func_idx++; |
|
ds@1952
|
308 |
} |
|
dvander@2226
|
309 |
#endif |
|
ds@1952
|
310 |
|
|
ds@1952
|
311 |
//push old frame on stack: |
|
ds@1952
|
312 |
//mov ecx, [esi+frm] |
|
ds@1952
|
313 |
//mov [edi-4], ecx |
|
ds@1952
|
314 |
//sub edi, 8 ;extra un-used slot for non-existant CIP |
|
ds@1952
|
315 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG); |
|
ds@1952
|
316 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4); |
|
ds@1952
|
317 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG); |
|
dvander@2226
|
318 |
|
|
ds@1952
|
319 |
//save frame: |
|
ds@1952
|
320 |
//mov ecx, edi - get new frame |
|
ds@1952
|
321 |
//mov ebx, edi - store frame back |
|
ds@1952
|
322 |
//sub ecx, ebp - relocate local frame |
|
ds@1952
|
323 |
//mov [esi+frm], ecx |
|
ds@1952
|
324 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG); |
|
ds@1952
|
325 |
IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG); |
|
ds@1952
|
326 |
IA32_Sub_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_DAT, MOD_REG); |
|
ds@1952
|
327 |
IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_TMP, MOD_MEM_REG); |
|
ds@1952
|
328 |
} |
|
ds@1952
|
329 |
|
|
ds@1952
|
330 |
inline void WriteOp_Lidx_B(JitWriter *jit) |
|
ds@1952
|
331 |
{ |
|
ds@1952
|
332 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
333 |
//shl eax, <val> |
|
ds@1952
|
334 |
//add eax, edx |
|
ds@1952
|
335 |
//mov eax, [ebp+eax] |
|
ds@1952
|
336 |
IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG); |
|
ds@1952
|
337 |
IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
338 |
Write_Check_VerifyAddr(jit, AMX_REG_PRI); |
|
ds@1952
|
339 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
ds@1952
|
340 |
} |
|
ds@1952
|
341 |
|
|
ds@1952
|
342 |
inline void WriteOp_Idxaddr_B(JitWriter *jit) |
|
ds@1952
|
343 |
{ |
|
ds@1952
|
344 |
//shl eax, <val> |
|
ds@1952
|
345 |
//add eax, edx |
|
ds@1952
|
346 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
347 |
IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG); |
|
ds@1952
|
348 |
IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
349 |
} |
|
ds@1952
|
350 |
|
|
ds@1952
|
351 |
inline void WriteOp_Shl(JitWriter *jit) |
|
ds@1952
|
352 |
{ |
|
ds@1952
|
353 |
//mov ecx, edx |
|
ds@1952
|
354 |
//shl eax, cl |
|
ds@1952
|
355 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
356 |
IA32_Shl_Rm_CL(jit, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
357 |
} |
|
ds@1952
|
358 |
|
|
ds@1952
|
359 |
inline void WriteOp_Shr(JitWriter *jit) |
|
ds@1952
|
360 |
{ |
|
ds@1952
|
361 |
//mov ecx, edx |
|
ds@1952
|
362 |
//shr eax, cl |
|
ds@1952
|
363 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
364 |
IA32_Shr_Rm_CL(jit, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
365 |
} |
|
ds@1952
|
366 |
|
|
ds@1952
|
367 |
inline void WriteOp_Sshr(JitWriter *jit) |
|
ds@1952
|
368 |
{ |
|
ds@1952
|
369 |
//mov ecx, edx |
|
ds@1952
|
370 |
//sar eax, cl |
|
ds@1952
|
371 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
372 |
IA32_Sar_Rm_CL(jit, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
373 |
} |
|
ds@1952
|
374 |
|
|
ds@1952
|
375 |
inline void WriteOp_Shl_C_Pri(JitWriter *jit) |
|
ds@1952
|
376 |
{ |
|
ds@1952
|
377 |
//shl eax, <val> |
|
ds@1952
|
378 |
jit_uint8_t val = (jit_uint8_t)jit->read_cell(); |
|
ds@1952
|
379 |
if (val == 1) |
|
ds@1952
|
380 |
{ |
|
ds@1952
|
381 |
IA32_Shl_Rm_1(jit, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
382 |
} else { |
|
ds@1952
|
383 |
IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG); |
|
ds@1952
|
384 |
} |
|
ds@1952
|
385 |
} |
|
ds@1952
|
386 |
|
|
ds@1952
|
387 |
inline void WriteOp_Shl_C_Alt(JitWriter *jit) |
|
ds@1952
|
388 |
{ |
|
ds@1952
|
389 |
//shl edx, <val> |
|
ds@1952
|
390 |
jit_uint8_t val = (jit_uint8_t)jit->read_cell(); |
|
ds@1952
|
391 |
if (val == 1) |
|
ds@1952
|
392 |
{ |
|
ds@1952
|
393 |
IA32_Shl_Rm_1(jit, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
394 |
} else { |
|
ds@1952
|
395 |
IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG); |
|
ds@1952
|
396 |
} |
|
ds@1952
|
397 |
} |
|
ds@1952
|
398 |
|
|
ds@1952
|
399 |
inline void WriteOp_Shr_C_Pri(JitWriter *jit) |
|
ds@1952
|
400 |
{ |
|
ds@1952
|
401 |
//shr eax, <val> |
|
ds@1952
|
402 |
jit_uint8_t val = (jit_uint8_t)jit->read_cell(); |
|
ds@1952
|
403 |
if (val == 1) |
|
ds@1952
|
404 |
{ |
|
ds@1952
|
405 |
IA32_Shr_Rm_1(jit, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
406 |
} else { |
|
ds@1952
|
407 |
IA32_Shr_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG); |
|
ds@1952
|
408 |
} |
|
ds@1952
|
409 |
} |
|
ds@1952
|
410 |
|
|
ds@1952
|
411 |
inline void WriteOp_Shr_C_Alt(JitWriter *jit) |
|
ds@1952
|
412 |
{ |
|
ds@1952
|
413 |
//shr edx, <val> |
|
ds@1952
|
414 |
jit_uint8_t val = (jit_uint8_t)jit->read_cell(); |
|
ds@1952
|
415 |
if (val == 1) |
|
ds@1952
|
416 |
{ |
|
ds@1952
|
417 |
IA32_Shr_Rm_1(jit, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
418 |
} else { |
|
ds@1952
|
419 |
IA32_Shr_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG); |
|
ds@1952
|
420 |
} |
|
ds@1952
|
421 |
} |
|
ds@1952
|
422 |
|
|
ds@1952
|
423 |
inline void WriteOp_SMul(JitWriter *jit) |
|
ds@1952
|
424 |
{ |
|
ds@1952
|
425 |
//mov ecx, edx |
|
ds@1952
|
426 |
//imul edx |
|
ds@1952
|
427 |
//mov edx, ecx |
|
ds@1952
|
428 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
429 |
IA32_IMul_Rm(jit, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
430 |
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG); |
|
ds@1952
|
431 |
} |
|
ds@1952
|
432 |
|
|
ds@1952
|
433 |
inline void WriteOp_Not(JitWriter *jit) |
|
ds@1952
|
434 |
{ |
|
ds@1952
|
435 |
//test eax, eax |
|
ds@1952
|
436 |
//mov eax, 0 |
|
ds@1952
|
437 |
//sete al |
|
ds@1952
|
438 |
IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
439 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
ds@1952
|
440 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E); |
|
ds@1952
|
441 |
} |
|
ds@1952
|
442 |
|
|
ds@1952
|
443 |
inline void WriteOp_Neg(JitWriter *jit) |
|
ds@1952
|
444 |
{ |
|
ds@1952
|
445 |
//neg eax |
|
ds@1952
|
446 |
IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
447 |
} |
|
ds@1952
|
448 |
|
|
ds@1952
|
449 |
inline void WriteOp_Xor(JitWriter *jit) |
|
ds@1952
|
450 |
{ |
|
ds@1952
|
451 |
//xor eax, edx |
|
ds@1952
|
452 |
IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
453 |
} |
|
ds@1952
|
454 |
|
|
ds@1952
|
455 |
inline void WriteOp_Or(JitWriter *jit) |
|
ds@1952
|
456 |
{ |
|
ds@1952
|
457 |
//or eax, edx |
|
ds@1952
|
458 |
IA32_Or_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
459 |
} |
|
ds@1952
|
460 |
|
|
ds@1952
|
461 |
inline void WriteOp_And(JitWriter *jit) |
|
ds@1952
|
462 |
{ |
|
ds@1952
|
463 |
//and eax, edx |
|
ds@1952
|
464 |
IA32_And_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
465 |
} |
|
ds@1952
|
466 |
|
|
ds@1952
|
467 |
inline void WriteOp_Invert(JitWriter *jit) |
|
ds@1952
|
468 |
{ |
|
ds@1952
|
469 |
//not eax |
|
ds@1952
|
470 |
IA32_Not_Rm(jit, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
471 |
} |
|
ds@1952
|
472 |
|
|
ds@1952
|
473 |
inline void WriteOp_Add_C(JitWriter *jit) |
|
ds@1952
|
474 |
{ |
|
ds@1952
|
475 |
//add eax, <val> |
|
ds@1952
|
476 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
477 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
478 |
IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG); |
|
ds@1952
|
479 |
else |
|
ds@1952
|
480 |
IA32_Add_Eax_Imm32(jit, val); |
|
ds@1952
|
481 |
} |
|
ds@1952
|
482 |
|
|
ds@1952
|
483 |
inline void WriteOp_SMul_C(JitWriter *jit) |
|
ds@1952
|
484 |
{ |
|
ds@1952
|
485 |
//imul eax, <val> |
|
ds@1952
|
486 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
487 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
488 |
IA32_IMul_Reg_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val); |
|
ds@1952
|
489 |
else |
|
ds@1952
|
490 |
IA32_IMul_Reg_Imm32(jit, AMX_REG_PRI, MOD_REG, val); |
|
ds@1952
|
491 |
} |
|
ds@1952
|
492 |
|
|
ds@1952
|
493 |
inline void WriteOp_Sign_Pri(JitWriter *jit) |
|
ds@1952
|
494 |
{ |
|
ds@1952
|
495 |
//shl eax, 24 |
|
ds@1952
|
496 |
//sar eax, 24 |
|
ds@1952
|
497 |
IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG); |
|
ds@1952
|
498 |
IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG); |
|
ds@1952
|
499 |
} |
|
ds@1952
|
500 |
|
|
ds@1952
|
501 |
inline void WriteOp_Sign_Alt(JitWriter *jit) |
|
ds@1952
|
502 |
{ |
|
ds@1952
|
503 |
//shl edx, 24 |
|
ds@1952
|
504 |
//sar edx, 24 |
|
ds@1952
|
505 |
IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG); |
|
ds@1952
|
506 |
IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG); |
|
ds@1952
|
507 |
} |
|
ds@1952
|
508 |
|
|
ds@1952
|
509 |
inline void WriteOp_Eq(JitWriter *jit) |
|
ds@1952
|
510 |
{ |
|
ds@1952
|
511 |
//cmp eax, edx ; PRI == ALT ? |
|
ds@1952
|
512 |
//mov eax, 0 |
|
ds@1952
|
513 |
//sete al |
|
ds@1952
|
514 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
515 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
ds@1952
|
516 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E); |
|
ds@1952
|
517 |
} |
|
ds@1952
|
518 |
|
|
ds@1952
|
519 |
inline void WriteOp_Neq(JitWriter *jit) |
|
ds@1952
|
520 |
{ |
|
ds@1952
|
521 |
//cmp eax, edx ; PRI != ALT ? |
|
ds@1952
|
522 |
//mov eax, 0 |
|
ds@1952
|
523 |
//setne al |
|
ds@1952
|
524 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
525 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
ds@1952
|
526 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_NE); |
|
ds@1952
|
527 |
} |
|
ds@1952
|
528 |
|
|
ds@1952
|
529 |
inline void WriteOp_Sless(JitWriter *jit) |
|
ds@1952
|
530 |
{ |
|
ds@1952
|
531 |
//cmp eax, edx ; PRI < ALT ? (signed) |
|
ds@1952
|
532 |
//mov eax, 0 |
|
ds@1952
|
533 |
//setl al |
|
ds@1952
|
534 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
535 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
ds@1952
|
536 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_L); |
|
ds@1952
|
537 |
} |
|
ds@1952
|
538 |
|
|
ds@1952
|
539 |
inline void WriteOp_Sleq(JitWriter *jit) |
|
ds@1952
|
540 |
{ |
|
ds@1952
|
541 |
//cmp eax, edx ; PRI <= ALT ? (signed) |
|
ds@1952
|
542 |
//mov eax, 0 |
|
ds@1952
|
543 |
//setle al |
|
ds@1952
|
544 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
545 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
ds@1952
|
546 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_LE); |
|
ds@1952
|
547 |
} |
|
ds@1952
|
548 |
|
|
ds@1952
|
549 |
inline void WriteOp_Sgrtr(JitWriter *jit) |
|
ds@1952
|
550 |
{ |
|
ds@1952
|
551 |
//cmp eax, edx ; PRI > ALT ? (signed) |
|
ds@1952
|
552 |
//mov eax, 0 |
|
ds@1952
|
553 |
//setg al |
|
ds@1952
|
554 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
555 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
ds@1952
|
556 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_G); |
|
ds@1952
|
557 |
} |
|
ds@1952
|
558 |
|
|
ds@1952
|
559 |
inline void WriteOp_Sgeq(JitWriter *jit) |
|
ds@1952
|
560 |
{ |
|
ds@1952
|
561 |
//cmp eax, edx ; PRI >= ALT ? (signed) |
|
ds@1952
|
562 |
//mov eax, 0 |
|
ds@1952
|
563 |
//setge al |
|
ds@1952
|
564 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
565 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
ds@1952
|
566 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_GE); |
|
ds@1952
|
567 |
} |
|
ds@1952
|
568 |
|
|
ds@1952
|
569 |
inline void WriteOp_Eq_C_Pri(JitWriter *jit) |
|
ds@1952
|
570 |
{ |
|
ds@1952
|
571 |
//cmp eax, <val> ; PRI == value ? |
|
ds@1952
|
572 |
//mov eax, 0 |
|
ds@1952
|
573 |
//sete al |
|
ds@1952
|
574 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
575 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
576 |
IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val); |
|
ds@1952
|
577 |
else |
|
ds@1952
|
578 |
IA32_Cmp_Eax_Imm32(jit, val); |
|
ds@1952
|
579 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
ds@1952
|
580 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E); |
|
ds@1952
|
581 |
} |
|
ds@1952
|
582 |
|
|
ds@1952
|
583 |
inline void WriteOp_Eq_C_Alt(JitWriter *jit) |
|
ds@1952
|
584 |
{ |
|
ds@1952
|
585 |
//xor eax, eax |
|
ds@1952
|
586 |
//cmp edx, <val> ; ALT == value ? |
|
ds@1952
|
587 |
//sete al |
|
ds@1952
|
588 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
589 |
IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); |
|
faluco@2029
|
590 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
591 |
IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_ALT, (jit_int8_t)val); |
|
ds@1952
|
592 |
else |
|
ds@1952
|
593 |
IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_ALT, val); |
|
ds@1952
|
594 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E); |
|
ds@1952
|
595 |
} |
|
ds@1952
|
596 |
|
|
ds@1952
|
597 |
inline void WriteOp_Inc_Pri(JitWriter *jit) |
|
ds@1952
|
598 |
{ |
|
ds@1952
|
599 |
//add eax, 1 |
|
ds@1952
|
600 |
IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG); |
|
ds@1952
|
601 |
} |
|
ds@1952
|
602 |
|
|
ds@1952
|
603 |
inline void WriteOp_Inc_Alt(JitWriter *jit) |
|
ds@1952
|
604 |
{ |
|
ds@1952
|
605 |
//add edx, 1 |
|
ds@1952
|
606 |
IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG); |
|
ds@1952
|
607 |
} |
|
ds@1952
|
608 |
|
|
ds@1952
|
609 |
inline void WriteOp_Inc(JitWriter *jit) |
|
ds@1952
|
610 |
{ |
|
ds@1952
|
611 |
//add [ebp+<val>], 1 |
|
ds@1952
|
612 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
613 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
614 |
IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val); |
|
ds@1952
|
615 |
else |
|
ds@1952
|
616 |
IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val); |
|
ds@1952
|
617 |
} |
|
ds@1952
|
618 |
|
|
ds@1952
|
619 |
inline void WriteOp_Inc_S(JitWriter *jit) |
|
ds@1952
|
620 |
{ |
|
ds@1952
|
621 |
//add [ebx+<val>], 1 |
|
ds@1952
|
622 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
623 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
624 |
IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val); |
|
ds@1952
|
625 |
else |
|
ds@1952
|
626 |
IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val); |
|
ds@1952
|
627 |
} |
|
ds@1952
|
628 |
|
|
ds@1952
|
629 |
inline void WriteOp_Inc_I(JitWriter *jit) |
|
ds@1952
|
630 |
{ |
|
ds@1952
|
631 |
//add [ebp+eax], 1 |
|
ds@1952
|
632 |
IA32_Add_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1); |
|
ds@1952
|
633 |
} |
|
ds@1952
|
634 |
|
|
ds@1952
|
635 |
inline void WriteOp_Dec_Pri(JitWriter *jit) |
|
ds@1952
|
636 |
{ |
|
ds@1952
|
637 |
//sub eax, 1 |
|
ds@1952
|
638 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG); |
|
ds@1952
|
639 |
} |
|
ds@1952
|
640 |
|
|
ds@1952
|
641 |
inline void WriteOp_Dec_Alt(JitWriter *jit) |
|
ds@1952
|
642 |
{ |
|
ds@1952
|
643 |
//sub edx, 1 |
|
ds@1952
|
644 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG); |
|
ds@1952
|
645 |
} |
|
ds@1952
|
646 |
|
|
ds@1952
|
647 |
inline void WriteOp_Dec(JitWriter *jit) |
|
ds@1952
|
648 |
{ |
|
ds@1952
|
649 |
//sub [ebp+<val>], 1 |
|
ds@1952
|
650 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
651 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
652 |
{ |
|
ds@1952
|
653 |
IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val); |
|
ds@1952
|
654 |
} else { |
|
ds@1952
|
655 |
IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val); |
|
ds@1952
|
656 |
} |
|
ds@1952
|
657 |
} |
|
ds@1952
|
658 |
|
|
ds@1952
|
659 |
inline void WriteOp_Dec_S(JitWriter *jit) |
|
ds@1952
|
660 |
{ |
|
ds@1952
|
661 |
//sub [ebx+<val>], 1 |
|
ds@1952
|
662 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
663 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
664 |
{ |
|
ds@1952
|
665 |
IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val); |
|
ds@1952
|
666 |
} else { |
|
ds@1952
|
667 |
IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val); |
|
ds@1952
|
668 |
} |
|
ds@1952
|
669 |
} |
|
ds@1952
|
670 |
|
|
ds@1952
|
671 |
inline void WriteOp_Dec_I(JitWriter *jit) |
|
ds@1952
|
672 |
{ |
|
ds@1952
|
673 |
//sub [ebp+eax], 1 |
|
ds@1952
|
674 |
IA32_Sub_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1); |
|
ds@1952
|
675 |
} |
|
ds@1952
|
676 |
|
|
ds@1952
|
677 |
inline void WriteOp_Load_Pri(JitWriter *jit) |
|
ds@1952
|
678 |
{ |
|
ds@1952
|
679 |
//mov eax, [ebp+<val>] |
|
ds@1952
|
680 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
681 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
682 |
{ |
|
ds@1952
|
683 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val); |
|
ds@1952
|
684 |
} else { |
|
ds@1952
|
685 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val); |
|
ds@1952
|
686 |
} |
|
ds@1952
|
687 |
} |
|
ds@1952
|
688 |
|
|
ds@1952
|
689 |
inline void WriteOp_Load_Alt(JitWriter *jit) |
|
ds@1952
|
690 |
{ |
|
ds@1952
|
691 |
//mov edx, [ebp+<val>] |
|
ds@1952
|
692 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
693 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
694 |
{ |
|
ds@1952
|
695 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val); |
|
ds@1952
|
696 |
} else { |
|
ds@1952
|
697 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val); |
|
ds@1952
|
698 |
} |
|
ds@1952
|
699 |
} |
|
ds@1952
|
700 |
|
|
ds@1952
|
701 |
inline void WriteOp_Load_S_Pri(JitWriter *jit) |
|
ds@1952
|
702 |
{ |
|
ds@1952
|
703 |
//mov eax, [ebx+<val>] |
|
ds@1952
|
704 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
705 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
706 |
{ |
|
ds@1952
|
707 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val); |
|
ds@1952
|
708 |
} else { |
|
ds@1952
|
709 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val); |
|
ds@1952
|
710 |
} |
|
ds@1952
|
711 |
} |
|
ds@1952
|
712 |
|
|
ds@1952
|
713 |
inline void WriteOp_Load_S_Alt(JitWriter *jit) |
|
ds@1952
|
714 |
{ |
|
ds@1952
|
715 |
//mov edx, [ebx+<val>] |
|
ds@1952
|
716 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
717 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
718 |
{ |
|
ds@1952
|
719 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val); |
|
ds@1952
|
720 |
} else { |
|
ds@1952
|
721 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val); |
|
ds@1952
|
722 |
} |
|
ds@1952
|
723 |
} |
|
ds@1952
|
724 |
|
|
ds@1952
|
725 |
inline void WriteOp_Lref_Pri(JitWriter *jit) |
|
ds@1952
|
726 |
{ |
|
ds@1952
|
727 |
//mov eax, [ebp+<val>] |
|
ds@1952
|
728 |
//mov eax, [ebp+eax] |
|
ds@1952
|
729 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
730 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
731 |
{ |
|
ds@1952
|
732 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val); |
|
ds@1952
|
733 |
} else { |
|
ds@1952
|
734 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val); |
|
ds@1952
|
735 |
} |
|
ds@1952
|
736 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
ds@1952
|
737 |
} |
|
ds@1952
|
738 |
|
|
ds@1952
|
739 |
inline void WriteOp_Lref_Alt(JitWriter *jit) |
|
ds@1952
|
740 |
{ |
|
ds@1952
|
741 |
//mov edx, [ebp+<val>] |
|
ds@1952
|
742 |
//mov edx, [ebp+edx] |
|
ds@1952
|
743 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
744 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
745 |
{ |
|
ds@1952
|
746 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val); |
|
ds@1952
|
747 |
} else { |
|
ds@1952
|
748 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val); |
|
ds@1952
|
749 |
} |
|
ds@1952
|
750 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE); |
|
ds@1952
|
751 |
} |
|
ds@1952
|
752 |
|
|
ds@1952
|
753 |
inline void WriteOp_Lref_S_Pri(JitWriter *jit) |
|
ds@1952
|
754 |
{ |
|
ds@1952
|
755 |
//mov eax, [ebx+<val>] |
|
ds@1952
|
756 |
//mov eax, [ebp+eax] |
|
ds@1952
|
757 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
758 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
759 |
{ |
|
ds@1952
|
760 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val); |
|
ds@1952
|
761 |
} else { |
|
ds@1952
|
762 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val); |
|
ds@1952
|
763 |
} |
|
ds@1952
|
764 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
ds@1952
|
765 |
} |
|
ds@1952
|
766 |
|
|
ds@1952
|
767 |
inline void WriteOp_Lref_S_Alt(JitWriter *jit) |
|
ds@1952
|
768 |
{ |
|
ds@1952
|
769 |
//mov edx, [ebx+<val>] |
|
ds@1952
|
770 |
//mov edx, [ebp+edx] |
|
ds@1952
|
771 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
772 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
773 |
{ |
|
ds@1952
|
774 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val); |
|
ds@1952
|
775 |
} else { |
|
ds@1952
|
776 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val); |
|
ds@1952
|
777 |
} |
|
ds@1952
|
778 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE); |
|
ds@1952
|
779 |
} |
|
ds@1952
|
780 |
|
|
ds@1952
|
781 |
inline void WriteOp_Const_Pri(JitWriter *jit) |
|
ds@1952
|
782 |
{ |
|
ds@1952
|
783 |
//mov eax, <val> |
|
ds@1952
|
784 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
785 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, val); |
|
ds@1952
|
786 |
} |
|
ds@1952
|
787 |
|
|
ds@1952
|
788 |
inline void WriteOp_Const_Alt(JitWriter *jit) |
|
ds@1952
|
789 |
{ |
|
ds@1952
|
790 |
//mov edx, <val> |
|
ds@1952
|
791 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
792 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_ALT, val); |
|
ds@1952
|
793 |
} |
|
ds@1952
|
794 |
|
|
ds@1952
|
795 |
inline void WriteOp_Addr_Pri(JitWriter *jit) |
|
ds@1952
|
796 |
{ |
|
ds@1952
|
797 |
//mov eax, [esi+frm] |
|
ds@1952
|
798 |
//add eax, <val> |
|
ds@1952
|
799 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
800 |
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG); |
|
faluco@2029
|
801 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
802 |
{ |
|
ds@1952
|
803 |
IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG); |
|
ds@1952
|
804 |
} else { |
|
ds@1952
|
805 |
IA32_Add_Eax_Imm32(jit, val); |
|
ds@1952
|
806 |
} |
|
ds@1952
|
807 |
} |
|
ds@1952
|
808 |
|
|
ds@1952
|
809 |
inline void WriteOp_Addr_Alt(JitWriter *jit) |
|
ds@1952
|
810 |
{ |
|
ds@1952
|
811 |
//mov edx, [esi+frm] |
|
ds@1952
|
812 |
//add edx, <val> |
|
ds@1952
|
813 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
814 |
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_INFO, MOD_MEM_REG); |
|
faluco@2029
|
815 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
816 |
{ |
|
ds@1952
|
817 |
IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, (jit_int8_t)val, MOD_REG); |
|
ds@1952
|
818 |
} else { |
|
ds@1952
|
819 |
IA32_Add_Rm_Imm32(jit, AMX_REG_ALT, val, MOD_REG); |
|
ds@1952
|
820 |
} |
|
ds@1952
|
821 |
} |
|
ds@1952
|
822 |
|
|
ds@1952
|
823 |
inline void WriteOp_Stor_Pri(JitWriter *jit) |
|
ds@1952
|
824 |
{ |
|
ds@1952
|
825 |
//mov [ebp+<val>], eax |
|
ds@1952
|
826 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
827 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
828 |
{ |
|
ds@1952
|
829 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_PRI, (jit_int8_t)val); |
|
ds@1952
|
830 |
} else { |
|
ds@1952
|
831 |
IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_PRI, val); |
|
ds@1952
|
832 |
} |
|
ds@1952
|
833 |
} |
|
ds@1952
|
834 |
|
|
ds@1952
|
835 |
inline void WriteOp_Stor_Alt(JitWriter *jit) |
|
ds@1952
|
836 |
{ |
|
ds@1952
|
837 |
//mov [ebp+<val>], edx |
|
ds@1952
|
838 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
839 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
840 |
{ |
|
ds@1952
|
841 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_ALT, (jit_int8_t)val); |
|
ds@1952
|
842 |
} else { |
|
ds@1952
|
843 |
IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_ALT, val); |
|
ds@1952
|
844 |
} |
|
ds@1952
|
845 |
} |
|
ds@1952
|
846 |
|
|
ds@1952
|
847 |
inline void WriteOp_Stor_S_Pri(JitWriter *jit) |
|
ds@1952
|
848 |
{ |
|
ds@1952
|
849 |
//mov [ebx+<val>], eax |
|
ds@1952
|
850 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
851 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
852 |
{ |
|
ds@1952
|
853 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_PRI, (jit_int8_t)val); |
|
ds@1952
|
854 |
} else { |
|
ds@1952
|
855 |
IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_PRI, val); |
|
ds@1952
|
856 |
} |
|
ds@1952
|
857 |
} |
|
ds@1952
|
858 |
|
|
ds@1952
|
859 |
inline void WriteOp_Stor_S_Alt(JitWriter *jit) |
|
ds@1952
|
860 |
{ |
|
ds@1952
|
861 |
//mov [ebx+<val>], edx |
|
ds@1952
|
862 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
863 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
864 |
{ |
|
ds@1952
|
865 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_ALT, (jit_int8_t)val); |
|
ds@1952
|
866 |
} else { |
|
ds@1952
|
867 |
IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_ALT, val); |
|
ds@1952
|
868 |
} |
|
ds@1952
|
869 |
} |
|
ds@1952
|
870 |
|
|
ds@1952
|
871 |
inline void WriteOp_Idxaddr(JitWriter *jit) |
|
ds@1952
|
872 |
{ |
|
ds@1952
|
873 |
//lea eax, [edx+4*eax] |
|
ds@1952
|
874 |
IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4); |
|
ds@1952
|
875 |
} |
|
ds@1952
|
876 |
|
|
ds@1952
|
877 |
inline void WriteOp_Sref_Pri(JitWriter *jit) |
|
ds@1952
|
878 |
{ |
|
ds@1952
|
879 |
//mov ecx, [ebp+<val>] |
|
ds@1952
|
880 |
//mov [ebp+ecx], eax |
|
ds@1952
|
881 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
882 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
883 |
{ |
|
ds@1952
|
884 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val); |
|
ds@1952
|
885 |
} else { |
|
ds@1952
|
886 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val); |
|
ds@1952
|
887 |
} |
|
ds@1952
|
888 |
IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI); |
|
ds@1952
|
889 |
} |
|
ds@1952
|
890 |
|
|
ds@1952
|
891 |
inline void WriteOp_Sref_Alt(JitWriter *jit) |
|
ds@1952
|
892 |
{ |
|
ds@1952
|
893 |
//mov ecx, [ebp+<val>] |
|
ds@1952
|
894 |
//mov [ebp+ecx], edx |
|
ds@1952
|
895 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
896 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
897 |
{ |
|
ds@1952
|
898 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val); |
|
ds@1952
|
899 |
} else { |
|
ds@1952
|
900 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val); |
|
ds@1952
|
901 |
} |
|
ds@1952
|
902 |
IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT); |
|
ds@1952
|
903 |
} |
|
ds@1952
|
904 |
|
|
ds@1952
|
905 |
inline void WriteOp_Sref_S_Pri(JitWriter *jit) |
|
ds@1952
|
906 |
{ |
|
ds@1952
|
907 |
//mov ecx, [ebx+<val>] |
|
ds@1952
|
908 |
//mov [ebp+ecx], eax |
|
ds@1952
|
909 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
910 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
911 |
{ |
|
ds@1952
|
912 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val); |
|
ds@1952
|
913 |
} else { |
|
ds@1952
|
914 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val); |
|
ds@1952
|
915 |
} |
|
ds@1952
|
916 |
IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI); |
|
ds@1952
|
917 |
} |
|
ds@1952
|
918 |
|
|
ds@1952
|
919 |
inline void WriteOp_Sref_S_Alt(JitWriter *jit) |
|
ds@1952
|
920 |
{ |
|
ds@1952
|
921 |
//mov ecx, [ebx+<val>] |
|
ds@1952
|
922 |
//mov [ebp+ecx], edx |
|
ds@1952
|
923 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
924 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
925 |
{ |
|
ds@1952
|
926 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val); |
|
ds@1952
|
927 |
} else { |
|
ds@1952
|
928 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val); |
|
ds@1952
|
929 |
} |
|
ds@1952
|
930 |
IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT); |
|
ds@1952
|
931 |
} |
|
ds@1952
|
932 |
|
|
ds@1952
|
933 |
inline void WriteOp_Pop_Pri(JitWriter *jit) |
|
ds@1952
|
934 |
{ |
|
ds@1952
|
935 |
//mov eax, [edi] |
|
ds@1952
|
936 |
//add edi, 4 |
|
ds@1952
|
937 |
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG); |
|
ds@1952
|
938 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
939 |
} |
|
ds@1952
|
940 |
|
|
ds@1952
|
941 |
inline void WriteOp_Pop_Alt(JitWriter *jit) |
|
ds@1952
|
942 |
{ |
|
ds@1952
|
943 |
//mov edx, [edi] |
|
ds@1952
|
944 |
//add edi, 4 |
|
ds@1952
|
945 |
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG); |
|
ds@1952
|
946 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
947 |
} |
|
ds@1952
|
948 |
|
|
ds@1952
|
949 |
inline void WriteOp_Swap_Pri(JitWriter *jit) |
|
ds@1952
|
950 |
{ |
|
ds@1952
|
951 |
//add [edi], eax |
|
ds@1952
|
952 |
//sub eax, [edi] |
|
ds@1952
|
953 |
//add [edi], eax |
|
ds@1952
|
954 |
//neg eax |
|
ds@1952
|
955 |
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG); |
|
ds@1952
|
956 |
IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG); |
|
ds@1952
|
957 |
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG); |
|
ds@1952
|
958 |
IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
959 |
} |
|
ds@1952
|
960 |
|
|
ds@1952
|
961 |
inline void WriteOp_Swap_Alt(JitWriter *jit) |
|
ds@1952
|
962 |
{ |
|
ds@1952
|
963 |
//add [edi], edx |
|
ds@1952
|
964 |
//sub edx, [edi] |
|
ds@1952
|
965 |
//add [edi], edx |
|
ds@1952
|
966 |
//neg edx |
|
ds@1952
|
967 |
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG); |
|
ds@1952
|
968 |
IA32_Sub_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG); |
|
ds@1952
|
969 |
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG); |
|
ds@1952
|
970 |
IA32_Neg_Rm(jit, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
971 |
} |
|
ds@1952
|
972 |
|
|
ds@1952
|
973 |
inline void WriteOp_PushAddr(JitWriter *jit) |
|
ds@1952
|
974 |
{ |
|
ds@1952
|
975 |
//mov ecx, [esi+frm] ;get address (offset from frame) |
|
ds@1952
|
976 |
//sub edi, 4 |
|
ds@1952
|
977 |
//add ecx, <val> |
|
ds@1952
|
978 |
//mov [edi], ecx |
|
ds@1952
|
979 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
980 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG); |
|
ds@1952
|
981 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
faluco@2029
|
982 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
983 |
{ |
|
ds@1952
|
984 |
IA32_Add_Rm_Imm8(jit, AMX_REG_TMP, (jit_int8_t)val, MOD_REG); |
|
ds@1952
|
985 |
} else { |
|
ds@1952
|
986 |
IA32_Add_Rm_Imm32(jit, AMX_REG_TMP, val, MOD_REG); |
|
ds@1952
|
987 |
} |
|
ds@1952
|
988 |
IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG); |
|
ds@1952
|
989 |
} |
|
ds@1952
|
990 |
|
|
ds@1952
|
991 |
inline void WriteOp_Movs(JitWriter *jit) |
|
ds@1952
|
992 |
{ |
|
ds@1952
|
993 |
//cld |
|
ds@1952
|
994 |
//push esi |
|
ds@1952
|
995 |
//push edi |
|
ds@1952
|
996 |
//lea esi, [ebp+eax] |
|
ds@1952
|
997 |
//lea edi, [ebp+edx] |
|
ds@1952
|
998 |
//if dword: |
|
ds@1952
|
999 |
// mov ecx, dword |
|
ds@1952
|
1000 |
// rep movsd |
|
ds@1952
|
1001 |
//if byte: |
|
ds@1952
|
1002 |
// mov ecx, byte |
|
ds@1952
|
1003 |
// rep movsb |
|
ds@1952
|
1004 |
//pop edi |
|
ds@1952
|
1005 |
//pop esi |
|
ds@1952
|
1006 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
1007 |
unsigned int dwords = val >> 2; |
|
ds@1952
|
1008 |
unsigned int bytes = val & 0x3; |
|
ds@1952
|
1009 |
|
|
ds@1952
|
1010 |
IA32_Cld(jit); |
|
ds@1952
|
1011 |
IA32_Push_Reg(jit, REG_ESI); |
|
ds@1952
|
1012 |
IA32_Push_Reg(jit, REG_EDI); |
|
ds@1952
|
1013 |
IA32_Lea_Reg_DispEBPRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
ds@1952
|
1014 |
IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE); |
|
ds@1952
|
1015 |
if (dwords) |
|
ds@1952
|
1016 |
{ |
|
ds@1952
|
1017 |
IA32_Mov_Reg_Imm32(jit, REG_ECX, dwords); |
|
ds@1952
|
1018 |
IA32_Rep(jit); |
|
ds@1952
|
1019 |
IA32_Movsd(jit); |
|
ds@1952
|
1020 |
} |
|
ds@1952
|
1021 |
if (bytes) |
|
ds@1952
|
1022 |
{ |
|
ds@1952
|
1023 |
IA32_Mov_Reg_Imm32(jit, REG_ECX, bytes); |
|
ds@1952
|
1024 |
IA32_Rep(jit); |
|
ds@1952
|
1025 |
IA32_Movsb(jit); |
|
ds@1952
|
1026 |
} |
|
ds@1952
|
1027 |
IA32_Pop_Reg(jit, REG_EDI); |
|
ds@1952
|
1028 |
IA32_Pop_Reg(jit, REG_ESI); |
|
ds@1952
|
1029 |
} |
|
ds@1952
|
1030 |
|
|
ds@1952
|
1031 |
inline void WriteOp_Fill(JitWriter *jit) |
|
ds@1952
|
1032 |
{ |
|
ds@1952
|
1033 |
//push edi |
|
ds@1952
|
1034 |
//lea edi, [ebp+edx] |
|
ds@1952
|
1035 |
//mov ecx, <val> >> 2 |
|
ds@1952
|
1036 |
//cld |
|
ds@1952
|
1037 |
//rep stosd |
|
ds@1952
|
1038 |
//pop edi |
|
ds@1952
|
1039 |
unsigned int val = jit->read_cell() >> 2; |
|
ds@1952
|
1040 |
|
|
ds@1952
|
1041 |
IA32_Push_Reg(jit, REG_EDI); |
|
ds@1952
|
1042 |
IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE); |
|
ds@1952
|
1043 |
IA32_Mov_Reg_Imm32(jit, REG_ECX, val); |
|
ds@1952
|
1044 |
IA32_Cld(jit); |
|
ds@1952
|
1045 |
IA32_Rep(jit); |
|
ds@1952
|
1046 |
IA32_Stosd(jit); |
|
ds@1952
|
1047 |
IA32_Pop_Reg(jit, REG_EDI); |
|
ds@1952
|
1048 |
} |
|
ds@1952
|
1049 |
|
|
ds@1952
|
1050 |
inline void WriteOp_GenArray(JitWriter *jit, bool autozero) |
|
ds@1952
|
1051 |
{ |
|
ds@1952
|
1052 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
1053 |
if (val == 1) |
|
ds@1952
|
1054 |
{ |
|
ds@1952
|
1055 |
/* flat array. we can generate this without indirection tables. */ |
|
ds@1952
|
1056 |
/* Note that we can overwrite ALT because technically STACK should be destroying ALT */ |
|
ds@1952
|
1057 |
//mov edx, [esi+info.heap] |
|
ds@1952
|
1058 |
//mov ecx, [edi] |
|
ds@1952
|
1059 |
//mov [edi], edx ;store base of array into stack |
|
ds@1952
|
1060 |
//lea edx, [edx+ecx*4] ;get the final new heap pointer |
|
ds@1952
|
1061 |
//mov [esi+info.heap], edx ;store heap pointer back |
|
ds@1952
|
1062 |
//add edx, ebp ;relocate |
|
ds@1952
|
1063 |
//cmp edx, edi ;compare against stack pointer |
|
ds@1952
|
1064 |
//jae :error ;error out if not enough space |
|
ds@1952
|
1065 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP); |
|
ds@1952
|
1066 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG); |
|
ds@1952
|
1067 |
IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG); |
|
ds@1952
|
1068 |
IA32_Lea_Reg_DispRegMult(jit, AMX_REG_ALT, AMX_REG_ALT, AMX_REG_TMP, SCALE4); |
|
ds@1952
|
1069 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_ALT, AMX_INFO_HEAP); |
|
ds@1952
|
1070 |
IA32_Add_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_DAT, MOD_REG); |
|
ds@1952
|
1071 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_REG); |
|
dvander@2226
|
1072 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_AE, ((CompData *)jit->data)->jit_error_heaplow); |
|
ds@1952
|
1073 |
|
|
ds@1952
|
1074 |
WriteOp_Tracker_Push_Reg(jit, REG_ECX); |
|
ds@1952
|
1075 |
|
|
ds@1952
|
1076 |
if (autozero) |
|
ds@1952
|
1077 |
{ |
|
ds@1952
|
1078 |
/* Zero out the array - inline a quick fill */ |
|
ds@1952
|
1079 |
//push eax ;save pri |
|
ds@1952
|
1080 |
//push edi ;save stk |
|
ds@1952
|
1081 |
//xor eax, eax ;zero source |
|
ds@1952
|
1082 |
//mov edi, [edi] ;get heap ptr out of the stack |
|
ds@1952
|
1083 |
//add edi, ebp ;relocate |
|
ds@1952
|
1084 |
//cld ;clear direction flag |
|
ds@1952
|
1085 |
//rep stosd ;copy (note: ECX is sane from above) |
|
ds@1952
|
1086 |
//pop edi ;pop stk |
|
ds@1952
|
1087 |
//pop eax ;pop pri |
|
ds@1952
|
1088 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
1089 |
IA32_Push_Reg(jit, REG_EDI); |
|
ds@1952
|
1090 |
IA32_Xor_Reg_Rm(jit, REG_EAX, REG_EAX, MOD_REG); |
|
ds@1952
|
1091 |
IA32_Mov_Reg_Rm(jit, REG_EDI, REG_EDI, MOD_MEM_REG); |
|
ds@1952
|
1092 |
IA32_Add_Reg_Rm(jit, REG_EDI, REG_EBP, MOD_REG); |
|
ds@1952
|
1093 |
IA32_Cld(jit); |
|
ds@1952
|
1094 |
IA32_Rep(jit); |
|
ds@1952
|
1095 |
IA32_Stosd(jit); |
|
ds@1952
|
1096 |
IA32_Pop_Reg(jit, REG_EDI); |
|
ds@1952
|
1097 |
IA32_Pop_Reg(jit, REG_EAX); |
|
ds@1952
|
1098 |
} |
|
ds@1952
|
1099 |
} else { |
|
ds@1952
|
1100 |
//mov ecx, num_dims |
|
ds@1952
|
1101 |
//mov edx, 0/1 |
|
ds@1952
|
1102 |
//call [genarray] |
|
ds@1952
|
1103 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, val); |
|
ds@1952
|
1104 |
if (autozero) |
|
ds@1952
|
1105 |
{ |
|
ds@1952
|
1106 |
IA32_Mov_Reg_Imm32(jit, REG_EDX, 1); |
|
ds@1952
|
1107 |
} else { |
|
ds@1952
|
1108 |
IA32_Mov_Reg_Imm32(jit, REG_EDX, 0); |
|
ds@1952
|
1109 |
} |
|
ds@1952
|
1110 |
jitoffs_t call = IA32_Call_Imm32(jit, 0); |
|
dvander@2226
|
1111 |
IA32_Write_Jump32_Abs(jit, call, g_Jit.GetGenArrayIntrinsic()); |
|
ds@1952
|
1112 |
} |
|
ds@1952
|
1113 |
} |
|
ds@1952
|
1114 |
|
|
ds@1952
|
1115 |
inline void WriteOp_Load_Both(JitWriter *jit) |
|
ds@1952
|
1116 |
{ |
|
ds@1952
|
1117 |
WriteOp_Load_Pri(jit); |
|
ds@1952
|
1118 |
WriteOp_Load_Alt(jit); |
|
ds@1952
|
1119 |
} |
|
ds@1952
|
1120 |
|
|
ds@1952
|
1121 |
inline void WriteOp_Load_S_Both(JitWriter *jit) |
|
ds@1952
|
1122 |
{ |
|
ds@1952
|
1123 |
WriteOp_Load_S_Pri(jit); |
|
ds@1952
|
1124 |
WriteOp_Load_S_Alt(jit); |
|
ds@1952
|
1125 |
} |
|
ds@1952
|
1126 |
|
|
ds@1952
|
1127 |
inline void WriteOp_Const(JitWriter *jit) |
|
ds@1952
|
1128 |
{ |
|
ds@1952
|
1129 |
//mov [ebp+<addr>], <val> |
|
ds@1952
|
1130 |
cell_t addr = jit->read_cell(); |
|
ds@1952
|
1131 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
1132 |
if (addr <= SCHAR_MAX && addr >= SCHAR_MIN) |
|
ds@1952
|
1133 |
{ |
|
ds@1952
|
1134 |
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, val, (jit_int8_t)addr); |
|
ds@1952
|
1135 |
} else { |
|
ds@1952
|
1136 |
IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, val, addr); |
|
ds@1952
|
1137 |
} |
|
ds@1952
|
1138 |
} |
|
ds@1952
|
1139 |
|
|
ds@1952
|
1140 |
inline void WriteOp_Const_S(JitWriter *jit) |
|
ds@1952
|
1141 |
{ |
|
ds@1952
|
1142 |
//mov [ebx+<offs>], <val> |
|
ds@1952
|
1143 |
cell_t offs = jit->read_cell(); |
|
ds@1952
|
1144 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
1145 |
if (offs <= SCHAR_MAX && offs >= SCHAR_MIN) |
|
ds@1952
|
1146 |
{ |
|
ds@1952
|
1147 |
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, val, (jit_int8_t)offs); |
|
ds@1952
|
1148 |
} else { |
|
ds@1952
|
1149 |
IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, val, offs); |
|
ds@1952
|
1150 |
} |
|
ds@1952
|
1151 |
} |
|
ds@1952
|
1152 |
|
|
ds@1952
|
1153 |
inline void WriteOp_Load_I(JitWriter *jit) |
|
ds@1952
|
1154 |
{ |
|
ds@1952
|
1155 |
//mov eax, [ebp+eax] |
|
ds@1952
|
1156 |
Write_Check_VerifyAddr(jit, AMX_REG_PRI); |
|
ds@1952
|
1157 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
ds@1952
|
1158 |
} |
|
ds@1952
|
1159 |
|
|
ds@1952
|
1160 |
inline void WriteOp_Lodb_I(JitWriter *jit) |
|
ds@1952
|
1161 |
{ |
|
ds@1952
|
1162 |
Write_Check_VerifyAddr(jit, AMX_REG_PRI); |
|
ds@1952
|
1163 |
|
|
ds@1952
|
1164 |
//mov eax, [ebp+eax] |
|
ds@1952
|
1165 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
ds@1952
|
1166 |
|
|
ds@1952
|
1167 |
//and eax, <bitmask> |
|
ds@1952
|
1168 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
1169 |
switch(val) |
|
ds@1952
|
1170 |
{ |
|
ds@1952
|
1171 |
case 1: |
|
ds@1952
|
1172 |
{ |
|
ds@1952
|
1173 |
IA32_And_Eax_Imm32(jit, 0x000000FF); |
|
ds@1952
|
1174 |
break; |
|
ds@1952
|
1175 |
} |
|
ds@1952
|
1176 |
case 2: |
|
ds@1952
|
1177 |
{ |
|
ds@1952
|
1178 |
IA32_And_Eax_Imm32(jit, 0x0000FFFF); |
|
ds@1952
|
1179 |
break; |
|
ds@1952
|
1180 |
} |
|
ds@1952
|
1181 |
} |
|
ds@1952
|
1182 |
} |
|
ds@1952
|
1183 |
|
|
ds@1952
|
1184 |
inline void WriteOp_Stor_I(JitWriter *jit) |
|
ds@1952
|
1185 |
{ |
|
ds@1952
|
1186 |
//mov [ebp+edx], eax |
|
ds@1952
|
1187 |
Write_Check_VerifyAddr(jit, AMX_REG_ALT); |
|
ds@1952
|
1188 |
IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); |
|
ds@1952
|
1189 |
} |
|
ds@1952
|
1190 |
|
|
ds@1952
|
1191 |
inline void WriteOp_Strb_I(JitWriter *jit) |
|
ds@1952
|
1192 |
{ |
|
ds@1952
|
1193 |
Write_Check_VerifyAddr(jit, AMX_REG_ALT); |
|
ds@1952
|
1194 |
//mov [ebp+edx], eax |
|
ds@1952
|
1195 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
1196 |
switch (val) |
|
ds@1952
|
1197 |
{ |
|
ds@1952
|
1198 |
case 1: |
|
ds@1952
|
1199 |
{ |
|
ds@1952
|
1200 |
IA32_Mov_Rm8EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); |
|
ds@1952
|
1201 |
break; |
|
ds@1952
|
1202 |
} |
|
ds@1952
|
1203 |
case 2: |
|
ds@1952
|
1204 |
{ |
|
ds@1952
|
1205 |
IA32_Mov_Rm16EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); |
|
ds@1952
|
1206 |
break; |
|
ds@1952
|
1207 |
} |
|
ds@1952
|
1208 |
case 4: |
|
ds@1952
|
1209 |
{ |
|
ds@1952
|
1210 |
IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); |
|
ds@1952
|
1211 |
break; |
|
ds@1952
|
1212 |
} |
|
ds@1952
|
1213 |
} |
|
ds@1952
|
1214 |
} |
|
ds@1952
|
1215 |
|
|
ds@1952
|
1216 |
inline void WriteOp_Lidx(JitWriter *jit) |
|
ds@1952
|
1217 |
{ |
|
ds@1952
|
1218 |
//lea eax, [edx+4*eax] |
|
ds@1952
|
1219 |
//mov eax, [ebp+eax] |
|
ds@1952
|
1220 |
IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4); |
|
ds@1952
|
1221 |
Write_Check_VerifyAddr(jit, AMX_REG_PRI); |
|
ds@1952
|
1222 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
ds@1952
|
1223 |
} |
|
ds@1952
|
1224 |
|
|
ds@1952
|
1225 |
inline void WriteOp_Stack(JitWriter *jit) |
|
ds@1952
|
1226 |
{ |
|
ds@1952
|
1227 |
//add edi, <val> |
|
ds@1952
|
1228 |
cell_t val = jit->read_cell(); |
|
faluco@2029
|
1229 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
1230 |
{ |
|
ds@1952
|
1231 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)val, MOD_REG); |
|
ds@1952
|
1232 |
} else { |
|
ds@1952
|
1233 |
IA32_Add_Rm_Imm32(jit, AMX_REG_STK, val, MOD_REG); |
|
ds@1952
|
1234 |
} |
|
ds@1952
|
1235 |
|
|
ds@1952
|
1236 |
if (val > 0) |
|
ds@1952
|
1237 |
{ |
|
ds@1952
|
1238 |
Write_CheckStack_Min(jit); |
|
ds@1952
|
1239 |
} else if (val < 0) { |
|
ds@1952
|
1240 |
Write_CheckStack_Low(jit); |
|
ds@1952
|
1241 |
} |
|
ds@1952
|
1242 |
} |
|
ds@1952
|
1243 |
|
|
ds@1952
|
1244 |
inline void WriteOp_StackAdjust(JitWriter *jit) |
|
ds@1952
|
1245 |
{ |
|
ds@1952
|
1246 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
1247 |
|
|
ds@1952
|
1248 |
assert(val <= 0); |
|
ds@1952
|
1249 |
|
|
ds@1952
|
1250 |
//lea edi, [ebx-val] |
|
ds@1952
|
1251 |
|
|
faluco@2029
|
1252 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
1253 |
{ |
|
ds@1952
|
1254 |
IA32_Lea_DispRegImm8(jit, AMX_REG_STK, AMX_REG_FRM, val); |
|
ds@1952
|
1255 |
} |
|
ds@1952
|
1256 |
else |
|
ds@1952
|
1257 |
{ |
|
ds@1952
|
1258 |
IA32_Lea_DispRegImm32(jit, AMX_REG_STK, AMX_REG_FRM, val); |
|
ds@1952
|
1259 |
} |
|
ds@1952
|
1260 |
|
|
ds@1952
|
1261 |
/* We assume the compiler has generated good code -- |
|
ds@1952
|
1262 |
* That is, we do not bother validating this amount! |
|
ds@1952
|
1263 |
*/ |
|
ds@1952
|
1264 |
} |
|
ds@1952
|
1265 |
|
|
ds@1952
|
1266 |
inline void WriteOp_Heap(JitWriter *jit) |
|
ds@1952
|
1267 |
{ |
|
ds@1952
|
1268 |
//mov edx, [esi+hea] |
|
ds@1952
|
1269 |
//add [esi+hea], <val> |
|
ds@1952
|
1270 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
1271 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP); |
|
faluco@2029
|
1272 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
1273 |
{ |
|
ds@1952
|
1274 |
IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_INFO, (jit_int8_t)val, AMX_INFO_HEAP); |
|
ds@1952
|
1275 |
} else { |
|
ds@1952
|
1276 |
IA32_Add_Rm_Imm32_Disp8(jit, AMX_REG_INFO, val, AMX_INFO_HEAP); |
|
ds@1952
|
1277 |
} |
|
ds@1952
|
1278 |
|
|
ds@1952
|
1279 |
/* NOTE: Backwards from op.stack */ |
|
ds@1952
|
1280 |
if (val > 0) |
|
ds@1952
|
1281 |
{ |
|
ds@1952
|
1282 |
Write_CheckHeap_Low(jit); |
|
ds@1952
|
1283 |
} else if (val < 0) { |
|
ds@1952
|
1284 |
Write_CheckHeap_Min(jit); |
|
ds@1952
|
1285 |
} |
|
ds@1952
|
1286 |
} |
|
ds@1952
|
1287 |
|
|
ds@1952
|
1288 |
inline void WriteOp_SDiv(JitWriter *jit) |
|
ds@1952
|
1289 |
{ |
|
ds@1952
|
1290 |
//mov ecx, edx |
|
ds@1952
|
1291 |
//mov edx, eax |
|
ds@1952
|
1292 |
//sar edx, 31 |
|
ds@1952
|
1293 |
//idiv ecx |
|
ds@1952
|
1294 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
1295 |
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
1296 |
IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG); |
|
ds@1952
|
1297 |
Write_Check_DivZero(jit, AMX_REG_TMP); |
|
ds@1952
|
1298 |
IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG); |
|
ds@1952
|
1299 |
} |
|
ds@1952
|
1300 |
|
|
ds@1952
|
1301 |
inline void WriteOp_SDiv_Alt(JitWriter *jit) |
|
ds@1952
|
1302 |
{ |
|
ds@1952
|
1303 |
//mov ecx, eax |
|
ds@1952
|
1304 |
//mov eax, edx |
|
ds@1952
|
1305 |
//sar edx, 31 |
|
ds@1952
|
1306 |
//idiv ecx |
|
ds@1952
|
1307 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
1308 |
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
ds@1952
|
1309 |
IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG); |
|
ds@1952
|
1310 |
Write_Check_DivZero(jit, AMX_REG_TMP); |
|
ds@1952
|
1311 |
IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG); |
|
ds@1952
|
1312 |
} |
|
ds@1952
|
1313 |
|
|
ds@1952
|
1314 |
inline void WriteOp_Retn(JitWriter *jit) |
|
ds@1952
|
1315 |
{ |
|
ds@1952
|
1316 |
//mov ebx, [edi+4] - get old frm |
|
ds@1952
|
1317 |
//add edi, 8 - pop stack |
|
ds@1952
|
1318 |
//mov [esi+frm], ebx - restore frame pointer |
|
ds@1952
|
1319 |
//add ebx, ebp - relocate |
|
ds@1952
|
1320 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_FRM, AMX_REG_STK, 4); |
|
ds@1952
|
1321 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG); |
|
ds@1952
|
1322 |
IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_FRM, MOD_MEM_REG); |
|
ds@1952
|
1323 |
IA32_Add_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG); |
|
ds@1952
|
1324 |
|
|
ds@1952
|
1325 |
/* pop params */ |
|
ds@1952
|
1326 |
//mov ecx, [edi] |
|
ds@1952
|
1327 |
//lea edi, [edi+ecx*4+4] |
|
ds@1952
|
1328 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG); |
|
ds@1952
|
1329 |
IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_STK, AMX_REG_STK, AMX_REG_TMP, SCALE4, 4); |
|
ds@1952
|
1330 |
|
|
ds@1952
|
1331 |
//ret - return (EIP on real stack!) |
|
ds@1952
|
1332 |
IA32_Return(jit); |
|
ds@1952
|
1333 |
} |
|
ds@1952
|
1334 |
|
|
ds@1952
|
1335 |
void ProfCallGate_Begin(sp_context_t *ctx, const char *name) |
|
ds@1952
|
1336 |
{ |
|
dvander@2193
|
1337 |
((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionBegin((IPluginContext *)ctx->vm[JITVARS_BASECTX], name); |
|
ds@1952
|
1338 |
} |
|
ds@1952
|
1339 |
|
|
ds@1952
|
1340 |
void ProfCallGate_End(sp_context_t *ctx) |
|
ds@1952
|
1341 |
{ |
|
dvander@2193
|
1342 |
((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionEnd(); |
|
ds@1952
|
1343 |
} |
|
ds@1952
|
1344 |
|
|
ds@1952
|
1345 |
const char *find_func_name(sp_plugin_t *plugin, uint32_t offs) |
|
ds@1952
|
1346 |
{ |
|
ds@1952
|
1347 |
uint32_t max, iter; |
|
ds@1952
|
1348 |
sp_fdbg_symbol_t *sym; |
|
ds@1952
|
1349 |
sp_fdbg_arraydim_t *arr; |
|
ds@1952
|
1350 |
uint8_t *cursor = (uint8_t *)(plugin->debug.symbols); |
|
ds@1952
|
1351 |
|
|
ds@1952
|
1352 |
max = plugin->debug.syms_num; |
|
ds@1952
|
1353 |
for (iter = 0; iter < max; iter++) |
|
ds@1952
|
1354 |
{ |
|
ds@1952
|
1355 |
sym = (sp_fdbg_symbol_t *)cursor; |
|
ds@1952
|
1356 |
|
|
ds@1952
|
1357 |
if (sym->ident == SP_SYM_FUNCTION |
|
ds@1952
|
1358 |
&& sym->codestart <= offs |
|
ds@1952
|
1359 |
&& sym->codeend > offs) |
|
ds@1952
|
1360 |
{ |
|
ds@1952
|
1361 |
return plugin->debug.stringbase + sym->name; |
|
ds@1952
|
1362 |
} |
|
ds@1952
|
1363 |
|
|
ds@1952
|
1364 |
if (sym->dimcount > 0) |
|
ds@1952
|
1365 |
{ |
|
ds@1952
|
1366 |
cursor += sizeof(sp_fdbg_symbol_t); |
|
ds@1952
|
1367 |
arr = (sp_fdbg_arraydim_t *)cursor; |
|
ds@1952
|
1368 |
cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount; |
|
ds@1952
|
1369 |
continue; |
|
ds@1952
|
1370 |
} |
|
ds@1952
|
1371 |
|
|
ds@1952
|
1372 |
cursor += sizeof(sp_fdbg_symbol_t); |
|
ds@1952
|
1373 |
} |
|
ds@1952
|
1374 |
|
|
ds@1952
|
1375 |
return NULL; |
|
ds@1952
|
1376 |
} |
|
ds@1952
|
1377 |
|
|
ds@1952
|
1378 |
inline void WriteOp_Call(JitWriter *jit) |
|
ds@1952
|
1379 |
{ |
|
ds@1952
|
1380 |
cell_t offs; |
|
ds@1952
|
1381 |
jitoffs_t jmp; |
|
ds@1952
|
1382 |
CompData *data; |
|
dvander@2226
|
1383 |
uint32_t func_idx; |
|
dvander@2226
|
1384 |
|
|
ds@1952
|
1385 |
data = (CompData *)jit->data; |
|
ds@1952
|
1386 |
offs = jit->read_cell(); |
|
ds@1952
|
1387 |
|
|
dvander@2226
|
1388 |
/* Get the context + rp */ |
|
dvander@2226
|
1389 |
//mov eax, [esi+ctx] |
|
dvander@2226
|
1390 |
//mov ecx, [eax+rp] |
|
dvander@2226
|
1391 |
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT); |
|
dvander@2226
|
1392 |
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, rp)); |
|
dvander@2226
|
1393 |
|
|
dvander@2226
|
1394 |
/* Check if the return stack is used up. */ |
|
dvander@2226
|
1395 |
//cmp ecx, <max stack> |
|
dvander@2226
|
1396 |
//jae :stacklow |
|
dvander@2226
|
1397 |
IA32_Cmp_Rm_Imm32(jit, MOD_REG, REG_ECX, SP_MAX_RETURN_STACK); |
|
dvander@2226
|
1398 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_AE, data->jit_error_stacklow); |
|
dvander@2226
|
1399 |
|
|
dvander@2226
|
1400 |
/* Add us to the return stack */ |
|
dvander@2226
|
1401 |
//mov [eax+ecx*4+cips], cip |
|
dvander@2226
|
1402 |
IA32_Mov_Rm_Imm32_SIB(jit, |
|
dvander@2226
|
1403 |
REG_EAX, |
|
dvander@2226
|
1404 |
(uint8_t *)(jit->inptr - 2) - data->plugin->pcode, |
|
dvander@2226
|
1405 |
offsetof(sp_context_t, rstk_cips), |
|
dvander@2226
|
1406 |
REG_ECX, |
|
dvander@2226
|
1407 |
SCALE4); |
|
dvander@2226
|
1408 |
|
|
dvander@2226
|
1409 |
/* Increment the return stack pointer */ |
|
dvander@2226
|
1410 |
//inc [eax+rp] |
|
dvander@2226
|
1411 |
if ((int)offsetof(sp_context_t, rp) >= SCHAR_MIN && (int)offsetof(sp_context_t, rp) <= SCHAR_MAX) |
|
ds@1952
|
1412 |
{ |
|
dvander@2226
|
1413 |
IA32_Inc_Rm_Disp8(jit, REG_EAX, offsetof(sp_context_t, rp)); |
|
ds@1952
|
1414 |
} |
|
ds@1952
|
1415 |
else |
|
ds@1952
|
1416 |
{ |
|
dvander@2226
|
1417 |
IA32_Inc_Rm_Disp32(jit, REG_EAX, offsetof(sp_context_t, rp)); |
|
dvander@2226
|
1418 |
} |
|
dvander@2226
|
1419 |
|
|
dvander@2226
|
1420 |
/* Store the CIP of the function we're about to call. */ |
|
dvander@2226
|
1421 |
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_INFO, offs, AMX_INFO_CIP); |
|
dvander@2226
|
1422 |
|
|
dvander@2226
|
1423 |
/* Call the function */ |
|
dvander@2226
|
1424 |
func_idx = FuncLookup(data, offs); |
|
dvander@2226
|
1425 |
|
|
dvander@2226
|
1426 |
/* We need to emit a delayed thunk instead. */ |
|
dvander@2226
|
1427 |
if (func_idx == 0) |
|
dvander@2226
|
1428 |
{ |
|
dvander@2226
|
1429 |
if (jit->outbase == NULL) |
|
dvander@2226
|
1430 |
{ |
|
dvander@2226
|
1431 |
data->num_thunks++; |
|
dvander@2226
|
1432 |
|
|
dvander@2226
|
1433 |
/* We still emit the call because we need consistent size counting */ |
|
dvander@2226
|
1434 |
IA32_Call_Imm32(jit, 0); |
|
dvander@2226
|
1435 |
} |
|
dvander@2226
|
1436 |
else |
|
dvander@2226
|
1437 |
{ |
|
dvander@2226
|
1438 |
call_thunk_t *thunk; |
|
dvander@2226
|
1439 |
|
|
dvander@2226
|
1440 |
/* Find the thunk we're associated with */ |
|
dvander@2226
|
1441 |
thunk = &data->thunks[data->num_thunks]; |
|
dvander@2226
|
1442 |
data->num_thunks++; |
|
dvander@2226
|
1443 |
|
|
dvander@2226
|
1444 |
/* Emit the call, save its target position. |
|
dvander@2226
|
1445 |
* Save thunk info, then patch the target to the thunk. |
|
dvander@2226
|
1446 |
*/ |
|
dvander@2226
|
1447 |
thunk->patch_addr = IA32_Call_Imm32(jit, 0); |
|
dvander@2226
|
1448 |
thunk->pcode_offs = offs; |
|
dvander@2226
|
1449 |
IA32_Write_Jump32(jit, thunk->patch_addr, thunk->thunk_addr); |
|
dvander@2226
|
1450 |
} |
|
dvander@2226
|
1451 |
} |
|
dvander@2226
|
1452 |
/* The function is already jitted. We can emit a direct call. */ |
|
dvander@2226
|
1453 |
else |
|
dvander@2226
|
1454 |
{ |
|
dvander@2226
|
1455 |
JitFunction *fn; |
|
dvander@2226
|
1456 |
|
|
dvander@2226
|
1457 |
fn = data->runtime->GetJittedFunction(func_idx); |
|
ds@1952
|
1458 |
jmp = IA32_Call_Imm32(jit, 0); |
|
dvander@2226
|
1459 |
IA32_Write_Jump32_Abs(jit, jmp, fn->GetEntryAddress()); |
|
ds@1952
|
1460 |
} |
|
dvander@2226
|
1461 |
|
|
dvander@2226
|
1462 |
/* Restore the last cip */ |
|
dvander@2226
|
1463 |
//mov [esi+cip], <cip> |
|
dvander@2226
|
1464 |
IA32_Mov_Rm_Imm32_Disp8(jit, |
|
dvander@2226
|
1465 |
AMX_REG_INFO, |
|
dvander@2226
|
1466 |
(uint8_t *)(jit->inptr - 2) - data->plugin->pcode, |
|
dvander@2226
|
1467 |
AMX_INFO_CIP); |
|
dvander@2226
|
1468 |
|
|
dvander@2226
|
1469 |
/* Mark us as leaving the last frame. */ |
|
dvander@2226
|
1470 |
//mov ecx, [esi+ctx] |
|
dvander@2226
|
1471 |
//dec [ecx+rp] |
|
dvander@2226
|
1472 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); |
|
dvander@2226
|
1473 |
IA32_Dec_Rm_Disp8(jit, REG_ECX, offsetof(sp_context_t, rp)); |
|
ds@1952
|
1474 |
} |
|
ds@1952
|
1475 |
|
|
ds@1952
|
1476 |
inline void WriteOp_Bounds(JitWriter *jit) |
|
ds@1952
|
1477 |
{ |
|
ds@1952
|
1478 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
1479 |
|
|
ds@1952
|
1480 |
//cmp eax, <val> |
|
ds@1952
|
1481 |
//ja :error |
|
faluco@2029
|
1482 |
if (val <= SCHAR_MAX && val >= SCHAR_MIN) |
|
ds@1952
|
1483 |
{ |
|
ds@1952
|
1484 |
IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val); |
|
ds@1952
|
1485 |
} else { |
|
ds@1952
|
1486 |
IA32_Cmp_Eax_Imm32(jit, val); |
|
ds@1952
|
1487 |
} |
|
dvander@2226
|
1488 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_A, ((CompData *)jit->data)->jit_error_bounds); |
|
ds@1952
|
1489 |
} |
|
ds@1952
|
1490 |
|
|
ds@1952
|
1491 |
inline void WriteOp_Halt(JitWriter *jit) |
|
ds@1952
|
1492 |
{ |
|
ds@1952
|
1493 |
AlignMe(jit); |
|
ds@1952
|
1494 |
|
|
ds@1952
|
1495 |
//mov ecx, [esi+ret] |
|
ds@1952
|
1496 |
//mov [ecx], eax |
|
ds@1952
|
1497 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_RETVAL); |
|
ds@1952
|
1498 |
IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_MEM_REG); |
|
ds@1952
|
1499 |
|
|
ds@1952
|
1500 |
/* :TODO: |
|
ds@1952
|
1501 |
* We don't support sleeping or halting with weird values. |
|
ds@1952
|
1502 |
* So we're omitting the mov eax <val> that was here. |
|
ds@1952
|
1503 |
*/ |
|
ds@1952
|
1504 |
jit->read_cell(); |
|
ds@1952
|
1505 |
|
|
dvander@2226
|
1506 |
IA32_Jump_Imm32_Abs(jit, g_Jit.GetReturnPoint()); |
|
ds@1952
|
1507 |
} |
|
ds@1952
|
1508 |
|
|
ds@1952
|
1509 |
inline void WriteOp_Break(JitWriter *jit) |
|
ds@1952
|
1510 |
{ |
|
dvander@2226
|
1511 |
CompData *data; |
|
dvander@2226
|
1512 |
|
|
dvander@2226
|
1513 |
data = (CompData *)jit->data; |
|
dvander@2226
|
1514 |
|
|
dvander@2226
|
1515 |
//mov [esi+cip], <cip> |
|
dvander@2226
|
1516 |
IA32_Mov_Rm_Imm32_Disp8(jit, |
|
dvander@2226
|
1517 |
AMX_REG_INFO, |
|
dvander@2226
|
1518 |
(uint8_t *)(jit->inptr - 1) - data->plugin->pcode, |
|
dvander@2226
|
1519 |
AMX_INFO_CIP); |
|
ds@1952
|
1520 |
} |
|
ds@1952
|
1521 |
|
|
ds@1952
|
1522 |
inline void WriteOp_Jump(JitWriter *jit) |
|
ds@1952
|
1523 |
{ |
|
ds@1952
|
1524 |
//jmp <offs> |
|
ds@1952
|
1525 |
cell_t amx_offs = jit->read_cell(); |
|
dvander@2226
|
1526 |
IA32_Jump_Imm32_Rel(jit, RelocLookup(jit, amx_offs, false)); |
|
ds@1952
|
1527 |
} |
|
ds@1952
|
1528 |
|
|
ds@1952
|
1529 |
inline void WriteOp_Jzer(JitWriter *jit) |
|
ds@1952
|
1530 |
{ |
|
ds@1952
|
1531 |
//test eax, eax |
|
ds@1952
|
1532 |
//jz <target> |
|
ds@1952
|
1533 |
cell_t target = jit->read_cell(); |
|
ds@1952
|
1534 |
IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); |
|
dvander@2226
|
1535 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_Z, RelocLookup(jit, target, false)); |
|
ds@1952
|
1536 |
} |
|
ds@1952
|
1537 |
|
|
ds@1952
|
1538 |
inline void WriteOp_Jnz(JitWriter *jit) |
|
ds@1952
|
1539 |
{ |
|
ds@1952
|
1540 |
//test eax, eax |
|
ds@1952
|
1541 |
//jnz <target> |
|
ds@1952
|
1542 |
cell_t target = jit->read_cell(); |
|
ds@1952
|
1543 |
IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); |
|
dvander@2226
|
1544 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_NZ, RelocLookup(jit, target, false)); |
|
ds@1952
|
1545 |
} |
|
ds@1952
|
1546 |
|
|
ds@1952
|
1547 |
inline void WriteOp_Jeq(JitWriter *jit) |
|
ds@1952
|
1548 |
{ |
|
ds@1952
|
1549 |
//cmp eax, edx |
|
ds@1952
|
1550 |
//je <target> |
|
ds@1952
|
1551 |
cell_t target = jit->read_cell(); |
|
ds@1952
|
1552 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@2226
|
1553 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_E, RelocLookup(jit, target, false)); |
|
ds@1952
|
1554 |
} |
|
ds@1952
|
1555 |
|
|
ds@1952
|
1556 |
inline void WriteOp_Jneq(JitWriter *jit) |
|
ds@1952
|
1557 |
{ |
|
ds@1952
|
1558 |
//cmp eax, edx |
|
ds@1952
|
1559 |
//jne <target> |
|
ds@1952
|
1560 |
cell_t target = jit->read_cell(); |
|
ds@1952
|
1561 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@2226
|
1562 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_NE, RelocLookup(jit, target, false)); |
|
ds@1952
|
1563 |
} |
|
ds@1952
|
1564 |
|
|
ds@1952
|
1565 |
inline void WriteOp_Jsless(JitWriter *jit) |
|
ds@1952
|
1566 |
{ |
|
ds@1952
|
1567 |
//cmp eax, edx |
|
ds@1952
|
1568 |
//jl <target> |
|
ds@1952
|
1569 |
cell_t target = jit->read_cell(); |
|
ds@1952
|
1570 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@2226
|
1571 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_L, RelocLookup(jit, target, false)); |
|
ds@1952
|
1572 |
} |
|
ds@1952
|
1573 |
|
|
ds@1952
|
1574 |
inline void WriteOp_Jsleq(JitWriter *jit) |
|
ds@1952
|
1575 |
{ |
|
ds@1952
|
1576 |
//cmp eax, edx |
|
ds@1952
|
1577 |
//jle <target> |
|
ds@1952
|
1578 |
cell_t target = jit->read_cell(); |
|
ds@1952
|
1579 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@2226
|
1580 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_LE, RelocLookup(jit, target, false)); |
|
ds@1952
|
1581 |
} |
|
ds@1952
|
1582 |
|
|
ds@1952
|
1583 |
inline void WriteOp_JsGrtr(JitWriter *jit) |
|
ds@1952
|
1584 |
{ |
|
ds@1952
|
1585 |
//cmp eax, edx |
|
ds@1952
|
1586 |
//jg <target> |
|
ds@1952
|
1587 |
cell_t target = jit->read_cell(); |
|
ds@1952
|
1588 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@2226
|
1589 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_G, RelocLookup(jit, target, false)); |
|
ds@1952
|
1590 |
} |
|
ds@1952
|
1591 |
|
|
ds@1952
|
1592 |
inline void WriteOp_JsGeq(JitWriter *jit) |
|
ds@1952
|
1593 |
{ |
|
ds@1952
|
1594 |
//cmp eax, edx |
|
ds@1952
|
1595 |
//jge <target> |
|
ds@1952
|
1596 |
cell_t target = jit->read_cell(); |
|
ds@1952
|
1597 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@2226
|
1598 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_GE, RelocLookup(jit, target, false)); |
|
ds@1952
|
1599 |
} |
|
ds@1952
|
1600 |
|
|
ds@1952
|
1601 |
inline void WriteOp_Switch(JitWriter *jit) |
|
ds@1952
|
1602 |
{ |
|
ds@1952
|
1603 |
cell_t offs = jit->read_cell(); |
|
ds@1952
|
1604 |
cell_t *tbl = (cell_t *)((char *)jit->inbase + offs + sizeof(cell_t)); |
|
ds@1952
|
1605 |
|
|
ds@1952
|
1606 |
struct casetbl |
|
ds@1952
|
1607 |
{ |
|
ds@1952
|
1608 |
cell_t val; |
|
ds@1952
|
1609 |
cell_t offs; |
|
ds@1952
|
1610 |
}; |
|
ds@1952
|
1611 |
|
|
ds@1952
|
1612 |
/* Read the number of cases, then advance by one */ |
|
ds@1952
|
1613 |
cell_t num_cases = *tbl++; |
|
ds@1952
|
1614 |
if (!num_cases) |
|
ds@1952
|
1615 |
{ |
|
ds@1952
|
1616 |
/* Special treatment for 0 cases */ |
|
ds@1952
|
1617 |
//jmp <default> |
|
dvander@2226
|
1618 |
IA32_Jump_Imm32_Rel(jit, RelocLookup(jit, *tbl, false)); |
|
ds@1952
|
1619 |
} else { |
|
ds@1952
|
1620 |
/* Check if the case layout is fully sequential */ |
|
ds@1952
|
1621 |
casetbl *iter = (casetbl *)(tbl + 1); |
|
ds@1952
|
1622 |
casetbl *cases = iter; |
|
ds@1952
|
1623 |
cell_t first = iter[0].val; |
|
ds@1952
|
1624 |
cell_t last = first; |
|
ds@1952
|
1625 |
bool sequential = true; |
|
ds@1952
|
1626 |
for (cell_t i=1; i<num_cases; i++) |
|
ds@1952
|
1627 |
{ |
|
ds@1952
|
1628 |
if (iter[i].val != ++last) |
|
ds@1952
|
1629 |
{ |
|
ds@1952
|
1630 |
sequential = false; |
|
ds@1952
|
1631 |
break; |
|
ds@1952
|
1632 |
} |
|
ds@1952
|
1633 |
} |
|
ds@1952
|
1634 |
/* Time to generate. |
|
ds@1952
|
1635 |
* First check whether the bounds are correct: if (a < LOW || a > HIGH) |
|
ds@1952
|
1636 |
* This check is valid for both sequential and non-sequential. |
|
ds@1952
|
1637 |
*/ |
|
ds@1952
|
1638 |
cell_t low_bound = cases[0].val; |
|
ds@1952
|
1639 |
if (low_bound != 0) |
|
ds@1952
|
1640 |
{ |
|
ds@1952
|
1641 |
/* negate it so we'll get a lower bound of 0 */ |
|
ds@1952
|
1642 |
//lea ecx, [eax-<LOWER_BOUND>] |
|
ds@1952
|
1643 |
low_bound = -low_bound; |
|
faluco@2029
|
1644 |
if (low_bound >= SCHAR_MIN && low_bound <= SCHAR_MAX) |
|
ds@1952
|
1645 |
{ |
|
ds@1952
|
1646 |
IA32_Lea_DispRegImm8(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound); |
|
ds@1952
|
1647 |
} else { |
|
ds@1952
|
1648 |
IA32_Lea_DispRegImm32(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound); |
|
ds@1952
|
1649 |
} |
|
ds@1952
|
1650 |
} else { |
|
ds@1952
|
1651 |
//mov ecx, eax |
|
ds@1952
|
1652 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG); |
|
ds@1952
|
1653 |
} |
|
ds@1952
|
1654 |
cell_t high_bound = abs(cases[0].val - cases[num_cases-1].val); |
|
ds@1952
|
1655 |
//cmp ecx, <UPPER BOUND BOUND> |
|
faluco@2029
|
1656 |
if (high_bound >= SCHAR_MIN && high_bound <= SCHAR_MAX) |
|
ds@1952
|
1657 |
{ |
|
ds@1952
|
1658 |
IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_TMP, high_bound); |
|
ds@1952
|
1659 |
} else { |
|
ds@1952
|
1660 |
IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_TMP, high_bound); |
|
ds@1952
|
1661 |
} |
|
ds@1952
|
1662 |
//ja <default case> |
|
dvander@2226
|
1663 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_A, RelocLookup(jit, *tbl, false)); |
|
ds@1952
|
1664 |
|
|
ds@1952
|
1665 |
/** |
|
ds@1952
|
1666 |
* Now we've taken the default case out of the way, it's time to do the |
|
ds@1952
|
1667 |
* full check, which is different for sequential vs. non-sequential. |
|
ds@1952
|
1668 |
*/ |
|
ds@1952
|
1669 |
if (sequential) |
|
ds@1952
|
1670 |
{ |
|
ds@1952
|
1671 |
/* we're now theoretically guaranteed to be jumping to a correct offset. |
|
ds@1952
|
1672 |
* ECX still has the correctly bound offset in it, luckily! |
|
ds@1952
|
1673 |
* thus, we simply need to relocate ECX and store the cases. |
|
ds@1952
|
1674 |
*/ |
|
ds@1952
|
1675 |
//lea ecx, [ecx*4] |
|
ds@1952
|
1676 |
//add ecx, <case table start> |
|
ds@1952
|
1677 |
IA32_Lea_Reg_RegMultImm32(jit, AMX_REG_TMP, AMX_REG_TMP, SCALE4, 0); |
|
ds@1952
|
1678 |
jitoffs_t tbl_offs = IA32_Add_Rm_Imm32_Later(jit, AMX_REG_TMP, MOD_REG); |
|
ds@1952
|
1679 |
IA32_Jump_Rm(jit, AMX_REG_TMP, MOD_MEM_REG); |
|
ds@1952
|
1680 |
/* The case table starts here. Go back and write the output pointer. */ |
|
ds@1952
|
1681 |
jitoffs_t cur_pos = jit->get_outputpos(); |
|
ds@1952
|
1682 |
jit->set_outputpos(tbl_offs); |
|
ds@1952
|
1683 |
jit->write_uint32((jit_uint32_t)(jit->outbase + cur_pos)); |
|
ds@1952
|
1684 |
jit->set_outputpos(cur_pos); |
|
ds@1952
|
1685 |
//now we can write the case table, finally! |
|
ds@1952
|
1686 |
jit_uint32_t base = (jit_uint32_t)jit->outbase; |
|
ds@1952
|
1687 |
for (cell_t i=0; i<num_cases; i++) |
|
ds@1952
|
1688 |
{ |
|
ds@1952
|
1689 |
jit->write_uint32(base + RelocLookup(jit, cases[i].offs, false)); |
|
ds@1952
|
1690 |
} |
|
ds@1952
|
1691 |
} else { |
|
ds@1952
|
1692 |
/* The slow version. Go through each case and generate a check. |
|
ds@1952
|
1693 |
* In the future we should replace case tables of more than ~8 cases with a |
|
ds@1952
|
1694 |
* hash table lookup. |
|
ds@1952
|
1695 |
* :THOUGHT: Another method of optimizing this - fill in the gaps with jumps to the default case, |
|
ds@1952
|
1696 |
* but only if we're under N cases or so! |
|
ds@1952
|
1697 |
* :THOUGHT: Write out a static btree lookup :) |
|
ds@1952
|
1698 |
*/ |
|
ds@1952
|
1699 |
cell_t val; |
|
ds@1952
|
1700 |
for (cell_t i=0; i<num_cases; i++) |
|
ds@1952
|
1701 |
{ |
|
ds@1952
|
1702 |
val = cases[i].val; |
|
ds@1952
|
1703 |
//cmp eax, <val> OR cmp al, <val> |
|
faluco@2029
|
1704 |
if (val >= SCHAR_MIN && val <= SCHAR_MAX) |
|
ds@1952
|
1705 |
{ |
|
ds@1952
|
1706 |
IA32_Cmp_Al_Imm8(jit, val); |
|
ds@1952
|
1707 |
} else { |
|
ds@1952
|
1708 |
IA32_Cmp_Eax_Imm32(jit, cases[i].val); |
|
ds@1952
|
1709 |
} |
|
dvander@2226
|
1710 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_E, RelocLookup(jit, cases[i].offs, false)); |
|
ds@1952
|
1711 |
} |
|
ds@1952
|
1712 |
/* After all this, jump to the default case! */ |
|
dvander@2226
|
1713 |
IA32_Jump_Imm32_Rel(jit, RelocLookup(jit, *tbl, false)); |
|
ds@1952
|
1714 |
} |
|
ds@1952
|
1715 |
} |
|
ds@1952
|
1716 |
} |
|
ds@1952
|
1717 |
|
|
ds@1952
|
1718 |
inline void WriteOp_Casetbl(JitWriter *jit) |
|
ds@1952
|
1719 |
{ |
|
ds@1952
|
1720 |
/* do nothing here, switch does all ze work */ |
|
ds@1952
|
1721 |
cell_t num_cases = jit->read_cell(); |
|
ds@1952
|
1722 |
|
|
ds@1952
|
1723 |
/* Two cells per case, one extra case for the default jump */ |
|
ds@1952
|
1724 |
num_cases = (num_cases * 2) + 1; |
|
ds@1952
|
1725 |
jit->inptr += num_cases; |
|
ds@1952
|
1726 |
} |
|
ds@1952
|
1727 |
|
|
ds@1952
|
1728 |
inline void WriteOp_Sysreq_C(JitWriter *jit) |
|
ds@1952
|
1729 |
{ |
|
ds@1952
|
1730 |
/* store the number of parameters on the stack, |
|
ds@1952
|
1731 |
* and store the native index as well. |
|
ds@1952
|
1732 |
*/ |
|
ds@1952
|
1733 |
cell_t native_index = jit->read_cell(); |
|
ds@1952
|
1734 |
|
|
dvander@2226
|
1735 |
if ((uint32_t)native_index >= ((CompData*)jit->data)->plugin->num_natives) |
|
ds@1952
|
1736 |
{ |
|
ds@1952
|
1737 |
((CompData *)jit->data)->error_set = SP_ERROR_INSTRUCTION_PARAM; |
|
ds@1952
|
1738 |
return; |
|
ds@1952
|
1739 |
} |
|
ds@1952
|
1740 |
|
|
ds@1952
|
1741 |
//mov ecx, <native_index> |
|
ds@1952
|
1742 |
IA32_Mov_Reg_Imm32(jit, REG_ECX, native_index); |
|
ds@1952
|
1743 |
|
|
ds@1952
|
1744 |
jitoffs_t call = IA32_Call_Imm32(jit, 0); |
|
ds@1952
|
1745 |
IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_sysreq_c); |
|
ds@1952
|
1746 |
} |
|
ds@1952
|
1747 |
|
|
ds@1952
|
1748 |
inline void WriteOp_Sysreq_N(JitWriter *jit) |
|
ds@1952
|
1749 |
{ |
|
ds@1952
|
1750 |
/* The big daddy of opcodes. */ |
|
ds@1952
|
1751 |
cell_t native_index = jit->read_cell(); |
|
ds@1952
|
1752 |
cell_t num_params = jit->read_cell(); |
|
ds@1952
|
1753 |
CompData *data = (CompData *)jit->data; |
|
ds@1952
|
1754 |
|
|
dvander@2226
|
1755 |
if ((uint32_t)native_index >= data->plugin->num_natives) |
|
ds@1952
|
1756 |
{ |
|
ds@1952
|
1757 |
data->error_set = SP_ERROR_INSTRUCTION_PARAM; |
|
ds@1952
|
1758 |
return; |
|
ds@1952
|
1759 |
} |
|
ds@1952
|
1760 |
|
|
ds@1952
|
1761 |
/* store the number of parameters on the stack */ |
|
ds@1952
|
1762 |
//mov [edi-4], num_params |
|
ds@1952
|
1763 |
//sub edi, 4 |
|
ds@1952
|
1764 |
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, num_params, -4); |
|
ds@1952
|
1765 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
1766 |
|
|
ds@1952
|
1767 |
/* save registers we will need */ |
|
ds@1952
|
1768 |
//push edx |
|
ds@1952
|
1769 |
IA32_Push_Reg(jit, AMX_REG_ALT); |
|
ds@1952
|
1770 |
|
|
ds@1952
|
1771 |
/* Align the stack to 16 bytes */ |
|
ds@1952
|
1772 |
//push ebx |
|
ds@1952
|
1773 |
//mov ebx, esp |
|
ds@1952
|
1774 |
//and esp, 0xFFFFFF0 |
|
ds@1952
|
1775 |
//sub esp, 4 |
|
ds@1952
|
1776 |
IA32_Push_Reg(jit, REG_EBX); |
|
ds@1952
|
1777 |
IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG); |
|
ds@1952
|
1778 |
IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16); |
|
ds@1952
|
1779 |
IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); |
|
ds@1952
|
1780 |
|
|
ds@1952
|
1781 |
/* push some callback stuff */ |
|
ds@1952
|
1782 |
//push edi ; stack |
|
ds@1952
|
1783 |
//push <native> ; native index |
|
ds@1952
|
1784 |
IA32_Push_Reg(jit, AMX_REG_STK); |
|
faluco@2029
|
1785 |
if (native_index <= SCHAR_MAX && native_index >= SCHAR_MIN) |
|
ds@1952
|
1786 |
{ |
|
ds@1952
|
1787 |
IA32_Push_Imm8(jit, (jit_int8_t)native_index); |
|
ds@1952
|
1788 |
} else { |
|
ds@1952
|
1789 |
IA32_Push_Imm32(jit, native_index); |
|
ds@1952
|
1790 |
} |
|
ds@1952
|
1791 |
|
|
ds@1952
|
1792 |
/* Relocate stack, heap, frm information, then store back */ |
|
ds@1952
|
1793 |
//mov eax, [esi+context] |
|
ds@1952
|
1794 |
//mov ecx, [esi+hea] |
|
ds@1952
|
1795 |
//sub edi, ebp |
|
ds@1952
|
1796 |
//mov [eax+hp], ecx |
|
ds@1952
|
1797 |
//mov ecx, [esi] |
|
ds@1952
|
1798 |
//mov [eax+sp], edi |
|
ds@1952
|
1799 |
//mov [eax+frm], ecx |
|
ds@1952
|
1800 |
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT); |
|
ds@1952
|
1801 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP); |
|
ds@1952
|
1802 |
IA32_Sub_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG); |
|
ds@1952
|
1803 |
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, hp)); |
|
ds@1952
|
1804 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG); |
|
ds@1952
|
1805 |
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_STK, offsetof(sp_context_t, sp)); |
|
ds@1952
|
1806 |
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, frm)); |
|
ds@1952
|
1807 |
|
|
ds@1952
|
1808 |
/* finally, push the last parameter and make the call */ |
|
ds@1952
|
1809 |
//push eax ; context |
|
ds@1952
|
1810 |
//call NativeCallback |
|
ds@1952
|
1811 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
1812 |
jitoffs_t call = IA32_Call_Imm32(jit, 0); |
|
dvander@2226
|
1813 |
if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES) |
|
ds@1952
|
1814 |
{ |
|
dvander@2226
|
1815 |
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Profile); |
|
ds@1952
|
1816 |
} |
|
ds@1952
|
1817 |
else |
|
ds@1952
|
1818 |
{ |
|
dvander@2226
|
1819 |
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback); |
|
ds@1952
|
1820 |
} |
|
ds@1952
|
1821 |
|
|
ds@1952
|
1822 |
/* check for errors */ |
|
ds@1952
|
1823 |
//mov ecx, [esi+context] |
|
ds@1952
|
1824 |
//cmp [ecx+err], 0 |
|
ds@1952
|
1825 |
//jnz :error |
|
ds@1952
|
1826 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); |
|
ds@1952
|
1827 |
IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, n_err), 0); |
|
dvander@2226
|
1828 |
IA32_Jump_Cond_Imm32_Rel(jit, CC_NZ, data->jit_extern_error); |
|
ds@1952
|
1829 |
|
|
ds@1952
|
1830 |
/* restore what we damaged */ |
|
ds@1952
|
1831 |
//mov esp, ebx |
|
ds@1952
|
1832 |
//pop ebx |
|
ds@1952
|
1833 |
//add edi, ebp |
|
ds@1952
|
1834 |
//pop edx |
|
ds@1952
|
1835 |
IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG); |
|
ds@1952
|
1836 |
IA32_Pop_Reg(jit, REG_EBX); |
|
ds@1952
|
1837 |
IA32_Add_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG); |
|
ds@1952
|
1838 |
IA32_Pop_Reg(jit, AMX_REG_ALT); |
|
ds@1952
|
1839 |
|
|
ds@1952
|
1840 |
/* pop the stack. do not check the margins. |
|
ds@1952
|
1841 |
* Note that this is not a true macro - we don't bother to |
|
ds@1952
|
1842 |
* set ALT here because nothing will be using it. |
|
ds@1952
|
1843 |
*/ |
|
ds@1952
|
1844 |
num_params++; |
|
ds@1952
|
1845 |
num_params *= 4; |
|
ds@1952
|
1846 |
//add edi, <val*4+4> |
|
faluco@2029
|
1847 |
if (num_params <= SCHAR_MAX && num_params >= SCHAR_MIN) |
|
ds@1952
|
1848 |
{ |
|
ds@1952
|
1849 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)num_params, MOD_REG); |
|
ds@1952
|
1850 |
} else { |
|
ds@1952
|
1851 |
IA32_Add_Rm_Imm32(jit, AMX_REG_STK, num_params, MOD_REG); |
|
ds@1952
|
1852 |
} |
|
ds@1952
|
1853 |
} |
|
ds@1952
|
1854 |
|
|
ds@1952
|
1855 |
inline void WriteOp_Tracker_Push_C(JitWriter *jit) |
|
ds@1952
|
1856 |
{ |
|
ds@1952
|
1857 |
cell_t val = jit->read_cell(); |
|
ds@1952
|
1858 |
|
|
ds@1952
|
1859 |
/* Save registers that may be damaged by the call */ |
|
ds@1952
|
1860 |
//push eax |
|
ds@1952
|
1861 |
//push edx |
|
ds@1952
|
1862 |
IA32_Push_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
1863 |
IA32_Push_Reg(jit, AMX_REG_ALT); |
|
ds@1952
|
1864 |
|
|
ds@1952
|
1865 |
/* Get the context ptr, push it and call the check */ |
|
ds@1952
|
1866 |
//mov eax, [esi+context] |
|
ds@1952
|
1867 |
//push eax |
|
ds@1952
|
1868 |
//call JIT_VerifyOrAllocateTracker |
|
ds@1952
|
1869 |
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT); |
|
ds@1952
|
1870 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
1871 |
jitoffs_t call = IA32_Call_Imm32(jit, 0); |
|
ds@1952
|
1872 |
IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyOrAllocateTracker); |
|
ds@1952
|
1873 |
|
|
ds@1952
|
1874 |
/* Check for errors */ |
|
ds@1952
|
1875 |
//cmp eax, 0 |
|
ds@1952
|
1876 |
//jnz :error |
|
ds@1952
|
1877 |
IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0); |
|
dvander@2226
|
1878 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, g_Jit.GetReturnPoint()); |
|
ds@1952
|
1879 |
|
|
ds@1952
|
1880 |
/* Restore */ |
|
ds@1952
|
1881 |
//pop eax |
|
ds@1952
|
1882 |
IA32_Pop_Reg(jit, REG_EAX); |
|
ds@1952
|
1883 |
|
|
ds@1952
|
1884 |
/* Push the value into the stack and increment pCur */ |
|
ds@1952
|
1885 |
//mov edx, [eax+vm[]] |
|
ds@1952
|
1886 |
//mov ecx, [edx+pcur] |
|
ds@1952
|
1887 |
//add [edx+pcur], 4 |
|
ds@1952
|
1888 |
//mov [ecx], <val>*4 ; we want the count in bytes not in cells |
|
ds@1952
|
1889 |
IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER])); |
|
ds@1952
|
1890 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur)); |
|
ds@1952
|
1891 |
IA32_Add_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur)); |
|
ds@1952
|
1892 |
IA32_Mov_Rm_Imm32(jit, AMX_REG_TMP, val*4, MOD_MEM_REG); |
|
ds@1952
|
1893 |
|
|
ds@1952
|
1894 |
/* Restore PRI & ALT */ |
|
ds@1952
|
1895 |
//pop edx |
|
ds@1952
|
1896 |
//pop eax |
|
ds@1952
|
1897 |
IA32_Pop_Reg(jit, AMX_REG_ALT); |
|
ds@1952
|
1898 |
IA32_Pop_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
1899 |
} |
|
ds@1952
|
1900 |
|
|
ds@1952
|
1901 |
inline void WriteOp_Tracker_Pop_SetHeap(JitWriter *jit) |
|
ds@1952
|
1902 |
{ |
|
ds@1952
|
1903 |
/* Save registers that may be damaged by the call */ |
|
ds@1952
|
1904 |
//push eax |
|
ds@1952
|
1905 |
//push edx |
|
ds@1952
|
1906 |
IA32_Push_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
1907 |
IA32_Push_Reg(jit, AMX_REG_ALT); |
|
ds@1952
|
1908 |
|
|
ds@1952
|
1909 |
/* Get the context ptr, push it and call the check */ |
|
ds@1952
|
1910 |
//mov eax, [esi+context] |
|
ds@1952
|
1911 |
//push eax |
|
ds@1952
|
1912 |
//call JIT_VerifyLowBoundTracker |
|
ds@1952
|
1913 |
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT); |
|
ds@1952
|
1914 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
1915 |
jitoffs_t call = IA32_Call_Imm32(jit, 0); |
|
ds@1952
|
1916 |
IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyLowBoundTracker); |
|
ds@1952
|
1917 |
|
|
ds@1952
|
1918 |
/* Check for errors */ |
|
ds@1952
|
1919 |
//cmp eax, 0 |
|
ds@1952
|
1920 |
//jnz :error |
|
ds@1952
|
1921 |
IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0); |
|
dvander@2226
|
1922 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, g_Jit.GetReturnPoint()); |
|
ds@1952
|
1923 |
|
|
ds@1952
|
1924 |
/* Restore */ |
|
ds@1952
|
1925 |
//pop eax |
|
ds@1952
|
1926 |
IA32_Pop_Reg(jit, REG_EAX); |
|
ds@1952
|
1927 |
|
|
ds@1952
|
1928 |
/* Pop the value from the stack and decrease the heap by it*/ |
|
ds@1952
|
1929 |
//mov edx, [eax+vm[]] |
|
ds@1952
|
1930 |
//sub [edx+pcur], 4 |
|
ds@1952
|
1931 |
//mov ecx, [edx+pcur] |
|
ds@1952
|
1932 |
//mov ecx, [ecx] |
|
ds@1952
|
1933 |
//sub [esi+hea], ecx |
|
ds@1952
|
1934 |
IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER])); |
|
ds@1952
|
1935 |
IA32_Sub_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur)); |
|
ds@1952
|
1936 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur)); |
|
ds@1952
|
1937 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_TMP, MOD_MEM_REG); |
|
ds@1952
|
1938 |
IA32_Sub_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_TMP, AMX_INFO_HEAP); |
|
ds@1952
|
1939 |
|
|
ds@1952
|
1940 |
Write_CheckHeap_Min(jit); |
|
ds@1952
|
1941 |
|
|
ds@1952
|
1942 |
/* Restore PRI & ALT */ |
|
ds@1952
|
1943 |
//pop edx |
|
ds@1952
|
1944 |
//pop eax |
|
ds@1952
|
1945 |
IA32_Pop_Reg(jit, AMX_REG_ALT); |
|
ds@1952
|
1946 |
IA32_Pop_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
1947 |
} |
|
ds@1952
|
1948 |
|
|
ds@1952
|
1949 |
inline void WriteOp_Stradjust_Pri(JitWriter *jit) |
|
ds@1952
|
1950 |
{ |
|
ds@1952
|
1951 |
//add eax, 4 |
|
ds@1952
|
1952 |
//sar eax, 2 |
|
ds@1952
|
1953 |
IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 4, MOD_REG); |
|
ds@1952
|
1954 |
IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 2, MOD_REG); |
|
ds@1952
|
1955 |
} |
|
ds@1952
|
1956 |
|
|
ds@1952
|
1957 |
inline void WriteOp_FloatAbs(JitWriter *jit) |
|
ds@1952
|
1958 |
{ |
|
ds@1952
|
1959 |
//mov eax, [edi] |
|
ds@1952
|
1960 |
//and eax, 0x7FFFFFFF |
|
ds@1952
|
1961 |
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG); |
|
ds@1952
|
1962 |
IA32_And_Eax_Imm32(jit, 0x7FFFFFFF); |
|
ds@1952
|
1963 |
|
|
ds@1952
|
1964 |
/* Rectify the stack */ |
|
ds@1952
|
1965 |
//add edi, 4 |
|
ds@1952
|
1966 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
1967 |
} |
|
ds@1952
|
1968 |
|
|
ds@1952
|
1969 |
inline void WriteOp_Float(JitWriter *jit) |
|
ds@1952
|
1970 |
{ |
|
ds@1952
|
1971 |
//fild [edi] |
|
ds@1952
|
1972 |
//push eax |
|
ds@1952
|
1973 |
//fstp [esp] |
|
ds@1952
|
1974 |
//pop eax |
|
ds@1952
|
1975 |
IA32_Fild_Mem32(jit, AMX_REG_STK); |
|
ds@1952
|
1976 |
IA32_Push_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
1977 |
IA32_Fstp_Mem32_ESP(jit); |
|
ds@1952
|
1978 |
IA32_Pop_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
1979 |
|
|
ds@1952
|
1980 |
/* Rectify the stack */ |
|
ds@1952
|
1981 |
//add edi, 4 |
|
ds@1952
|
1982 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
1983 |
} |
|
ds@1952
|
1984 |
|
|
ds@1952
|
1985 |
inline void WriteOp_FloatAdd(JitWriter *jit) |
|
ds@1952
|
1986 |
{ |
|
ds@1952
|
1987 |
//push eax |
|
ds@1952
|
1988 |
//fld [edi] |
|
ds@1952
|
1989 |
//fadd [edi+4] |
|
ds@1952
|
1990 |
//fstp [esp] |
|
ds@1952
|
1991 |
//pop eax |
|
ds@1952
|
1992 |
IA32_Push_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
1993 |
IA32_Fld_Mem32(jit, AMX_REG_STK); |
|
ds@1952
|
1994 |
IA32_Fadd_Mem32_Disp8(jit, AMX_REG_STK, 4); |
|
ds@1952
|
1995 |
IA32_Fstp_Mem32_ESP(jit); |
|
ds@1952
|
1996 |
IA32_Pop_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
1997 |
|
|
ds@1952
|
1998 |
/* Rectify the stack */ |
|
ds@1952
|
1999 |
//add edi, 8 |
|
ds@1952
|
2000 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG); |
|
ds@1952
|
2001 |
} |
|
ds@1952
|
2002 |
|
|
ds@1952
|
2003 |
inline void WriteOp_FloatSub(JitWriter *jit) |
|
ds@1952
|
2004 |
{ |
|
ds@1952
|
2005 |
//push eax |
|
ds@1952
|
2006 |
//fld [edi] |
|
ds@1952
|
2007 |
//fsub [edi+4] |
|
ds@1952
|
2008 |
//fstp [esp] |
|
ds@1952
|
2009 |
//pop eax |
|
ds@1952
|
2010 |
IA32_Push_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
2011 |
IA32_Fld_Mem32(jit, AMX_REG_STK); |
|
ds@1952
|
2012 |
IA32_Fsub_Mem32_Disp8(jit, AMX_REG_STK, 4); |
|
ds@1952
|
2013 |
IA32_Fstp_Mem32_ESP(jit); |
|
ds@1952
|
2014 |
IA32_Pop_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
2015 |
|
|
ds@1952
|
2016 |
/* Rectify the stack */ |
|
ds@1952
|
2017 |
//add edi, 8 |
|
ds@1952
|
2018 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG); |
|
ds@1952
|
2019 |
} |
|
ds@1952
|
2020 |
|
|
ds@1952
|
2021 |
inline void WriteOp_FloatMul(JitWriter *jit) |
|
ds@1952
|
2022 |
{ |
|
ds@1952
|
2023 |
//push eax |
|
ds@1952
|
2024 |
//fld [edi] |
|
ds@1952
|
2025 |
//fmul [edi+4] |
|
ds@1952
|
2026 |
//fstp [esp] |
|
ds@1952
|
2027 |
//pop eax |
|
ds@1952
|
2028 |
IA32_Push_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
2029 |
IA32_Fld_Mem32(jit, AMX_REG_STK); |
|
ds@1952
|
2030 |
IA32_Fmul_Mem32_Disp8(jit, AMX_REG_STK, 4); |
|
ds@1952
|
2031 |
IA32_Fstp_Mem32_ESP(jit); |
|
ds@1952
|
2032 |
IA32_Pop_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
2033 |
|
|
ds@1952
|
2034 |
/* Rectify the stack */ |
|
ds@1952
|
2035 |
//add edi, 8 |
|
ds@1952
|
2036 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG); |
|
ds@1952
|
2037 |
} |
|
ds@1952
|
2038 |
|
|
ds@1952
|
2039 |
inline void WriteOp_FloatDiv(JitWriter *jit) |
|
ds@1952
|
2040 |
{ |
|
ds@1952
|
2041 |
//push eax |
|
ds@1952
|
2042 |
//fld [edi] |
|
ds@1952
|
2043 |
//fdiv [edi+4] |
|
ds@1952
|
2044 |
//fstp [esp] |
|
ds@1952
|
2045 |
//pop eax |
|
ds@1952
|
2046 |
IA32_Push_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
2047 |
IA32_Fld_Mem32(jit, AMX_REG_STK); |
|
ds@1952
|
2048 |
IA32_Fdiv_Mem32_Disp8(jit, AMX_REG_STK, 4); |
|
ds@1952
|
2049 |
IA32_Fstp_Mem32_ESP(jit); |
|
ds@1952
|
2050 |
IA32_Pop_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
2051 |
|
|
ds@1952
|
2052 |
/* Rectify the stack */ |
|
ds@1952
|
2053 |
//add edi, 8 |
|
ds@1952
|
2054 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG); |
|
ds@1952
|
2055 |
} |
|
ds@1952
|
2056 |
|
|
ds@1952
|
2057 |
inline void WriteOp_RountToNearest(JitWriter *jit) |
|
ds@1952
|
2058 |
{ |
|
ds@1952
|
2059 |
//push eax |
|
ds@1952
|
2060 |
//fld [edi] |
|
ds@1952
|
2061 |
|
|
ds@1952
|
2062 |
//fstcw [esp] |
|
ds@1952
|
2063 |
//mov eax, [esp] |
|
ds@1952
|
2064 |
//push eax |
|
ds@1952
|
2065 |
|
|
ds@1952
|
2066 |
//mov [esp+4], 0x3FF |
|
ds@1952
|
2067 |
//fadd st(0), st(0) |
|
ds@1952
|
2068 |
//fldcw [esp+4] |
|
ds@1952
|
2069 |
|
|
ds@1952
|
2070 |
//push eax |
|
ds@1952
|
2071 |
//push 0x3F000000 ; 0.5f |
|
ds@1952
|
2072 |
//fadd [esp] |
|
ds@1952
|
2073 |
//fistp [esp+4] |
|
ds@1952
|
2074 |
//pop eax |
|
ds@1952
|
2075 |
//pop eax |
|
ds@1952
|
2076 |
|
|
ds@1952
|
2077 |
//pop ecx |
|
ds@1952
|
2078 |
//sar eax, 1 |
|
ds@1952
|
2079 |
//mov [esp], ecx |
|
ds@1952
|
2080 |
//fldcw [esp] |
|
ds@1952
|
2081 |
//add esp, 4 |
|
ds@1952
|
2082 |
|
|
ds@1952
|
2083 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
2084 |
IA32_Fld_Mem32(jit, AMX_REG_STK); |
|
ds@1952
|
2085 |
|
|
ds@1952
|
2086 |
IA32_Fstcw_Mem16_ESP(jit); |
|
ds@1952
|
2087 |
IA32_Mov_Reg_RmESP(jit, REG_EAX); |
|
ds@1952
|
2088 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
2089 |
|
|
ds@1952
|
2090 |
IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0x3FF); |
|
ds@1952
|
2091 |
IA32_Fadd_FPUreg_ST0(jit, 0); |
|
ds@1952
|
2092 |
IA32_Fldcw_Mem16_Disp8_ESP(jit, 4); |
|
ds@1952
|
2093 |
|
|
ds@1952
|
2094 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
2095 |
IA32_Push_Imm32(jit, 0x3F000000); |
|
ds@1952
|
2096 |
IA32_Fadd_Mem32_ESP(jit); |
|
ds@1952
|
2097 |
IA32_Fistp_Mem32_Disp8_Esp(jit, 4); |
|
ds@1952
|
2098 |
IA32_Pop_Reg(jit, REG_EAX); |
|
ds@1952
|
2099 |
IA32_Pop_Reg(jit, AMX_REG_PRI); |
|
ds@1952
|
2100 |
|
|
ds@1952
|
2101 |
IA32_Pop_Reg(jit, REG_ECX); |
|
ds@1952
|
2102 |
IA32_Sar_Rm_1(jit, REG_EAX, MOD_REG); |
|
ds@1952
|
2103 |
IA32_Mov_RmESP_Reg(jit, REG_ECX); |
|
ds@1952
|
2104 |
IA32_Fldcw_Mem16_ESP(jit); |
|
ds@1952
|
2105 |
IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); |
|
ds@1952
|
2106 |
|
|
ds@1952
|
2107 |
/* Rectify the stack */ |
|
ds@1952
|
2108 |
//add edi, 4 |
|
ds@1952
|
2109 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
2110 |
} |
|
ds@1952
|
2111 |
|
|
ds@1952
|
2112 |
inline void WriteOp_RoundToFloor(JitWriter *jit) |
|
ds@1952
|
2113 |
{ |
|
ds@1952
|
2114 |
//push eax |
|
ds@1952
|
2115 |
//fld [edi] |
|
ds@1952
|
2116 |
|
|
ds@1952
|
2117 |
//fstcw [esp] |
|
ds@1952
|
2118 |
//mov eax, [esp] |
|
ds@1952
|
2119 |
//push eax |
|
ds@1952
|
2120 |
|
|
ds@1952
|
2121 |
//mov [esp+4], 0x7FF |
|
ds@1952
|
2122 |
//fldcw [esp+4] |
|
ds@1952
|
2123 |
|
|
ds@1952
|
2124 |
//push eax |
|
ds@1952
|
2125 |
//fistp [esp] |
|
ds@1952
|
2126 |
//pop eax |
|
ds@1952
|
2127 |
|
|
ds@1952
|
2128 |
//pop ecx |
|
ds@1952
|
2129 |
//mov [esp], ecx |
|
ds@1952
|
2130 |
//fldcw [esp] |
|
ds@1952
|
2131 |
//add esp, 4 |
|
ds@1952
|
2132 |
|
|
ds@1952
|
2133 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
2134 |
IA32_Fld_Mem32(jit, AMX_REG_STK); |
|
ds@1952
|
2135 |
|
|
ds@1952
|
2136 |
IA32_Fstcw_Mem16_ESP(jit); |
|
ds@1952
|
2137 |
IA32_Mov_Reg_RmESP(jit, REG_EAX); |
|
ds@1952
|
2138 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
2139 |
|
|
ds@1952
|
2140 |
IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0x7FF); |
|
ds@1952
|
2141 |
IA32_Fldcw_Mem16_Disp8_ESP(jit, 4); |
|
ds@1952
|
2142 |
|
|
ds@1952
|
2143 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
2144 |
IA32_Fistp_Mem32_ESP(jit); |
|
ds@1952
|
2145 |
IA32_Pop_Reg(jit, REG_EAX); |
|
ds@1952
|
2146 |
|
|
ds@1952
|
2147 |
IA32_Pop_Reg(jit, REG_ECX); |
|
ds@1952
|
2148 |
IA32_Mov_RmESP_Reg(jit, REG_ECX); |
|
ds@1952
|
2149 |
IA32_Fldcw_Mem16_ESP(jit); |
|
ds@1952
|
2150 |
IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); |
|
ds@1952
|
2151 |
|
|
ds@1952
|
2152 |
/* Rectify the stack */ |
|
ds@1952
|
2153 |
//add edi, 4 |
|
ds@1952
|
2154 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
2155 |
} |
|
ds@1952
|
2156 |
|
|
ds@1952
|
2157 |
inline void WriteOp_RoundToCeil(JitWriter *jit) |
|
ds@1952
|
2158 |
{ |
|
ds@1952
|
2159 |
//push eax |
|
ds@1952
|
2160 |
//fld [edi] |
|
ds@1952
|
2161 |
|
|
ds@1952
|
2162 |
//fstcw [esp] |
|
ds@1952
|
2163 |
//mov eax, [esp] |
|
ds@1952
|
2164 |
//push eax |
|
ds@1952
|
2165 |
|
|
ds@1952
|
2166 |
//mov [esp+4], 0xBFF |
|
ds@1952
|
2167 |
//fldcw [esp+4] |
|
ds@1952
|
2168 |
|
|
ds@1952
|
2169 |
//push eax |
|
ds@1952
|
2170 |
//fistp [esp] |
|
ds@1952
|
2171 |
//pop eax |
|
ds@1952
|
2172 |
|
|
ds@1952
|
2173 |
//pop ecx |
|
ds@1952
|
2174 |
//mov [esp], ecx |
|
ds@1952
|
2175 |
//fldcw [esp] |
|
ds@1952
|
2176 |
//add esp, 4 |
|
ds@1952
|
2177 |
|
|
ds@1952
|
2178 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
2179 |
IA32_Fld_Mem32(jit, AMX_REG_STK); |
|
ds@1952
|
2180 |
|
|
ds@1952
|
2181 |
IA32_Fstcw_Mem16_ESP(jit); |
|
ds@1952
|
2182 |
IA32_Mov_Reg_RmESP(jit, REG_EAX); |
|
ds@1952
|
2183 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
2184 |
|
|
ds@1952
|
2185 |
IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0xBFF); |
|
ds@1952
|
2186 |
IA32_Fldcw_Mem16_Disp8_ESP(jit, 4); |
|
ds@1952
|
2187 |
|
|
ds@1952
|
2188 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
2189 |
IA32_Fistp_Mem32_ESP(jit); |
|
ds@1952
|
2190 |
IA32_Pop_Reg(jit, REG_EAX); |
|
ds@1952
|
2191 |
|
|
ds@1952
|
2192 |
IA32_Pop_Reg(jit, REG_ECX); |
|
ds@1952
|
2193 |
IA32_Mov_RmESP_Reg(jit, REG_ECX); |
|
ds@1952
|
2194 |
IA32_Fldcw_Mem16_ESP(jit); |
|
ds@1952
|
2195 |
IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); |
|
ds@1952
|
2196 |
|
|
ds@1952
|
2197 |
/* Rectify the stack */ |
|
ds@1952
|
2198 |
//add edi, 4 |
|
ds@1952
|
2199 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
2200 |
} |
|
ds@1952
|
2201 |
|
|
ds@1952
|
2202 |
inline void WriteOp_RoundToZero(JitWriter *jit) |
|
ds@1952
|
2203 |
{ |
|
ds@1952
|
2204 |
//push eax |
|
ds@1952
|
2205 |
//fld [edi] |
|
ds@1952
|
2206 |
|
|
ds@1952
|
2207 |
//fstcw [esp] |
|
ds@1952
|
2208 |
//mov eax, [esp] |
|
ds@1952
|
2209 |
//push eax |
|
ds@1952
|
2210 |
|
|
ds@1952
|
2211 |
//mov [esp+4], 0xFFF |
|
ds@1952
|
2212 |
//fldcw [esp+4] |
|
ds@1952
|
2213 |
|
|
ds@1952
|
2214 |
//push eax |
|
ds@1952
|
2215 |
//fistp [esp] |
|
ds@1952
|
2216 |
//pop eax |
|
ds@1952
|
2217 |
|
|
ds@1952
|
2218 |
//pop ecx |
|
ds@1952
|
2219 |
//mov [esp], ecx |
|
ds@1952
|
2220 |
//fldcw [esp] |
|
ds@1952
|
2221 |
//add esp, 4 |
|
ds@1952
|
2222 |
|
|
ds@1952
|
2223 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
2224 |
IA32_Fld_Mem32(jit, AMX_REG_STK); |
|
ds@1952
|
2225 |
|
|
ds@1952
|
2226 |
IA32_Fstcw_Mem16_ESP(jit); |
|
ds@1952
|
2227 |
IA32_Mov_Reg_RmESP(jit, REG_EAX); |
|
ds@1952
|
2228 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
2229 |
|
|
ds@1952
|
2230 |
IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0xFFF); |
|
ds@1952
|
2231 |
IA32_Fldcw_Mem16_Disp8_ESP(jit, 4); |
|
ds@1952
|
2232 |
|
|
ds@1952
|
2233 |
IA32_Push_Reg(jit, REG_EAX); |
|
ds@1952
|
2234 |
IA32_Fistp_Mem32_ESP(jit); |
|
ds@1952
|
2235 |
IA32_Pop_Reg(jit, REG_EAX); |
|
ds@1952
|
2236 |
|
|
ds@1952
|
2237 |
IA32_Pop_Reg(jit, REG_ECX); |
|
ds@1952
|
2238 |
IA32_Mov_RmESP_Reg(jit, REG_ECX); |
|
ds@1952
|
2239 |
IA32_Fldcw_Mem16_ESP(jit); |
|
ds@1952
|
2240 |
IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); |
|
ds@1952
|
2241 |
|
|
ds@1952
|
2242 |
/* Rectify the stack */ |
|
ds@1952
|
2243 |
//add edi, 4 |
|
ds@1952
|
2244 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
ds@1952
|
2245 |
} |
|
ds@1952
|
2246 |
|
|
ds@1952
|
2247 |
inline void WriteOp_FloatCompare(JitWriter *jit) |
|
ds@1952
|
2248 |
{ |
|
ds@1952
|
2249 |
//fld [edi] |
|
ds@1952
|
2250 |
//fld [edi+4] |
|
ds@1952
|
2251 |
//fucomip st(0), st(1) |
|
ds@1952
|
2252 |
//mov ecx, <round_table> |
|
ds@1952
|
2253 |
//cmovz eax, [ecx+4] |
|
ds@1952
|
2254 |
//cmovb eax, [ecx+8] |
|
ds@1952
|
2255 |
//cmova eax, [ecx] |
|
ds@1952
|
2256 |
//fstp st(0) |
|
ds@1952
|
2257 |
|
|
ds@1952
|
2258 |
IA32_Fld_Mem32(jit, AMX_REG_STK); |
|
ds@1952
|
2259 |
IA32_Fld_Mem32_Disp8(jit, AMX_REG_STK, 4); |
|
ds@1952
|
2260 |
IA32_Fucomip_ST0_FPUreg(jit, 1); |
|
dvander@2226
|
2261 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, (jit_int32_t)g_Jit.GetRoundingTable()); |
|
ds@1952
|
2262 |
IA32_CmovCC_Rm_Disp8(jit, AMX_REG_TMP, CC_Z, 4); |
|
ds@1952
|
2263 |
IA32_CmovCC_Rm_Disp8(jit, AMX_REG_TMP, CC_B, 8); |
|
ds@1952
|
2264 |
IA32_CmovCC_Rm(jit, AMX_REG_TMP, CC_A); |
|
ds@1952
|
2265 |
IA32_Fstp_FPUreg(jit, 0); |
|
ds@1952
|
2266 |
|
|
ds@1952
|
2267 |
/* Rectify the stack */ |
|
ds@1952
|
2268 |
//add edi, 8 |
|
ds@1952
|
2269 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG); |
|
ds@1952
|
2270 |
} |
|
ds@1952
|
2271 |
|
|
dvander@2226
|
2272 |
inline void WriteOp_EndProc(JitWriter *jit) |
|
dvander@2226
|
2273 |
{ |
|
dvander@2226
|
2274 |
} |
|
dvander@2226
|
2275 |
|
|
dvander@2226
|
2276 |
void Write_CallThunk(JitWriter *jit, jitoffs_t jmploc, cell_t pcode_offs) |
|
dvander@2226
|
2277 |
{ |
|
dvander@2226
|
2278 |
CompData *data; |
|
dvander@2226
|
2279 |
jitoffs_t call; |
|
dvander@2226
|
2280 |
|
|
dvander@2226
|
2281 |
data = (CompData *)jit->data; |
|
dvander@2226
|
2282 |
|
|
dvander@2226
|
2283 |
//push <jmploc_addr> |
|
dvander@2226
|
2284 |
//push <pcode_offs> |
|
dvander@2226
|
2285 |
//push <runtime> |
|
dvander@2226
|
2286 |
//call CompileFromThunk |
|
dvander@2226
|
2287 |
//add esp, 4*3 |
|
dvander@2226
|
2288 |
//test eax, eax |
|
dvander@2226
|
2289 |
//jz :error |
|
dvander@2226
|
2290 |
//call eax |
|
dvander@2226
|
2291 |
//ret |
|
dvander@2226
|
2292 |
IA32_Push_Imm32(jit, (jit_int32_t)(jit->outbase + jmploc)); |
|
dvander@2226
|
2293 |
IA32_Push_Imm32(jit, pcode_offs); |
|
dvander@2226
|
2294 |
IA32_Push_Imm32(jit, (jit_int32_t)(data->runtime)); |
|
dvander@2226
|
2295 |
call = IA32_Call_Imm32(jit, 0); |
|
dvander@2226
|
2296 |
IA32_Write_Jump32_Abs(jit, call, (void *)CompileThunk); |
|
dvander@2226
|
2297 |
IA32_Add_Rm_Imm32(jit, REG_ESP, 4*3, MOD_REG); |
|
dvander@2226
|
2298 |
IA32_Test_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG); |
|
dvander@2226
|
2299 |
call = IA32_Jump_Cond_Imm8(jit, CC_Z, 0); |
|
dvander@2226
|
2300 |
IA32_Call_Reg(jit, REG_EAX); |
|
dvander@2226
|
2301 |
IA32_Return(jit); |
|
dvander@2226
|
2302 |
|
|
dvander@2226
|
2303 |
/* We decrement the frame and store the target cip. */ |
|
dvander@2226
|
2304 |
//:error |
|
dvander@2226
|
2305 |
//mov [esi+cip], pcode_offs |
|
dvander@2226
|
2306 |
//goto error |
|
dvander@2226
|
2307 |
IA32_Send_Jump8_Here(jit, call); |
|
dvander@2226
|
2308 |
Write_SetError(jit, SP_ERROR_INVALID_INSTRUCTION); |
|
dvander@2226
|
2309 |
} |
|
dvander@2226
|
2310 |
|
|
ds@1952
|
2311 |
/************************************************* |
|
ds@1952
|
2312 |
************************************************* |
|
ds@1952
|
2313 |
* JIT PROPER ************************************ |
|
ds@1952
|
2314 |
* The rest from now on is the JIT engine * |
|
ds@1952
|
2315 |
************************************************* |
|
ds@1952
|
2316 |
*************************************************/ |
|
ds@1952
|
2317 |
|
|
dvander@2226
|
2318 |
void *CompileThunk(BaseRuntime *runtime, cell_t pcode_offs, void *jmploc_addr) |
|
dvander@2226
|
2319 |
{ |
|
dvander@2226
|
2320 |
int err; |
|
dvander@2226
|
2321 |
JitFunction *fn; |
|
dvander@2226
|
2322 |
uint32_t func_idx; |
|
dvander@2226
|
2323 |
void *target_addr; |
|
dvander@2226
|
2324 |
|
|
dvander@2226
|
2325 |
if ((func_idx = FuncLookup((CompData *)runtime->m_pCo, pcode_offs)) == 0) |
|
dvander@2226
|
2326 |
{ |
|
dvander@2226
|
2327 |
fn = g_Jit.CompileFunction(runtime, pcode_offs, &err); |
|
dvander@2226
|
2328 |
} |
|
dvander@2226
|
2329 |
else |
|
dvander@2226
|
2330 |
{ |
|
dvander@2226
|
2331 |
fn = runtime->GetJittedFunction(func_idx); |
|
dvander@2226
|
2332 |
|
|
dvander@2226
|
2333 |
#if defined _DEBUG |
|
dvander@2226
|
2334 |
g_engine1.GetDebugHook()->OnDebugSpew("Patching thunk to %s::%s", runtime->m_pPlugin->name, find_func_name(runtime->m_pPlugin, pcode_offs)); |
|
dvander@2226
|
2335 |
#endif |
|
dvander@2226
|
2336 |
|
|
dvander@2226
|
2337 |
} |
|
dvander@2226
|
2338 |
|
|
dvander@2226
|
2339 |
if (fn == NULL) |
|
dvander@2226
|
2340 |
{ |
|
dvander@2226
|
2341 |
return NULL; |
|
dvander@2226
|
2342 |
} |
|
dvander@2226
|
2343 |
|
|
dvander@2226
|
2344 |
target_addr = fn->GetEntryAddress(); |
|
dvander@2226
|
2345 |
|
|
dvander@2226
|
2346 |
/* Right now, we always keep the code RWE */ |
|
dvander@2226
|
2347 |
*(intptr_t *)((char *)jmploc_addr) = |
|
dvander@2226
|
2348 |
intptr_t(target_addr) - (intptr_t(jmploc_addr) + 4); |
|
dvander@2226
|
2349 |
|
|
dvander@2226
|
2350 |
return target_addr; |
|
dvander@2226
|
2351 |
} |
|
dvander@2226
|
2352 |
|
|
ds@1952
|
2353 |
cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params) |
|
ds@1952
|
2354 |
{ |
|
ds@1952
|
2355 |
sp_native_t *native; |
|
ds@1952
|
2356 |
cell_t save_sp = ctx->sp; |
|
ds@1952
|
2357 |
cell_t save_hp = ctx->hp; |
|
dvander@2193
|
2358 |
sp_plugin_t *pl = GETPLUGIN(ctx); |
|
dvander@2193
|
2359 |
|
|
ds@1952
|
2360 |
ctx->n_idx = native_idx; |
|
ds@1952
|
2361 |
|
|
dvander@2193
|
2362 |
if (ctx->hp < (cell_t)pl->data_size) |
|
ds@1952
|
2363 |
{ |
|
ds@1952
|
2364 |
ctx->n_err = SP_ERROR_HEAPMIN; |
|
ds@1952
|
2365 |
return 0; |
|
ds@1952
|
2366 |
} |
|
ds@1952
|
2367 |
|
|
ds@1952
|
2368 |
if (ctx->hp + STACK_MARGIN > ctx->sp) |
|
ds@1952
|
2369 |
{ |
|
ds@1952
|
2370 |
ctx->n_err = SP_ERROR_STACKLOW; |
|
ds@1952
|
2371 |
return 0; |
|
ds@1952
|
2372 |
} |
|
ds@1952
|
2373 |
|
|
dvander@2193
|
2374 |
if ((uint32_t)ctx->sp >= pl->mem_size) |
|
ds@1952
|
2375 |
{ |
|
ds@1952
|
2376 |
ctx->n_err = SP_ERROR_STACKMIN; |
|
ds@1952
|
2377 |
return 0; |
|
ds@1952
|
2378 |
} |
|
ds@1952
|
2379 |
|
|
dvander@2226
|
2380 |
native = &pl->natives[native_idx]; |
|
dvander@2226
|
2381 |
|
|
dvander@2226
|
2382 |
if (native->status == SP_NATIVE_UNBOUND) |
|
dvander@2226
|
2383 |
{ |
|
dvander@2226
|
2384 |
ctx->n_err = SP_ERROR_INVALID_NATIVE; |
|
dvander@2226
|
2385 |
return 0; |
|
dvander@2226
|
2386 |
} |
|
dvander@2226
|
2387 |
|
|
dvander@2226
|
2388 |
cell_t result = native->pfn(GET_CONTEXT(ctx), params); |
|
ds@1952
|
2389 |
|
|
ds@1952
|
2390 |
if (ctx->n_err != SP_ERROR_NONE) |
|
ds@1952
|
2391 |
{ |
|
ds@1952
|
2392 |
return result; |
|
ds@1952
|
2393 |
} |
|
ds@1952
|
2394 |
|
|
ds@1952
|
2395 |
if (save_sp != ctx->sp) |
|
ds@1952
|
2396 |
{ |
|
ds@1952
|
2397 |
ctx->n_err = SP_ERROR_STACKLEAK; |
|
ds@1952
|
2398 |
return result; |
|
ds@1952
|
2399 |
} |
|
ds@1952
|
2400 |
else if (save_hp != ctx->hp) |
|
ds@1952
|
2401 |
{ |
|
ds@1952
|
2402 |
ctx->n_err = SP_ERROR_HEAPLEAK; |
|
ds@1952
|
2403 |
return result; |
|
ds@1952
|
2404 |
} |
|
ds@1952
|
2405 |
|
|
ds@1952
|
2406 |
return result; |
|
ds@1952
|
2407 |
} |
|
ds@1952
|
2408 |
|
|
dvander@2226
|
2409 |
cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params) |
|
ds@1952
|
2410 |
{ |
|
dvander@2226
|
2411 |
/* :TODO: */ |
|
dvander@2226
|
2412 |
return NativeCallback(ctx, native_idx, params); |
|
ds@1952
|
2413 |
} |
|
ds@1952
|
2414 |
|
|
dvander@2226
|
2415 |
uint32_t FuncLookup(CompData *data, cell_t pcode_offs) |
|
ds@1952
|
2416 |
{ |
|
dvander@2226
|
2417 |
/* Offset must always be 1)positive and 2)less than or equal to the codesize */ |
|
dvander@2226
|
2418 |
assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->plugin->pcode_size); |
|
dvander@2226
|
2419 |
|
|
dvander@2226
|
2420 |
/* Do the lookup in the native dictionary. */ |
|
dvander@2226
|
2421 |
return *(jitoffs_t *)(data->rebase + pcode_offs); |
|
ds@1952
|
2422 |
} |
|
ds@1952
|
2423 |
|
|
ds@1952
|
2424 |
jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative) |
|
ds@1952
|
2425 |
{ |
|
ds@1952
|
2426 |
if (jit->outptr) |
|
ds@1952
|
2427 |
{ |
|
ds@1952
|
2428 |
CompData *data = (CompData *)jit->data; |
|
ds@1952
|
2429 |
if (relative) |
|
ds@1952
|
2430 |
{ |
|
ds@1952
|
2431 |
/* The actual offset is EIP relative. We need to relocate it. |
|
ds@1952
|
2432 |
* Note that this assumes that we're pointing to the next op. |
|
ds@1952
|
2433 |
*/ |
|
ds@1952
|
2434 |
pcode_offs += jit->get_inputpos(); |
|
ds@1952
|
2435 |
} |
|
ds@1952
|
2436 |
/* Offset must always be 1)positive and 2)less than or equal to the codesize */ |
|
dvander@2226
|
2437 |
assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->plugin->pcode_size); |
|
ds@1952
|
2438 |
/* Do the lookup in the native dictionary. */ |
|
ds@1952
|
2439 |
return *(jitoffs_t *)(data->rebase + pcode_offs); |
|
ds@1952
|
2440 |
} |
|
ds@1952
|
2441 |
else |
|
ds@1952
|
2442 |
{ |
|
ds@1952
|
2443 |
return 0; |
|
ds@1952
|
2444 |
} |
|
ds@1952
|
2445 |
} |
|
ds@1952
|
2446 |
|
|
ds@1952
|
2447 |
void WriteErrorRoutines(CompData *data, JitWriter *jit) |
|
ds@1952
|
2448 |
{ |
|
ds@1952
|
2449 |
AlignMe(jit); |
|
ds@1952
|
2450 |
|
|
ds@1952
|
2451 |
data->jit_error_divzero = jit->get_outputpos(); |
|
ds@1952
|
2452 |
Write_SetError(jit, SP_ERROR_DIVIDE_BY_ZERO); |
|
ds@1952
|
2453 |
|
|
ds@1952
|
2454 |
data->jit_error_stacklow = jit->get_outputpos(); |
|
ds@1952
|
2455 |
Write_SetError(jit, SP_ERROR_STACKLOW); |
|
ds@1952
|
2456 |
|
|
ds@1952
|
2457 |
data->jit_error_stackmin = jit->get_outputpos(); |
|
ds@1952
|
2458 |
Write_SetError(jit, SP_ERROR_STACKMIN); |
|
ds@1952
|
2459 |
|
|
ds@1952
|
2460 |
data->jit_error_bounds = jit->get_outputpos(); |
|
ds@1952
|
2461 |
Write_SetError(jit, SP_ERROR_ARRAY_BOUNDS); |
|
ds@1952
|
2462 |
|
|
ds@1952
|
2463 |
data->jit_error_memaccess = jit->get_outputpos(); |
|
ds@1952
|
2464 |
Write_SetError(jit, SP_ERROR_MEMACCESS); |
|
ds@1952
|
2465 |
|
|
ds@1952
|
2466 |
data->jit_error_heaplow = jit->get_outputpos(); |
|
ds@1952
|
2467 |
Write_SetError(jit, SP_ERROR_HEAPLOW); |
|
ds@1952
|
2468 |
|
|
ds@1952
|
2469 |
data->jit_error_heapmin = jit->get_outputpos(); |
|
ds@1952
|
2470 |
Write_SetError(jit, SP_ERROR_HEAPMIN); |
|
ds@1952
|
2471 |
|
|
ds@1952
|
2472 |
data->jit_extern_error = jit->get_outputpos(); |
|
ds@1952
|
2473 |
Write_GetError(jit); |
|
ds@1952
|
2474 |
} |
|
ds@1952
|
2475 |
|
|
dvander@2226
|
2476 |
ICompilation *JITX86::ApplyOptions(ICompilation *_IN, ICompilation *_OUT) |
|
ds@1952
|
2477 |
{ |
|
dvander@2226
|
2478 |
if (_IN == NULL) |
|
dvander@2193
|
2479 |
{ |
|
dvander@2226
|
2480 |
return _OUT; |
|
dvander@2193
|
2481 |
} |
|
dvander@2193
|
2482 |
|
|
dvander@2226
|
2483 |
CompData *_in = (CompData * )_IN; |
|
dvander@2226
|
2484 |
CompData *_out = (CompData * )_OUT; |
|
dvander@2226
|
2485 |
|
|
dvander@2226
|
2486 |
_in->inline_level = _out->inline_level; |
|
dvander@2226
|
2487 |
_in->profile = _out->profile; |
|
dvander@2226
|
2488 |
|
|
dvander@2226
|
2489 |
_out->Abort(); |
|
dvander@2226
|
2490 |
|
|
dvander@2226
|
2491 |
return _in; |
|
dvander@2226
|
2492 |
} |
|
dvander@2226
|
2493 |
|
|
dvander@2226
|
2494 |
JITX86::JITX86() |
|
dvander@2226
|
2495 |
{ |
|
dvander@2226
|
2496 |
m_pJitEntry = NULL; |
|
dvander@2226
|
2497 |
m_pJitReturn = NULL; |
|
dvander@2226
|
2498 |
m_RoundTable[0] = -1; |
|
dvander@2226
|
2499 |
m_RoundTable[1] = 0; |
|
dvander@2226
|
2500 |
m_RoundTable[2] = 1; |
|
dvander@2226
|
2501 |
m_pJitGenArray = NULL; |
|
dvander@2226
|
2502 |
} |
|
dvander@2226
|
2503 |
|
|
dvander@2226
|
2504 |
bool JITX86::InitializeJIT() |
|
dvander@2226
|
2505 |
{ |
|
dvander@2226
|
2506 |
jitoffs_t offs; |
|
dvander@2226
|
2507 |
JitWriter writer, *jit; |
|
dvander@2226
|
2508 |
|
|
dvander@2226
|
2509 |
g_pCodeCache = KE_CreateCodeCache(); |
|
dvander@2226
|
2510 |
|
|
dvander@2226
|
2511 |
jit = &writer; |
|
dvander@2226
|
2512 |
|
|
dvander@2226
|
2513 |
/* Build the genarray intrinsic */ |
|
dvander@2226
|
2514 |
jit->outbase = NULL; |
|
dvander@2226
|
2515 |
jit->outptr = NULL; |
|
dvander@2226
|
2516 |
WriteIntrinsic_GenArray(jit); |
|
dvander@2226
|
2517 |
m_pJitGenArray = Knight::KE_AllocCode(g_pCodeCache, jit->get_outputpos()); |
|
dvander@2226
|
2518 |
jit->outbase = (jitcode_t)m_pJitGenArray; |
|
dvander@2226
|
2519 |
jit->outptr = jit->outbase; |
|
dvander@2226
|
2520 |
WriteIntrinsic_GenArray(jit); |
|
dvander@2226
|
2521 |
|
|
dvander@2226
|
2522 |
/* Build the entry point */ |
|
dvander@2226
|
2523 |
writer = JitWriter(); |
|
dvander@2226
|
2524 |
jit->outbase = NULL; |
|
dvander@2226
|
2525 |
jit->outptr = NULL; |
|
dvander@2226
|
2526 |
Write_Execute_Function(jit); |
|
dvander@2226
|
2527 |
m_pJitEntry = Knight::KE_AllocCode(g_pCodeCache, jit->get_outputpos()); |
|
dvander@2226
|
2528 |
jit->outbase = (jitcode_t)m_pJitEntry; |
|
dvander@2226
|
2529 |
jit->outptr = jit->outbase; |
|
dvander@2226
|
2530 |
offs = Write_Execute_Function(jit); |
|
dvander@2226
|
2531 |
m_pJitReturn = (uint8_t *)m_pJitEntry + offs; |
|
dvander@2226
|
2532 |
|
|
dvander@2226
|
2533 |
return true; |
|
dvander@2226
|
2534 |
} |
|
dvander@2226
|
2535 |
|
|
dvander@2226
|
2536 |
void JITX86::ShutdownJIT() |
|
dvander@2226
|
2537 |
{ |
|
dvander@2226
|
2538 |
KE_DestroyCodeCache(g_pCodeCache); |
|
dvander@2226
|
2539 |
} |
|
dvander@2226
|
2540 |
|
|
dvander@2226
|
2541 |
JitFunction *JITX86::CompileFunction(BaseRuntime *prt, cell_t pcode_offs, int *err) |
|
dvander@2226
|
2542 |
{ |
|
dvander@2226
|
2543 |
CompData *data = (CompData *)prt->m_pCo; |
|
dvander@2226
|
2544 |
sp_plugin_t *plugin = data->plugin; |
|
dvander@2226
|
2545 |
|
|
dvander@2226
|
2546 |
uint8_t *code = plugin->pcode + pcode_offs; |
|
dvander@2226
|
2547 |
uint8_t *end_code = plugin->pcode + plugin->pcode_size; |
|
dvander@2226
|
2548 |
|
|
dvander@2226
|
2549 |
assert(FuncLookup(data, pcode_offs) == 0); |
|
dvander@2226
|
2550 |
|
|
dvander@2226
|
2551 |
if (code >= end_code || *(cell_t *)code != OP_PROC) |
|
dvander@2226
|
2552 |
{ |
|
dvander@2226
|
2553 |
*err = SP_ERROR_INVALID_INSTRUCTION; |
|
dvander@2226
|
2554 |
return NULL; |
|
dvander@2226
|
2555 |
} |
|
dvander@2226
|
2556 |
|
|
dvander@2226
|
2557 |
#if defined _DEBUG |
|
dvander@2226
|
2558 |
g_engine1.GetDebugHook()->OnDebugSpew("Compiling function %s::%s", prt->m_pPlugin->name, find_func_name(prt->m_pPlugin, pcode_offs)); |
|
dvander@2226
|
2559 |
#endif |
|
dvander@2226
|
2560 |
|
|
dvander@2226
|
2561 |
code += sizeof(cell_t); |
|
dvander@2226
|
2562 |
|
|
ds@1952
|
2563 |
OPCODE op; |
|
dvander@2226
|
2564 |
uint32_t code_size; |
|
dvander@2226
|
2565 |
cell_t *cip, *end_cip; |
|
dvander@2226
|
2566 |
JitWriter writer, *jit; |
|
dvander@2226
|
2567 |
|
|
dvander@2226
|
2568 |
jit = &writer; |
|
dvander@2226
|
2569 |
cip = (cell_t *)code; |
|
dvander@2226
|
2570 |
end_cip = (cell_t *)end_code; |
|
ds@1952
|
2571 |
writer.data = data; |
|
dvander@2226
|
2572 |
writer.inbase = cip; |
|
ds@1952
|
2573 |
writer.outptr = NULL; |
|
ds@1952
|
2574 |
writer.outbase = NULL; |
|
dvander@2226
|
2575 |
data->cur_func = pcode_offs; |
|
dvander@2226
|
2576 |
|
|
ds@1952
|
2577 |
jit_rewind: |
|
dvander@2226
|
2578 |
data->num_thunks = 0; |
|
ds@1952
|
2579 |
writer.inptr = writer.inbase; |
|
dvander@2226
|
2580 |
|
|
dvander@2226
|
2581 |
WriteOp_Proc(jit); |
|
ds@1952
|
2582 |
|
|
ds@1952
|
2583 |
/* Actual code generation! */ |
|
ds@1952
|
2584 |
if (writer.outbase == NULL) |
|
ds@1952
|
2585 |
{ |
|
ds@1952
|
2586 |
/* First Pass - find codesize and resolve relocation */ |
|
dvander@2226
|
2587 |
jitoffs_t jpcode_offs; |
|
ds@1952
|
2588 |
jitoffs_t native_offs; |
|
ds@1952
|
2589 |
|
|
dvander@2226
|
2590 |
for (; writer.inptr < end_cip;) |
|
ds@1952
|
2591 |
{ |
|
dvander@2226
|
2592 |
op = (OPCODE)writer.peek_cell(); |
|
dvander@2226
|
2593 |
|
|
dvander@2226
|
2594 |
/* If we hit another function, we must stop. */ |
|
dvander@2226
|
2595 |
if (op == OP_PROC || op == OP_ENDPROC) |
|
dvander@2226
|
2596 |
{ |
|
dvander@2226
|
2597 |
break; |
|
dvander@2226
|
2598 |
} |
|
dvander@2226
|
2599 |
|
|
ds@1952
|
2600 |
/* Store the native offset into the rebase memory. |
|
ds@1952
|
2601 |
* This large chunk of memory lets us do an instant lookup |
|
ds@1952
|
2602 |
* based on an original pcode offset. |
|
ds@1952
|
2603 |
*/ |
|
dvander@2226
|
2604 |
jpcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - plugin->pcode); |
|
ds@1952
|
2605 |
native_offs = jit->get_outputpos(); |
|
dvander@2226
|
2606 |
*((jitoffs_t *)(data->rebase + jpcode_offs)) = native_offs; |
|
dvander@2226
|
2607 |
|
|
dvander@2226
|
2608 |
/* Read past the opcode. */ |
|
dvander@2226
|
2609 |
writer.read_cell(); |
|
ds@1952
|
2610 |
|
|
ds@1952
|
2611 |
/* Patch the floating point natives with our opcodes */ |
|
ds@1952
|
2612 |
if (op == OP_SYSREQ_N) |
|
ds@1952
|
2613 |
{ |
|
ds@1952
|
2614 |
cell_t idx = writer.read_cell(); |
|
ds@1952
|
2615 |
if (data->jit_float_table[idx].found) |
|
ds@1952
|
2616 |
{ |
|
ds@1952
|
2617 |
writer.inptr -= 2; |
|
ds@1952
|
2618 |
*(writer.inptr++) = data->jit_float_table[idx].index; |
|
ds@1952
|
2619 |
*(writer.inptr++) = OP_NOP; |
|
ds@1952
|
2620 |
*(writer.inptr++) = OP_NOP; |
|
ds@1952
|
2621 |
op = (OPCODE)data->jit_float_table[idx].index; |
|
dvander@2093
|
2622 |
} |
|
dvander@2093
|
2623 |
else |
|
dvander@2093
|
2624 |
{ |
|
ds@1952
|
2625 |
writer.inptr--; |
|
ds@1952
|
2626 |
} |
|
ds@1952
|
2627 |
} |
|
ds@1952
|
2628 |
switch (op) |
|
ds@1952
|
2629 |
{ |
|
ds@1952
|
2630 |
#include "opcode_switch.inc" |
|
ds@1952
|
2631 |
} |
|
ds@1952
|
2632 |
/* Check for errors. This should only happen in the first pass. */ |
|
ds@1952
|
2633 |
if (data->error_set != SP_ERROR_NONE) |
|
ds@1952
|
2634 |
{ |
|
ds@1952
|
2635 |
*err = data->error_set; |
|
dvander@2226
|
2636 |
return NULL; |
|
ds@1952
|
2637 |
} |
|
ds@1952
|
2638 |
} |
|
dvander@2226
|
2639 |
|
|
dvander@2226
|
2640 |
/* Write these last because error jumps should be predicted forwardly (not taken) */ |
|
ds@1952
|
2641 |
WriteErrorRoutines(data, jit); |
|
ds@1952
|
2642 |
|
|
dvander@2226
|
2643 |
/* Build thunk tables */ |
|
dvander@2226
|
2644 |
if (data->num_thunks > data->max_thunks) |
|
dvander@2226
|
2645 |
{ |
|
dvander@2226
|
2646 |
data->max_thunks = data->num_thunks; |
|
dvander@2226
|
2647 |
data->thunks = (call_thunk_t *)realloc( |
|
dvander@2226
|
2648 |
data->thunks, |
|
dvander@2226
|
2649 |
data->max_thunks * sizeof(call_thunk_t)); |
|
dvander@2226
|
2650 |
} |
|
dvander@2226
|
2651 |
|
|
dvander@2226
|
2652 |
/* Write the thunk offsets. |
|
dvander@2226
|
2653 |
* :TODO: we can emit all but one call to Write_CallThunk(). |
|
dvander@2226
|
2654 |
*/ |
|
dvander@2226
|
2655 |
for (unsigned int i = 0; i < data->num_thunks; i++) |
|
dvander@2226
|
2656 |
{ |
|
dvander@2226
|
2657 |
data->thunks[i].thunk_addr = jit->get_outputpos(); |
|
dvander@2226
|
2658 |
Write_CallThunk(jit, 0, 0); |
|
dvander@2226
|
2659 |
} |
|
dvander@2226
|
2660 |
|
|
dvander@2226
|
2661 |
/** |
|
dvander@2226
|
2662 |
* I don't understand the purpose of this code. |
|
dvander@2226
|
2663 |
* Why do we want to know about the last opcode? |
|
dvander@2226
|
2664 |
* It should already have gotten written. |
|
dvander@2226
|
2665 |
*/ |
|
dvander@2226
|
2666 |
#if 0 |
|
ds@1952
|
2667 |
/* Write the final CIP to the last position in the reloc array */ |
|
ds@1952
|
2668 |
pcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - code); |
|
ds@1952
|
2669 |
native_offs = jit->get_outputpos(); |
|
ds@1952
|
2670 |
*((jitoffs_t *)(data->rebase + pcode_offs)) = native_offs; |
|
dvander@2226
|
2671 |
#endif |
|
ds@1952
|
2672 |
|
|
ds@1952
|
2673 |
/* the total codesize is now known! */ |
|
dvander@2226
|
2674 |
code_size = writer.get_outputpos(); |
|
dvander@2226
|
2675 |
writer.outbase = (jitcode_t)Knight::KE_AllocCode(g_pCodeCache, code_size); |
|
ds@1952
|
2676 |
writer.outptr = writer.outbase; |
|
dvander@2226
|
2677 |
|
|
dvander@2226
|
2678 |
/* go back for second pass */ |
|
ds@1952
|
2679 |
goto jit_rewind; |
|
dvander@2093
|
2680 |
} |
|
dvander@2093
|
2681 |
else |
|
dvander@2093
|
2682 |
{ |
|
ds@1952
|
2683 |
/******* |
|
dvander@2226
|
2684 |
* SECOND PASS - write opcode info |
|
ds@1952
|
2685 |
*******/ |
|
dvander@2226
|
2686 |
for (; writer.inptr < end_cip;) |
|
ds@1952
|
2687 |
{ |
|
ds@1952
|
2688 |
op = (OPCODE)writer.read_cell(); |
|
dvander@2226
|
2689 |
|
|
dvander@2226
|
2690 |
/* If we hit another function, we must stop. */ |
|
dvander@2226
|
2691 |
if (op == OP_PROC || op == OP_ENDPROC) |
|
dvander@2226
|
2692 |
{ |
|
dvander@2226
|
2693 |
break; |
|
dvander@2226
|
2694 |
} |
|
dvander@2226
|
2695 |
|
|
ds@1952
|
2696 |
switch (op) |
|
ds@1952
|
2697 |
{ |
|
ds@1952
|
2698 |
#include "opcode_switch.inc" |
|
ds@1952
|
2699 |
} |
|
ds@1952
|
2700 |
} |
|
dvander@2226
|
2701 |
|
|
dvander@2226
|
2702 |
/* Write these last because error jumps should be predicted as not taken (forward) */ |
|
ds@1952
|
2703 |
WriteErrorRoutines(data, jit); |
|
ds@1952
|
2704 |
|
|
dvander@2226
|
2705 |
/* Write the thunk offsets. */ |
|
dvander@2226
|
2706 |
for (unsigned int i = 0; i < data->num_thunks; i++) |
|
ds@1952
|
2707 |
{ |
|
dvander@2226
|
2708 |
Write_CallThunk(jit, data->thunks[i].patch_addr, data->thunks[i].pcode_offs); |
|
ds@1952
|
2709 |
} |
|
ds@1952
|
2710 |
} |
|
ds@1952
|
2711 |
|
|
dvander@2226
|
2712 |
plugin->prof_flags = data->profile; |
|
dvander@2226
|
2713 |
|
|
dvander@2226
|
2714 |
*err = SP_ERROR_NONE; |
|
dvander@2226
|
2715 |
|
|
dvander@2226
|
2716 |
JitFunction *fn; |
|
dvander@2226
|
2717 |
uint32_t func_idx; |
|
dvander@2226
|
2718 |
|
|
dvander@2226
|
2719 |
fn = new JitFunction(writer.outbase, pcode_offs); |
|
dvander@2226
|
2720 |
func_idx = prt->AddJittedFunction(fn); |
|
dvander@2226
|
2721 |
*(cell_t *)(data->rebase + pcode_offs) = func_idx; |
|
dvander@2226
|
2722 |
|
|
dvander@2226
|
2723 |
return fn; |
|
dvander@2226
|
2724 |
} |
|
dvander@2226
|
2725 |
|
|
dvander@2226
|
2726 |
void JITX86::SetupContextVars(BaseRuntime *runtime, BaseContext *pCtx, sp_context_t *ctx) |
|
dvander@2226
|
2727 |
{ |
|
ds@1952
|
2728 |
tracker_t *trk = new tracker_t; |
|
dvander@2226
|
2729 |
|
|
ds@1952
|
2730 |
ctx->vm[JITVARS_TRACKER] = trk; |
|
dvander@2226
|
2731 |
ctx->vm[JITVARS_BASECTX] = pCtx; /* GetDefaultContext() is not constructed yet */ |
|
dvander@2193
|
2732 |
ctx->vm[JITVARS_PROFILER] = g_engine2.GetProfiler(); |
|
dvander@2226
|
2733 |
ctx->vm[JITVARS_PLUGIN] = runtime->m_pPlugin; |
|
dvander@2226
|
2734 |
|
|
ds@1952
|
2735 |
trk->pBase = (ucell_t *)malloc(1024); |
|
ds@1952
|
2736 |
trk->pCur = trk->pBase; |
|
ds@1952
|
2737 |
trk->size = 1024 / sizeof(cell_t); |
|
ds@1952
|
2738 |
} |
|
ds@1952
|
2739 |
|
|
ds@1952
|
2740 |
SPVM_NATIVE_FUNC JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData) |
|
ds@1952
|
2741 |
{ |
|
ds@1952
|
2742 |
JitWriter jw; |
|
ds@1952
|
2743 |
JitWriter *jit = &jw; |
|
ds@1952
|
2744 |
|
|
ds@1952
|
2745 |
jw.outbase = NULL; |
|
ds@1952
|
2746 |
jw.outptr = NULL; |
|
ds@1952
|
2747 |
jw.data = NULL; |
|
ds@1952
|
2748 |
|
|
ds@1952
|
2749 |
/* First pass, calculate size */ |
|
ds@1952
|
2750 |
rewind: |
|
ds@1952
|
2751 |
/* Align the stack to 16 bytes */ |
|
ds@1952
|
2752 |
//push ebx |
|
ds@1952
|
2753 |
//push edi |
|
ds@1952
|
2754 |
//push esi |
|
ds@1952
|
2755 |
//mov edi, [esp+16] ;store ctx |
|
ds@1952
|
2756 |
//mov esi, [esp+20] ;store params |
|
ds@1952
|
2757 |
//mov ebx, esp |
|
ds@1952
|
2758 |
//and esp, 0xFFFFFF0 |
|
ds@1952
|
2759 |
//sub esp, 4 |
|
ds@1952
|
2760 |
IA32_Push_Reg(jit, REG_EBX); |
|
ds@1952
|
2761 |
IA32_Push_Reg(jit, REG_EDI); |
|
ds@1952
|
2762 |
IA32_Push_Reg(jit, REG_ESI); |
|
ds@1952
|
2763 |
IA32_Mov_Reg_Esp_Disp8(jit, REG_EDI, 16); |
|
ds@1952
|
2764 |
IA32_Mov_Reg_Esp_Disp8(jit, REG_ESI, 20); |
|
ds@1952
|
2765 |
IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG); |
|
ds@1952
|
2766 |
IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16); |
|
ds@1952
|
2767 |
IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); |
|
ds@1952
|
2768 |
|
|
ds@1952
|
2769 |
//push pData ;push pData |
|
ds@1952
|
2770 |
//push esi ;push params |
|
ds@1952
|
2771 |
//push edi ;push ctx |
|
ds@1952
|
2772 |
//call [callback] ;invoke the meta-callback |
|
ds@1952
|
2773 |
//mov esp, ebx ;restore the stack |
|
ds@1952
|
2774 |
//pop esi ;restore esi |
|
ds@1952
|
2775 |
//pop edi ;restore edi |
|
ds@1952
|
2776 |
//pop ebx ;restore ebx |
|
ds@1952
|
2777 |
//ret ;return |
|
ds@1952
|
2778 |
IA32_Push_Imm32(jit, (jit_int32_t)pData); |
|
ds@1952
|
2779 |
IA32_Push_Reg(jit, REG_ESI); |
|
ds@1952
|
2780 |
IA32_Push_Reg(jit, REG_EDI); |
|
ds@1952
|
2781 |
uint32_t call = IA32_Call_Imm32(jit, 0); |
|
ds@1952
|
2782 |
IA32_Write_Jump32_Abs(jit, call, (void *)callback); |
|
ds@1952
|
2783 |
IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG); |
|
ds@1952
|
2784 |
IA32_Pop_Reg(jit, REG_ESI); |
|
ds@1952
|
2785 |
IA32_Pop_Reg(jit, REG_EDI); |
|
ds@1952
|
2786 |
IA32_Pop_Reg(jit, REG_EBX); |
|
ds@1952
|
2787 |
IA32_Return(jit); |
|
ds@1952
|
2788 |
|
|
ds@1952
|
2789 |
if (jw.outbase == NULL) |
|
ds@1952
|
2790 |
{ |
|
ds@1952
|
2791 |
/* Second pass: Actually write */ |
|
dvander@2226
|
2792 |
jw.outbase = (jitcode_t)KE_AllocCode(g_pCodeCache, jw.get_outputpos()); |
|
ds@1952
|
2793 |
if (!jw.outbase) |
|
ds@1952
|
2794 |
{ |
|
ds@1952
|
2795 |
return NULL; |
|
ds@1952
|
2796 |
} |
|
ds@1952
|
2797 |
jw.outptr = jw.outbase; |
|
ds@1952
|
2798 |
|
|
ds@1952
|
2799 |
goto rewind; |
|
ds@1952
|
2800 |
} |
|
ds@1952
|
2801 |
|
|
ds@1952
|
2802 |
return (SPVM_NATIVE_FUNC)jw.outbase; |
|
ds@1952
|
2803 |
} |
|
ds@1952
|
2804 |
|
|
ds@1952
|
2805 |
void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func) |
|
ds@1952
|
2806 |
{ |
|
dvander@2226
|
2807 |
KE_FreeCode(g_pCodeCache, (void *)func); |
|
ds@1952
|
2808 |
} |
|
ds@1952
|
2809 |
|
|
dvander@2193
|
2810 |
ICompilation *JITX86::StartCompilation() |
|
ds@1952
|
2811 |
{ |
|
ds@1952
|
2812 |
CompData *data = new CompData; |
|
dvander@2193
|
2813 |
|
|
dvander@2193
|
2814 |
data->jit_float_table = NULL; |
|
dvander@2193
|
2815 |
|
|
dvander@2193
|
2816 |
return data; |
|
dvander@2193
|
2817 |
} |
|
dvander@2193
|
2818 |
|
|
dvander@2193
|
2819 |
void CompData::SetRuntime(BaseRuntime *runtime) |
|
dvander@2193
|
2820 |
{ |
|
dvander@2193
|
2821 |
plugin = runtime->m_pPlugin; |
|
dvander@2193
|
2822 |
|
|
dvander@2226
|
2823 |
uint32_t max_natives = plugin->num_natives; |
|
ds@1952
|
2824 |
|
|
dvander@2193
|
2825 |
this->runtime = runtime; |
|
dvander@2226
|
2826 |
this->plugin = runtime->m_pPlugin; |
|
dvander@2193
|
2827 |
|
|
dvander@2193
|
2828 |
inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES; |
|
dvander@2193
|
2829 |
error_set = SP_ERROR_NONE; |
|
dvander@2193
|
2830 |
|
|
dvander@2193
|
2831 |
jit_float_table = new floattbl_t[max_natives]; |
|
ds@1952
|
2832 |
for (uint32_t i=0; i<max_natives; i++) |
|
ds@1952
|
2833 |
{ |
|
dvander@2226
|
2834 |
const char *name = plugin->natives[i].name; |
|
ds@1952
|
2835 |
if (!strcmp(name, "FloatAbs")) |
|
ds@1952
|
2836 |
{ |
|
dvander@2193
|
2837 |
jit_float_table[i].found = true; |
|
dvander@2193
|
2838 |
jit_float_table[i].index = OP_FABS; |
|
dvander@2226
|
2839 |
} |
|
dvander@2226
|
2840 |
else if (!strcmp(name, "FloatAdd")) |
|
dvander@2226
|
2841 |
{ |
|
dvander@2193
|
2842 |
jit_float_table[i].found = true; |
|
dvander@2193
|
2843 |
jit_float_table[i].index = OP_FLOATADD; |
|
dvander@2226
|
2844 |
} |
|
dvander@2226
|
2845 |
else if (!strcmp(name, "FloatSub")) |
|
dvander@2226
|
2846 |
{ |
|
dvander@2193
|
2847 |
jit_float_table[i].found = true; |
|
dvander@2193
|
2848 |
jit_float_table[i].index = OP_FLOATSUB; |
|
dvander@2226
|
2849 |
} |
|
dvander@2226
|
2850 |
else if (!strcmp(name, "FloatMul")) |
|
dvander@2226
|
2851 |
{ |
|
dvander@2193
|
2852 |
jit_float_table[i].found = true; |
|
dvander@2193
|
2853 |
jit_float_table[i].index = OP_FLOATMUL; |
|
dvander@2226
|
2854 |
} |
|
dvander@2226
|
2855 |
else if (!strcmp(name, "FloatDiv")) |
|
dvander@2226
|
2856 |
{ |
|
dvander@2193
|
2857 |
jit_float_table[i].found = true; |
|
dvander@2193
|
2858 |
jit_float_table[i].index = OP_FLOATDIV; |
|
dvander@2226
|
2859 |
} |
|
dvander@2226
|
2860 |
else if (!strcmp(name, "float")) |
|
dvander@2226
|
2861 |
{ |
|
dvander@2193
|
2862 |
jit_float_table[i].found = true; |
|
dvander@2193
|
2863 |
jit_float_table[i].index = OP_FLOAT; |
|
dvander@2226
|
2864 |
} |
|
dvander@2226
|
2865 |
else if (!strcmp(name, "FloatCompare")) |
|
dvander@2226
|
2866 |
{ |
|
dvander@2193
|
2867 |
jit_float_table[i].found = true; |
|
dvander@2193
|
2868 |
jit_float_table[i].index = OP_FLOATCMP; |
|
dvander@2226
|
2869 |
} |
|
dvander@2226
|
2870 |
else if (!strcmp(name, "RoundToZero")) |
|
dvander@2226
|
2871 |
{ |
|
dvander@2193
|
2872 |
jit_float_table[i].found = true; |
|
dvander@2193
|
2873 |
jit_float_table[i].index = OP_RND_TO_ZERO; |
|
dvander@2226
|
2874 |
} |
|
dvander@2226
|
2875 |
else if (!strcmp(name, "RoundToCeil")) |
|
dvander@2226
|
2876 |
{ |
|
dvander@2193
|
2877 |
jit_float_table[i].found = true; |
|
dvander@2193
|
2878 |
jit_float_table[i].index = OP_RND_TO_CEIL; |
|
dvander@2226
|
2879 |
} |
|
dvander@2226
|
2880 |
else if (!strcmp(name, "RoundToFloor")) |
|
dvander@2226
|
2881 |
{ |
|
dvander@2193
|
2882 |
jit_float_table[i].found = true; |
|
dvander@2193
|
2883 |
jit_float_table[i].index = OP_RND_TO_FLOOR; |
|
dvander@2226
|
2884 |
} |
|
dvander@2226
|
2885 |
else if (!strcmp(name, "RoundToNearest")) |
|
dvander@2226
|
2886 |
{ |
|
dvander@2193
|
2887 |
jit_float_table[i].found = true; |
|
dvander@2193
|
2888 |
jit_float_table[i].index = OP_RND_TO_NEAREST; |
|
ds@1952
|
2889 |
} |
|
ds@1952
|
2890 |
} |
|
dvander@2226
|
2891 |
|
|
dvander@2226
|
2892 |
/* We need a relocation table. This is the relocation table we'll use for jumps |
|
dvander@2226
|
2893 |
* and calls alike. One extra cell for final CIP. |
|
dvander@2226
|
2894 |
*/ |
|
dvander@2226
|
2895 |
this->rebase = (uint8_t *)engine->BaseAlloc(plugin->pcode_size + sizeof(cell_t)); |
|
dvander@2226
|
2896 |
memset(this->rebase, 0, plugin->pcode_size + sizeof(cell_t)); |
|
dvander@2193
|
2897 |
} |
|
dvander@2193
|
2898 |
|
|
dvander@2193
|
2899 |
ICompilation *JITX86::StartCompilation(BaseRuntime *runtime) |
|
dvander@2193
|
2900 |
{ |
|
dvander@2193
|
2901 |
CompData *data = new CompData; |
|
dvander@2193
|
2902 |
|
|
dvander@2193
|
2903 |
data->SetRuntime(runtime); |
|
ds@1952
|
2904 |
|
|
ds@1952
|
2905 |
return data; |
|
ds@1952
|
2906 |
} |
|
ds@1952
|
2907 |
|
|
dvander@2193
|
2908 |
void CompData::Abort() |
|
ds@1952
|
2909 |
{ |
|
dvander@2193
|
2910 |
if (rebase) |
|
ds@1952
|
2911 |
{ |
|
dvander@2193
|
2912 |
engine->BaseFree(rebase); |
|
ds@1952
|
2913 |
} |
|
dvander@2226
|
2914 |
delete [] thunks; |
|
dvander@2193
|
2915 |
delete [] jit_float_table; |
|
dvander@2193
|
2916 |
delete this; |
|
dvander@2193
|
2917 |
} |
|
dvander@2193
|
2918 |
|
|
dvander@2193
|
2919 |
void JITX86::FreeContextVars(sp_context_t *ctx) |
|
dvander@2193
|
2920 |
{ |
|
dvander@2193
|
2921 |
free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase); |
|
dvander@2193
|
2922 |
delete (tracker_t *)ctx->vm[JITVARS_TRACKER]; |
|
ds@1952
|
2923 |
} |
|
ds@1952
|
2924 |
|
|
dvander@2193
|
2925 |
bool CompData::SetOption(const char *key, const char *val) |
|
dvander@2193
|
2926 |
{ |
|
ds@1952
|
2927 |
if (strcmp(key, SP_JITCONF_DEBUG) == 0) |
|
ds@1952
|
2928 |
{ |
|
ds@1952
|
2929 |
return true; |
|
ds@1952
|
2930 |
} |
|
ds@1952
|
2931 |
else if (strcmp(key, SP_JITCONF_PROFILE) == 0) |
|
ds@1952
|
2932 |
{ |
|
dvander@2193
|
2933 |
profile = atoi(val); |
|
ds@1952
|
2934 |
|
|
ds@1952
|
2935 |
/** Callbacks must be profiled to profile functions! */ |
|
dvander@2193
|
2936 |
if ((profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS) |
|
ds@1952
|
2937 |
{ |
|
dvander@2193
|
2938 |
profile |= SP_PROF_CALLBACKS; |
|
ds@1952
|
2939 |
} |
|
ds@1952
|
2940 |
|
|
ds@1952
|
2941 |
return true; |
|
ds@1952
|
2942 |
} |
|
ds@1952
|
2943 |
|
|
ds@1952
|
2944 |
return false; |
|
ds@1952
|
2945 |
} |
|
ds@1952
|
2946 |
|
|
dvander@2226
|
2947 |
void *JITX86::GetGenArrayIntrinsic() |
|
dvander@2226
|
2948 |
{ |
|
dvander@2226
|
2949 |
return m_pJitGenArray; |
|
dvander@2226
|
2950 |
} |
|
dvander@2226
|
2951 |
|
|
dvander@2226
|
2952 |
void *JITX86::GetReturnPoint() |
|
dvander@2226
|
2953 |
{ |
|
dvander@2226
|
2954 |
return m_pJitReturn; |
|
dvander@2226
|
2955 |
} |
|
dvander@2226
|
2956 |
|
|
dvander@2226
|
2957 |
void *JITX86::GetRoundingTable() |
|
dvander@2226
|
2958 |
{ |
|
dvander@2226
|
2959 |
return m_RoundTable; |
|
dvander@2226
|
2960 |
} |
|
dvander@2226
|
2961 |
|
|
dvander@2226
|
2962 |
typedef int (*JIT_EXECUTE)(cell_t *vars, void *addr); |
|
dvander@2226
|
2963 |
int JITX86::InvokeFunction(BaseRuntime *runtime, JitFunction *fn, cell_t *result) |
|
dvander@2226
|
2964 |
{ |
|
dvander@2226
|
2965 |
int err; |
|
dvander@2226
|
2966 |
JIT_EXECUTE pfn; |
|
dvander@2226
|
2967 |
sp_context_t *ctx; |
|
dvander@2226
|
2968 |
cell_t vars[AMX_NUM_INFO_VARS]; |
|
dvander@2226
|
2969 |
|
|
dvander@2226
|
2970 |
ctx = runtime->GetBaseContext()->GetCtx(); |
|
dvander@2226
|
2971 |
|
|
dvander@2226
|
2972 |
vars[0] = ctx->sp; |
|
dvander@2226
|
2973 |
vars[1] = ctx->hp; |
|
dvander@2226
|
2974 |
vars[2] = (cell_t)result; |
|
dvander@2226
|
2975 |
vars[3] = (cell_t)ctx; |
|
dvander@2226
|
2976 |
vars[4] = (cell_t)(runtime->m_pPlugin->memory + runtime->m_pPlugin->mem_size); |
|
dvander@2226
|
2977 |
vars[5] = fn->GetPCodeAddress(); |
|
dvander@2226
|
2978 |
vars[6] = runtime->m_pPlugin->data_size; |
|
dvander@2226
|
2979 |
vars[7] = (cell_t)(runtime->m_pPlugin->memory); |
|
dvander@2226
|
2980 |
/* vars[8] will be set to ESP */ |
|
dvander@2226
|
2981 |
|
|
dvander@2226
|
2982 |
pfn = (JIT_EXECUTE)m_pJitEntry; |
|
dvander@2226
|
2983 |
err = pfn(vars, fn->GetEntryAddress()); |
|
dvander@2226
|
2984 |
|
|
dvander@2226
|
2985 |
ctx->hp = vars[1]; |
|
dvander@2226
|
2986 |
ctx->err_cip = vars[5]; |
|
dvander@2226
|
2987 |
|
|
dvander@2226
|
2988 |
return err; |
|
dvander@2226
|
2989 |
} |
|
dvander@2226
|
2990 |
|
|
dvander@2226
|
2991 |
void *JITX86::AllocCode(size_t size) |
|
dvander@2226
|
2992 |
{ |
|
dvander@2226
|
2993 |
return Knight::KE_AllocCode(g_pCodeCache, size); |
|
dvander@2226
|
2994 |
} |
|
dvander@2226
|
2995 |
|
|
dvander@2226
|
2996 |
void JITX86::FreeCode(void *code) |
|
dvander@2226
|
2997 |
{ |
|
dvander@2226
|
2998 |
KE_FreeCode(g_pCodeCache, code); |
|
dvander@2226
|
2999 |
} |