|
dvander@367
|
1 |
/** |
|
dvander@371
|
2 |
* ================================================================ |
|
dvander@371
|
3 |
* SourcePawn (C)2004-2007 AlliedModders LLC. All rights reserved. |
|
dvander@371
|
4 |
* ================================================================ |
|
dvander@367
|
5 |
* |
|
dvander@367
|
6 |
* This file is not open source and may not be copied without explicit |
|
dvander@367
|
7 |
* written permission of AlliedModders LLC. This file may not be redistributed |
|
dvander@367
|
8 |
* in whole or significant part. |
|
dvander@367
|
9 |
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php |
|
dvander@367
|
10 |
* |
|
dvander@367
|
11 |
* Version: $Id$ |
|
dvander@367
|
12 |
*/ |
|
dvander@367
|
13 |
|
|
dvander@157
|
14 |
#include <string.h> |
|
dvander@157
|
15 |
#include <stdlib.h> |
|
dvander@157
|
16 |
#include <assert.h> |
|
dvander@157
|
17 |
#include "jit_x86.h" |
|
dvander@157
|
18 |
#include "opcode_helpers.h" |
|
dvander@157
|
19 |
#include "x86_macros.h" |
|
dvander@386
|
20 |
#include "jit_version.h" |
|
dvander@157
|
21 |
|
|
dvander@157
|
22 |
#if defined USE_UNGEN_OPCODES |
|
dvander@157
|
23 |
#include "ungen_opcodes.h" |
|
dvander@157
|
24 |
#endif |
|
dvander@157
|
25 |
|
|
dvander@157
|
26 |
inline void WriteOp_Move_Pri(JitWriter *jit) |
|
dvander@157
|
27 |
{ |
|
dvander@157
|
28 |
//mov eax, edx |
|
dvander@157
|
29 |
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
30 |
} |
|
dvander@157
|
31 |
|
|
dvander@157
|
32 |
inline void WriteOp_Move_Alt(JitWriter *jit) |
|
dvander@157
|
33 |
{ |
|
dvander@157
|
34 |
//mov edx, eax |
|
dvander@157
|
35 |
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
36 |
} |
|
dvander@157
|
37 |
|
|
dvander@157
|
38 |
inline void WriteOp_Xchg(JitWriter *jit) |
|
dvander@157
|
39 |
{ |
|
dvander@157
|
40 |
//xchg eax, edx |
|
dvander@157
|
41 |
IA32_Xchg_Eax_Reg(jit, AMX_REG_ALT); |
|
dvander@157
|
42 |
} |
|
dvander@157
|
43 |
|
|
dvander@157
|
44 |
inline void WriteOp_Push(JitWriter *jit) |
|
dvander@157
|
45 |
{ |
|
dvander@157
|
46 |
//push stack, DAT offset based |
|
dvander@157
|
47 |
//sub edi, 4 |
|
dvander@157
|
48 |
//mov ecx, [ebp+<val>] |
|
dvander@157
|
49 |
//mov [edi], ecx |
|
dvander@157
|
50 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
51 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
dvander@157
|
52 |
//optimize encoding a bit... |
|
dvander@157
|
53 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
54 |
{ |
|
dvander@157
|
55 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val); |
|
dvander@157
|
56 |
} else { |
|
dvander@157
|
57 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val); |
|
dvander@157
|
58 |
} |
|
dvander@157
|
59 |
IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG); |
|
dvander@157
|
60 |
} |
|
dvander@157
|
61 |
|
|
dvander@157
|
62 |
inline void WriteOp_Push_C(JitWriter *jit) |
|
dvander@157
|
63 |
{ |
|
dvander@157
|
64 |
//push stack |
|
dvander@157
|
65 |
//mov [edi-4], <val> |
|
dvander@157
|
66 |
//sub edi, 4 |
|
dvander@157
|
67 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
68 |
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, val, -4); |
|
dvander@157
|
69 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
dvander@157
|
70 |
} |
|
dvander@157
|
71 |
|
|
dvander@157
|
72 |
inline void WriteOp_Zero(JitWriter *jit) |
|
dvander@157
|
73 |
{ |
|
dvander@157
|
74 |
//mov [ebp+<val>], 0 |
|
dvander@157
|
75 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
76 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
77 |
{ |
|
dvander@157
|
78 |
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, 0, (jit_int8_t)val); |
|
dvander@157
|
79 |
} else { |
|
dvander@157
|
80 |
IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, 0, val); |
|
dvander@157
|
81 |
} |
|
dvander@157
|
82 |
} |
|
dvander@157
|
83 |
|
|
dvander@157
|
84 |
inline void WriteOp_Zero_S(JitWriter *jit) |
|
dvander@157
|
85 |
{ |
|
dvander@157
|
86 |
//mov [ebx+<val>], 0 |
|
dvander@157
|
87 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
88 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
89 |
{ |
|
dvander@157
|
90 |
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, 0, (jit_int8_t)val); |
|
dvander@157
|
91 |
} else { |
|
dvander@157
|
92 |
IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, 0, val); |
|
dvander@157
|
93 |
} |
|
dvander@157
|
94 |
} |
|
dvander@157
|
95 |
|
|
dvander@157
|
96 |
inline void WriteOp_Push_S(JitWriter *jit) |
|
dvander@157
|
97 |
{ |
|
dvander@157
|
98 |
//push stack, FRM offset based |
|
dvander@157
|
99 |
//sub edi, 4 |
|
dvander@157
|
100 |
//mov ecx, [ebx+<val>] |
|
dvander@157
|
101 |
//mov [edi], ecx |
|
dvander@157
|
102 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
103 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
dvander@157
|
104 |
//optimize encoding a bit... |
|
dvander@157
|
105 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
106 |
{ |
|
dvander@157
|
107 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val); |
|
dvander@157
|
108 |
} else { |
|
dvander@157
|
109 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val); |
|
dvander@157
|
110 |
} |
|
dvander@157
|
111 |
IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG); |
|
dvander@157
|
112 |
} |
|
dvander@157
|
113 |
|
|
dvander@157
|
114 |
inline void WriteOp_Push_Pri(JitWriter *jit) |
|
dvander@157
|
115 |
{ |
|
dvander@157
|
116 |
//mov [edi-4], eax |
|
dvander@157
|
117 |
//sub edi, 4 |
|
dvander@157
|
118 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_PRI, -4); |
|
dvander@157
|
119 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
dvander@157
|
120 |
} |
|
dvander@157
|
121 |
|
|
dvander@157
|
122 |
inline void WriteOp_Push_Alt(JitWriter *jit) |
|
dvander@157
|
123 |
{ |
|
dvander@157
|
124 |
//mov [edi-4], edx |
|
dvander@157
|
125 |
//sub edi, 4 |
|
dvander@157
|
126 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_ALT, -4); |
|
dvander@157
|
127 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
dvander@157
|
128 |
} |
|
dvander@157
|
129 |
|
|
dvander@157
|
130 |
inline void WriteOp_Push2_C(JitWriter *jit) |
|
dvander@157
|
131 |
{ |
|
dvander@157
|
132 |
Macro_PushN_C(jit, 2); |
|
dvander@157
|
133 |
} |
|
dvander@157
|
134 |
|
|
dvander@157
|
135 |
inline void WriteOp_Push3_C(JitWriter *jit) |
|
dvander@157
|
136 |
{ |
|
dvander@157
|
137 |
Macro_PushN_C(jit, 3); |
|
dvander@157
|
138 |
} |
|
dvander@157
|
139 |
|
|
dvander@157
|
140 |
inline void WriteOp_Push4_C(JitWriter *jit) |
|
dvander@157
|
141 |
{ |
|
dvander@157
|
142 |
Macro_PushN_C(jit, 4); |
|
dvander@157
|
143 |
} |
|
dvander@157
|
144 |
|
|
dvander@157
|
145 |
inline void WriteOp_Push5_C(JitWriter *jit) |
|
dvander@157
|
146 |
{ |
|
dvander@157
|
147 |
Macro_PushN_C(jit, 5); |
|
dvander@157
|
148 |
} |
|
dvander@157
|
149 |
|
|
dvander@157
|
150 |
inline void WriteOp_Push2_Adr(JitWriter *jit) |
|
dvander@157
|
151 |
{ |
|
dvander@157
|
152 |
Macro_PushN_Addr(jit, 2); |
|
dvander@157
|
153 |
} |
|
dvander@157
|
154 |
|
|
dvander@157
|
155 |
inline void WriteOp_Push3_Adr(JitWriter *jit) |
|
dvander@157
|
156 |
{ |
|
dvander@157
|
157 |
Macro_PushN_Addr(jit, 3); |
|
dvander@157
|
158 |
} |
|
dvander@157
|
159 |
|
|
dvander@157
|
160 |
inline void WriteOp_Push4_Adr(JitWriter *jit) |
|
dvander@157
|
161 |
{ |
|
dvander@157
|
162 |
Macro_PushN_Addr(jit, 4); |
|
dvander@157
|
163 |
} |
|
dvander@157
|
164 |
|
|
dvander@157
|
165 |
inline void WriteOp_Push5_Adr(JitWriter *jit) |
|
dvander@157
|
166 |
{ |
|
dvander@157
|
167 |
Macro_PushN_Addr(jit, 5); |
|
dvander@157
|
168 |
} |
|
dvander@157
|
169 |
|
|
dvander@157
|
170 |
inline void WriteOp_Push2_S(JitWriter *jit) |
|
dvander@157
|
171 |
{ |
|
dvander@157
|
172 |
Macro_PushN_S(jit, 2); |
|
dvander@157
|
173 |
} |
|
dvander@157
|
174 |
|
|
dvander@157
|
175 |
inline void WriteOp_Push3_S(JitWriter *jit) |
|
dvander@157
|
176 |
{ |
|
dvander@157
|
177 |
Macro_PushN_S(jit, 3); |
|
dvander@157
|
178 |
} |
|
dvander@157
|
179 |
|
|
dvander@157
|
180 |
inline void WriteOp_Push4_S(JitWriter *jit) |
|
dvander@157
|
181 |
{ |
|
dvander@157
|
182 |
Macro_PushN_S(jit, 4); |
|
dvander@157
|
183 |
} |
|
dvander@157
|
184 |
|
|
dvander@157
|
185 |
inline void WriteOp_Push5_S(JitWriter *jit) |
|
dvander@157
|
186 |
{ |
|
dvander@157
|
187 |
Macro_PushN_S(jit, 5); |
|
dvander@157
|
188 |
} |
|
dvander@157
|
189 |
|
|
dvander@157
|
190 |
inline void WriteOp_Push5(JitWriter *jit) |
|
dvander@157
|
191 |
{ |
|
dvander@157
|
192 |
Macro_PushN(jit, 5); |
|
dvander@157
|
193 |
} |
|
dvander@157
|
194 |
|
|
dvander@157
|
195 |
inline void WriteOp_Push4(JitWriter *jit) |
|
dvander@157
|
196 |
{ |
|
dvander@157
|
197 |
Macro_PushN(jit, 4); |
|
dvander@157
|
198 |
} |
|
dvander@157
|
199 |
|
|
dvander@157
|
200 |
inline void WriteOp_Push3(JitWriter *jit) |
|
dvander@157
|
201 |
{ |
|
dvander@157
|
202 |
Macro_PushN(jit, 3); |
|
dvander@157
|
203 |
} |
|
dvander@157
|
204 |
|
|
dvander@157
|
205 |
inline void WriteOp_Push2(JitWriter *jit) |
|
dvander@157
|
206 |
{ |
|
dvander@157
|
207 |
Macro_PushN(jit, 2); |
|
dvander@157
|
208 |
} |
|
dvander@157
|
209 |
|
|
dvander@157
|
210 |
inline void WriteOp_Zero_Pri(JitWriter *jit) |
|
dvander@157
|
211 |
{ |
|
dvander@157
|
212 |
//xor eax, eax |
|
dvander@157
|
213 |
IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
214 |
} |
|
dvander@157
|
215 |
|
|
dvander@157
|
216 |
inline void WriteOp_Zero_Alt(JitWriter *jit) |
|
dvander@157
|
217 |
{ |
|
dvander@157
|
218 |
//xor edx, edx |
|
dvander@157
|
219 |
IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
220 |
} |
|
dvander@157
|
221 |
|
|
dvander@157
|
222 |
inline void WriteOp_Add(JitWriter *jit) |
|
dvander@157
|
223 |
{ |
|
dvander@157
|
224 |
//add eax, edx |
|
dvander@157
|
225 |
IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
226 |
} |
|
dvander@157
|
227 |
|
|
dvander@157
|
228 |
inline void WriteOp_Sub(JitWriter *jit) |
|
dvander@157
|
229 |
{ |
|
dvander@157
|
230 |
//sub eax, edx |
|
dvander@157
|
231 |
IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
232 |
} |
|
dvander@157
|
233 |
|
|
dvander@157
|
234 |
inline void WriteOp_Sub_Alt(JitWriter *jit) |
|
dvander@157
|
235 |
{ |
|
dvander@157
|
236 |
//neg eax |
|
dvander@157
|
237 |
//add eax, edx |
|
dvander@157
|
238 |
IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
239 |
IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
240 |
} |
|
dvander@157
|
241 |
|
|
dvander@157
|
242 |
inline void WriteOp_Proc(JitWriter *jit) |
|
dvander@157
|
243 |
{ |
|
dvander@157
|
244 |
/* align this to four byte boundaries! |
|
dvander@157
|
245 |
* This is a decent optimization - x86 likes calls to be properly aligned, otherwise there's an alignment exception |
|
dvander@157
|
246 |
* Since all calls are jumped to by relocation, the nops/garbage will never be hit by the runtime process. |
|
dvander@157
|
247 |
* Just in case, we guard this memory with INT3 to break into the debugger. |
|
dvander@157
|
248 |
*/ |
|
dvander@157
|
249 |
jitoffs_t cur_offs = jit->get_outputpos(); |
|
dvander@175
|
250 |
CompData *co = (CompData *)jit->data; |
|
dvander@157
|
251 |
if (cur_offs % 4) |
|
dvander@157
|
252 |
{ |
|
dvander@157
|
253 |
cur_offs = 4 - (cur_offs % 4); |
|
dvander@157
|
254 |
for (unsigned int i=0; i<cur_offs; i++) |
|
dvander@157
|
255 |
{ |
|
dvander@157
|
256 |
jit->write_ubyte(IA32_INT3); |
|
dvander@157
|
257 |
} |
|
dvander@175
|
258 |
} |
|
dvander@175
|
259 |
|
|
dvander@175
|
260 |
/* Write the info struct about this function */ |
|
dvander@175
|
261 |
jit->write_uint32(JIT_FUNCMAGIC); |
|
dvander@175
|
262 |
jit->write_uint32(co->func_idx); |
|
dvander@175
|
263 |
|
|
dvander@175
|
264 |
/* Now we have to backpatch our reloction offset! */ |
|
dvander@175
|
265 |
{ |
|
dvander@157
|
266 |
jitoffs_t offs = jit->get_inputpos() - sizeof(cell_t); |
|
dvander@157
|
267 |
jitcode_t rebase = ((CompData *)jit->data)->rebase; |
|
dvander@157
|
268 |
*(jitoffs_t *)((unsigned char *)rebase + offs) = jit->get_outputpos(); |
|
dvander@157
|
269 |
} |
|
dvander@175
|
270 |
|
|
dvander@175
|
271 |
/* Lastly, if we're writing, keep track of the function count */ |
|
dvander@175
|
272 |
if (jit->outbase) |
|
dvander@175
|
273 |
{ |
|
dvander@175
|
274 |
co->func_idx++; |
|
dvander@175
|
275 |
} |
|
dvander@175
|
276 |
|
|
dvander@157
|
277 |
//push old frame on stack: |
|
dvander@157
|
278 |
//mov ecx, [esi+frm] |
|
dvander@157
|
279 |
//mov [edi-4], ecx |
|
dvander@157
|
280 |
//sub edi, 8 ;extra un-used slot for non-existant CIP |
|
dvander@157
|
281 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG); |
|
dvander@157
|
282 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4); |
|
dvander@157
|
283 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG); |
|
dvander@157
|
284 |
//save frame: |
|
dvander@157
|
285 |
//mov ecx, edi - get new frame |
|
dvander@157
|
286 |
//mov ebx, edi - store frame back |
|
dvander@157
|
287 |
//sub ecx, ebp - relocate local frame |
|
dvander@157
|
288 |
//mov [esi+frm], ecx |
|
dvander@157
|
289 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG); |
|
dvander@157
|
290 |
IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG); |
|
dvander@157
|
291 |
IA32_Sub_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_DAT, MOD_REG); |
|
dvander@157
|
292 |
IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_TMP, MOD_MEM_REG); |
|
dvander@157
|
293 |
} |
|
dvander@157
|
294 |
|
|
dvander@157
|
295 |
inline void WriteOp_Lidx_B(JitWriter *jit) |
|
dvander@157
|
296 |
{ |
|
dvander@157
|
297 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
298 |
//shl eax, <val> |
|
dvander@157
|
299 |
//add eax, edx |
|
dvander@157
|
300 |
//mov eax, [ebp+eax] |
|
dvander@157
|
301 |
IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG); |
|
dvander@157
|
302 |
IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
303 |
Write_Check_VerifyAddr(jit, AMX_REG_PRI); |
|
dvander@157
|
304 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
dvander@157
|
305 |
} |
|
dvander@157
|
306 |
|
|
dvander@157
|
307 |
inline void WriteOp_Idxaddr_B(JitWriter *jit) |
|
dvander@157
|
308 |
{ |
|
dvander@157
|
309 |
//shl eax, <val> |
|
dvander@157
|
310 |
//add eax, edx |
|
dvander@157
|
311 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
312 |
IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG); |
|
dvander@157
|
313 |
IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
314 |
} |
|
dvander@157
|
315 |
|
|
dvander@157
|
316 |
inline void WriteOp_Shl(JitWriter *jit) |
|
dvander@157
|
317 |
{ |
|
dvander@157
|
318 |
//mov ecx, edx |
|
dvander@157
|
319 |
//shl eax, cl |
|
dvander@157
|
320 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
321 |
IA32_Shl_Rm_CL(jit, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
322 |
} |
|
dvander@157
|
323 |
|
|
dvander@157
|
324 |
inline void WriteOp_Shr(JitWriter *jit) |
|
dvander@157
|
325 |
{ |
|
dvander@157
|
326 |
//mov ecx, edx |
|
dvander@157
|
327 |
//shr eax, cl |
|
dvander@157
|
328 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
329 |
IA32_Shr_Rm_CL(jit, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
330 |
} |
|
dvander@157
|
331 |
|
|
dvander@157
|
332 |
inline void WriteOp_Sshr(JitWriter *jit) |
|
dvander@157
|
333 |
{ |
|
dvander@157
|
334 |
//mov ecx, edx |
|
dvander@157
|
335 |
//sar eax, cl |
|
dvander@157
|
336 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
337 |
IA32_Sar_Rm_CL(jit, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
338 |
} |
|
dvander@157
|
339 |
|
|
dvander@157
|
340 |
inline void WriteOp_Shl_C_Pri(JitWriter *jit) |
|
dvander@157
|
341 |
{ |
|
dvander@157
|
342 |
//shl eax, <val> |
|
dvander@157
|
343 |
jit_uint8_t val = (jit_uint8_t)jit->read_cell(); |
|
dvander@157
|
344 |
if (val == 1) |
|
dvander@157
|
345 |
{ |
|
dvander@157
|
346 |
IA32_Shl_Rm_1(jit, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
347 |
} else { |
|
dvander@157
|
348 |
IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG); |
|
dvander@157
|
349 |
} |
|
dvander@157
|
350 |
} |
|
dvander@157
|
351 |
|
|
dvander@157
|
352 |
inline void WriteOp_Shl_C_Alt(JitWriter *jit) |
|
dvander@157
|
353 |
{ |
|
dvander@157
|
354 |
//shl edx, <val> |
|
dvander@157
|
355 |
jit_uint8_t val = (jit_uint8_t)jit->read_cell(); |
|
dvander@157
|
356 |
if (val == 1) |
|
dvander@157
|
357 |
{ |
|
dvander@157
|
358 |
IA32_Shl_Rm_1(jit, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
359 |
} else { |
|
dvander@157
|
360 |
IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG); |
|
dvander@157
|
361 |
} |
|
dvander@157
|
362 |
} |
|
dvander@157
|
363 |
|
|
dvander@157
|
364 |
inline void WriteOp_Shr_C_Pri(JitWriter *jit) |
|
dvander@157
|
365 |
{ |
|
dvander@157
|
366 |
//shr eax, <val> |
|
dvander@157
|
367 |
jit_uint8_t val = (jit_uint8_t)jit->read_cell(); |
|
dvander@157
|
368 |
if (val == 1) |
|
dvander@157
|
369 |
{ |
|
dvander@157
|
370 |
IA32_Shr_Rm_1(jit, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
371 |
} else { |
|
dvander@157
|
372 |
IA32_Shr_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG); |
|
dvander@157
|
373 |
} |
|
dvander@157
|
374 |
} |
|
dvander@157
|
375 |
|
|
dvander@157
|
376 |
inline void WriteOp_Shr_C_Alt(JitWriter *jit) |
|
dvander@157
|
377 |
{ |
|
dvander@157
|
378 |
//shr edx, <val> |
|
dvander@157
|
379 |
jit_uint8_t val = (jit_uint8_t)jit->read_cell(); |
|
dvander@157
|
380 |
if (val == 1) |
|
dvander@157
|
381 |
{ |
|
dvander@157
|
382 |
IA32_Shr_Rm_1(jit, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
383 |
} else { |
|
dvander@157
|
384 |
IA32_Shr_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG); |
|
dvander@157
|
385 |
} |
|
dvander@157
|
386 |
} |
|
dvander@157
|
387 |
|
|
dvander@157
|
388 |
inline void WriteOp_SMul(JitWriter *jit) |
|
dvander@157
|
389 |
{ |
|
dvander@157
|
390 |
//mov ecx, edx |
|
dvander@157
|
391 |
//imul edx |
|
dvander@157
|
392 |
//mov edx, ecx |
|
dvander@157
|
393 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
394 |
IA32_IMul_Rm(jit, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
395 |
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG); |
|
dvander@157
|
396 |
} |
|
dvander@157
|
397 |
|
|
dvander@157
|
398 |
inline void WriteOp_Not(JitWriter *jit) |
|
dvander@157
|
399 |
{ |
|
dvander@157
|
400 |
//test eax, eax |
|
dvander@157
|
401 |
//mov eax, 0 |
|
dvander@157
|
402 |
//sete al |
|
dvander@157
|
403 |
IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
404 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
dvander@157
|
405 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E); |
|
dvander@157
|
406 |
} |
|
dvander@157
|
407 |
|
|
dvander@157
|
408 |
inline void WriteOp_Neg(JitWriter *jit) |
|
dvander@157
|
409 |
{ |
|
dvander@157
|
410 |
//neg eax |
|
dvander@157
|
411 |
IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
412 |
} |
|
dvander@157
|
413 |
|
|
dvander@157
|
414 |
inline void WriteOp_Xor(JitWriter *jit) |
|
dvander@157
|
415 |
{ |
|
dvander@157
|
416 |
//xor eax, edx |
|
dvander@157
|
417 |
IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
418 |
} |
|
dvander@157
|
419 |
|
|
dvander@157
|
420 |
inline void WriteOp_Or(JitWriter *jit) |
|
dvander@157
|
421 |
{ |
|
dvander@157
|
422 |
//or eax, edx |
|
dvander@157
|
423 |
IA32_Or_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
424 |
} |
|
dvander@157
|
425 |
|
|
dvander@157
|
426 |
inline void WriteOp_And(JitWriter *jit) |
|
dvander@157
|
427 |
{ |
|
dvander@157
|
428 |
//and eax, edx |
|
dvander@157
|
429 |
IA32_And_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
430 |
} |
|
dvander@157
|
431 |
|
|
dvander@157
|
432 |
inline void WriteOp_Invert(JitWriter *jit) |
|
dvander@157
|
433 |
{ |
|
dvander@157
|
434 |
//not eax |
|
dvander@157
|
435 |
IA32_Not_Rm(jit, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
436 |
} |
|
dvander@157
|
437 |
|
|
dvander@157
|
438 |
inline void WriteOp_Add_C(JitWriter *jit) |
|
dvander@157
|
439 |
{ |
|
dvander@157
|
440 |
//add eax, <val> |
|
dvander@157
|
441 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
442 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
443 |
IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG); |
|
dvander@157
|
444 |
else |
|
dvander@157
|
445 |
IA32_Add_Eax_Imm32(jit, val); |
|
dvander@157
|
446 |
} |
|
dvander@157
|
447 |
|
|
dvander@157
|
448 |
inline void WriteOp_SMul_C(JitWriter *jit) |
|
dvander@157
|
449 |
{ |
|
dvander@157
|
450 |
//imul eax, <val> |
|
dvander@157
|
451 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
452 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
453 |
IA32_IMul_Reg_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val); |
|
dvander@157
|
454 |
else |
|
dvander@157
|
455 |
IA32_IMul_Reg_Imm32(jit, AMX_REG_PRI, MOD_REG, val); |
|
dvander@157
|
456 |
} |
|
dvander@157
|
457 |
|
|
dvander@157
|
458 |
inline void WriteOp_Sign_Pri(JitWriter *jit) |
|
dvander@157
|
459 |
{ |
|
dvander@157
|
460 |
//shl eax, 24 |
|
dvander@157
|
461 |
//sar eax, 24 |
|
dvander@157
|
462 |
IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG); |
|
dvander@157
|
463 |
IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG); |
|
dvander@157
|
464 |
} |
|
dvander@157
|
465 |
|
|
dvander@157
|
466 |
inline void WriteOp_Sign_Alt(JitWriter *jit) |
|
dvander@157
|
467 |
{ |
|
dvander@157
|
468 |
//shl edx, 24 |
|
dvander@157
|
469 |
//sar edx, 24 |
|
dvander@157
|
470 |
IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG); |
|
dvander@157
|
471 |
IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG); |
|
dvander@157
|
472 |
} |
|
dvander@157
|
473 |
|
|
dvander@157
|
474 |
inline void WriteOp_Eq(JitWriter *jit) |
|
dvander@157
|
475 |
{ |
|
dvander@157
|
476 |
//cmp eax, edx ; PRI == ALT ? |
|
dvander@157
|
477 |
//mov eax, 0 |
|
dvander@157
|
478 |
//sete al |
|
dvander@157
|
479 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
480 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
dvander@157
|
481 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E); |
|
dvander@157
|
482 |
} |
|
dvander@157
|
483 |
|
|
dvander@157
|
484 |
inline void WriteOp_Neq(JitWriter *jit) |
|
dvander@157
|
485 |
{ |
|
dvander@157
|
486 |
//cmp eax, edx ; PRI != ALT ? |
|
dvander@157
|
487 |
//mov eax, 0 |
|
dvander@157
|
488 |
//setne al |
|
dvander@157
|
489 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
490 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
dvander@157
|
491 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_NE); |
|
dvander@157
|
492 |
} |
|
dvander@157
|
493 |
|
|
dvander@157
|
494 |
inline void WriteOp_Sless(JitWriter *jit) |
|
dvander@157
|
495 |
{ |
|
dvander@157
|
496 |
//cmp eax, edx ; PRI < ALT ? (signed) |
|
dvander@157
|
497 |
//mov eax, 0 |
|
dvander@157
|
498 |
//setl al |
|
dvander@157
|
499 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
500 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
dvander@157
|
501 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_L); |
|
dvander@157
|
502 |
} |
|
dvander@157
|
503 |
|
|
dvander@157
|
504 |
inline void WriteOp_Sleq(JitWriter *jit) |
|
dvander@157
|
505 |
{ |
|
dvander@157
|
506 |
//cmp eax, edx ; PRI <= ALT ? (signed) |
|
dvander@157
|
507 |
//mov eax, 0 |
|
dvander@157
|
508 |
//setle al |
|
dvander@157
|
509 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
510 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
dvander@157
|
511 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_LE); |
|
dvander@157
|
512 |
} |
|
dvander@157
|
513 |
|
|
dvander@157
|
514 |
inline void WriteOp_Sgrtr(JitWriter *jit) |
|
dvander@157
|
515 |
{ |
|
dvander@157
|
516 |
//cmp eax, edx ; PRI > ALT ? (signed) |
|
dvander@157
|
517 |
//mov eax, 0 |
|
dvander@157
|
518 |
//setg al |
|
dvander@157
|
519 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
520 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
dvander@157
|
521 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_G); |
|
dvander@157
|
522 |
} |
|
dvander@157
|
523 |
|
|
dvander@157
|
524 |
inline void WriteOp_Sgeq(JitWriter *jit) |
|
dvander@157
|
525 |
{ |
|
dvander@157
|
526 |
//cmp eax, edx ; PRI >= ALT ? (signed) |
|
dvander@157
|
527 |
//mov eax, 0 |
|
dvander@157
|
528 |
//setge al |
|
dvander@157
|
529 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
530 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
dvander@157
|
531 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_GE); |
|
dvander@157
|
532 |
} |
|
dvander@157
|
533 |
|
|
dvander@157
|
534 |
inline void WriteOp_Eq_C_Pri(JitWriter *jit) |
|
dvander@157
|
535 |
{ |
|
dvander@157
|
536 |
//cmp eax, <val> ; PRI == value ? |
|
dvander@157
|
537 |
//mov eax, 0 |
|
dvander@157
|
538 |
//sete al |
|
dvander@157
|
539 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
540 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
541 |
IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val); |
|
dvander@157
|
542 |
else |
|
dvander@157
|
543 |
IA32_Cmp_Eax_Imm32(jit, val); |
|
dvander@157
|
544 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); |
|
dvander@157
|
545 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E); |
|
dvander@157
|
546 |
} |
|
dvander@157
|
547 |
|
|
dvander@157
|
548 |
inline void WriteOp_Eq_C_Alt(JitWriter *jit) |
|
dvander@157
|
549 |
{ |
|
dvander@157
|
550 |
//xor eax, eax |
|
dvander@157
|
551 |
//cmp edx, <val> ; ALT == value ? |
|
dvander@157
|
552 |
//sete al |
|
dvander@157
|
553 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
554 |
IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
555 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
556 |
IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_ALT, (jit_int8_t)val); |
|
dvander@157
|
557 |
else |
|
dvander@157
|
558 |
IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_ALT, val); |
|
dvander@157
|
559 |
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E); |
|
dvander@157
|
560 |
} |
|
dvander@157
|
561 |
|
|
dvander@157
|
562 |
inline void WriteOp_Inc_Pri(JitWriter *jit) |
|
dvander@157
|
563 |
{ |
|
dvander@157
|
564 |
//add eax, 1 |
|
dvander@157
|
565 |
IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG); |
|
dvander@157
|
566 |
} |
|
dvander@157
|
567 |
|
|
dvander@157
|
568 |
inline void WriteOp_Inc_Alt(JitWriter *jit) |
|
dvander@157
|
569 |
{ |
|
dvander@157
|
570 |
//add edx, 1 |
|
dvander@157
|
571 |
IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG); |
|
dvander@157
|
572 |
} |
|
dvander@157
|
573 |
|
|
dvander@157
|
574 |
inline void WriteOp_Inc(JitWriter *jit) |
|
dvander@157
|
575 |
{ |
|
dvander@157
|
576 |
//add [ebp+<val>], 1 |
|
dvander@157
|
577 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
578 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
579 |
IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val); |
|
dvander@157
|
580 |
else |
|
dvander@157
|
581 |
IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val); |
|
dvander@157
|
582 |
} |
|
dvander@157
|
583 |
|
|
dvander@157
|
584 |
inline void WriteOp_Inc_S(JitWriter *jit) |
|
dvander@157
|
585 |
{ |
|
dvander@157
|
586 |
//add [ebx+<val>], 1 |
|
dvander@157
|
587 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
588 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
589 |
IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val); |
|
dvander@157
|
590 |
else |
|
dvander@157
|
591 |
IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val); |
|
dvander@157
|
592 |
} |
|
dvander@157
|
593 |
|
|
dvander@157
|
594 |
inline void WriteOp_Inc_I(JitWriter *jit) |
|
dvander@157
|
595 |
{ |
|
dvander@157
|
596 |
//add [ebp+eax], 1 |
|
dvander@157
|
597 |
IA32_Add_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1); |
|
dvander@157
|
598 |
} |
|
dvander@157
|
599 |
|
|
dvander@157
|
600 |
inline void WriteOp_Dec_Pri(JitWriter *jit) |
|
dvander@157
|
601 |
{ |
|
dvander@157
|
602 |
//sub eax, 1 |
|
dvander@157
|
603 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG); |
|
dvander@157
|
604 |
} |
|
dvander@157
|
605 |
|
|
dvander@157
|
606 |
inline void WriteOp_Dec_Alt(JitWriter *jit) |
|
dvander@157
|
607 |
{ |
|
dvander@157
|
608 |
//sub edx, 1 |
|
dvander@157
|
609 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG); |
|
dvander@157
|
610 |
} |
|
dvander@157
|
611 |
|
|
dvander@157
|
612 |
inline void WriteOp_Dec(JitWriter *jit) |
|
dvander@157
|
613 |
{ |
|
dvander@157
|
614 |
//sub [ebp+<val>], 1 |
|
dvander@157
|
615 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
616 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
617 |
{ |
|
dvander@157
|
618 |
IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val); |
|
dvander@157
|
619 |
} else { |
|
dvander@157
|
620 |
IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val); |
|
dvander@157
|
621 |
} |
|
dvander@157
|
622 |
} |
|
dvander@157
|
623 |
|
|
dvander@157
|
624 |
inline void WriteOp_Dec_S(JitWriter *jit) |
|
dvander@157
|
625 |
{ |
|
dvander@157
|
626 |
//sub [ebx+<val>], 1 |
|
dvander@157
|
627 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
628 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
629 |
{ |
|
dvander@157
|
630 |
IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val); |
|
dvander@157
|
631 |
} else { |
|
dvander@157
|
632 |
IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val); |
|
dvander@157
|
633 |
} |
|
dvander@157
|
634 |
} |
|
dvander@157
|
635 |
|
|
dvander@157
|
636 |
inline void WriteOp_Dec_I(JitWriter *jit) |
|
dvander@157
|
637 |
{ |
|
dvander@157
|
638 |
//sub [ebp+eax], 1 |
|
dvander@157
|
639 |
IA32_Sub_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1); |
|
dvander@157
|
640 |
} |
|
dvander@157
|
641 |
|
|
dvander@157
|
642 |
inline void WriteOp_Load_Pri(JitWriter *jit) |
|
dvander@157
|
643 |
{ |
|
dvander@157
|
644 |
//mov eax, [ebp+<val>] |
|
dvander@157
|
645 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
646 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
647 |
{ |
|
dvander@157
|
648 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val); |
|
dvander@157
|
649 |
} else { |
|
dvander@157
|
650 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val); |
|
dvander@157
|
651 |
} |
|
dvander@157
|
652 |
} |
|
dvander@157
|
653 |
|
|
dvander@157
|
654 |
inline void WriteOp_Load_Alt(JitWriter *jit) |
|
dvander@157
|
655 |
{ |
|
dvander@157
|
656 |
//mov edx, [ebp+<val>] |
|
dvander@157
|
657 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
658 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
659 |
{ |
|
dvander@157
|
660 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val); |
|
dvander@157
|
661 |
} else { |
|
dvander@157
|
662 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val); |
|
dvander@157
|
663 |
} |
|
dvander@157
|
664 |
} |
|
dvander@157
|
665 |
|
|
dvander@157
|
666 |
inline void WriteOp_Load_S_Pri(JitWriter *jit) |
|
dvander@157
|
667 |
{ |
|
dvander@157
|
668 |
//mov eax, [ebx+<val>] |
|
dvander@157
|
669 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
670 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
671 |
{ |
|
dvander@157
|
672 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val); |
|
dvander@157
|
673 |
} else { |
|
dvander@157
|
674 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val); |
|
dvander@157
|
675 |
} |
|
dvander@157
|
676 |
} |
|
dvander@157
|
677 |
|
|
dvander@157
|
678 |
inline void WriteOp_Load_S_Alt(JitWriter *jit) |
|
dvander@157
|
679 |
{ |
|
dvander@157
|
680 |
//mov edx, [ebx+<val>] |
|
dvander@157
|
681 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
682 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
683 |
{ |
|
dvander@157
|
684 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val); |
|
dvander@157
|
685 |
} else { |
|
dvander@157
|
686 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val); |
|
dvander@157
|
687 |
} |
|
dvander@157
|
688 |
} |
|
dvander@157
|
689 |
|
|
dvander@157
|
690 |
inline void WriteOp_Lref_Pri(JitWriter *jit) |
|
dvander@157
|
691 |
{ |
|
dvander@157
|
692 |
//mov eax, [ebp+<val>] |
|
dvander@157
|
693 |
//mov eax, [ebp+eax] |
|
dvander@157
|
694 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
695 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
696 |
{ |
|
dvander@157
|
697 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val); |
|
dvander@157
|
698 |
} else { |
|
dvander@157
|
699 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val); |
|
dvander@157
|
700 |
} |
|
dvander@157
|
701 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
dvander@157
|
702 |
} |
|
dvander@157
|
703 |
|
|
dvander@157
|
704 |
inline void WriteOp_Lref_Alt(JitWriter *jit) |
|
dvander@157
|
705 |
{ |
|
dvander@157
|
706 |
//mov edx, [ebp+<val>] |
|
dvander@157
|
707 |
//mov edx, [ebp+edx] |
|
dvander@157
|
708 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
709 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
710 |
{ |
|
dvander@157
|
711 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val); |
|
dvander@157
|
712 |
} else { |
|
dvander@157
|
713 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val); |
|
dvander@157
|
714 |
} |
|
dvander@157
|
715 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE); |
|
dvander@157
|
716 |
} |
|
dvander@157
|
717 |
|
|
dvander@157
|
718 |
inline void WriteOp_Lref_S_Pri(JitWriter *jit) |
|
dvander@157
|
719 |
{ |
|
dvander@157
|
720 |
//mov eax, [ebx+<val>] |
|
dvander@157
|
721 |
//mov eax, [ebp+eax] |
|
dvander@157
|
722 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
723 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
724 |
{ |
|
dvander@157
|
725 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val); |
|
dvander@157
|
726 |
} else { |
|
dvander@157
|
727 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val); |
|
dvander@157
|
728 |
} |
|
dvander@157
|
729 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
dvander@157
|
730 |
} |
|
dvander@157
|
731 |
|
|
dvander@157
|
732 |
inline void WriteOp_Lref_S_Alt(JitWriter *jit) |
|
dvander@157
|
733 |
{ |
|
dvander@157
|
734 |
//mov edx, [ebx+<val>] |
|
dvander@157
|
735 |
//mov edx, [ebp+edx] |
|
dvander@157
|
736 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
737 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
738 |
{ |
|
dvander@157
|
739 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val); |
|
dvander@157
|
740 |
} else { |
|
dvander@157
|
741 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val); |
|
dvander@157
|
742 |
} |
|
dvander@157
|
743 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE); |
|
dvander@157
|
744 |
} |
|
dvander@157
|
745 |
|
|
dvander@157
|
746 |
inline void WriteOp_Const_Pri(JitWriter *jit) |
|
dvander@157
|
747 |
{ |
|
dvander@157
|
748 |
//mov eax, <val> |
|
dvander@157
|
749 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
750 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, val); |
|
dvander@157
|
751 |
} |
|
dvander@157
|
752 |
|
|
dvander@157
|
753 |
inline void WriteOp_Const_Alt(JitWriter *jit) |
|
dvander@157
|
754 |
{ |
|
dvander@157
|
755 |
//mov edx, <val> |
|
dvander@157
|
756 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
757 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_ALT, val); |
|
dvander@157
|
758 |
} |
|
dvander@157
|
759 |
|
|
dvander@157
|
760 |
inline void WriteOp_Addr_Pri(JitWriter *jit) |
|
dvander@157
|
761 |
{ |
|
dvander@157
|
762 |
//mov eax, [esi+frm] |
|
dvander@157
|
763 |
//add eax, <val> |
|
dvander@157
|
764 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
765 |
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG); |
|
dvander@157
|
766 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
767 |
{ |
|
dvander@157
|
768 |
IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG); |
|
dvander@157
|
769 |
} else { |
|
dvander@157
|
770 |
IA32_Add_Eax_Imm32(jit, val); |
|
dvander@157
|
771 |
} |
|
dvander@157
|
772 |
} |
|
dvander@157
|
773 |
|
|
dvander@157
|
774 |
inline void WriteOp_Addr_Alt(JitWriter *jit) |
|
dvander@157
|
775 |
{ |
|
dvander@157
|
776 |
//mov edx, [esi+frm] |
|
dvander@157
|
777 |
//add edx, <val> |
|
dvander@157
|
778 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
779 |
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_INFO, MOD_MEM_REG); |
|
dvander@157
|
780 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
781 |
{ |
|
dvander@157
|
782 |
IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, (jit_int8_t)val, MOD_REG); |
|
dvander@157
|
783 |
} else { |
|
dvander@157
|
784 |
IA32_Add_Rm_Imm32(jit, AMX_REG_ALT, val, MOD_REG); |
|
dvander@157
|
785 |
} |
|
dvander@157
|
786 |
} |
|
dvander@157
|
787 |
|
|
dvander@157
|
788 |
inline void WriteOp_Stor_Pri(JitWriter *jit) |
|
dvander@157
|
789 |
{ |
|
dvander@157
|
790 |
//mov [ebp+<val>], eax |
|
dvander@157
|
791 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
792 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
793 |
{ |
|
dvander@157
|
794 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_PRI, (jit_int8_t)val); |
|
dvander@157
|
795 |
} else { |
|
dvander@157
|
796 |
IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_PRI, val); |
|
dvander@157
|
797 |
} |
|
dvander@157
|
798 |
} |
|
dvander@157
|
799 |
|
|
dvander@157
|
800 |
inline void WriteOp_Stor_Alt(JitWriter *jit) |
|
dvander@157
|
801 |
{ |
|
dvander@157
|
802 |
//mov [ebp+<val>], edx |
|
dvander@157
|
803 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
804 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
805 |
{ |
|
dvander@157
|
806 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_ALT, (jit_int8_t)val); |
|
dvander@157
|
807 |
} else { |
|
dvander@157
|
808 |
IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_ALT, val); |
|
dvander@157
|
809 |
} |
|
dvander@157
|
810 |
} |
|
dvander@157
|
811 |
|
|
dvander@157
|
812 |
inline void WriteOp_Stor_S_Pri(JitWriter *jit) |
|
dvander@157
|
813 |
{ |
|
dvander@157
|
814 |
//mov [ebx+<val>], eax |
|
dvander@157
|
815 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
816 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
817 |
{ |
|
dvander@157
|
818 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_PRI, (jit_int8_t)val); |
|
dvander@157
|
819 |
} else { |
|
dvander@157
|
820 |
IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_PRI, val); |
|
dvander@157
|
821 |
} |
|
dvander@157
|
822 |
} |
|
dvander@157
|
823 |
|
|
dvander@157
|
824 |
inline void WriteOp_Stor_S_Alt(JitWriter *jit) |
|
dvander@157
|
825 |
{ |
|
dvander@157
|
826 |
//mov [ebx+<val>], edx |
|
dvander@157
|
827 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
828 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
829 |
{ |
|
dvander@157
|
830 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_ALT, (jit_int8_t)val); |
|
dvander@157
|
831 |
} else { |
|
dvander@157
|
832 |
IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_ALT, val); |
|
dvander@157
|
833 |
} |
|
dvander@157
|
834 |
} |
|
dvander@157
|
835 |
|
|
dvander@157
|
836 |
inline void WriteOp_Idxaddr(JitWriter *jit) |
|
dvander@157
|
837 |
{ |
|
dvander@157
|
838 |
//lea eax, [edx+4*eax] |
|
dvander@157
|
839 |
IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4); |
|
dvander@157
|
840 |
} |
|
dvander@157
|
841 |
|
|
dvander@157
|
842 |
inline void WriteOp_Sref_Pri(JitWriter *jit) |
|
dvander@157
|
843 |
{ |
|
dvander@157
|
844 |
//mov ecx, [ebp+<val>] |
|
dvander@157
|
845 |
//mov [ebp+ecx], eax |
|
dvander@157
|
846 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
847 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
848 |
{ |
|
dvander@157
|
849 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val); |
|
dvander@157
|
850 |
} else { |
|
dvander@157
|
851 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val); |
|
dvander@157
|
852 |
} |
|
dvander@157
|
853 |
IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI); |
|
dvander@157
|
854 |
} |
|
dvander@157
|
855 |
|
|
dvander@157
|
856 |
inline void WriteOp_Sref_Alt(JitWriter *jit) |
|
dvander@157
|
857 |
{ |
|
dvander@157
|
858 |
//mov ecx, [ebp+<val>] |
|
dvander@157
|
859 |
//mov [ebp+ecx], edx |
|
dvander@157
|
860 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
861 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
862 |
{ |
|
dvander@157
|
863 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val); |
|
dvander@157
|
864 |
} else { |
|
dvander@157
|
865 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val); |
|
dvander@157
|
866 |
} |
|
dvander@157
|
867 |
IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT); |
|
dvander@157
|
868 |
} |
|
dvander@157
|
869 |
|
|
dvander@157
|
870 |
inline void WriteOp_Sref_S_Pri(JitWriter *jit) |
|
dvander@157
|
871 |
{ |
|
dvander@157
|
872 |
//mov ecx, [ebx+<val>] |
|
dvander@157
|
873 |
//mov [ebp+ecx], eax |
|
dvander@157
|
874 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
875 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
876 |
{ |
|
dvander@157
|
877 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val); |
|
dvander@157
|
878 |
} else { |
|
dvander@157
|
879 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val); |
|
dvander@157
|
880 |
} |
|
dvander@157
|
881 |
IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI); |
|
dvander@157
|
882 |
} |
|
dvander@157
|
883 |
|
|
dvander@157
|
884 |
inline void WriteOp_Sref_S_Alt(JitWriter *jit) |
|
dvander@157
|
885 |
{ |
|
dvander@157
|
886 |
//mov ecx, [ebx+<val>] |
|
dvander@157
|
887 |
//mov [ebp+ecx], edx |
|
dvander@157
|
888 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
889 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
890 |
{ |
|
dvander@157
|
891 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val); |
|
dvander@157
|
892 |
} else { |
|
dvander@157
|
893 |
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val); |
|
dvander@157
|
894 |
} |
|
dvander@157
|
895 |
IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT); |
|
dvander@157
|
896 |
} |
|
dvander@157
|
897 |
|
|
dvander@157
|
898 |
inline void WriteOp_Pop_Pri(JitWriter *jit) |
|
dvander@157
|
899 |
{ |
|
dvander@157
|
900 |
//mov eax, [edi] |
|
dvander@157
|
901 |
//add edi, 4 |
|
dvander@157
|
902 |
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG); |
|
dvander@157
|
903 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
dvander@157
|
904 |
} |
|
dvander@157
|
905 |
|
|
dvander@157
|
906 |
inline void WriteOp_Pop_Alt(JitWriter *jit) |
|
dvander@157
|
907 |
{ |
|
dvander@157
|
908 |
//mov edx, [edi] |
|
dvander@157
|
909 |
//add edi, 4 |
|
dvander@157
|
910 |
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG); |
|
dvander@157
|
911 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
dvander@157
|
912 |
} |
|
dvander@157
|
913 |
|
|
dvander@157
|
914 |
inline void WriteOp_Swap_Pri(JitWriter *jit) |
|
dvander@157
|
915 |
{ |
|
dvander@157
|
916 |
//add [edi], eax |
|
dvander@157
|
917 |
//sub eax, [edi] |
|
dvander@157
|
918 |
//add [edi], eax |
|
dvander@157
|
919 |
//neg eax |
|
dvander@157
|
920 |
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG); |
|
dvander@157
|
921 |
IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG); |
|
dvander@157
|
922 |
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG); |
|
dvander@157
|
923 |
IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
924 |
} |
|
dvander@157
|
925 |
|
|
dvander@157
|
926 |
inline void WriteOp_Swap_Alt(JitWriter *jit) |
|
dvander@157
|
927 |
{ |
|
dvander@157
|
928 |
//add [edi], edx |
|
dvander@157
|
929 |
//sub edx, [edi] |
|
dvander@157
|
930 |
//add [edi], edx |
|
dvander@157
|
931 |
//neg edx |
|
dvander@157
|
932 |
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG); |
|
dvander@157
|
933 |
IA32_Sub_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG); |
|
dvander@157
|
934 |
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG); |
|
dvander@157
|
935 |
IA32_Neg_Rm(jit, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
936 |
} |
|
dvander@157
|
937 |
|
|
dvander@157
|
938 |
inline void WriteOp_PushAddr(JitWriter *jit) |
|
dvander@157
|
939 |
{ |
|
dvander@157
|
940 |
//mov ecx, [esi+frm] ;get address (offset from frame) |
|
dvander@157
|
941 |
//sub edi, 4 |
|
dvander@157
|
942 |
//add ecx, <val> |
|
dvander@157
|
943 |
//mov [edi], ecx |
|
dvander@157
|
944 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
945 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG); |
|
dvander@157
|
946 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
dvander@157
|
947 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
948 |
{ |
|
dvander@157
|
949 |
IA32_Add_Rm_Imm8(jit, AMX_REG_TMP, (jit_int8_t)val, MOD_REG); |
|
dvander@157
|
950 |
} else { |
|
dvander@157
|
951 |
IA32_Add_Rm_Imm32(jit, AMX_REG_TMP, val, MOD_REG); |
|
dvander@157
|
952 |
} |
|
dvander@157
|
953 |
IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG); |
|
dvander@157
|
954 |
} |
|
dvander@157
|
955 |
|
|
dvander@157
|
956 |
inline void WriteOp_Movs(JitWriter *jit) |
|
dvander@157
|
957 |
{ |
|
dvander@157
|
958 |
//cld |
|
dvander@157
|
959 |
//push esi |
|
dvander@157
|
960 |
//push edi |
|
dvander@157
|
961 |
//lea esi, [ebp+eax] |
|
dvander@157
|
962 |
//lea edi, [ebp+edx] |
|
dvander@157
|
963 |
//if dword: |
|
dvander@157
|
964 |
// mov ecx, dword |
|
dvander@157
|
965 |
// rep movsd |
|
dvander@157
|
966 |
//if byte: |
|
dvander@157
|
967 |
// mov ecx, byte |
|
dvander@157
|
968 |
// rep movsb |
|
dvander@157
|
969 |
//pop edi |
|
dvander@157
|
970 |
//pop esi |
|
dvander@157
|
971 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
972 |
unsigned int dwords = val >> 2; |
|
dvander@157
|
973 |
unsigned int bytes = val & 0x3; |
|
dvander@157
|
974 |
|
|
dvander@157
|
975 |
IA32_Cld(jit); |
|
dvander@157
|
976 |
IA32_Push_Reg(jit, REG_ESI); |
|
dvander@157
|
977 |
IA32_Push_Reg(jit, REG_EDI); |
|
dvander@157
|
978 |
IA32_Lea_Reg_DispEBPRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
dvander@157
|
979 |
IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE); |
|
dvander@157
|
980 |
if (dwords) |
|
dvander@157
|
981 |
{ |
|
dvander@157
|
982 |
IA32_Mov_Reg_Imm32(jit, REG_ECX, dwords); |
|
dvander@157
|
983 |
IA32_Rep(jit); |
|
dvander@157
|
984 |
IA32_Movsd(jit); |
|
dvander@157
|
985 |
} |
|
dvander@157
|
986 |
if (bytes) |
|
dvander@157
|
987 |
{ |
|
dvander@157
|
988 |
IA32_Mov_Reg_Imm32(jit, REG_ECX, bytes); |
|
dvander@157
|
989 |
IA32_Rep(jit); |
|
dvander@157
|
990 |
IA32_Movsb(jit); |
|
dvander@157
|
991 |
} |
|
dvander@157
|
992 |
IA32_Pop_Reg(jit, REG_EDI); |
|
dvander@157
|
993 |
IA32_Pop_Reg(jit, REG_ESI); |
|
dvander@157
|
994 |
} |
|
dvander@157
|
995 |
|
|
dvander@157
|
996 |
inline void WriteOp_Fill(JitWriter *jit) |
|
dvander@157
|
997 |
{ |
|
dvander@157
|
998 |
//push edi |
|
dvander@157
|
999 |
//lea edi, [ebp+edx] |
|
dvander@157
|
1000 |
//mov ecx, <val> >> 2 |
|
dvander@157
|
1001 |
//cld |
|
dvander@157
|
1002 |
//rep stosd |
|
dvander@157
|
1003 |
//pop edi |
|
dvander@157
|
1004 |
unsigned int val = jit->read_cell() >> 2; |
|
dvander@157
|
1005 |
|
|
dvander@157
|
1006 |
IA32_Push_Reg(jit, REG_EDI); |
|
dvander@157
|
1007 |
IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE); |
|
dvander@157
|
1008 |
IA32_Mov_Reg_Imm32(jit, REG_ECX, val); |
|
dvander@157
|
1009 |
IA32_Cld(jit); |
|
dvander@157
|
1010 |
IA32_Rep(jit); |
|
dvander@157
|
1011 |
IA32_Stosd(jit); |
|
dvander@157
|
1012 |
IA32_Pop_Reg(jit, REG_EDI); |
|
dvander@157
|
1013 |
} |
|
dvander@157
|
1014 |
|
|
dvander@157
|
1015 |
inline void WriteOp_GenArray(JitWriter *jit, bool autozero) |
|
dvander@157
|
1016 |
{ |
|
dvander@157
|
1017 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
1018 |
if (val == 1) |
|
dvander@157
|
1019 |
{ |
|
dvander@157
|
1020 |
/* flat array. we can generate this without indirection tables. */ |
|
dvander@157
|
1021 |
/* Note that we can overwrite ALT because technically STACK should be destroying ALT */ |
|
dvander@157
|
1022 |
//mov edx, [esi+info.heap] |
|
dvander@157
|
1023 |
//mov ecx, [edi] |
|
dvander@157
|
1024 |
//mov [edi], edx ;store base of array into stack |
|
dvander@157
|
1025 |
//lea edx, [edx+ecx*4] ;get the final new heap pointer |
|
dvander@157
|
1026 |
//mov [esi+info.heap], edx ;store heap pointer back |
|
dvander@157
|
1027 |
//add edx, ebp ;relocate |
|
dvander@157
|
1028 |
//cmp edx, edi ;compare against stack pointer |
|
dvander@157
|
1029 |
//jae :error ;error out if not enough space |
|
dvander@157
|
1030 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP); |
|
dvander@157
|
1031 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG); |
|
dvander@157
|
1032 |
IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG); |
|
dvander@157
|
1033 |
IA32_Lea_Reg_DispRegMult(jit, AMX_REG_ALT, AMX_REG_ALT, AMX_REG_TMP, SCALE4); |
|
dvander@157
|
1034 |
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_ALT, AMX_INFO_HEAP); |
|
dvander@157
|
1035 |
IA32_Add_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_DAT, MOD_REG); |
|
dvander@157
|
1036 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_REG); |
|
dvander@157
|
1037 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_heaplow); |
|
dvander@157
|
1038 |
|
|
dvander@157
|
1039 |
WriteOp_Tracker_Push_Reg(jit, REG_ECX); |
|
dvander@157
|
1040 |
|
|
dvander@157
|
1041 |
if (autozero) |
|
dvander@157
|
1042 |
{ |
|
dvander@157
|
1043 |
/* Zero out the array - inline a quick fill */ |
|
dvander@157
|
1044 |
//push eax ;save pri |
|
dvander@157
|
1045 |
//push edi ;save stk |
|
dvander@157
|
1046 |
//xor eax, eax ;zero source |
|
dvander@157
|
1047 |
//mov edi, [edi] ;get heap ptr out of the stack |
|
dvander@157
|
1048 |
//add edi, ebp ;relocate |
|
dvander@157
|
1049 |
//cld ;clear direction flag |
|
dvander@157
|
1050 |
//rep stosd ;copy (note: ECX is sane from above) |
|
dvander@157
|
1051 |
//pop edi ;pop stk |
|
dvander@157
|
1052 |
//pop eax ;pop pri |
|
dvander@157
|
1053 |
IA32_Push_Reg(jit, REG_EAX); |
|
dvander@157
|
1054 |
IA32_Push_Reg(jit, REG_EDI); |
|
dvander@157
|
1055 |
IA32_Xor_Reg_Rm(jit, REG_EAX, REG_EAX, MOD_REG); |
|
dvander@157
|
1056 |
IA32_Mov_Reg_Rm(jit, REG_EDI, REG_EDI, MOD_MEM_REG); |
|
dvander@157
|
1057 |
IA32_Add_Reg_Rm(jit, REG_EDI, REG_EBP, MOD_REG); |
|
dvander@157
|
1058 |
IA32_Cld(jit); |
|
dvander@157
|
1059 |
IA32_Rep(jit); |
|
dvander@157
|
1060 |
IA32_Stosd(jit); |
|
dvander@157
|
1061 |
IA32_Pop_Reg(jit, REG_EDI); |
|
dvander@157
|
1062 |
IA32_Pop_Reg(jit, REG_EAX); |
|
dvander@157
|
1063 |
} |
|
dvander@157
|
1064 |
} else { |
|
dvander@157
|
1065 |
//mov ecx, num_dims |
|
dvander@157
|
1066 |
//mov edx, 0/1 |
|
dvander@157
|
1067 |
//call [genarray] |
|
dvander@157
|
1068 |
IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, val); |
|
dvander@157
|
1069 |
if (autozero) |
|
dvander@157
|
1070 |
{ |
|
dvander@157
|
1071 |
IA32_Mov_Reg_Imm32(jit, REG_EDX, 1); |
|
dvander@157
|
1072 |
} else { |
|
dvander@157
|
1073 |
IA32_Mov_Reg_Imm32(jit, REG_EDX, 0); |
|
dvander@157
|
1074 |
} |
|
dvander@157
|
1075 |
jitoffs_t call = IA32_Call_Imm32(jit, 0); |
|
dvander@157
|
1076 |
IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_genarray); |
|
dvander@157
|
1077 |
} |
|
dvander@157
|
1078 |
} |
|
dvander@157
|
1079 |
|
|
dvander@157
|
1080 |
inline void WriteOp_Load_Both(JitWriter *jit) |
|
dvander@157
|
1081 |
{ |
|
dvander@157
|
1082 |
WriteOp_Load_Pri(jit); |
|
dvander@157
|
1083 |
WriteOp_Load_Alt(jit); |
|
dvander@157
|
1084 |
} |
|
dvander@157
|
1085 |
|
|
dvander@157
|
1086 |
inline void WriteOp_Load_S_Both(JitWriter *jit) |
|
dvander@157
|
1087 |
{ |
|
dvander@157
|
1088 |
WriteOp_Load_S_Pri(jit); |
|
dvander@157
|
1089 |
WriteOp_Load_S_Alt(jit); |
|
dvander@157
|
1090 |
} |
|
dvander@157
|
1091 |
|
|
dvander@157
|
1092 |
inline void WriteOp_Const(JitWriter *jit) |
|
dvander@157
|
1093 |
{ |
|
dvander@157
|
1094 |
//mov [ebp+<addr>], <val> |
|
dvander@157
|
1095 |
cell_t addr = jit->read_cell(); |
|
dvander@157
|
1096 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
1097 |
if (addr < SCHAR_MAX && addr > SCHAR_MIN) |
|
dvander@157
|
1098 |
{ |
|
dvander@157
|
1099 |
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, val, (jit_int8_t)addr); |
|
dvander@157
|
1100 |
} else { |
|
dvander@157
|
1101 |
IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, val, addr); |
|
dvander@157
|
1102 |
} |
|
dvander@157
|
1103 |
} |
|
dvander@157
|
1104 |
|
|
dvander@157
|
1105 |
inline void WriteOp_Const_S(JitWriter *jit) |
|
dvander@157
|
1106 |
{ |
|
dvander@157
|
1107 |
//mov [ebx+<offs>], <val> |
|
dvander@157
|
1108 |
cell_t offs = jit->read_cell(); |
|
dvander@157
|
1109 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
1110 |
if (offs < SCHAR_MAX && offs > SCHAR_MIN) |
|
dvander@157
|
1111 |
{ |
|
dvander@157
|
1112 |
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, val, (jit_int8_t)offs); |
|
dvander@157
|
1113 |
} else { |
|
dvander@157
|
1114 |
IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, val, offs); |
|
dvander@157
|
1115 |
} |
|
dvander@157
|
1116 |
} |
|
dvander@157
|
1117 |
|
|
dvander@157
|
1118 |
inline void WriteOp_Load_I(JitWriter *jit) |
|
dvander@157
|
1119 |
{ |
|
dvander@157
|
1120 |
//mov eax, [ebp+eax] |
|
dvander@157
|
1121 |
Write_Check_VerifyAddr(jit, AMX_REG_PRI); |
|
dvander@157
|
1122 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
dvander@157
|
1123 |
} |
|
dvander@157
|
1124 |
|
|
dvander@157
|
1125 |
inline void WriteOp_Lodb_I(JitWriter *jit) |
|
dvander@157
|
1126 |
{ |
|
dvander@157
|
1127 |
Write_Check_VerifyAddr(jit, AMX_REG_PRI); |
|
dvander@157
|
1128 |
|
|
dvander@157
|
1129 |
//mov eax, [ebp+eax] |
|
dvander@157
|
1130 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
dvander@157
|
1131 |
|
|
dvander@157
|
1132 |
//and eax, <bitmask> |
|
dvander@157
|
1133 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
1134 |
switch(val) |
|
dvander@157
|
1135 |
{ |
|
dvander@157
|
1136 |
case 1: |
|
dvander@157
|
1137 |
{ |
|
dvander@157
|
1138 |
IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x000000FF); |
|
dvander@157
|
1139 |
break; |
|
dvander@157
|
1140 |
} |
|
dvander@157
|
1141 |
case 2: |
|
dvander@157
|
1142 |
{ |
|
dvander@157
|
1143 |
IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x0000FFFF); |
|
dvander@157
|
1144 |
break; |
|
dvander@157
|
1145 |
} |
|
dvander@157
|
1146 |
} |
|
dvander@157
|
1147 |
} |
|
dvander@157
|
1148 |
|
|
dvander@157
|
1149 |
inline void WriteOp_Stor_I(JitWriter *jit) |
|
dvander@157
|
1150 |
{ |
|
dvander@157
|
1151 |
//mov [ebp+edx], eax |
|
dvander@157
|
1152 |
Write_Check_VerifyAddr(jit, AMX_REG_ALT); |
|
dvander@157
|
1153 |
IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); |
|
dvander@157
|
1154 |
} |
|
dvander@157
|
1155 |
|
|
dvander@157
|
1156 |
inline void WriteOp_Strb_I(JitWriter *jit) |
|
dvander@157
|
1157 |
{ |
|
dvander@157
|
1158 |
Write_Check_VerifyAddr(jit, AMX_REG_ALT); |
|
dvander@157
|
1159 |
//mov [ebp+edx], eax |
|
dvander@157
|
1160 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
1161 |
switch (val) |
|
dvander@157
|
1162 |
{ |
|
dvander@157
|
1163 |
case 1: |
|
dvander@157
|
1164 |
{ |
|
dvander@157
|
1165 |
IA32_Mov_Rm8EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); |
|
dvander@157
|
1166 |
break; |
|
dvander@157
|
1167 |
} |
|
dvander@157
|
1168 |
case 2: |
|
dvander@157
|
1169 |
{ |
|
dvander@157
|
1170 |
IA32_Mov_Rm16EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); |
|
dvander@157
|
1171 |
break; |
|
dvander@157
|
1172 |
} |
|
dvander@157
|
1173 |
case 4: |
|
dvander@157
|
1174 |
{ |
|
dvander@157
|
1175 |
IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); |
|
dvander@157
|
1176 |
break; |
|
dvander@157
|
1177 |
} |
|
dvander@157
|
1178 |
} |
|
dvander@157
|
1179 |
} |
|
dvander@157
|
1180 |
|
|
dvander@157
|
1181 |
inline void WriteOp_Lidx(JitWriter *jit) |
|
dvander@157
|
1182 |
{ |
|
dvander@157
|
1183 |
//lea eax, [edx+4*eax] |
|
dvander@157
|
1184 |
//mov eax, [ebp+eax] |
|
dvander@157
|
1185 |
IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4); |
|
dvander@157
|
1186 |
Write_Check_VerifyAddr(jit, AMX_REG_PRI); |
|
dvander@157
|
1187 |
IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); |
|
dvander@157
|
1188 |
} |
|
dvander@157
|
1189 |
|
|
dvander@157
|
1190 |
inline void WriteOp_Stack(JitWriter *jit) |
|
dvander@157
|
1191 |
{ |
|
dvander@157
|
1192 |
//add edi, <val> |
|
dvander@157
|
1193 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
1194 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
1195 |
{ |
|
dvander@157
|
1196 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)val, MOD_REG); |
|
dvander@157
|
1197 |
} else { |
|
dvander@157
|
1198 |
IA32_Add_Rm_Imm32(jit, AMX_REG_STK, val, MOD_REG); |
|
dvander@157
|
1199 |
} |
|
dvander@157
|
1200 |
|
|
dvander@157
|
1201 |
if (val > 0) |
|
dvander@157
|
1202 |
{ |
|
dvander@157
|
1203 |
Write_CheckStack_Min(jit); |
|
dvander@157
|
1204 |
} else if (val < 0) { |
|
dvander@157
|
1205 |
Write_CheckStack_Low(jit); |
|
dvander@157
|
1206 |
} |
|
dvander@157
|
1207 |
} |
|
dvander@157
|
1208 |
|
|
dvander@157
|
1209 |
inline void WriteOp_Heap(JitWriter *jit) |
|
dvander@157
|
1210 |
{ |
|
dvander@157
|
1211 |
//mov edx, [esi+hea] |
|
dvander@157
|
1212 |
//add [esi+hea], <val> |
|
dvander@157
|
1213 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
1214 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP); |
|
dvander@157
|
1215 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
1216 |
{ |
|
dvander@157
|
1217 |
IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_INFO, (jit_int8_t)val, AMX_INFO_HEAP); |
|
dvander@157
|
1218 |
} else { |
|
dvander@157
|
1219 |
IA32_Add_Rm_Imm32_Disp8(jit, AMX_REG_INFO, val, AMX_INFO_HEAP); |
|
dvander@157
|
1220 |
} |
|
dvander@157
|
1221 |
|
|
dvander@157
|
1222 |
/* NOTE: Backwards from op.stack */ |
|
dvander@157
|
1223 |
if (val > 0) |
|
dvander@157
|
1224 |
{ |
|
dvander@157
|
1225 |
Write_CheckHeap_Low(jit); |
|
dvander@157
|
1226 |
} else if (val < 0) { |
|
dvander@157
|
1227 |
Write_CheckHeap_Min(jit); |
|
dvander@157
|
1228 |
} |
|
dvander@157
|
1229 |
} |
|
dvander@157
|
1230 |
|
|
dvander@157
|
1231 |
inline void WriteOp_SDiv(JitWriter *jit) |
|
dvander@157
|
1232 |
{ |
|
dvander@157
|
1233 |
//mov ecx, edx |
|
dvander@157
|
1234 |
//mov edx, eax |
|
dvander@157
|
1235 |
//sar edx, 31 |
|
dvander@157
|
1236 |
//idiv ecx |
|
dvander@157
|
1237 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
1238 |
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
1239 |
IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG); |
|
dvander@157
|
1240 |
Write_Check_DivZero(jit, AMX_REG_TMP); |
|
dvander@157
|
1241 |
IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG); |
|
dvander@157
|
1242 |
} |
|
dvander@157
|
1243 |
|
|
dvander@157
|
1244 |
inline void WriteOp_SDiv_Alt(JitWriter *jit) |
|
dvander@157
|
1245 |
{ |
|
dvander@157
|
1246 |
//mov ecx, eax |
|
dvander@157
|
1247 |
//mov eax, edx |
|
dvander@157
|
1248 |
//sar edx, 31 |
|
dvander@157
|
1249 |
//idiv ecx |
|
dvander@157
|
1250 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
1251 |
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
1252 |
IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG); |
|
dvander@157
|
1253 |
Write_Check_DivZero(jit, AMX_REG_TMP); |
|
dvander@157
|
1254 |
IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG); |
|
dvander@157
|
1255 |
} |
|
dvander@157
|
1256 |
|
|
dvander@157
|
1257 |
inline void WriteOp_Retn(JitWriter *jit) |
|
dvander@157
|
1258 |
{ |
|
dvander@157
|
1259 |
//mov ebx, [edi+4] - get old frm |
|
dvander@157
|
1260 |
//add edi, 8 - pop stack |
|
dvander@157
|
1261 |
//mov [esi+frm], ebx - restore frame pointer |
|
dvander@157
|
1262 |
//add ebx, ebp - relocate |
|
dvander@157
|
1263 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_FRM, AMX_REG_STK, 4); |
|
dvander@157
|
1264 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG); |
|
dvander@157
|
1265 |
IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_FRM, MOD_MEM_REG); |
|
dvander@157
|
1266 |
IA32_Add_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG); |
|
dvander@157
|
1267 |
|
|
dvander@157
|
1268 |
/* pop params */ |
|
dvander@157
|
1269 |
//mov ecx, [edi] |
|
dvander@157
|
1270 |
//lea edi, [edi+ecx*4+4] |
|
dvander@157
|
1271 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG); |
|
dvander@157
|
1272 |
IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_STK, AMX_REG_STK, AMX_REG_TMP, SCALE4, 4); |
|
dvander@157
|
1273 |
|
|
dvander@157
|
1274 |
//ret - return (EIP on real stack!) |
|
dvander@157
|
1275 |
IA32_Return(jit); |
|
dvander@157
|
1276 |
} |
|
dvander@157
|
1277 |
|
|
dvander@157
|
1278 |
inline void WriteOp_Call(JitWriter *jit) |
|
dvander@157
|
1279 |
{ |
|
dvander@157
|
1280 |
cell_t offs = jit->read_cell(); |
|
dvander@157
|
1281 |
|
|
dvander@157
|
1282 |
jitoffs_t jmp = IA32_Call_Imm32(jit, 0); |
|
dvander@157
|
1283 |
IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false)); |
|
dvander@157
|
1284 |
} |
|
dvander@157
|
1285 |
|
|
dvander@157
|
1286 |
inline void WriteOp_Bounds(JitWriter *jit) |
|
dvander@157
|
1287 |
{ |
|
dvander@157
|
1288 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
1289 |
|
|
dvander@157
|
1290 |
//cmp eax, <val> |
|
dvander@157
|
1291 |
//ja :error |
|
dvander@157
|
1292 |
if (val < SCHAR_MAX && val > SCHAR_MIN) |
|
dvander@157
|
1293 |
{ |
|
dvander@157
|
1294 |
IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val); |
|
dvander@157
|
1295 |
} else { |
|
dvander@157
|
1296 |
IA32_Cmp_Eax_Imm32(jit, val); |
|
dvander@157
|
1297 |
} |
|
dvander@157
|
1298 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_A, ((CompData *)jit->data)->jit_error_bounds); |
|
dvander@157
|
1299 |
} |
|
dvander@157
|
1300 |
|
|
dvander@157
|
1301 |
inline void WriteOp_Halt(JitWriter *jit) |
|
dvander@157
|
1302 |
{ |
|
dvander@157
|
1303 |
//mov ecx, [esi+ret] |
|
dvander@157
|
1304 |
//mov [ecx], eax |
|
dvander@157
|
1305 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_RETVAL); |
|
dvander@157
|
1306 |
IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_MEM_REG); |
|
dvander@157
|
1307 |
|
|
dvander@157
|
1308 |
/* :TODO: |
|
dvander@157
|
1309 |
* We don't support sleeping or halting with weird values. |
|
dvander@157
|
1310 |
* So we're omitting the mov eax <val> that was here. |
|
dvander@157
|
1311 |
*/ |
|
dvander@157
|
1312 |
jit->read_cell(); |
|
dvander@157
|
1313 |
|
|
dvander@157
|
1314 |
CompData *data = (CompData *)jit->data; |
|
dvander@157
|
1315 |
IA32_Jump_Imm32_Abs(jit, data->jit_return); |
|
dvander@157
|
1316 |
} |
|
dvander@157
|
1317 |
|
|
dvander@157
|
1318 |
inline void WriteOp_Break(JitWriter *jit) |
|
dvander@157
|
1319 |
{ |
|
dvander@157
|
1320 |
CompData *data = (CompData *)jit->data; |
|
dvander@157
|
1321 |
if (data->debug) |
|
dvander@157
|
1322 |
{ |
|
dvander@243
|
1323 |
//jit->write_ubyte(IA32_INT3); |
|
dvander@157
|
1324 |
//mov ecx, <cip> |
|
dvander@157
|
1325 |
jitoffs_t wr = IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, 0); |
|
dvander@157
|
1326 |
jitoffs_t save = jit->get_outputpos(); |
|
dvander@157
|
1327 |
jit->set_outputpos(wr); |
|
dvander@241
|
1328 |
jit->write_uint32((uint32_t)(wr)); |
|
dvander@157
|
1329 |
jit->set_outputpos(save); |
|
dvander@157
|
1330 |
|
|
dvander@157
|
1331 |
wr = IA32_Call_Imm32(jit, 0); |
|
dvander@157
|
1332 |
IA32_Write_Jump32(jit, wr, data->jit_break); |
|
dvander@157
|
1333 |
} |
|
dvander@157
|
1334 |
} |
|
dvander@157
|
1335 |
|
|
dvander@157
|
1336 |
inline void WriteOp_Jump(JitWriter *jit) |
|
dvander@157
|
1337 |
{ |
|
dvander@157
|
1338 |
//jmp <offs> |
|
dvander@157
|
1339 |
cell_t amx_offs = jit->read_cell(); |
|
dvander@157
|
1340 |
IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, amx_offs, false)); |
|
dvander@157
|
1341 |
} |
|
dvander@157
|
1342 |
|
|
dvander@157
|
1343 |
inline void WriteOp_Jzer(JitWriter *jit) |
|
dvander@157
|
1344 |
{ |
|
dvander@157
|
1345 |
//test eax, eax |
|
dvander@157
|
1346 |
//jz <target> |
|
dvander@157
|
1347 |
cell_t target = jit->read_cell(); |
|
dvander@157
|
1348 |
IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
1349 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_Z, RelocLookup(jit, target, false)); |
|
dvander@157
|
1350 |
} |
|
dvander@157
|
1351 |
|
|
dvander@157
|
1352 |
inline void WriteOp_Jnz(JitWriter *jit) |
|
dvander@157
|
1353 |
{ |
|
dvander@157
|
1354 |
//test eax, eax |
|
dvander@157
|
1355 |
//jnz <target> |
|
dvander@157
|
1356 |
cell_t target = jit->read_cell(); |
|
dvander@157
|
1357 |
IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); |
|
dvander@157
|
1358 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, RelocLookup(jit, target, false)); |
|
dvander@157
|
1359 |
} |
|
dvander@157
|
1360 |
|
|
dvander@157
|
1361 |
inline void WriteOp_Jeq(JitWriter *jit) |
|
dvander@157
|
1362 |
{ |
|
dvander@157
|
1363 |
//cmp eax, edx |
|
dvander@157
|
1364 |
//je <target> |
|
dvander@157
|
1365 |
cell_t target = jit->read_cell(); |
|
dvander@157
|
1366 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
1367 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_E, RelocLookup(jit, target, false)); |
|
dvander@157
|
1368 |
} |
|
dvander@157
|
1369 |
|
|
dvander@157
|
1370 |
inline void WriteOp_Jneq(JitWriter *jit) |
|
dvander@157
|
1371 |
{ |
|
dvander@157
|
1372 |
//cmp eax, edx |
|
dvander@157
|
1373 |
//jne <target> |
|
dvander@157
|
1374 |
cell_t target = jit->read_cell(); |
|
dvander@157
|
1375 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
1376 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_NE, RelocLookup(jit, target, false)); |
|
dvander@157
|
1377 |
} |
|
dvander@157
|
1378 |
|
|
dvander@157
|
1379 |
inline void WriteOp_Jsless(JitWriter *jit) |
|
dvander@157
|
1380 |
{ |
|
dvander@157
|
1381 |
//cmp eax, edx |
|
dvander@157
|
1382 |
//jl <target> |
|
dvander@157
|
1383 |
cell_t target = jit->read_cell(); |
|
dvander@157
|
1384 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
1385 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_L, RelocLookup(jit, target, false)); |
|
dvander@157
|
1386 |
} |
|
dvander@157
|
1387 |
|
|
dvander@157
|
1388 |
inline void WriteOp_Jsleq(JitWriter *jit) |
|
dvander@157
|
1389 |
{ |
|
dvander@157
|
1390 |
//cmp eax, edx |
|
dvander@157
|
1391 |
//jle <target> |
|
dvander@157
|
1392 |
cell_t target = jit->read_cell(); |
|
dvander@157
|
1393 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
1394 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_LE, RelocLookup(jit, target, false)); |
|
dvander@157
|
1395 |
} |
|
dvander@157
|
1396 |
|
|
dvander@157
|
1397 |
inline void WriteOp_JsGrtr(JitWriter *jit) |
|
dvander@157
|
1398 |
{ |
|
dvander@157
|
1399 |
//cmp eax, edx |
|
dvander@157
|
1400 |
//jg <target> |
|
dvander@157
|
1401 |
cell_t target = jit->read_cell(); |
|
dvander@157
|
1402 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
1403 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_G, RelocLookup(jit, target, false)); |
|
dvander@157
|
1404 |
} |
|
dvander@157
|
1405 |
|
|
dvander@157
|
1406 |
inline void WriteOp_JsGeq(JitWriter *jit) |
|
dvander@157
|
1407 |
{ |
|
dvander@157
|
1408 |
//cmp eax, edx |
|
dvander@157
|
1409 |
//jge <target> |
|
dvander@157
|
1410 |
cell_t target = jit->read_cell(); |
|
dvander@157
|
1411 |
IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); |
|
dvander@157
|
1412 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_GE, RelocLookup(jit, target, false)); |
|
dvander@157
|
1413 |
} |
|
dvander@157
|
1414 |
|
|
dvander@157
|
1415 |
inline void WriteOp_Switch(JitWriter *jit) |
|
dvander@157
|
1416 |
{ |
|
dvander@157
|
1417 |
cell_t offs = jit->read_cell(); |
|
dvander@157
|
1418 |
cell_t *tbl = (cell_t *)((char *)jit->inbase + offs + sizeof(cell_t)); |
|
dvander@157
|
1419 |
|
|
dvander@157
|
1420 |
struct casetbl |
|
dvander@157
|
1421 |
{ |
|
dvander@157
|
1422 |
cell_t val; |
|
dvander@157
|
1423 |
cell_t offs; |
|
dvander@157
|
1424 |
}; |
|
dvander@157
|
1425 |
|
|
dvander@157
|
1426 |
/* Read the number of cases, then advance by one */ |
|
dvander@157
|
1427 |
cell_t num_cases = *tbl++; |
|
dvander@157
|
1428 |
if (!num_cases) |
|
dvander@157
|
1429 |
{ |
|
dvander@157
|
1430 |
/* Special treatment for 0 cases */ |
|
dvander@157
|
1431 |
//jmp <default> |
|
dvander@157
|
1432 |
IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, *tbl, false)); |
|
dvander@157
|
1433 |
} else { |
|
dvander@157
|
1434 |
/* Check if the case layout is fully sequential */ |
|
dvander@157
|
1435 |
casetbl *iter = (casetbl *)(tbl + 1); |
|
dvander@157
|
1436 |
casetbl *cases = iter; |
|
dvander@157
|
1437 |
cell_t first = iter[0].val; |
|
dvander@157
|
1438 |
cell_t last = first; |
|
dvander@157
|
1439 |
bool sequential = true; |
|
dvander@157
|
1440 |
for (cell_t i=1; i<num_cases; i++) |
|
dvander@157
|
1441 |
{ |
|
dvander@157
|
1442 |
if (iter[i].val != ++last) |
|
dvander@157
|
1443 |
{ |
|
dvander@157
|
1444 |
sequential = false; |
|
dvander@157
|
1445 |
break; |
|
dvander@157
|
1446 |
} |
|
dvander@157
|
1447 |
} |
|
dvander@157
|
1448 |
/* Time to generate. |
|
dvander@157
|
1449 |
* First check whether the bounds are correct: if (a < LOW || a > HIGH) |
|
dvander@157
|
1450 |
* This check is valid for both sequential and non-sequential. |
|
dvander@157
|
1451 |
*/ |
|
dvander@157
|
1452 |
cell_t low_bound = cases[0].val; |
|
dvander@157
|
1453 |
if (low_bound != 0) |
|
dvander@157
|
1454 |
{ |
|
dvander@157
|
1455 |
/* negate it so we'll get a lower bound of 0 */ |
|
dvander@157
|
1456 |
//lea ecx, [eax-<LOWER_BOUND>] |
|
dvander@157
|
1457 |
low_bound = -low_bound; |
|
dvander@157
|
1458 |
if (low_bound > SCHAR_MIN && low_bound < SCHAR_MAX) |
|
dvander@157
|
1459 |
{ |
|
dvander@157
|
1460 |
IA32_Lea_DispRegImm8(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound); |
|
dvander@157
|
1461 |
} else { |
|
dvander@157
|
1462 |
IA32_Lea_DispRegImm32(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound); |
|
dvander@157
|
1463 |
} |
|
dvander@157
|
1464 |
} |
|
dvander@157
|
1465 |
cell_t high_bound = abs(cases[0].val - cases[num_cases-1].val); |
|
dvander@157
|
1466 |
//cmp ecx, <UPPER BOUND BOUND> |
|
dvander@157
|
1467 |
if (high_bound > SCHAR_MIN && high_bound < SCHAR_MAX) |
|
dvander@157
|
1468 |
{ |
|
dvander@157
|
1469 |
IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_TMP, high_bound); |
|
dvander@157
|
1470 |
} else { |
|
dvander@157
|
1471 |
IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_TMP, high_bound); |
|
dvander@157
|
1472 |
} |
|
dvander@157
|
1473 |
//ja <default case> |
|
dvander@157
|
1474 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_A, RelocLookup(jit, *tbl, false)); |
|
dvander@157
|
1475 |
|
|
dvander@157
|
1476 |
/** |
|
dvander@157
|
1477 |
* Now we've taken the default case out of the way, it's time to do the |
|
dvander@157
|
1478 |
* full check, which is different for sequential vs. non-sequential. |
|
dvander@157
|
1479 |
*/ |
|
dvander@157
|
1480 |
if (sequential) |
|
dvander@157
|
1481 |
{ |
|
dvander@157
|
1482 |
/* we're now theoretically guaranteed to be jumping to a correct offset. |
|
dvander@157
|
1483 |
* ECX still has the correctly bound offset in it, luckily! |
|
dvander@157
|
1484 |
* thus, we simply need to relocate ECX and store the cases. |
|
dvander@157
|
1485 |
*/ |
|
dvander@157
|
1486 |
//lea ecx, [ecx*4] |
|
dvander@157
|
1487 |
//add ecx, <case table start> |
|
dvander@157
|
1488 |
IA32_Lea_Reg_RegMultImm32(jit, AMX_REG_TMP, AMX_REG_TMP, SCALE4, 0); |
|
dvander@157
|
1489 |
jitoffs_t tbl_offs = IA32_Add_Rm_Imm32_Later(jit, AMX_REG_TMP, MOD_REG); |
|
dvander@157
|
1490 |
IA32_Jump_Rm(jit, AMX_REG_TMP, MOD_MEM_REG); |
|
dvander@157
|
1491 |
/* The case table starts here. Go back and write the output pointer. */ |
|
dvander@157
|
1492 |
jitoffs_t cur_pos = jit->get_outputpos(); |
|
dvander@157
|
1493 |
jit->set_outputpos(tbl_offs); |
|
dvander@157
|
1494 |
jit->write_uint32((jit_uint32_t)(jit->outbase + cur_pos)); |
|
dvander@157
|
1495 |
jit->set_outputpos(cur_pos); |
|
dvander@157
|
1496 |
//now we can write the case table, finally! |
|
dvander@157
|
1497 |
jit_uint32_t base = (jit_uint32_t)jit->outbase; |
|
dvander@157
|
1498 |
for (cell_t i=0; i<num_cases; i++) |
|
dvander@157
|
1499 |
{ |
|
dvander@157
|
1500 |
jit->write_uint32(base + RelocLookup(jit, cases[i].offs, false)); |
|
dvander@157
|
1501 |
} |
|
dvander@157
|
1502 |
} else { |
|
dvander@157
|
1503 |
/* The slow version. Go through each case and generate a check. |
|
dvander@157
|
1504 |
* In the future we should replace case tables of more than ~8 cases with a |
|
dvander@157
|
1505 |
* hash table lookup. |
|
dvander@157
|
1506 |
* :THOUGHT: Another method of optimizing this - fill in the gaps with jumps to the default case, |
|
dvander@157
|
1507 |
* but only if we're under N cases or so! |
|
dvander@157
|
1508 |
* :THOUGHT: Write out a static btree lookup :) |
|
dvander@157
|
1509 |
*/ |
|
dvander@157
|
1510 |
cell_t val; |
|
dvander@157
|
1511 |
for (cell_t i=0; i<num_cases; i++) |
|
dvander@157
|
1512 |
{ |
|
dvander@157
|
1513 |
val = cases[i].val; |
|
dvander@157
|
1514 |
//cmp eax, <val> OR cmp al, <val> |
|
dvander@157
|
1515 |
if (val > SCHAR_MIN && val < SCHAR_MAX) |
|
dvander@157
|
1516 |
{ |
|
dvander@157
|
1517 |
IA32_Cmp_Al_Imm8(jit, val); |
|
dvander@157
|
1518 |
} else { |
|
dvander@157
|
1519 |
IA32_Cmp_Eax_Imm32(jit, cases[i].val); |
|
dvander@157
|
1520 |
} |
|
dvander@157
|
1521 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_E, RelocLookup(jit, cases[i].offs, false)); |
|
dvander@157
|
1522 |
} |
|
dvander@157
|
1523 |
/* After all this, jump to the default case! */ |
|
dvander@157
|
1524 |
IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, *tbl, false)); |
|
dvander@157
|
1525 |
} |
|
dvander@157
|
1526 |
} |
|
dvander@157
|
1527 |
} |
|
dvander@157
|
1528 |
|
|
dvander@157
|
1529 |
inline void WriteOp_Casetbl(JitWriter *jit) |
|
dvander@157
|
1530 |
{ |
|
dvander@157
|
1531 |
/* do nothing here, switch does all ze work */ |
|
dvander@157
|
1532 |
cell_t num_cases = jit->read_cell(); |
|
dvander@157
|
1533 |
|
|
dvander@157
|
1534 |
/* Two cells per case, one extra case for the default jump */ |
|
dvander@157
|
1535 |
num_cases = (num_cases * 2) + 1; |
|
dvander@157
|
1536 |
jit->inptr += num_cases; |
|
dvander@157
|
1537 |
} |
|
dvander@157
|
1538 |
|
|
dvander@157
|
1539 |
inline void WriteOp_Sysreq_C(JitWriter *jit) |
|
dvander@157
|
1540 |
{ |
|
dvander@157
|
1541 |
/* store the number of parameters on the stack, |
|
dvander@157
|
1542 |
* and store the native index as well. |
|
dvander@157
|
1543 |
*/ |
|
dvander@157
|
1544 |
cell_t native_index = jit->read_cell(); |
|
dvander@157
|
1545 |
|
|
dvander@157
|
1546 |
if ((uint32_t)native_index >= ((CompData*)jit->data)->plugin->info.natives_num) |
|
dvander@157
|
1547 |
{ |
|
dvander@157
|
1548 |
((CompData *)jit->data)->error_set = SP_ERROR_INSTRUCTION_PARAM; |
|
dvander@157
|
1549 |
return; |
|
dvander@157
|
1550 |
} |
|
dvander@157
|
1551 |
|
|
dvander@157
|
1552 |
//mov ecx, <native_index> |
|
dvander@157
|
1553 |
IA32_Mov_Reg_Imm32(jit, REG_ECX, native_index); |
|
dvander@157
|
1554 |
|
|
dvander@157
|
1555 |
jitoffs_t call = IA32_Call_Imm32(jit, 0); |
|
dvander@157
|
1556 |
IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_sysreq_c); |
|
dvander@157
|
1557 |
} |
|
dvander@157
|
1558 |
|
|
dvander@157
|
1559 |
inline void WriteOp_Sysreq_N_NoInline(JitWriter *jit) |
|
dvander@157
|
1560 |
{ |
|
dvander@157
|
1561 |
/* store the number of parameters on the stack, |
|
dvander@157
|
1562 |
* and store the native index as well. |
|
dvander@157
|
1563 |
*/ |
|
dvander@157
|
1564 |
cell_t native_index = jit->read_cell(); |
|
dvander@157
|
1565 |
cell_t num_params = jit->read_cell(); |
|
dvander@157
|
1566 |
|
|
dvander@157
|
1567 |
if ((uint32_t)native_index >= ((CompData*)jit->data)->plugin->info.natives_num) |
|
dvander@157
|
1568 |
{ |
|
dvander@157
|
1569 |
((CompData *)jit->data)->error_set = SP_ERROR_INSTRUCTION_PARAM; |
|
dvander@157
|
1570 |
return; |
|
dvander@157
|
1571 |
} |
|
dvander@157
|
1572 |
|
|
dvander@157
|
1573 |
//mov eax, <num_params> |
|
dvander@157
|
1574 |
//mov ecx, <native_index> |
|
dvander@157
|
1575 |
IA32_Mov_Reg_Imm32(jit, REG_EAX, num_params); |
|
dvander@157
|
1576 |
IA32_Mov_Reg_Imm32(jit, REG_ECX, native_index); |
|
dvander@157
|
1577 |
|
|
dvander@157
|
1578 |
jitoffs_t call = IA32_Call_Imm32(jit, 0); |
|
dvander@157
|
1579 |
IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_sysreq_n); |
|
dvander@157
|
1580 |
} |
|
dvander@157
|
1581 |
|
|
dvander@157
|
1582 |
inline void WriteOp_Sysreq_N(JitWriter *jit) |
|
dvander@157
|
1583 |
{ |
|
dvander@157
|
1584 |
/* The big daddy of opcodes. */ |
|
dvander@157
|
1585 |
cell_t native_index = jit->read_cell(); |
|
dvander@157
|
1586 |
cell_t num_params = jit->read_cell(); |
|
dvander@157
|
1587 |
CompData *data = (CompData *)jit->data; |
|
dvander@157
|
1588 |
|
|
dvander@157
|
1589 |
if ((uint32_t)native_index >= data->plugin->info.natives_num) |
|
dvander@157
|
1590 |
{ |
|
dvander@157
|
1591 |
data->error_set = SP_ERROR_INSTRUCTION_PARAM; |
|
dvander@157
|
1592 |
return; |
|
dvander@157
|
1593 |
} |
|
dvander@157
|
1594 |
|
|
dvander@157
|
1595 |
/* store the number of parameters on the stack */ |
|
dvander@157
|
1596 |
//mov [edi-4], num_params |
|
dvander@157
|
1597 |
//sub edi, 4 |
|
dvander@157
|
1598 |
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, num_params, -4); |
|
dvander@157
|
1599 |
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); |
|
dvander@157
|
1600 |
|
|
dvander@157
|
1601 |
/* save registers we will need */ |
|
dvander@157
|
1602 |
//push edx |
|
dvander@157
|
1603 |
IA32_Push_Reg(jit, AMX_REG_ALT); |
|
dvander@157
|
1604 |
|
|
dvander@157
|
1605 |
/* push some callback stuff */ |
|
dvander@157
|
1606 |
//push edi ; stack |
|
dvander@157
|
1607 |
//push <native> ; native index |
|
dvander@157
|
1608 |
IA32_Push_Reg(jit, AMX_REG_STK); |
|
dvander@157
|
1609 |
if (native_index < SCHAR_MAX && native_index > SCHAR_MIN) |
|
dvander@157
|
1610 |
{ |
|
dvander@157
|
1611 |
IA32_Push_Imm8(jit, (jit_int8_t)native_index); |
|
dvander@157
|
1612 |
} else { |
|
dvander@157
|
1613 |
IA32_Push_Imm32(jit, native_index); |
|
dvander@157
|
1614 |
} |
|
dvander@157
|
1615 |
|
|
dvander@157
|
1616 |
/* Relocate stack, heap, frm information, then store back */ |
|
dvander@157
|
1617 |
//mov eax, [esi+context] |
|
dvander@157
|
1618 |
//mov ecx, [esi+hea] |
|
dvander@157
|
1619 |
//sub edi, ebp |
|
dvander@157
|
1620 |
//mov [eax+hp], ecx |
|
dvander@157
|
1621 |
//mov ecx, [esi] |
|
dvander@157
|
1622 |
//mov [eax+sp], edi |
|
dvander@157
|
1623 |
//mov [eax+frm], ecx |
|
dvander@157
|
1624 |
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT); |
|
dvander@157
|
1625 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP); |
|
dvander@157
|
1626 |
IA32_Sub_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG); |
|
dvander@157
|
1627 |
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, hp)); |
|
dvander@157
|
1628 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG); |
|
dvander@157
|
1629 |
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_STK, offsetof(sp_context_t, sp)); |
|
dvander@157
|
1630 |
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, frm)); |
|
dvander@157
|
1631 |
|
|
dvander@157
|
1632 |
/* finally, push the last parameter and make the call */ |
|
dvander@157
|
1633 |
//push eax ; context |
|
dvander@157
|
1634 |
//call NativeCallback |
|
dvander@157
|
1635 |
IA32_Push_Reg(jit, REG_EAX); |
|
dvander@157
|
1636 |
jitoffs_t call = IA32_Call_Imm32(jit, 0); |
|
dvander@157
|
1637 |
if (!data->debug) |
|
dvander@157
|
1638 |
{ |
|
dvander@350
|
1639 |
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback); |
|
dvander@157
|
1640 |
} else { |
|
dvander@350
|
1641 |
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug); |
|
dvander@157
|
1642 |
} |
|
dvander@157
|
1643 |
|
|
dvander@157
|
1644 |
/* check for errors */ |
|
dvander@157
|
1645 |
//mov ecx, [esi+context] |
|
dvander@157
|
1646 |
//cmp [ecx+err], 0 |
|
dvander@157
|
1647 |
//jnz :error |
|
dvander@157
|
1648 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); |
|
dvander@237
|
1649 |
IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, n_err), 0); |
|
dvander@157
|
1650 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_extern_error); |
|
dvander@157
|
1651 |
|
|
dvander@157
|
1652 |
/* restore what we damaged */ |
|
dvander@157
|
1653 |
//add esp, 4*3 |
|
dvander@157
|
1654 |
//add edi, ebp |
|
dvander@157
|
1655 |
//pop edx |
|
dvander@157
|
1656 |
IA32_Add_Rm_Imm8(jit, REG_ESP, 4*3, MOD_REG); |
|
dvander@157
|
1657 |
IA32_Add_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG); |
|
dvander@157
|
1658 |
IA32_Pop_Reg(jit, AMX_REG_ALT); |
|
dvander@157
|
1659 |
|
|
dvander@157
|
1660 |
/* pop the stack. do not check the margins. |
|
dvander@157
|
1661 |
* Note that this is not a true macro - we don't bother to |
|
dvander@157
|
1662 |
* set ALT here because nothing will be using it. |
|
dvander@157
|
1663 |
*/ |
|
dvander@157
|
1664 |
num_params++; |
|
dvander@157
|
1665 |
num_params *= 4; |
|
dvander@157
|
1666 |
//add edi, <val*4+4> |
|
dvander@157
|
1667 |
if (num_params < SCHAR_MAX && num_params > SCHAR_MIN) |
|
dvander@157
|
1668 |
{ |
|
dvander@157
|
1669 |
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)num_params, MOD_REG); |
|
dvander@157
|
1670 |
} else { |
|
dvander@157
|
1671 |
IA32_Add_Rm_Imm32(jit, AMX_REG_STK, num_params, MOD_REG); |
|
dvander@157
|
1672 |
} |
|
dvander@157
|
1673 |
} |
|
dvander@157
|
1674 |
|
|
dvander@157
|
1675 |
inline void WriteOp_Tracker_Push_C(JitWriter *jit) |
|
dvander@157
|
1676 |
{ |
|
dvander@157
|
1677 |
CompData *data = (CompData *)jit->data; |
|
dvander@157
|
1678 |
cell_t val = jit->read_cell(); |
|
dvander@157
|
1679 |
|
|
dvander@157
|
1680 |
/* Save registers that may be damaged by the call */ |
|
dvander@157
|
1681 |
//push eax |
|
dvander@157
|
1682 |
//push edx |
|
dvander@157
|
1683 |
IA32_Push_Reg(jit, AMX_REG_PRI); |
|
dvander@157
|
1684 |
IA32_Push_Reg(jit, AMX_REG_ALT); |
|
dvander@157
|
1685 |
|
|
dvander@157
|
1686 |
/* Get the context ptr, push it and call the check */ |
|
dvander@157
|
1687 |
//mov eax, [esi+context] |
|
dvander@157
|
1688 |
//push eax |
|
dvander@157
|
1689 |
//call JIT_VerifyOrAllocateTracker |
|
dvander@157
|
1690 |
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT); |
|
dvander@157
|
1691 |
IA32_Push_Reg(jit, REG_EAX); |
|
dvander@157
|
1692 |
jitoffs_t call = IA32_Call_Imm32(jit, 0); |
|
dvander@350
|
1693 |
IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyOrAllocateTracker); |
|
dvander@157
|
1694 |
|
|
dvander@157
|
1695 |
/* Check for errors */ |
|
dvander@237
|
1696 |
//cmp eax, 0 |
|
dvander@157
|
1697 |
//jnz :error |
|
faluco@238
|
1698 |
IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0); |
|
dvander@237
|
1699 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_return); |
|
dvander@237
|
1700 |
|
|
dvander@237
|
1701 |
/* Restore */ |
|
dvander@237
|
1702 |
//pop eax |
|
dvander@157
|
1703 |
IA32_Pop_Reg(jit, REG_EAX); |
|
dvander@157
|
1704 |
|
|
dvander@157
|
1705 |
/* Push the value into the stack and increment pCur */ |
|
dvander@157
|
1706 |
//mov edx, [eax+vm[]] |
|
dvander@157
|
1707 |
//mov ecx, [edx+pcur] |
|
dvander@157
|
1708 |
//add [edx+pcur], 4 |
|
dvander@157
|
1709 |
//mov [ecx], <val>*4 ; we want the count in bytes not in cells |
|
dvander@157
|
1710 |
IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER])); |
|
dvander@157
|
1711 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur)); |
|
dvander@157
|
1712 |
IA32_Add_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur)); |
|
dvander@157
|
1713 |
IA32_Mov_Rm_Imm32(jit, AMX_REG_TMP, val*4, MOD_MEM_REG); |
|
dvander@157
|
1714 |
|
|
dvander@157
|
1715 |
/* Restore PRI & ALT */ |
|
dvander@157
|
1716 |
//pop edx |
|
dvander@157
|
1717 |
//pop eax |
|
dvander@157
|
1718 |
IA32_Pop_Reg(jit, AMX_REG_ALT); |
|
dvander@157
|
1719 |
IA32_Pop_Reg(jit, AMX_REG_PRI); |
|
dvander@157
|
1720 |
} |
|
dvander@157
|
1721 |
|
|
dvander@157
|
1722 |
inline void WriteOp_Tracker_Pop_SetHeap(JitWriter *jit) |
|
dvander@157
|
1723 |
{ |
|
dvander@157
|
1724 |
CompData *data = (CompData *)jit->data; |
|
dvander@157
|
1725 |
|
|
dvander@157
|
1726 |
/* Save registers that may be damaged by the call */ |
|
dvander@157
|
1727 |
//push eax |
|
dvander@157
|
1728 |
//push edx |
|
dvander@157
|
1729 |
IA32_Push_Reg(jit, AMX_REG_PRI); |
|
dvander@157
|
1730 |
IA32_Push_Reg(jit, AMX_REG_ALT); |
|
dvander@157
|
1731 |
|
|
dvander@157
|
1732 |
/* Get the context ptr, push it and call the check */ |
|
dvander@157
|
1733 |
//mov eax, [esi+context] |
|
dvander@157
|
1734 |
//push eax |
|
dvander@157
|
1735 |
//call JIT_VerifyLowBoundTracker |
|
dvander@157
|
1736 |
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT); |
|
dvander@157
|
1737 |
IA32_Push_Reg(jit, REG_EAX); |
|
dvander@157
|
1738 |
jitoffs_t call = IA32_Call_Imm32(jit, 0); |
|
dvander@350
|
1739 |
IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyLowBoundTracker); |
|
dvander@157
|
1740 |
|
|
dvander@157
|
1741 |
/* Check for errors */ |
|
dvander@237
|
1742 |
//cmp eax, 0 |
|
dvander@157
|
1743 |
//jnz :error |
|
faluco@238
|
1744 |
IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0); |
|
dvander@237
|
1745 |
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_return); |
|
dvander@237
|
1746 |
|
|
dvander@237
|
1747 |
/* Restore */ |
|
dvander@237
|
1748 |
//pop eax |
|
dvander@157
|
1749 |
IA32_Pop_Reg(jit, REG_EAX); |
|
dvander@157
|
1750 |
|
|
dvander@157
|
1751 |
/* Pop the value from the stack and decrease the heap by it*/ |
|
dvander@157
|
1752 |
//mov edx, [eax+vm[]] |
|
dvander@157
|
1753 |
//sub [edx+pcur], 4 |
|
dvander@157
|
1754 |
//mov ecx, [edx+pcur] |
|
dvander@157
|
1755 |
//mov ecx, [ecx] |
|
dvander@157
|
1756 |
//sub [esi+hea], ecx |
|
dvander@157
|
1757 |
IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER])); |
|
dvander@157
|
1758 |
IA32_Sub_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur)); |
|
dvander@157
|
1759 |
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur)); |
|
dvander@157
|
1760 |
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_TMP, MOD_MEM_REG); |
|
dvander@157
|
1761 |
IA32_Sub_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_TMP, AMX_INFO_HEAP); |
|
dvander@157
|
1762 |
|
|
dvander@157
|
1763 |
Write_CheckHeap_Min(jit); |
|
dvander@157
|
1764 |
|
|
dvander@157
|
1765 |
/* Restore PRI & ALT */ |
|
dvander@157
|
1766 |
//pop edx |
|
dvander@157
|
1767 |
//pop eax |
|
dvander@157
|
1768 |
IA32_Pop_Reg(jit, AMX_REG_ALT); |
|
dvander@157
|
1769 |
IA32_Pop_Reg(jit, AMX_REG_PRI); |
|
dvander@157
|
1770 |
} |
|
dvander@157
|
1771 |
|
|
faluco@201
|
1772 |
inline void WriteOp_Stradjust_Pri(JitWriter *jit) |
|
faluco@201
|
1773 |
{ |
|
faluco@201
|
1774 |
//add eax, 4 |
|
faluco@201
|
1775 |
//sar eax, 2 |
|
faluco@201
|
1776 |
IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 4, MOD_REG); |
|
faluco@201
|
1777 |
IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 2, MOD_REG); |
|
faluco@201
|
1778 |
} |
|
faluco@201
|
1779 |
|
|
dvander@157
|
1780 |
/************************************************* |
|
dvander@157
|
1781 |
************************************************* |
|
dvander@157
|
1782 |
* JIT PROPER ************************************ |
|
dvander@157
|
1783 |
* The rest from now on is the JIT engine * |
|
dvander@157
|
1784 |
************************************************* |
|
dvander@157
|
1785 |
*************************************************/ |
|
dvander@157
|
1786 |
|
|
dvander@157
|
1787 |
cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params) |
|
dvander@157
|
1788 |
{ |
|
dvander@157
|
1789 |
sp_native_t *native = &ctx->natives[native_idx]; |
|
dvander@237
|
1790 |
|
|
dvander@237
|
1791 |
ctx->n_idx = native_idx; |
|
dvander@157
|
1792 |
|
|
dvander@157
|
1793 |
/* Technically both aren't needed, I guess */ |
|
dvander@164
|
1794 |
if (native->status == SP_NATIVE_UNBOUND) |
|
dvander@157
|
1795 |
{ |
|
dvander@237
|
1796 |
ctx->n_err = SP_ERROR_INVALID_NATIVE; |
|
dvander@157
|
1797 |
return 0; |
|
dvander@157
|
1798 |
} |
|
dvander@157
|
1799 |
|
|
faluco@225
|
1800 |
return native->pfn(ctx->context, params); |
|
dvander@157
|
1801 |
} |
|
dvander@157
|
1802 |
|
|
faluco@225
|
1803 |
static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params) |
|
dvander@164
|
1804 |
{ |
|
faluco@225
|
1805 |
sp_context_t *ctx = pCtx->GetContext(); |
|
dvander@237
|
1806 |
ctx->n_err = SP_ERROR_INVALID_NATIVE; |
|
dvander@164
|
1807 |
|
|
dvander@164
|
1808 |
return 0; |
|
dvander@164
|
1809 |
} |
|
dvander@164
|
1810 |
|
|
dvander@157
|
1811 |
cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params) |
|
dvander@157
|
1812 |
{ |
|
dvander@157
|
1813 |
cell_t save_sp = ctx->sp; |
|
dvander@157
|
1814 |
cell_t save_hp = ctx->hp; |
|
dvander@157
|
1815 |
|
|
dvander@237
|
1816 |
ctx->n_idx = native_idx; |
|
dvander@237
|
1817 |
|
|
dvander@157
|
1818 |
if (ctx->hp < ctx->heap_base) |
|
dvander@157
|
1819 |
{ |
|
dvander@237
|
1820 |
ctx->n_err = SP_ERROR_HEAPMIN; |
|
dvander@157
|
1821 |
return 0; |
|
dvander@157
|
1822 |
} |
|
dvander@157
|
1823 |
|
|
dvander@157
|
1824 |
if (ctx->hp + STACK_MARGIN > ctx->sp) |
|
dvander@157
|
1825 |
{ |
|
dvander@237
|
1826 |
ctx->n_err = SP_ERROR_STACKLOW; |
|
dvander@157
|
1827 |
return 0; |
|
dvander@157
|
1828 |
} |
|
dvander@157
|
1829 |
|
|
dvander@157
|
1830 |
if ((uint32_t)ctx->sp >= ctx->mem_size) |
|
dvander@157
|
1831 |
{ |
|
dvander@237
|
1832 |
ctx->n_err = SP_ERROR_STACKMIN; |
|
dvander@157
|
1833 |
return 0; |
|
dvander@157
|
1834 |
} |
|
dvander@157
|
1835 |
|
|
dvander@157
|
1836 |
cell_t result = NativeCallback(ctx, native_idx, params); |
|
dvander@157
|
1837 |
|
|
dvander@237
|
1838 |
if (ctx->n_err != SP_ERROR_NONE) |
|
dvander@157
|
1839 |
{ |
|
dvander@157
|
1840 |
return result; |
|
dvander@157
|
1841 |
} |
|
dvander@157
|
1842 |
|
|
dvander@157
|
1843 |
if (save_sp != ctx->sp) |
|
dvander@157
|
1844 |
{ |
|
dvander@237
|
1845 |
ctx->n_err = SP_ERROR_STACKLEAK; |
|
dvander@157
|
1846 |
return result; |
|
dvander@157
|
1847 |
} else if (save_hp != ctx->hp) { |
|
dvander@237
|
1848 |
ctx->n_err = SP_ERROR_HEAPLEAK; |
|
dvander@157
|
1849 |
return result; |
|
dvander@157
|
1850 |
} |
|
dvander@157
|
1851 |
|
|
dvander@157
|
1852 |
return result; |
|
dvander@157
|
1853 |
} |
|
dvander@157
|
1854 |
|
|
dvander@157
|
1855 |
jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative) |
|
dvander@157
|
1856 |
{ |
|
dvander@157
|
1857 |
if (jit->outptr) |
|
dvander@157
|
1858 |
{ |
|
dvander@157
|
1859 |
CompData *data = (CompData *)jit->data; |
|
dvander@157
|
1860 |
if (relative) |
|
dvander@157
|
1861 |
{ |
|
dvander@157
|
1862 |
/* The actual offset is EIP relative. We need to relocate it. |
|
dvander@157
|
1863 |
* Note that this assumes that we're pointing to the next op. |
|
dvander@157
|
1864 |
*/ |
|
dvander@157
|
1865 |
pcode_offs += jit->get_inputpos(); |
|
dvander@157
|
1866 |
} |
|
dvander@241
|
1867 |
/* Offset must always be 1)positive and 2)less than or equal to the codesize */ |
|
dvander@241
|
1868 |
assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->codesize); |
|
dvander@157
|
1869 |
/* Do the lookup in the native dictionary. */ |
|
dvander@157
|
1870 |
return *(jitoffs_t *)(data->rebase + pcode_offs); |
|
dvander@157
|
1871 |
} else { |
|
dvander@157
|
1872 |
return 0; |
|
dvander@157
|
1873 |
} |
|
dvander@157
|
1874 |
} |
|
dvander@157
|
1875 |
|
|
dvander@157
|
1876 |
void WriteErrorRoutines(CompData *data, JitWriter *jit) |
|
dvander@157
|
1877 |
{ |
|
dvander@157
|
1878 |
data->jit_error_divzero = jit->get_outputpos(); |
|
dvander@157
|
1879 |
Write_SetError(jit, SP_ERROR_DIVIDE_BY_ZERO); |
|
dvander@157
|
1880 |
|
|
dvander@157
|
1881 |
data->jit_error_stacklow = jit->get_outputpos(); |
|
dvander@157
|
1882 |
Write_SetError(jit, SP_ERROR_STACKLOW); |
|
dvander@157
|
1883 |
|
|
dvander@157
|
1884 |
data->jit_error_stackmin = jit->get_outputpos(); |
|
dvander@157
|
1885 |
Write_SetError(jit, SP_ERROR_STACKMIN); |
|
dvander@157
|
1886 |
|
|
dvander@157
|
1887 |
data->jit_error_bounds = jit->get_outputpos(); |
|
dvander@157
|
1888 |
Write_SetError(jit, SP_ERROR_ARRAY_BOUNDS); |
|
dvander@157
|
1889 |
|
|
dvander@157
|
1890 |
data->jit_error_memaccess = jit->get_outputpos(); |
|
dvander@157
|
1891 |
Write_SetError(jit, SP_ERROR_MEMACCESS); |
|
dvander@157
|
1892 |
|
|
dvander@157
|
1893 |
data->jit_error_heaplow = jit->get_outputpos(); |
|
dvander@157
|
1894 |
Write_SetError(jit, SP_ERROR_HEAPLOW); |
|
dvander@157
|
1895 |
|
|
dvander@157
|
1896 |
data->jit_error_heapmin = jit->get_outputpos(); |
|
dvander@157
|
1897 |
Write_SetError(jit, SP_ERROR_HEAPMIN); |
|
dvander@157
|
1898 |
|
|
dvander@157
|
1899 |
data->jit_error_array_too_big = jit->get_outputpos(); |
|
dvander@157
|
1900 |
Write_SetError(jit, SP_ERROR_ARRAY_TOO_BIG); |
|
dvander@157
|
1901 |
|
|
dvander@157
|
1902 |
data->jit_extern_error = jit->get_outputpos(); |
|
dvander@157
|
1903 |
Write_GetError(jit); |
|
dvander@157
|
1904 |
} |
|
dvander@157
|
1905 |
|
|
dvander@157
|
1906 |
sp_context_t *JITX86::CompileToContext(ICompilation *co, int *err) |
|
dvander@157
|
1907 |
{ |
|
dvander@157
|
1908 |
CompData *data = (CompData *)co; |
|
dvander@157
|
1909 |
sp_plugin_t *plugin = data->plugin; |
|
dvander@157
|
1910 |
|
|
dvander@157
|
1911 |
/* The first phase is to browse */ |
|
dvander@157
|
1912 |
uint8_t *code = plugin->pcode; |
|
dvander@157
|
1913 |
uint8_t *end_cip = plugin->pcode + plugin->pcode_size; |
|
dvander@157
|
1914 |
OPCODE op; |
|
dvander@157
|
1915 |
|
|
dvander@157
|
1916 |
/********************************************* |
|
dvander@157
|
1917 |
* FIRST PASS (medium load): writer.outbase is NULL, getting size only |
|
dvander@157
|
1918 |
* SECOND PASS (heavy load!!): writer.outbase is valid and output is written |
|
dvander@157
|
1919 |
*********************************************/ |
|
dvander@157
|
1920 |
|
|
dvander@157
|
1921 |
JitWriter writer; |
|
dvander@157
|
1922 |
JitWriter *jit = &writer; |
|
dvander@157
|
1923 |
cell_t *endptr = (cell_t *)(end_cip); |
|
dvander@175
|
1924 |
uint32_t codemem = 0; |
|
dvander@157
|
1925 |
|
|
dvander@157
|
1926 |
/* Initial code is written "blank," |
|
dvander@157
|
1927 |
* so we can check the exact memory usage. |
|
dvander@157
|
1928 |
*/ |
|
dvander@157
|
1929 |
data->codesize = plugin->pcode_size; |
|
dvander@157
|
1930 |
writer.data = data; |
|
dvander@157
|
1931 |
writer.inbase = (cell_t *)code; |
|
dvander@157
|
1932 |
writer.outptr = NULL; |
|
dvander@157
|
1933 |
writer.outbase = NULL; |
|
dvander@241
|
1934 |
/* Allocate relocation. One extra cell for final CIP. */ |
|
dvander@241
|
1935 |
data->rebase = (jitcode_t)engine->BaseAlloc(plugin->pcode_size + sizeof(cell_t)); |
|
dvander@157
|
1936 |
|
|
dvander@157
|
1937 |
/* We will jump back here for second pass */ |
|
dvander@157
|
1938 |
jit_rewind: |
|
dvander@157
|
1939 |
/* Initialize pass vars */ |
|
dvander@157
|
1940 |
writer.inptr = writer.inbase; |
|
dvander@157
|
1941 |
data->jit_verify_addr_eax = 0; |
|
dvander@157
|
1942 |
data->jit_verify_addr_edx = 0; |
|
dvander@157
|
1943 |
|
|
dvander@157
|
1944 |
/* Write the prologue of the JIT */ |
|
dvander@157
|
1945 |
data->jit_return = Write_Execute_Function(jit); |
|
dvander@157
|
1946 |
|
|
dvander@157
|
1947 |
/* Write the SYSREQ.N opcode if we need to */ |
|
dvander@157
|
1948 |
if (!(data->inline_level & JIT_INLINE_NATIVES)) |
|
dvander@157
|
1949 |
{ |
|
dvander@157
|
1950 |
data->jit_sysreq_n = jit->get_outputpos(); |
|
dvander@157
|
1951 |
WriteOp_Sysreq_N_Function(jit); |
|
dvander@157
|
1952 |
} |
|
dvander@157
|
1953 |
|
|
dvander@241
|
1954 |
/* Write the debug section if we need it */ |
|
dvander@241
|
1955 |
if (data->debug == true) |
|
dvander@241
|
1956 |
{ |
|
dvander@241
|
1957 |
data->jit_break = jit->get_outputpos(); |
|
dvander@241
|
1958 |
Write_BreakDebug(jit); |
|
dvander@241
|
1959 |
} |
|
dvander@241
|
1960 |
|
|
dvander@157
|
1961 |
/* Plugins compiled with -O0 will need this! */ |
|
dvander@157
|
1962 |
data->jit_sysreq_c = jit->get_outputpos(); |
|
dvander@157
|
1963 |
WriteOp_Sysreq_C_Function(jit); |
|
dvander@157
|
1964 |
|
|
dvander@157
|
1965 |
data->jit_genarray = jit->get_outputpos(); |
|
dvander@157
|
1966 |
WriteIntrinsic_GenArray(jit); |
|
dvander@157
|
1967 |
|
|
dvander@157
|
1968 |
/* Write error checking routines that are called to */ |
|
dvander@157
|
1969 |
if (!(data->inline_level & JIT_INLINE_ERRORCHECKS)) |
|
dvander@157
|
1970 |
{ |
|
dvander@157
|
1971 |
data->jit_verify_addr_eax = jit->get_outputpos(); |
|
dvander@157
|
1972 |
Write_Check_VerifyAddr(jit, REG_EAX); |
|
dvander@157
|
1973 |
|
|
dvander@157
|
1974 |
data->jit_verify_addr_edx = jit->get_outputpos(); |
|
dvander@157
|
1975 |
Write_Check_VerifyAddr(jit, REG_EDX); |
|
dvander@157
|
1976 |
} |
|
dvander@157
|
1977 |
|
|
dvander@157
|
1978 |
/* Actual code generation! */ |
|
dvander@157
|
1979 |
if (writer.outbase == NULL) |
|
dvander@157
|
1980 |
{ |
|
dvander@157
|
1981 |
/* First Pass - find codesize and resolve relocation */ |
|
dvander@157
|
1982 |
jitoffs_t pcode_offs; |
|
dvander@157
|
1983 |
jitoffs_t native_offs; |
|
dvander@157
|
1984 |
|
|
dvander@157
|
1985 |
for (; writer.inptr < endptr;) |
|
dvander@157
|
1986 |
{ |
|
dvander@157
|
1987 |
/* Store the native offset into the rebase memory. |
|
dvander@157
|
1988 |
* This large chunk of memory lets us do an instant lookup |
|
dvander@157
|
1989 |
* based on an original pcode offset. |
|
dvander@157
|
1990 |
*/ |
|
dvander@157
|
1991 |
pcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - code); |
|
dvander@157
|
1992 |
native_offs = jit->get_outputpos(); |
|
dvander@157
|
1993 |
*((jitoffs_t *)(data->rebase + pcode_offs)) = native_offs; |
|
dvander@157
|
1994 |
|
|
dvander@157
|
1995 |
/* Now read the opcode and continue. */ |
|
dvander@157
|
1996 |
op = (OPCODE)writer.read_cell(); |
|
dvander@157
|
1997 |
switch (op) |
|
dvander@157
|
1998 |
{ |
|
dvander@157
|
1999 |
#include "opcode_switch.inc" |
|
dvander@157
|
2000 |
} |
|
dvander@157
|
2001 |
/* Check for errors. This should only happen in the first pass. */ |
|
dvander@157
|
2002 |
if (data->error_set != SP_ERROR_NONE) |
|
dvander@157
|
2003 |
{ |
|
dvander@157
|
2004 |
*err = data->error_set; |
|
dvander@157
|
2005 |
AbortCompilation(co); |
|
dvander@157
|
2006 |
return NULL; |
|
dvander@157
|
2007 |
} |
|
dvander@157
|
2008 |
} |
|
dvander@157
|
2009 |
/* Write these last because error jumps should be unpredicted, and thus forward */ |
|
dvander@157
|
2010 |
WriteErrorRoutines(data, jit); |
|
dvander@157
|
2011 |
|
|
dvander@241
|
2012 |
/* Write the final CIP to the last position in the reloc array */ |
|
dvander@241
|
2013 |
pcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - code); |
|
dvander@241
|
2014 |
native_offs = jit->get_outputpos(); |
|
dvander@241
|
2015 |
*((jitoffs_t *)(data->rebase + pcode_offs)) = native_offs; |
|
dvander@241
|
2016 |
|
|
dvander@157
|
2017 |
/* the total codesize is now known! */ |
|
dvander@175
|
2018 |
codemem = writer.get_outputpos(); |
|
dvander@175
|
2019 |
writer.outbase = (jitcode_t)engine->ExecAlloc(codemem); |
|
dvander@157
|
2020 |
writer.outptr = writer.outbase; |
|
dvander@157
|
2021 |
/* go back for third pass */ |
|
dvander@157
|
2022 |
goto jit_rewind; |
|
dvander@157
|
2023 |
} else { |
|
dvander@157
|
2024 |
/******* |
|
dvander@157
|
2025 |
* THIRD PASS - write opcode info |
|
dvander@157
|
2026 |
*******/ |
|
dvander@157
|
2027 |
for (; writer.inptr < endptr;) |
|
dvander@157
|
2028 |
{ |
|
dvander@157
|
2029 |
op = (OPCODE)writer.read_cell(); |
|
dvander@157
|
2030 |
switch (op) |
|
dvander@157
|
2031 |
{ |
|
dvander@157
|
2032 |
#include "opcode_switch.inc" |
|
dvander@157
|
2033 |
} |
|
dvander@157
|
2034 |
} |
|
dvander@157
|
2035 |
/* Write these last because error jumps should be unpredicted, and thus forward */ |
|
dvander@157
|
2036 |
WriteErrorRoutines(data, jit); |
|
dvander@157
|
2037 |
} |
|
dvander@157
|
2038 |
|
|
dvander@157
|
2039 |
/************* |
|
dvander@157
|
2040 |
* FOURTH PASS - Context Setup |
|
dvander@157
|
2041 |
*************/ |
|
dvander@157
|
2042 |
|
|
dvander@157
|
2043 |
sp_context_t *ctx = new sp_context_t; |
|
dvander@157
|
2044 |
memset(ctx, 0, sizeof(sp_context_t)); |
|
dvander@157
|
2045 |
|
|
dvander@157
|
2046 |
/* setup basics */ |
|
dvander@157
|
2047 |
ctx->codebase = writer.outbase; |
|
dvander@157
|
2048 |
ctx->plugin = plugin; |
|
dvander@157
|
2049 |
ctx->vmbase = this; |
|
dvander@157
|
2050 |
ctx->flags = (data->debug ? SPFLAG_PLUGIN_DEBUG : 0); |
|
dvander@157
|
2051 |
|
|
dvander@157
|
2052 |
/* setup memory */ |
|
dvander@157
|
2053 |
ctx->memory = new uint8_t[plugin->memory]; |
|
dvander@157
|
2054 |
memcpy(ctx->memory, plugin->data, plugin->data_size); |
|
dvander@157
|
2055 |
ctx->mem_size = plugin->memory; |
|
dvander@157
|
2056 |
ctx->heap_base = plugin->data_size; |
|
dvander@157
|
2057 |
ctx->hp = ctx->heap_base; |
|
dvander@157
|
2058 |
ctx->sp = ctx->mem_size - sizeof(cell_t); |
|
dvander@157
|
2059 |
|
|
dvander@157
|
2060 |
const char *strbase = plugin->info.stringbase; |
|
dvander@157
|
2061 |
uint32_t max, iter; |
|
dvander@157
|
2062 |
|
|
dvander@157
|
2063 |
/* relocate public info */ |
|
dvander@157
|
2064 |
if ((max = plugin->info.publics_num)) |
|
dvander@157
|
2065 |
{ |
|
dvander@157
|
2066 |
ctx->publics = new sp_public_t[max]; |
|
dvander@157
|
2067 |
for (iter=0; iter<max; iter++) |
|
dvander@157
|
2068 |
{ |
|
dvander@157
|
2069 |
ctx->publics[iter].name = strbase + plugin->info.publics[iter].name; |
|
dvander@164
|
2070 |
ctx->publics[iter].code_offs = RelocLookup(jit, plugin->info.publics[iter].address, false); |
|
dvander@164
|
2071 |
/* Encode the ID as a straight code offset */ |
|
dvander@164
|
2072 |
ctx->publics[iter].funcid = (ctx->publics[iter].code_offs << 1); |
|
dvander@157
|
2073 |
} |
|
dvander@157
|
2074 |
} |
|
dvander@157
|
2075 |
|
|
dvander@157
|
2076 |
/* relocate pubvar info */ |
|
dvander@157
|
2077 |
if ((max = plugin->info.pubvars_num)) |
|
dvander@157
|
2078 |
{ |
|
dvander@157
|
2079 |
uint8_t *dat = ctx->memory; |
|
dvander@157
|
2080 |
ctx->pubvars = new sp_pubvar_t[max]; |
|
dvander@157
|
2081 |
for (iter=0; iter<max; iter++) |
|
dvander@157
|
2082 |
{ |
|
dvander@157
|
2083 |
ctx->pubvars[iter].name = strbase + plugin->info.pubvars[iter].name; |
|
dvander@157
|
2084 |
ctx->pubvars[iter].offs = (cell_t *)(dat + plugin->info.pubvars[iter].address); |
|
dvander@157
|
2085 |
} |
|
dvander@157
|
2086 |
} |
|
dvander@157
|
2087 |
|
|
dvander@157
|
2088 |
/* relocate native info */ |
|
dvander@157
|
2089 |
if ((max = plugin->info.natives_num)) |
|
dvander@157
|
2090 |
{ |
|
dvander@157
|
2091 |
ctx->natives = new sp_native_t[max]; |
|
dvander@157
|
2092 |
for (iter=0; iter<max; iter++) |
|
dvander@157
|
2093 |
{ |
|
dvander@157
|
2094 |
ctx->natives[iter].name = strbase + plugin->info.natives[iter].name; |
|
dvander@164
|
2095 |
ctx->natives[iter].pfn = &InvalidNative; |
|
dvander@164
|
2096 |
ctx->natives[iter].status = SP_NATIVE_UNBOUND; |
|
dvander@157
|
2097 |
} |
|
dvander@157
|
2098 |
} |
|
dvander@157
|
2099 |
|
|
dvander@157
|
2100 |
/** |
|
dvander@157
|
2101 |
* If we're debugging, make sure we copy the necessary info. |
|
dvander@157
|
2102 |
*/ |
|
dvander@157
|
2103 |
if (data->debug) |
|
dvander@157
|
2104 |
{ |
|
dvander@157
|
2105 |
strbase = plugin->debug.stringbase; |
|
dvander@157
|
2106 |
|
|
dvander@157
|
2107 |
/* relocate files */ |
|
dvander@157
|
2108 |
max = plugin->debug.files_num; |
|
dvander@157
|
2109 |
ctx->files = new sp_debug_file_t[max]; |
|
dvander@157
|
2110 |
for (iter=0; iter<max; iter++) |
|
dvander@157
|
2111 |
{ |
|
dvander@157
|
2112 |
ctx->files[iter].addr = RelocLookup(jit, plugin->debug.files[iter].addr, false); |
|
dvander@157
|
2113 |
ctx->files[iter].name = strbase + plugin->debug.files[iter].name; |
|
dvander@157
|
2114 |
} |
|
dvander@157
|
2115 |
|
|
dvander@157
|
2116 |
/* relocate lines */ |
|
dvander@157
|
2117 |
max = plugin->debug.lines_num; |
|
dvander@157
|
2118 |
ctx->lines = new sp_debug_line_t[max]; |
|
dvander@157
|
2119 |
for (iter=0; iter<max; iter++) |
|
dvander@157
|
2120 |
{ |
|
dvander@157
|
2121 |
ctx->lines[iter].addr = RelocLookup(jit, plugin->debug.lines[iter].addr, false); |
|
dvander@157
|
2122 |
ctx->lines[iter].line = plugin->debug.lines[iter].line; |
|
dvander@157
|
2123 |
} |
|
dvander@157
|
2124 |
|
|
dvander@157
|
2125 |
/* relocate arrays */ |
|
dvander@157
|
2126 |
sp_fdbg_symbol_t *sym; |
|
dvander@157
|
2127 |
sp_fdbg_arraydim_t *arr; |
|
dvander@157
|
2128 |
uint8_t *cursor = (uint8_t *)(plugin->debug.symbols); |
|
dvander@157
|
2129 |
|
|
dvander@157
|
2130 |
max = plugin->debug.syms_num; |
|
dvander@157
|
2131 |
ctx->symbols = new sp_debug_symbol_t[max]; |
|
dvander@157
|
2132 |
for (iter=0; iter<max; iter++) |
|
dvander@157
|
2133 |
{ |
|
dvander@157
|
2134 |
sym = (sp_fdbg_symbol_t *)cursor; |
|
dvander@157
|
2135 |
|
|
dvander@253
|
2136 |
/** |
|
dvander@253
|
2137 |
* @brief There is an "issue" where the compiler will give totally bogus code |
|
dvander@253
|
2138 |
* address because codegeneration is still being calculated. A simple fix for |
|
dvander@253
|
2139 |
* this is to coerce the codestart value to 0 when it's invalid. |
|
dvander@253
|
2140 |
*/ |
|
dvander@253
|
2141 |
if (sym->codestart > data->codesize) |
|
dvander@253
|
2142 |
{ |
|
dvander@253
|
2143 |
ctx->symbols[iter].codestart = 0; |
|
dvander@253
|
2144 |
} else { |
|
dvander@253
|
2145 |
ctx->symbols[iter].codestart = RelocLookup(jit, sym->codestart, false); |
|
dvander@253
|
2146 |
} |
|
dvander@253
|
2147 |
if (sym->codeend > data->codesize) |
|
dvander@253
|
2148 |
{ |
|
dvander@253
|
2149 |
ctx->symbols[iter].codeend = data->codesize; |
|
dvander@253
|
2150 |
} else { |
|
dvander@253
|
2151 |
ctx->symbols[iter].codeend = RelocLookup(jit, sym->codeend, false); |
|
dvander@253
|
2152 |
} |
|
dvander@157
|
2153 |
ctx->symbols[iter].name = strbase + sym->name; |
|
dvander@157
|
2154 |
ctx->symbols[iter].sym = sym; |
|
dvander@157
|
2155 |
|
|
dvander@157
|
2156 |
if (sym->dimcount > 0) |
|
dvander@157
|
2157 |
{ |
|
dvander@157
|
2158 |
cursor += sizeof(sp_fdbg_symbol_t); |
|
dvander@157
|
2159 |
arr = (sp_fdbg_arraydim_t *)cursor; |
|
dvander@157
|
2160 |
ctx->symbols[iter].dims = arr; |
|
dvander@157
|
2161 |
cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount; |
|
dvander@157
|
2162 |
continue; |
|
dvander@157
|
2163 |
} |
|
dvander@157
|
2164 |
|
|
dvander@157
|
2165 |
ctx->symbols[iter].dims = NULL; |
|
dvander@157
|
2166 |
cursor += sizeof(sp_fdbg_symbol_t); |
|
dvander@157
|
2167 |
} |
|
dvander@157
|
2168 |
} |
|
dvander@157
|
2169 |
|
|
dvander@157
|
2170 |
tracker_t *trk = new tracker_t; |
|
dvander@157
|
2171 |
ctx->vm[JITVARS_TRACKER] = trk; |
|
dvander@157
|
2172 |
trk->pBase = (ucell_t *)malloc(1024); |
|
dvander@157
|
2173 |
trk->pCur = trk->pBase; |
|
dvander@157
|
2174 |
trk->size = 1024 / sizeof(cell_t); |
|
dvander@157
|
2175 |
|
|
dvander@175
|
2176 |
functracker_t *fnc = new functracker_t; |
|
dvander@175
|
2177 |
ctx->vm[JITVARS_FUNCINFO] = fnc; |
|
dvander@344
|
2178 |
ctx->vm[JITVARS_REBASE] = data->rebase; |
|
dvander@175
|
2179 |
fnc->code_size = codemem; |
|
dvander@175
|
2180 |
fnc->num_functions = data->func_idx; |
|
dvander@175
|
2181 |
|
|
dvander@157
|
2182 |
/* clean up relocation+compilation memory */ |
|
dvander@344
|
2183 |
data->rebase = NULL; |
|
dvander@157
|
2184 |
AbortCompilation(co); |
|
dvander@157
|
2185 |
|
|
dvander@157
|
2186 |
*err = SP_ERROR_NONE; |
|
dvander@157
|
2187 |
|
|
dvander@157
|
2188 |
return ctx; |
|
dvander@157
|
2189 |
} |
|
dvander@157
|
2190 |
|
|
dvander@601
|
2191 |
SPVM_NATIVE_FUNC JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData) |
|
dvander@601
|
2192 |
{ |
|
dvander@601
|
2193 |
JitWriter jw; |
|
dvander@601
|
2194 |
JitWriter *jit = &jw; |
|
dvander@601
|
2195 |
|
|
dvander@601
|
2196 |
jw.outbase = NULL; |
|
dvander@601
|
2197 |
jw.outptr = NULL; |
|
dvander@601
|
2198 |
jw.data = NULL; |
|
dvander@601
|
2199 |
|
|
dvander@601
|
2200 |
/* First pass, calculate size */ |
|
dvander@601
|
2201 |
rewind: |
|
dvander@601
|
2202 |
//push pData ;push pData |
|
dvander@601
|
2203 |
//push [esp+12] ;push params |
|
dvander@601
|
2204 |
//push [esp+12] ;push ctx |
|
dvander@601
|
2205 |
//call [callback] ;invoke the meta-callback |
|
dvander@601
|
2206 |
//add esp, 12 ;restore the stack |
|
dvander@601
|
2207 |
//ret ;return |
|
dvander@601
|
2208 |
IA32_Push_Imm32(jit, (jit_int32_t)pData); |
|
dvander@601
|
2209 |
IA32_Push_Rm_Disp8_ESP(jit, 12); |
|
dvander@601
|
2210 |
IA32_Push_Rm_Disp8_ESP(jit, 12); |
|
dvander@601
|
2211 |
uint32_t call = IA32_Call_Imm32(jit, 0); |
|
dvander@601
|
2212 |
IA32_Write_Jump32_Abs(jit, call, (void *)callback); |
|
dvander@601
|
2213 |
IA32_Add_Rm_Imm8(jit, REG_ESP, 12, MOD_REG); |
|
dvander@601
|
2214 |
IA32_Return(jit); |
|
dvander@601
|
2215 |
|
|
dvander@601
|
2216 |
if (jw.outbase == NULL) |
|
dvander@601
|
2217 |
{ |
|
dvander@601
|
2218 |
/* Second pass: Actually write */ |
|
dvander@601
|
2219 |
jw.outbase = (jitcode_t)engine->ExecAlloc(jw.get_outputpos()); |
|
dvander@601
|
2220 |
if (!jw.outbase) |
|
dvander@601
|
2221 |
{ |
|
dvander@601
|
2222 |
return NULL; |
|
dvander@601
|
2223 |
} |
|
dvander@601
|
2224 |
jw.outptr = jw.outbase; |
|
dvander@601
|
2225 |
|
|
dvander@601
|
2226 |
goto rewind; |
|
dvander@601
|
2227 |
} |
|
dvander@601
|
2228 |
|
|
dvander@601
|
2229 |
return (SPVM_NATIVE_FUNC)jw.outbase; |
|
dvander@601
|
2230 |
} |
|
dvander@601
|
2231 |
|
|
dvander@605
|
2232 |
void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func) |
|
dvander@601
|
2233 |
{ |
|
dvander@602
|
2234 |
engine->ExecFree((void *)func); |
|
dvander@601
|
2235 |
} |
|
dvander@601
|
2236 |
|
|
dvander@157
|
2237 |
const char *JITX86::GetVMName() |
|
dvander@157
|
2238 |
{ |
|
dvander@157
|
2239 |
return "JIT (x86)"; |
|
dvander@157
|
2240 |
} |
|
dvander@157
|
2241 |
|
|
dvander@157
|
2242 |
int JITX86::ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result) |
|
dvander@157
|
2243 |
{ |
|
dvander@157
|
2244 |
typedef int (*CONTEXT_EXECUTE)(sp_context_t *, uint32_t, cell_t *); |
|
dvander@157
|
2245 |
CONTEXT_EXECUTE fn = (CONTEXT_EXECUTE)ctx->codebase; |
|
dvander@157
|
2246 |
return fn(ctx, code_idx, result); |
|
dvander@157
|
2247 |
} |
|
dvander@157
|
2248 |
|
|
dvander@157
|
2249 |
void JITX86::FreeContext(sp_context_t *ctx) |
|
dvander@157
|
2250 |
{ |
|
dvander@157
|
2251 |
engine->ExecFree(ctx->codebase); |
|
dvander@157
|
2252 |
delete [] ctx->memory; |
|
dvander@157
|
2253 |
delete [] ctx->files; |
|
dvander@157
|
2254 |
delete [] ctx->lines; |
|
dvander@157
|
2255 |
delete [] ctx->natives; |
|
dvander@157
|
2256 |
delete [] ctx->publics; |
|
dvander@157
|
2257 |
delete [] ctx->pubvars; |
|
dvander@157
|
2258 |
delete [] ctx->symbols; |
|
dvander@344
|
2259 |
engine->BaseFree(ctx->vm[JITVARS_REBASE]); |
|
dvander@157
|
2260 |
free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase); |
|
faluco@641
|
2261 |
delete (tracker_t *)ctx->vm[JITVARS_TRACKER]; |
|
faluco@641
|
2262 |
delete (functracker_t *)ctx->vm[JITVARS_FUNCINFO]; |
|
dvander@157
|
2263 |
delete ctx; |
|
dvander@157
|
2264 |
} |
|
dvander@157
|
2265 |
|
|
dvander@157
|
2266 |
ICompilation *JITX86::StartCompilation(sp_plugin_t *plugin) |
|
dvander@157
|
2267 |
{ |
|
dvander@157
|
2268 |
CompData *data = new CompData; |
|
dvander@157
|
2269 |
|
|
dvander@157
|
2270 |
data->plugin = plugin; |
|
dvander@157
|
2271 |
data->inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES; |
|
dvander@157
|
2272 |
data->error_set = SP_ERROR_NONE; |
|
dvander@157
|
2273 |
|
|
dvander@157
|
2274 |
return data; |
|
dvander@157
|
2275 |
} |
|
dvander@157
|
2276 |
|
|
dvander@157
|
2277 |
void JITX86::AbortCompilation(ICompilation *co) |
|
dvander@157
|
2278 |
{ |
|
dvander@157
|
2279 |
if (((CompData *)co)->rebase) |
|
dvander@157
|
2280 |
{ |
|
dvander@157
|
2281 |
engine->BaseFree(((CompData *)co)->rebase); |
|
dvander@157
|
2282 |
} |
|
dvander@157
|
2283 |
delete (CompData *)co; |
|
dvander@157
|
2284 |
} |
|
dvander@157
|
2285 |
|
|
dvander@157
|
2286 |
bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char *val) |
|
dvander@157
|
2287 |
{ |
|
dvander@157
|
2288 |
CompData *data = (CompData *)co; |
|
dvander@157
|
2289 |
|
|
dvander@157
|
2290 |
if (strcmp(key, "debug") == 0) |
|
dvander@157
|
2291 |
{ |
|
dvander@241
|
2292 |
if ((atoi(val) == 1) || !strcmp(val, "yes")) |
|
dvander@241
|
2293 |
{ |
|
dvander@241
|
2294 |
data->debug = true; |
|
dvander@241
|
2295 |
} else { |
|
dvander@241
|
2296 |
data->debug = false; |
|
dvander@241
|
2297 |
} |
|
dvander@157
|
2298 |
if (data->debug && !(data->plugin->flags & SP_FLAG_DEBUG)) |
|
dvander@157
|
2299 |
{ |
|
dvander@157
|
2300 |
data->debug = false; |
|
dvander@157
|
2301 |
return false; |
|
dvander@157
|
2302 |
} |
|
dvander@157
|
2303 |
return true; |
|
dvander@157
|
2304 |
} |
|
dvander@157
|
2305 |
|
|
dvander@157
|
2306 |
return false; |
|
dvander@157
|
2307 |
} |
|
dvander@175
|
2308 |
|
|
dvander@175
|
2309 |
unsigned int JITX86::GetAPIVersion() |
|
dvander@175
|
2310 |
{ |
|
dvander@175
|
2311 |
return SOURCEPAWN_VM_API_VERSION; |
|
dvander@175
|
2312 |
} |
|
dvander@175
|
2313 |
|
|
dvander@344
|
2314 |
bool JITX86::FunctionPLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result) |
|
dvander@175
|
2315 |
{ |
|
dvander@344
|
2316 |
uint8_t *rebase = (uint8_t *)ctx->vm[JITVARS_REBASE]; |
|
dvander@344
|
2317 |
|
|
dvander@344
|
2318 |
/* Is this within the pcode bounds? */ |
|
dvander@344
|
2319 |
if (code_addr >= ctx->plugin->pcode_size - sizeof(uint32_t)) |
|
dvander@344
|
2320 |
{ |
|
dvander@344
|
2321 |
return false; |
|
dvander@344
|
2322 |
} |
|
dvander@344
|
2323 |
|
|
dvander@344
|
2324 |
/* Relocate this */ |
|
dvander@344
|
2325 |
code_addr = *(jitoffs_t *)(rebase + code_addr); |
|
dvander@344
|
2326 |
|
|
dvander@344
|
2327 |
/* Check if this is in the relocation bounds */ |
|
dvander@175
|
2328 |
functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO]; |
|
dvander@175
|
2329 |
if (code_addr >= fnc->code_size) |
|
dvander@175
|
2330 |
{ |
|
dvander@175
|
2331 |
return false; |
|
dvander@175
|
2332 |
} |
|
dvander@175
|
2333 |
|
|
dvander@344
|
2334 |
/* Get the function info and sanity check */ |
|
dvander@344
|
2335 |
funcinfo_t *f = (funcinfo_t *)((char *)ctx->codebase + code_addr - sizeof(funcinfo_t)); |
|
dvander@344
|
2336 |
if (f->magic != JIT_FUNCMAGIC || f->index >= fnc->num_functions) |
|
dvander@344
|
2337 |
{ |
|
dvander@344
|
2338 |
return false; |
|
dvander@344
|
2339 |
} |
|
dvander@344
|
2340 |
|
|
dvander@344
|
2341 |
if (result) |
|
dvander@344
|
2342 |
{ |
|
dvander@344
|
2343 |
*result = f->index; |
|
dvander@344
|
2344 |
} |
|
dvander@344
|
2345 |
|
|
dvander@344
|
2346 |
return true; |
|
dvander@344
|
2347 |
} |
|
dvander@344
|
2348 |
|
|
dvander@344
|
2349 |
bool JITX86::FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result) |
|
dvander@344
|
2350 |
{ |
|
dvander@344
|
2351 |
/* Check if this is in the relocation bounds */ |
|
dvander@344
|
2352 |
functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO]; |
|
dvander@344
|
2353 |
if (code_addr >= fnc->code_size) |
|
dvander@344
|
2354 |
{ |
|
dvander@344
|
2355 |
return false; |
|
dvander@344
|
2356 |
} |
|
dvander@344
|
2357 |
|
|
dvander@344
|
2358 |
/* Get the function info and sanity check */ |
|
dvander@175
|
2359 |
funcinfo_t *f = (funcinfo_t *)((char *)ctx->codebase + code_addr - sizeof(funcinfo_t)); |
|
dvander@175
|
2360 |
if (f->magic != JIT_FUNCMAGIC || f->index >= fnc->num_functions) |
|
dvander@175
|
2361 |
{ |
|
dvander@175
|
2362 |
return false; |
|
dvander@175
|
2363 |
} |
|
dvander@175
|
2364 |
|
|
dvander@175
|
2365 |
if (result) |
|
dvander@175
|
2366 |
{ |
|
dvander@175
|
2367 |
*result = f->index; |
|
dvander@175
|
2368 |
} |
|
dvander@175
|
2369 |
|
|
dvander@175
|
2370 |
return true; |
|
dvander@175
|
2371 |
} |
|
dvander@175
|
2372 |
|
|
dvander@175
|
2373 |
unsigned int JITX86::FunctionCount(const sp_context_t *ctx) |
|
dvander@175
|
2374 |
{ |
|
dvander@175
|
2375 |
functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO]; |
|
dvander@175
|
2376 |
|
|
dvander@175
|
2377 |
return fnc->num_functions; |
|
dvander@175
|
2378 |
} |
|
dvander@253
|
2379 |
|
|
dvander@253
|
2380 |
const char *JITX86::GetVersionString() |
|
dvander@253
|
2381 |
{ |
|
dvander@566
|
2382 |
return SVN_FULL_VERSION; |
|
dvander@253
|
2383 |
} |
|
dvander@253
|
2384 |
|
|
dvander@253
|
2385 |
const char *JITX86::GetCPUOptimizations() |
|
dvander@253
|
2386 |
{ |
|
dvander@253
|
2387 |
return "Generic 80486"; |
|
dvander@253
|
2388 |
} |