/[pcre]/code/trunk/sljit/sljitNativeX86_64.c
ViewVC logotype

Contents of /code/trunk/sljit/sljitNativeX86_64.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 956 - (show annotations)
Wed Apr 4 05:35:52 2012 UTC (7 years, 6 months ago) by zherczeg
File MIME type: text/plain
File size: 21141 byte(s)
JIT compiler update: fix x86-64 alignemnt issue
1 /*
2 * Stack-less Just-In-Time compiler
3 *
4 * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without modification, are
7 * permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice, this list of
10 * conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 * of conditions and the following disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 /* x86 64-bit arch dependent functions. */
28
29 static int emit_load_imm64(struct sljit_compiler *compiler, int reg, sljit_w imm)
30 {
31 sljit_ub *buf;
32
33 buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_w));
34 FAIL_IF(!buf);
35 INC_SIZE(2 + sizeof(sljit_w));
36 *buf++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
37 *buf++ = 0xb8 + (reg_map[reg] & 0x7);
38 *(sljit_w*)buf = imm;
39 return SLJIT_SUCCESS;
40 }
41
42 static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type)
43 {
44 if (type < SLJIT_JUMP) {
45 *code_ptr++ = get_jump_code(type ^ 0x1) - 0x10;
46 *code_ptr++ = 10 + 3;
47 }
48
49 SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_first);
50 *code_ptr++ = REX_W | REX_B;
51 *code_ptr++ = 0xb8 + 1;
52 jump->addr = (sljit_uw)code_ptr;
53
54 if (jump->flags & JUMP_LABEL)
55 jump->flags |= PATCH_MD;
56 else
57 *(sljit_w*)code_ptr = jump->u.target;
58
59 code_ptr += sizeof(sljit_w);
60 *code_ptr++ = REX_B;
61 *code_ptr++ = 0xff;
62 *code_ptr++ = (type >= SLJIT_FAST_CALL) ? 0xd1 /* call */ : 0xe1 /* jmp */;
63
64 return code_ptr;
65 }
66
67 static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_w addr, int type)
68 {
69 sljit_w delta = addr - ((sljit_w)code_ptr + 1 + sizeof(sljit_hw));
70
71 if (delta <= SLJIT_W(0x7fffffff) && delta >= SLJIT_W(-0x80000000)) {
72 *code_ptr++ = (type == 2) ? 0xe8 /* call */ : 0xe9 /* jmp */;
73 *(sljit_w*)code_ptr = delta;
74 }
75 else {
76 SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second);
77 *code_ptr++ = REX_W | REX_B;
78 *code_ptr++ = 0xb8 + 1;
79 *(sljit_w*)code_ptr = addr;
80 code_ptr += sizeof(sljit_w);
81 *code_ptr++ = REX_B;
82 *code_ptr++ = 0xff;
83 *code_ptr++ = (type == 2) ? 0xd1 /* call */ : 0xe1 /* jmp */;
84 }
85
86 return code_ptr;
87 }
88
89 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
90 {
91 int size, pushed_size;
92 sljit_ub *buf;
93
94 CHECK_ERROR();
95 check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
96
97 compiler->temporaries = temporaries;
98 compiler->saveds = saveds;
99 compiler->flags_saved = 0;
100 #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
101 compiler->logical_local_size = local_size;
102 #endif
103
104 size = saveds;
105 /* Including the return address saved by the call instruction. */
106 pushed_size = (saveds + 1) * sizeof(sljit_w);
107 #ifndef _WIN64
108 if (saveds >= 2)
109 size += saveds - 1;
110 #else
111 if (saveds >= 4)
112 size += saveds - 3;
113 if (temporaries >= 5) {
114 size += (5 - 4) * 2;
115 pushed_size += sizeof(sljit_w);
116 }
117 #endif
118 size += args * 3;
119 if (size > 0) {
120 buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
121 FAIL_IF(!buf);
122
123 INC_SIZE(size);
124 if (saveds >= 5) {
125 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG2] >= 8, saved_ereg2_is_hireg);
126 *buf++ = REX_B;
127 PUSH_REG(reg_lmap[SLJIT_SAVED_EREG2]);
128 }
129 if (saveds >= 4) {
130 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG1] >= 8, saved_ereg1_is_hireg);
131 *buf++ = REX_B;
132 PUSH_REG(reg_lmap[SLJIT_SAVED_EREG1]);
133 }
134 if (saveds >= 3) {
135 #ifndef _WIN64
136 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] >= 8, saved_reg3_is_hireg);
137 *buf++ = REX_B;
138 #else
139 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] < 8, saved_reg3_is_loreg);
140 #endif
141 PUSH_REG(reg_lmap[SLJIT_SAVED_REG3]);
142 }
143 if (saveds >= 2) {
144 #ifndef _WIN64
145 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] >= 8, saved_reg2_is_hireg);
146 *buf++ = REX_B;
147 #else
148 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] < 8, saved_reg2_is_loreg);
149 #endif
150 PUSH_REG(reg_lmap[SLJIT_SAVED_REG2]);
151 }
152 if (saveds >= 1) {
153 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG1] < 8, saved_reg1_is_loreg);
154 PUSH_REG(reg_lmap[SLJIT_SAVED_REG1]);
155 }
156 #ifdef _WIN64
157 if (temporaries >= 5) {
158 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_EREG2] >= 8, temporary_ereg2_is_hireg);
159 *buf++ = REX_B;
160 PUSH_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
161 }
162 #endif
163
164 #ifndef _WIN64
165 if (args > 0) {
166 *buf++ = REX_W;
167 *buf++ = 0x8b;
168 *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x7;
169 }
170 if (args > 1) {
171 *buf++ = REX_W | REX_R;
172 *buf++ = 0x8b;
173 *buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG2] << 3) | 0x6;
174 }
175 if (args > 2) {
176 *buf++ = REX_W | REX_R;
177 *buf++ = 0x8b;
178 *buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG3] << 3) | 0x2;
179 }
180 #else
181 if (args > 0) {
182 *buf++ = REX_W;
183 *buf++ = 0x8b;
184 *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x1;
185 }
186 if (args > 1) {
187 *buf++ = REX_W;
188 *buf++ = 0x8b;
189 *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | 0x2;
190 }
191 if (args > 2) {
192 *buf++ = REX_W | REX_B;
193 *buf++ = 0x8b;
194 *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x0;
195 }
196 #endif
197 }
198
199 local_size = ((local_size + FIXED_LOCALS_OFFSET + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
200 compiler->local_size = local_size;
201 #ifdef _WIN64
202 if (local_size > 1024) {
203 /* Allocate stack for the callback, which grows the stack. */
204 buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
205 FAIL_IF(!buf);
206 INC_SIZE(4);
207 *buf++ = REX_W;
208 *buf++ = 0x83;
209 *buf++ = 0xc0 | (5 << 3) | 4;
210 /* Pushed size must be divisible by 8. */
211 SLJIT_ASSERT(!(pushed_size & 0x7));
212 if (pushed_size & 0x8) {
213 *buf++ = 5 * sizeof(sljit_w);
214 local_size -= 5 * sizeof(sljit_w);
215 } else {
216 *buf++ = 4 * sizeof(sljit_w);
217 local_size -= 4 * sizeof(sljit_w);
218 }
219 FAIL_IF(emit_load_imm64(compiler, SLJIT_TEMPORARY_REG1, local_size));
220 FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
221 }
222 #endif
223 SLJIT_ASSERT(local_size > 0);
224 if (local_size <= 127) {
225 buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
226 FAIL_IF(!buf);
227 INC_SIZE(4);
228 *buf++ = REX_W;
229 *buf++ = 0x83;
230 *buf++ = 0xc0 | (5 << 3) | 4;
231 *buf++ = local_size;
232 }
233 else {
234 buf = (sljit_ub*)ensure_buf(compiler, 1 + 7);
235 FAIL_IF(!buf);
236 INC_SIZE(7);
237 *buf++ = REX_W;
238 *buf++ = 0x81;
239 *buf++ = 0xc0 | (5 << 3) | 4;
240 *(sljit_hw*)buf = local_size;
241 buf += sizeof(sljit_hw);
242 }
243
244 return SLJIT_SUCCESS;
245 }
246
247 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
248 {
249 int pushed_size;
250
251 CHECK_ERROR_VOID();
252 check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
253
254 compiler->temporaries = temporaries;
255 compiler->saveds = saveds;
256 #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
257 compiler->logical_local_size = local_size;
258 #endif
259
260 /* Including the return address saved by the call instruction. */
261 pushed_size = (saveds + 1) * sizeof(sljit_w);
262 #ifdef _WIN64
263 if (temporaries >= 5)
264 pushed_size += sizeof(sljit_w);
265 #endif
266 compiler->local_size = ((local_size + FIXED_LOCALS_OFFSET + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
267 }
268
269 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
270 {
271 int size;
272 sljit_ub *buf;
273
274 CHECK_ERROR();
275 check_sljit_emit_return(compiler, op, src, srcw);
276 ADJUST_LOCAL_OFFSET(src, srcw);
277
278 compiler->flags_saved = 0;
279 FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
280
281 SLJIT_ASSERT(compiler->local_size > 0);
282 if (compiler->local_size <= 127) {
283 buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
284 FAIL_IF(!buf);
285 INC_SIZE(4);
286 *buf++ = REX_W;
287 *buf++ = 0x83;
288 *buf++ = 0xc0 | (0 << 3) | 4;
289 *buf = compiler->local_size;
290 }
291 else {
292 buf = (sljit_ub*)ensure_buf(compiler, 1 + 7);
293 FAIL_IF(!buf);
294 INC_SIZE(7);
295 *buf++ = REX_W;
296 *buf++ = 0x81;
297 *buf++ = 0xc0 | (0 << 3) | 4;
298 *(sljit_hw*)buf = compiler->local_size;
299 }
300
301 size = 1 + compiler->saveds;
302 #ifndef _WIN64
303 if (compiler->saveds >= 2)
304 size += compiler->saveds - 1;
305 #else
306 if (compiler->saveds >= 4)
307 size += compiler->saveds - 3;
308 if (compiler->temporaries >= 5)
309 size += (5 - 4) * 2;
310 #endif
311 buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
312 FAIL_IF(!buf);
313
314 INC_SIZE(size);
315
316 #ifdef _WIN64
317 if (compiler->temporaries >= 5) {
318 *buf++ = REX_B;
319 POP_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
320 }
321 #endif
322 if (compiler->saveds >= 1)
323 POP_REG(reg_map[SLJIT_SAVED_REG1]);
324 if (compiler->saveds >= 2) {
325 #ifndef _WIN64
326 *buf++ = REX_B;
327 #endif
328 POP_REG(reg_lmap[SLJIT_SAVED_REG2]);
329 }
330 if (compiler->saveds >= 3) {
331 #ifndef _WIN64
332 *buf++ = REX_B;
333 #endif
334 POP_REG(reg_lmap[SLJIT_SAVED_REG3]);
335 }
336 if (compiler->saveds >= 4) {
337 *buf++ = REX_B;
338 POP_REG(reg_lmap[SLJIT_SAVED_EREG1]);
339 }
340 if (compiler->saveds >= 5) {
341 *buf++ = REX_B;
342 POP_REG(reg_lmap[SLJIT_SAVED_EREG2]);
343 }
344
345 RET();
346 return SLJIT_SUCCESS;
347 }
348
349 /* --------------------------------------------------------------------- */
350 /* Operators */
351 /* --------------------------------------------------------------------- */
352
353 static int emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_w imm)
354 {
355 sljit_ub *buf;
356
357 if (rex != 0) {
358 buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_hw));
359 FAIL_IF(!buf);
360 INC_SIZE(2 + sizeof(sljit_hw));
361 *buf++ = rex;
362 *buf++ = opcode;
363 *(sljit_hw*)buf = imm;
364 }
365 else {
366 buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_hw));
367 FAIL_IF(!buf);
368 INC_SIZE(1 + sizeof(sljit_hw));
369 *buf++ = opcode;
370 *(sljit_hw*)buf = imm;
371 }
372 return SLJIT_SUCCESS;
373 }
374
375 static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
376 /* The register or immediate operand. */
377 int a, sljit_w imma,
378 /* The general operand (not immediate). */
379 int b, sljit_w immb)
380 {
381 sljit_ub *buf;
382 sljit_ub *buf_ptr;
383 sljit_ub rex = 0;
384 int flags = size & ~0xf;
385 int inst_size;
386
387 /* The immediate operand must be 32 bit. */
388 SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));
389 /* Both cannot be switched on. */
390 SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
391 /* Size flags not allowed for typed instructions. */
392 SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
393 /* Both size flags cannot be switched on. */
394 SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
395 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
396 /* SSE2 and immediate is not possible. */
397 SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
398 #endif
399
400 size &= 0xf;
401 inst_size = size;
402
403 if ((b & SLJIT_MEM) && !(b & 0xf0) && NOT_HALFWORD(immb)) {
404 if (emit_load_imm64(compiler, TMP_REG3, immb))
405 return NULL;
406 immb = 0;
407 if (b & 0xf)
408 b |= TMP_REG3 << 4;
409 else
410 b |= TMP_REG3;
411 }
412
413 if (!compiler->mode32 && !(flags & EX86_NO_REXW))
414 rex |= REX_W;
415 else if (flags & EX86_REX)
416 rex |= REX;
417
418 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
419 if (flags & EX86_PREF_F2)
420 inst_size++;
421 #endif
422 if (flags & EX86_PREF_66)
423 inst_size++;
424
425 /* Calculate size of b. */
426 inst_size += 1; /* mod r/m byte. */
427 if (b & SLJIT_MEM) {
428 if ((b & 0x0f) == SLJIT_UNUSED)
429 inst_size += 1 + sizeof(sljit_hw); /* SIB byte required to avoid RIP based addressing. */
430 else {
431 if (reg_map[b & 0x0f] >= 8)
432 rex |= REX_B;
433 if (immb != 0 && !(b & 0xf0)) {
434 /* Immediate operand. */
435 if (immb <= 127 && immb >= -128)
436 inst_size += sizeof(sljit_b);
437 else
438 inst_size += sizeof(sljit_hw);
439 }
440 }
441
442 if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0))
443 b |= SLJIT_LOCALS_REG << 4;
444
445 if ((b & 0xf0) != SLJIT_UNUSED) {
446 inst_size += 1; /* SIB byte. */
447 if (reg_map[(b >> 4) & 0x0f] >= 8)
448 rex |= REX_X;
449 }
450 }
451 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
452 else if (!(flags & EX86_SSE2) && reg_map[b] >= 8)
453 rex |= REX_B;
454 #else
455 else if (reg_map[b] >= 8)
456 rex |= REX_B;
457 #endif
458
459 if (a & SLJIT_IMM) {
460 if (flags & EX86_BIN_INS) {
461 if (imma <= 127 && imma >= -128) {
462 inst_size += 1;
463 flags |= EX86_BYTE_ARG;
464 } else
465 inst_size += 4;
466 }
467 else if (flags & EX86_SHIFT_INS) {
468 imma &= compiler->mode32 ? 0x1f : 0x3f;
469 if (imma != 1) {
470 inst_size ++;
471 flags |= EX86_BYTE_ARG;
472 }
473 } else if (flags & EX86_BYTE_ARG)
474 inst_size++;
475 else if (flags & EX86_HALF_ARG)
476 inst_size += sizeof(short);
477 else
478 inst_size += sizeof(sljit_hw);
479 }
480 else {
481 SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
482 /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */
483 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
484 if (!(flags & EX86_SSE2) && reg_map[a] >= 8)
485 rex |= REX_R;
486 #else
487 if (reg_map[a] >= 8)
488 rex |= REX_R;
489 #endif
490 }
491
492 if (rex)
493 inst_size++;
494
495 buf = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
496 PTR_FAIL_IF(!buf);
497
498 /* Encoding the byte. */
499 INC_SIZE(inst_size);
500 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
501 if (flags & EX86_PREF_F2)
502 *buf++ = 0xf2;
503 #endif
504 if (flags & EX86_PREF_66)
505 *buf++ = 0x66;
506 if (rex)
507 *buf++ = rex;
508 buf_ptr = buf + size;
509
510 /* Encode mod/rm byte. */
511 if (!(flags & EX86_SHIFT_INS)) {
512 if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
513 *buf = (flags & EX86_BYTE_ARG) ? 0x83 : 0x81;
514
515 if ((a & SLJIT_IMM) || (a == 0))
516 *buf_ptr = 0;
517 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
518 else if (!(flags & EX86_SSE2))
519 *buf_ptr = reg_lmap[a] << 3;
520 else
521 *buf_ptr = a << 3;
522 #else
523 else
524 *buf_ptr = reg_lmap[a] << 3;
525 #endif
526 }
527 else {
528 if (a & SLJIT_IMM) {
529 if (imma == 1)
530 *buf = 0xd1;
531 else
532 *buf = 0xc1;
533 } else
534 *buf = 0xd3;
535 *buf_ptr = 0;
536 }
537
538 if (!(b & SLJIT_MEM))
539 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
540 *buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_lmap[b] : b);
541 #else
542 *buf_ptr++ |= 0xc0 + reg_lmap[b];
543 #endif
544 else if ((b & 0x0f) != SLJIT_UNUSED) {
545 if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
546 if (immb != 0) {
547 if (immb <= 127 && immb >= -128)
548 *buf_ptr |= 0x40;
549 else
550 *buf_ptr |= 0x80;
551 }
552
553 if ((b & 0xf0) == SLJIT_UNUSED)
554 *buf_ptr++ |= reg_lmap[b & 0x0f];
555 else {
556 *buf_ptr++ |= 0x04;
557 *buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3);
558 }
559
560 if (immb != 0) {
561 if (immb <= 127 && immb >= -128)
562 *buf_ptr++ = immb; /* 8 bit displacement. */
563 else {
564 *(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */
565 buf_ptr += sizeof(sljit_hw);
566 }
567 }
568 }
569 else {
570 *buf_ptr++ |= 0x04;
571 *buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3) | (immb << 6);
572 }
573 }
574 else {
575 *buf_ptr++ |= 0x04;
576 *buf_ptr++ = 0x25;
577 *(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */
578 buf_ptr += sizeof(sljit_hw);
579 }
580
581 if (a & SLJIT_IMM) {
582 if (flags & EX86_BYTE_ARG)
583 *buf_ptr = imma;
584 else if (flags & EX86_HALF_ARG)
585 *(short*)buf_ptr = imma;
586 else if (!(flags & EX86_SHIFT_INS))
587 *(sljit_hw*)buf_ptr = imma;
588 }
589
590 return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1);
591 }
592
593 /* --------------------------------------------------------------------- */
594 /* Call / return instructions */
595 /* --------------------------------------------------------------------- */
596
597 static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type)
598 {
599 sljit_ub *buf;
600
601 #ifndef _WIN64
602 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 6 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers);
603
604 buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
605 FAIL_IF(!buf);
606 INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
607 if (type >= SLJIT_CALL3) {
608 *buf++ = REX_W;
609 *buf++ = 0x8b;
610 *buf++ = 0xc0 | (0x2 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3];
611 }
612 *buf++ = REX_W;
613 *buf++ = 0x8b;
614 *buf++ = 0xc0 | (0x7 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
615 #else
616 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 2 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers);
617
618 buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
619 FAIL_IF(!buf);
620 INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
621 if (type >= SLJIT_CALL3) {
622 *buf++ = REX_W | REX_R;
623 *buf++ = 0x8b;
624 *buf++ = 0xc0 | (0x0 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3];
625 }
626 *buf++ = REX_W;
627 *buf++ = 0x8b;
628 *buf++ = 0xc0 | (0x1 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
629 #endif
630 return SLJIT_SUCCESS;
631 }
632
633 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw)
634 {
635 sljit_ub *buf;
636
637 CHECK_ERROR();
638 check_sljit_emit_fast_enter(compiler, dst, dstw);
639 ADJUST_LOCAL_OFFSET(dst, dstw);
640
641 /* For UNUSED dst. Uncommon, but possible. */
642 if (dst == SLJIT_UNUSED)
643 dst = TMP_REGISTER;
644
645 if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
646 if (reg_map[dst] < 8) {
647 buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
648 FAIL_IF(!buf);
649
650 INC_SIZE(1);
651 POP_REG(reg_lmap[dst]);
652 }
653 else {
654 buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
655 FAIL_IF(!buf);
656
657 INC_SIZE(2);
658 *buf++ = REX_B;
659 POP_REG(reg_lmap[dst]);
660 }
661 }
662 else if (dst & SLJIT_MEM) {
663 /* REX_W is not necessary (src is not immediate). */
664 compiler->mode32 = 1;
665 buf = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
666 FAIL_IF(!buf);
667 *buf++ = 0x8f;
668 }
669 return SLJIT_SUCCESS;
670 }
671
672 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
673 {
674 sljit_ub *buf;
675
676 CHECK_ERROR();
677 check_sljit_emit_fast_return(compiler, src, srcw);
678 ADJUST_LOCAL_OFFSET(src, srcw);
679
680 if ((src & SLJIT_IMM) && NOT_HALFWORD(srcw)) {
681 FAIL_IF(emit_load_imm64(compiler, TMP_REGISTER, srcw));
682 src = TMP_REGISTER;
683 }
684
685 if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REGISTER) {
686 if (reg_map[src] < 8) {
687 buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
688 FAIL_IF(!buf);
689
690 INC_SIZE(1 + 1);
691 PUSH_REG(reg_lmap[src]);
692 }
693 else {
694 buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1);
695 FAIL_IF(!buf);
696
697 INC_SIZE(2 + 1);
698 *buf++ = REX_B;
699 PUSH_REG(reg_lmap[src]);
700 }
701 }
702 else if (src & SLJIT_MEM) {
703 /* REX_W is not necessary (src is not immediate). */
704 compiler->mode32 = 1;
705 buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
706 FAIL_IF(!buf);
707 *buf++ = 0xff;
708 *buf |= 6 << 3;
709
710 buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
711 FAIL_IF(!buf);
712 INC_SIZE(1);
713 }
714 else {
715 SLJIT_ASSERT(IS_HALFWORD(srcw));
716 /* SLJIT_IMM. */
717 buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
718 FAIL_IF(!buf);
719
720 INC_SIZE(5 + 1);
721 *buf++ = 0x68;
722 *(sljit_hw*)buf = srcw;
723 buf += sizeof(sljit_hw);
724 }
725
726 RET();
727 return SLJIT_SUCCESS;
728 }
729
730
731 /* --------------------------------------------------------------------- */
732 /* Extend input */
733 /* --------------------------------------------------------------------- */
734
735 static int emit_mov_int(struct sljit_compiler *compiler, int sign,
736 int dst, sljit_w dstw,
737 int src, sljit_w srcw)
738 {
739 sljit_ub* code;
740 int dst_r;
741
742 compiler->mode32 = 0;
743
744 if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
745 return SLJIT_SUCCESS; /* Empty instruction. */
746
747 if (src & SLJIT_IMM) {
748 if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
749 if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {
750 code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
751 FAIL_IF(!code);
752 *code = 0xc7;
753 return SLJIT_SUCCESS;
754 }
755 return emit_load_imm64(compiler, dst, srcw);
756 }
757 compiler->mode32 = 1;
758 code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
759 FAIL_IF(!code);
760 *code = 0xc7;
761 compiler->mode32 = 0;
762 return SLJIT_SUCCESS;
763 }
764
765 dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_SAVED_REG3) ? dst : TMP_REGISTER;
766
767 if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_SAVED_REG3))
768 dst_r = src;
769 else {
770 if (sign) {
771 code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
772 FAIL_IF(!code);
773 *code++ = 0x63;
774 } else {
775 compiler->mode32 = 1;
776 FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw));
777 compiler->mode32 = 0;
778 }
779 }
780
781 if (dst & SLJIT_MEM) {
782 compiler->mode32 = 1;
783 code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
784 FAIL_IF(!code);
785 *code = 0x89;
786 compiler->mode32 = 0;
787 }
788
789 return SLJIT_SUCCESS;
790 }

  ViewVC Help
Powered by ViewVC 1.1.5