/[pcre]/code/branches/pcre16/sljit/sljitNativeX86_64.c
ViewVC logotype

Contents of /code/branches/pcre16/sljit/sljitNativeX86_64.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 755 - (show annotations) (download)
Mon Nov 21 10:41:54 2011 UTC (2 years, 9 months ago) by ph10
File MIME type: text/plain
File size: 23060 byte(s)
Created a new branch for the development of 16-bit support.

1 /*
2 * Stack-less Just-In-Time compiler
3 *
4 * Copyright 2009-2010 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 generals, 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, generals, local_size);
96
97 compiler->temporaries = temporaries;
98 compiler->generals = generals;
99 compiler->flags_saved = 0;
100
101 size = generals;
102 /* Including the return address saved by the call instruction. */
103 pushed_size = (generals + 1) * sizeof(sljit_w);
104 #ifndef _WIN64
105 if (generals >= 2)
106 size += generals - 1;
107 #else
108 /* Saving the virtual stack pointer. */
109 compiler->has_locals = local_size > 0;
110 if (local_size > 0) {
111 size += 2;
112 pushed_size += sizeof(sljit_w);
113 }
114 if (generals >= 4)
115 size += generals - 3;
116 if (temporaries >= 5) {
117 size += (5 - 4) * 2;
118 pushed_size += sizeof(sljit_w);
119 }
120 #endif
121 size += args * 3;
122 if (size > 0) {
123 buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
124 FAIL_IF(!buf);
125
126 INC_SIZE(size);
127 if (generals >= 5) {
128 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_EREG2] >= 8, general_ereg2_is_hireg);
129 *buf++ = REX_B;
130 PUSH_REG(reg_lmap[SLJIT_GENERAL_EREG2]);
131 }
132 if (generals >= 4) {
133 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_EREG1] >= 8, general_ereg1_is_hireg);
134 *buf++ = REX_B;
135 PUSH_REG(reg_lmap[SLJIT_GENERAL_EREG1]);
136 }
137 if (generals >= 3) {
138 #ifndef _WIN64
139 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG3] >= 8, general_reg3_is_hireg);
140 *buf++ = REX_B;
141 #else
142 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG3] < 8, general_reg3_is_loreg);
143 #endif
144 PUSH_REG(reg_lmap[SLJIT_GENERAL_REG3]);
145 }
146 if (generals >= 2) {
147 #ifndef _WIN64
148 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG2] >= 8, general_reg2_is_hireg);
149 *buf++ = REX_B;
150 #else
151 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG2] < 8, general_reg2_is_loreg);
152 #endif
153 PUSH_REG(reg_lmap[SLJIT_GENERAL_REG2]);
154 }
155 if (generals >= 1) {
156 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG1] < 8, general_reg1_is_loreg);
157 PUSH_REG(reg_lmap[SLJIT_GENERAL_REG1]);
158 }
159 #ifdef _WIN64
160 if (temporaries >= 5) {
161 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_EREG2] >= 8, temporary_ereg2_is_hireg);
162 *buf++ = REX_B;
163 PUSH_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
164 }
165 if (local_size > 0) {
166 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_LOCALS_REG] >= 8, locals_reg_is_hireg);
167 *buf++ = REX_B;
168 PUSH_REG(reg_lmap[SLJIT_LOCALS_REG]);
169 }
170 #endif
171
172 #ifndef _WIN64
173 if (args > 0) {
174 *buf++ = REX_W;
175 *buf++ = 0x8b;
176 *buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG1] << 3) | 0x7;
177 }
178 if (args > 1) {
179 *buf++ = REX_W | REX_R;
180 *buf++ = 0x8b;
181 *buf++ = 0xc0 | (reg_lmap[SLJIT_GENERAL_REG2] << 3) | 0x6;
182 }
183 if (args > 2) {
184 *buf++ = REX_W | REX_R;
185 *buf++ = 0x8b;
186 *buf++ = 0xc0 | (reg_lmap[SLJIT_GENERAL_REG3] << 3) | 0x2;
187 }
188 #else
189 if (args > 0) {
190 *buf++ = REX_W;
191 *buf++ = 0x8b;
192 *buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG1] << 3) | 0x1;
193 }
194 if (args > 1) {
195 *buf++ = REX_W;
196 *buf++ = 0x8b;
197 *buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG2] << 3) | 0x2;
198 }
199 if (args > 2) {
200 *buf++ = REX_W | REX_B;
201 *buf++ = 0x8b;
202 *buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG3] << 3) | 0x0;
203 }
204 #endif
205 }
206
207 local_size = ((local_size + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
208 #ifdef _WIN64
209 local_size += 4 * sizeof(sljit_w);
210 compiler->local_size = local_size;
211 if (local_size > 1024) {
212 /* Allocate the stack for the function itself. */
213 buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
214 FAIL_IF(!buf);
215 INC_SIZE(4);
216 *buf++ = REX_W;
217 *buf++ = 0x83;
218 *buf++ = 0xc0 | (5 << 3) | 4;
219 /* Pushed size must be divisible by 8. */
220 SLJIT_ASSERT(!(pushed_size & 0x7));
221 if (pushed_size & 0x8) {
222 *buf++ = 5 * sizeof(sljit_w);
223 local_size -= 5 * sizeof(sljit_w);
224 } else {
225 *buf++ = 4 * sizeof(sljit_w);
226 local_size -= 4 * sizeof(sljit_w);
227 }
228 FAIL_IF(emit_load_imm64(compiler, SLJIT_TEMPORARY_REG1, local_size));
229 FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_touch_stack)));
230 }
231 #else
232 compiler->local_size = local_size;
233 if (local_size > 0) {
234 #endif
235 /* In case of Win64, local_size is always > 4 * sizeof(sljit_w) */
236 if (local_size <= 127) {
237 buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
238 FAIL_IF(!buf);
239 INC_SIZE(4);
240 *buf++ = REX_W;
241 *buf++ = 0x83;
242 *buf++ = 0xc0 | (5 << 3) | 4;
243 *buf++ = local_size;
244 }
245 else {
246 buf = (sljit_ub*)ensure_buf(compiler, 1 + 7);
247 FAIL_IF(!buf);
248 INC_SIZE(7);
249 *buf++ = REX_W;
250 *buf++ = 0x81;
251 *buf++ = 0xc0 | (5 << 3) | 4;
252 *(sljit_hw*)buf = local_size;
253 buf += sizeof(sljit_hw);
254 }
255 #ifndef _WIN64
256 }
257 #endif
258
259 #ifdef _WIN64
260 if (compiler->has_locals) {
261 buf = (sljit_ub*)ensure_buf(compiler, 1 + 5);
262 FAIL_IF(!buf);
263 INC_SIZE(5);
264 *buf++ = REX_W | REX_R;
265 *buf++ = 0x8d;
266 *buf++ = 0x40 | (reg_lmap[SLJIT_LOCALS_REG] << 3) | 0x4;
267 *buf++ = 0x24;
268 *buf = 4 * sizeof(sljit_w);
269 }
270 #endif
271
272 /* Mov arguments to general registers. */
273 return SLJIT_SUCCESS;
274 }
275
276 SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size)
277 {
278 int pushed_size;
279
280 CHECK_ERROR_VOID();
281 check_sljit_fake_enter(compiler, args, temporaries, generals, local_size);
282
283 compiler->temporaries = temporaries;
284 compiler->generals = generals;
285 /* Including the return address saved by the call instruction. */
286 pushed_size = (generals + 1) * sizeof(sljit_w);
287 #ifdef _WIN64
288 compiler->has_locals = local_size > 0;
289 if (local_size > 0)
290 pushed_size += sizeof(sljit_w);
291 if (temporaries >= 5)
292 pushed_size += sizeof(sljit_w);
293 #endif
294 compiler->local_size = ((local_size + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
295 #ifdef _WIN64
296 compiler->local_size += 4 * sizeof(sljit_w);
297 #endif
298 }
299
300 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
301 {
302 int size;
303 sljit_ub *buf;
304
305 CHECK_ERROR();
306 check_sljit_emit_return(compiler, src, srcw);
307
308 compiler->flags_saved = 0;
309
310 if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG) {
311 compiler->mode32 = 0;
312 FAIL_IF(emit_mov(compiler, SLJIT_RETURN_REG, 0, src, srcw));
313 }
314
315 if (compiler->local_size > 0) {
316 if (compiler->local_size <= 127) {
317 buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
318 FAIL_IF(!buf);
319 INC_SIZE(4);
320 *buf++ = REX_W;
321 *buf++ = 0x83;
322 *buf++ = 0xc0 | (0 << 3) | 4;
323 *buf = compiler->local_size;
324 }
325 else {
326 buf = (sljit_ub*)ensure_buf(compiler, 1 + 7);
327 FAIL_IF(!buf);
328 INC_SIZE(7);
329 *buf++ = REX_W;
330 *buf++ = 0x81;
331 *buf++ = 0xc0 | (0 << 3) | 4;
332 *(sljit_hw*)buf = compiler->local_size;
333 }
334 }
335
336 size = 1 + compiler->generals;
337 #ifndef _WIN64
338 if (compiler->generals >= 2)
339 size += compiler->generals - 1;
340 #else
341 if (compiler->has_locals)
342 size += 2;
343 if (compiler->generals >= 4)
344 size += compiler->generals - 3;
345 if (compiler->temporaries >= 5)
346 size += (5 - 4) * 2;
347 #endif
348 buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
349 FAIL_IF(!buf);
350
351 INC_SIZE(size);
352
353 #ifdef _WIN64
354 if (compiler->has_locals) {
355 *buf++ = REX_B;
356 POP_REG(reg_lmap[SLJIT_LOCALS_REG]);
357 }
358 if (compiler->temporaries >= 5) {
359 *buf++ = REX_B;
360 POP_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
361 }
362 #endif
363 if (compiler->generals >= 1)
364 POP_REG(reg_map[SLJIT_GENERAL_REG1]);
365 if (compiler->generals >= 2) {
366 #ifndef _WIN64
367 *buf++ = REX_B;
368 #endif
369 POP_REG(reg_lmap[SLJIT_GENERAL_REG2]);
370 }
371 if (compiler->generals >= 3) {
372 #ifndef _WIN64
373 *buf++ = REX_B;
374 #endif
375 POP_REG(reg_lmap[SLJIT_GENERAL_REG3]);
376 }
377 if (compiler->generals >= 4) {
378 *buf++ = REX_B;
379 POP_REG(reg_lmap[SLJIT_GENERAL_EREG1]);
380 }
381 if (compiler->generals >= 5) {
382 *buf++ = REX_B;
383 POP_REG(reg_lmap[SLJIT_GENERAL_EREG2]);
384 }
385
386 RET();
387 return SLJIT_SUCCESS;
388 }
389
390 /* --------------------------------------------------------------------- */
391 /* Operators */
392 /* --------------------------------------------------------------------- */
393
394 static int emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_w imm)
395 {
396 sljit_ub *buf;
397
398 if (rex != 0) {
399 buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_hw));
400 FAIL_IF(!buf);
401 INC_SIZE(2 + sizeof(sljit_hw));
402 *buf++ = rex;
403 *buf++ = opcode;
404 *(sljit_hw*)buf = imm;
405 }
406 else {
407 buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_hw));
408 FAIL_IF(!buf);
409 INC_SIZE(1 + sizeof(sljit_hw));
410 *buf++ = opcode;
411 *(sljit_hw*)buf = imm;
412 }
413 return SLJIT_SUCCESS;
414 }
415
416 static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
417 /* The register or immediate operand. */
418 int a, sljit_w imma,
419 /* The general operand (not immediate). */
420 int b, sljit_w immb)
421 {
422 sljit_ub *buf;
423 sljit_ub *buf_ptr;
424 sljit_ub rex = 0;
425 int flags = size & ~0xf;
426 int inst_size;
427
428 /* The immediate operand must be 32 bit. */
429 SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));
430 /* Both cannot be switched on. */
431 SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
432 /* Size flags not allowed for typed instructions. */
433 SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
434 /* Both size flags cannot be switched on. */
435 SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
436 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
437 /* SSE2 and immediate is not possible. */
438 SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
439 #endif
440
441 size &= 0xf;
442 inst_size = size;
443
444 if ((b & SLJIT_MEM) && !(b & 0xf0) && NOT_HALFWORD(immb)) {
445 if (emit_load_imm64(compiler, TMP_REG3, immb))
446 return NULL;
447 immb = 0;
448 if (b & 0xf)
449 b |= TMP_REG3 << 4;
450 else
451 b |= TMP_REG3;
452 }
453
454 if (!compiler->mode32 && !(flags & EX86_NO_REXW))
455 rex |= REX_W;
456 else if (flags & EX86_REX)
457 rex |= REX;
458
459 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
460 if (flags & EX86_PREF_F2)
461 inst_size++;
462 #endif
463 if (flags & EX86_PREF_66)
464 inst_size++;
465
466 /* Calculate size of b. */
467 inst_size += 1; /* mod r/m byte. */
468 if (b & SLJIT_MEM) {
469 if ((b & 0x0f) == SLJIT_UNUSED)
470 inst_size += 1 + sizeof(sljit_hw); /* SIB byte required to avoid RIP based addressing. */
471 else {
472 if (reg_map[b & 0x0f] >= 8)
473 rex |= REX_B;
474 if (immb != 0 && !(b & 0xf0)) {
475 /* Immediate operand. */
476 if (immb <= 127 && immb >= -128)
477 inst_size += sizeof(sljit_b);
478 else
479 inst_size += sizeof(sljit_hw);
480 }
481 }
482
483 #ifndef _WIN64
484 if ((b & 0xf) == SLJIT_LOCALS_REG && (b & 0xf0) == 0)
485 b |= SLJIT_LOCALS_REG << 4;
486 #endif
487
488 if ((b & 0xf0) != SLJIT_UNUSED) {
489 inst_size += 1; /* SIB byte. */
490 if (reg_map[(b >> 4) & 0x0f] >= 8)
491 rex |= REX_X;
492 }
493 }
494 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
495 else if (!(flags & EX86_SSE2) && reg_map[b] >= 8)
496 rex |= REX_B;
497 #else
498 else if (reg_map[b] >= 8)
499 rex |= REX_B;
500 #endif
501
502 if (a & SLJIT_IMM) {
503 if (flags & EX86_BIN_INS) {
504 if (imma <= 127 && imma >= -128) {
505 inst_size += 1;
506 flags |= EX86_BYTE_ARG;
507 } else
508 inst_size += 4;
509 }
510 else if (flags & EX86_SHIFT_INS) {
511 imma &= 0x3f;
512 if (imma != 1) {
513 inst_size ++;
514 flags |= EX86_BYTE_ARG;
515 }
516 } else if (flags & EX86_BYTE_ARG)
517 inst_size++;
518 else if (flags & EX86_HALF_ARG)
519 inst_size += sizeof(short);
520 else
521 inst_size += sizeof(sljit_hw);
522 }
523 else {
524 SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
525 /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */
526 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
527 if (!(flags & EX86_SSE2) && reg_map[a] >= 8)
528 rex |= REX_R;
529 #else
530 if (reg_map[a] >= 8)
531 rex |= REX_R;
532 #endif
533 }
534
535 if (rex)
536 inst_size++;
537
538 buf = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
539 PTR_FAIL_IF(!buf);
540
541 /* Encoding the byte. */
542 INC_SIZE(inst_size);
543 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
544 if (flags & EX86_PREF_F2)
545 *buf++ = 0xf2;
546 #endif
547 if (flags & EX86_PREF_66)
548 *buf++ = 0x66;
549 if (rex)
550 *buf++ = rex;
551 buf_ptr = buf + size;
552
553 /* Encode mod/rm byte. */
554 if (!(flags & EX86_SHIFT_INS)) {
555 if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
556 *buf = (flags & EX86_BYTE_ARG) ? 0x83 : 0x81;
557
558 if ((a & SLJIT_IMM) || (a == 0))
559 *buf_ptr = 0;
560 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
561 else if (!(flags & EX86_SSE2))
562 *buf_ptr = reg_lmap[a] << 3;
563 else
564 *buf_ptr = a << 3;
565 #else
566 else
567 *buf_ptr = reg_lmap[a] << 3;
568 #endif
569 }
570 else {
571 if (a & SLJIT_IMM) {
572 if (imma == 1)
573 *buf = 0xd1;
574 else
575 *buf = 0xc1;
576 } else
577 *buf = 0xd3;
578 *buf_ptr = 0;
579 }
580
581 if (!(b & SLJIT_MEM))
582 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
583 *buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_lmap[b] : b);
584 #else
585 *buf_ptr++ |= 0xc0 + reg_lmap[b];
586 #endif
587 else if ((b & 0x0f) != SLJIT_UNUSED) {
588 #ifdef _WIN64
589 SLJIT_ASSERT((b & 0xf0) != (SLJIT_LOCALS_REG << 4));
590 #endif
591 if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
592 if (immb != 0) {
593 if (immb <= 127 && immb >= -128)
594 *buf_ptr |= 0x40;
595 else
596 *buf_ptr |= 0x80;
597 }
598
599 if ((b & 0xf0) == SLJIT_UNUSED)
600 *buf_ptr++ |= reg_lmap[b & 0x0f];
601 else {
602 *buf_ptr++ |= 0x04;
603 *buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3);
604 }
605
606 if (immb != 0) {
607 if (immb <= 127 && immb >= -128)
608 *buf_ptr++ = immb; /* 8 bit displacement. */
609 else {
610 *(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */
611 buf_ptr += sizeof(sljit_hw);
612 }
613 }
614 }
615 else {
616 *buf_ptr++ |= 0x04;
617 *buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3) | (immb << 6);
618 }
619 }
620 else {
621 *buf_ptr++ |= 0x04;
622 *buf_ptr++ = 0x25;
623 *(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */
624 buf_ptr += sizeof(sljit_hw);
625 }
626
627 if (a & SLJIT_IMM) {
628 if (flags & EX86_BYTE_ARG)
629 *buf_ptr = imma;
630 else if (flags & EX86_HALF_ARG)
631 *(short*)buf_ptr = imma;
632 else if (!(flags & EX86_SHIFT_INS))
633 *(sljit_hw*)buf_ptr = imma;
634 }
635
636 return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1);
637 }
638
639 /* --------------------------------------------------------------------- */
640 /* Call / return instructions */
641 /* --------------------------------------------------------------------- */
642
643 static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type)
644 {
645 sljit_ub *buf;
646
647 #ifndef _WIN64
648 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 6 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers);
649
650 buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
651 FAIL_IF(!buf);
652 INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
653 if (type >= SLJIT_CALL3) {
654 *buf++ = REX_W;
655 *buf++ = 0x8b;
656 *buf++ = 0xc0 | (0x2 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3];
657 }
658 *buf++ = REX_W;
659 *buf++ = 0x8b;
660 *buf++ = 0xc0 | (0x7 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
661 #else
662 SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 2 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers);
663
664 buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
665 FAIL_IF(!buf);
666 INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
667 if (type >= SLJIT_CALL3) {
668 *buf++ = REX_W | REX_R;
669 *buf++ = 0x8b;
670 *buf++ = 0xc0 | (0x0 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3];
671 }
672 *buf++ = REX_W;
673 *buf++ = 0x8b;
674 *buf++ = 0xc0 | (0x1 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
675 #endif
676 return SLJIT_SUCCESS;
677 }
678
679 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int generals, int local_size)
680 {
681 sljit_ub *buf;
682
683 CHECK_ERROR();
684 check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, generals, local_size);
685
686 compiler->temporaries = temporaries;
687 compiler->generals = generals;
688 compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
689 #ifdef _WIN64
690 compiler->local_size += 4 * sizeof(sljit_w);
691 #endif
692
693 /* For UNUSED dst. Uncommon, but possible. */
694 if (dst == SLJIT_UNUSED)
695 dst = TMP_REGISTER;
696
697 if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
698 if (reg_map[dst] < 8) {
699 buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
700 FAIL_IF(!buf);
701
702 INC_SIZE(1);
703 POP_REG(reg_lmap[dst]);
704 }
705 else {
706 buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
707 FAIL_IF(!buf);
708
709 INC_SIZE(2);
710 *buf++ = REX_B;
711 POP_REG(reg_lmap[dst]);
712 }
713 }
714 else if (dst & SLJIT_MEM) {
715 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
716 /* REX_W is not necessary (src is not immediate). */
717 compiler->mode32 = 1;
718 #endif
719 buf = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
720 FAIL_IF(!buf);
721 *buf++ = 0x8f;
722 }
723 return SLJIT_SUCCESS;
724 }
725
726 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
727 {
728 sljit_ub *buf;
729
730 CHECK_ERROR();
731 check_sljit_emit_fast_return(compiler, src, srcw);
732
733 CHECK_EXTRA_REGS(src, srcw, (void)0);
734
735 if ((src & SLJIT_IMM) && NOT_HALFWORD(srcw)) {
736 FAIL_IF(emit_load_imm64(compiler, TMP_REGISTER, srcw));
737 src = TMP_REGISTER;
738 }
739
740 if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REGISTER) {
741 if (reg_map[src] < 8) {
742 buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
743 FAIL_IF(!buf);
744
745 INC_SIZE(1 + 1);
746 PUSH_REG(reg_lmap[src]);
747 }
748 else {
749 buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1);
750 FAIL_IF(!buf);
751
752 INC_SIZE(2 + 1);
753 *buf++ = REX_B;
754 PUSH_REG(reg_lmap[src]);
755 }
756 }
757 else if (src & SLJIT_MEM) {
758 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
759 /* REX_W is not necessary (src is not immediate). */
760 compiler->mode32 = 1;
761 #endif
762 buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
763 FAIL_IF(!buf);
764 *buf++ = 0xff;
765 *buf |= 6 << 3;
766
767 buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
768 FAIL_IF(!buf);
769 INC_SIZE(1);
770 }
771 else {
772 SLJIT_ASSERT(IS_HALFWORD(srcw));
773 /* SLJIT_IMM. */
774 buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
775 FAIL_IF(!buf);
776
777 INC_SIZE(5 + 1);
778 *buf++ = 0x68;
779 *(sljit_hw*)buf = srcw;
780 buf += sizeof(sljit_hw);
781 }
782
783 RET();
784 return SLJIT_SUCCESS;
785 }
786
787
788 /* --------------------------------------------------------------------- */
789 /* Extend input */
790 /* --------------------------------------------------------------------- */
791
792 static int emit_mov_int(struct sljit_compiler *compiler, int sign,
793 int dst, sljit_w dstw,
794 int src, sljit_w srcw)
795 {
796 sljit_ub* code;
797 int dst_r;
798
799 compiler->mode32 = 0;
800
801 if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
802 return SLJIT_SUCCESS; /* Empty instruction. */
803
804 if (src & SLJIT_IMM) {
805 if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
806 return emit_load_imm64(compiler, dst, srcw);
807 compiler->mode32 = 1;
808 code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(int)srcw, dst, dstw);
809 FAIL_IF(!code);
810 *code = 0xc7;
811 compiler->mode32 = 0;
812 return SLJIT_SUCCESS;
813 }
814
815 dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_GENERAL_REG3) ? dst : TMP_REGISTER;
816
817 if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_GENERAL_REG3))
818 dst_r = src;
819 else {
820 if (sign) {
821 code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
822 FAIL_IF(!code);
823 *code++ = 0x63;
824 }
825 else {
826 if (dst_r == src) {
827 compiler->mode32 = 1;
828 code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, 0);
829 FAIL_IF(!code);
830 *code++ = 0x8b;
831 compiler->mode32 = 0;
832 }
833 /* xor reg, reg. */
834 code = emit_x86_instruction(compiler, 1, dst_r, 0, dst_r, 0);
835 FAIL_IF(!code);
836 *code++ = 0x33;
837 if (dst_r != src) {
838 compiler->mode32 = 1;
839 code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
840 FAIL_IF(!code);
841 *code++ = 0x8b;
842 compiler->mode32 = 0;
843 }
844 else {
845 compiler->mode32 = 1;
846 code = emit_x86_instruction(compiler, 1, src, 0, TMP_REGISTER, 0);
847 FAIL_IF(!code);
848 *code++ = 0x8b;
849 compiler->mode32 = 0;
850 }
851 }
852 }
853
854 if (dst & SLJIT_MEM) {
855 compiler->mode32 = 1;
856 code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
857 FAIL_IF(!code);
858 *code = 0x89;
859 compiler->mode32 = 0;
860 }
861
862 return SLJIT_SUCCESS;
863 }

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12