Annotation of embedaddon/pcre/sljit/sljitNativeX86_64.c, revision 1.1.1.3
1.1 misho 1: /*
2: * Stack-less Just-In-Time compiler
3: *
1.1.1.2 misho 4: * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
1.1 misho 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:
1.1.1.2 misho 89: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
1.1 misho 90: {
91: int size, pushed_size;
92: sljit_ub *buf;
93:
94: CHECK_ERROR();
1.1.1.2 misho 95: check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
1.1 misho 96:
97: compiler->temporaries = temporaries;
1.1.1.2 misho 98: compiler->saveds = saveds;
1.1 misho 99: compiler->flags_saved = 0;
1.1.1.3 ! misho 100: #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
! 101: compiler->logical_local_size = local_size;
! 102: #endif
1.1 misho 103:
1.1.1.2 misho 104: size = saveds;
1.1 misho 105: /* Including the return address saved by the call instruction. */
1.1.1.2 misho 106: pushed_size = (saveds + 1) * sizeof(sljit_w);
1.1 misho 107: #ifndef _WIN64
1.1.1.2 misho 108: if (saveds >= 2)
109: size += saveds - 1;
1.1 misho 110: #else
1.1.1.2 misho 111: if (saveds >= 4)
112: size += saveds - 3;
1.1 misho 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);
1.1.1.2 misho 124: if (saveds >= 5) {
125: SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG2] >= 8, saved_ereg2_is_hireg);
1.1 misho 126: *buf++ = REX_B;
1.1.1.2 misho 127: PUSH_REG(reg_lmap[SLJIT_SAVED_EREG2]);
1.1 misho 128: }
1.1.1.2 misho 129: if (saveds >= 4) {
130: SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG1] >= 8, saved_ereg1_is_hireg);
1.1 misho 131: *buf++ = REX_B;
1.1.1.2 misho 132: PUSH_REG(reg_lmap[SLJIT_SAVED_EREG1]);
1.1 misho 133: }
1.1.1.2 misho 134: if (saveds >= 3) {
1.1 misho 135: #ifndef _WIN64
1.1.1.2 misho 136: SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] >= 8, saved_reg3_is_hireg);
1.1 misho 137: *buf++ = REX_B;
138: #else
1.1.1.2 misho 139: SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] < 8, saved_reg3_is_loreg);
1.1 misho 140: #endif
1.1.1.2 misho 141: PUSH_REG(reg_lmap[SLJIT_SAVED_REG3]);
1.1 misho 142: }
1.1.1.2 misho 143: if (saveds >= 2) {
1.1 misho 144: #ifndef _WIN64
1.1.1.2 misho 145: SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] >= 8, saved_reg2_is_hireg);
1.1 misho 146: *buf++ = REX_B;
147: #else
1.1.1.2 misho 148: SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] < 8, saved_reg2_is_loreg);
1.1 misho 149: #endif
1.1.1.2 misho 150: PUSH_REG(reg_lmap[SLJIT_SAVED_REG2]);
1.1 misho 151: }
1.1.1.2 misho 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]);
1.1 misho 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;
1.1.1.2 misho 168: *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x7;
1.1 misho 169: }
170: if (args > 1) {
171: *buf++ = REX_W | REX_R;
172: *buf++ = 0x8b;
1.1.1.2 misho 173: *buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG2] << 3) | 0x6;
1.1 misho 174: }
175: if (args > 2) {
176: *buf++ = REX_W | REX_R;
177: *buf++ = 0x8b;
1.1.1.2 misho 178: *buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG3] << 3) | 0x2;
1.1 misho 179: }
180: #else
181: if (args > 0) {
182: *buf++ = REX_W;
183: *buf++ = 0x8b;
1.1.1.2 misho 184: *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x1;
1.1 misho 185: }
186: if (args > 1) {
187: *buf++ = REX_W;
188: *buf++ = 0x8b;
1.1.1.2 misho 189: *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | 0x2;
1.1 misho 190: }
191: if (args > 2) {
192: *buf++ = REX_W | REX_B;
193: *buf++ = 0x8b;
1.1.1.2 misho 194: *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x0;
1.1 misho 195: }
196: #endif
197: }
198:
1.1.1.3 ! misho 199: local_size = ((local_size + FIXED_LOCALS_OFFSET + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
1.1 misho 200: compiler->local_size = local_size;
1.1.1.3 ! misho 201: #ifdef _WIN64
1.1 misho 202: if (local_size > 1024) {
1.1.1.3 ! misho 203: /* Allocate stack for the callback, which grows the stack. */
1.1 misho 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));
1.1.1.3 ! misho 220: FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
1.1 misho 221: }
222: #endif
1.1.1.3 ! misho 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;
1.1 misho 232: }
1.1.1.3 ! misho 233: else {
! 234: buf = (sljit_ub*)ensure_buf(compiler, 1 + 7);
1.1 misho 235: FAIL_IF(!buf);
1.1.1.3 ! misho 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);
1.1 misho 242: }
243:
244: return SLJIT_SUCCESS;
245: }
246:
1.1.1.2 misho 247: SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
1.1 misho 248: {
249: int pushed_size;
250:
251: CHECK_ERROR_VOID();
1.1.1.2 misho 252: check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
1.1 misho 253:
254: compiler->temporaries = temporaries;
1.1.1.2 misho 255: compiler->saveds = saveds;
1.1.1.3 ! misho 256: #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
! 257: compiler->logical_local_size = local_size;
! 258: #endif
! 259:
1.1 misho 260: /* Including the return address saved by the call instruction. */
1.1.1.2 misho 261: pushed_size = (saveds + 1) * sizeof(sljit_w);
1.1 misho 262: #ifdef _WIN64
263: if (temporaries >= 5)
264: pushed_size += sizeof(sljit_w);
265: #endif
1.1.1.3 ! misho 266: compiler->local_size = ((local_size + FIXED_LOCALS_OFFSET + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
1.1 misho 267: }
268:
1.1.1.2 misho 269: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
1.1 misho 270: {
271: int size;
272: sljit_ub *buf;
273:
274: CHECK_ERROR();
1.1.1.2 misho 275: check_sljit_emit_return(compiler, op, src, srcw);
1.1.1.3 ! misho 276: ADJUST_LOCAL_OFFSET(src, srcw);
1.1 misho 277:
278: compiler->flags_saved = 0;
1.1.1.2 misho 279: FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
1.1 misho 280:
1.1.1.3 ! misho 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;
1.1 misho 299: }
300:
1.1.1.2 misho 301: size = 1 + compiler->saveds;
1.1 misho 302: #ifndef _WIN64
1.1.1.2 misho 303: if (compiler->saveds >= 2)
304: size += compiler->saveds - 1;
1.1 misho 305: #else
1.1.1.2 misho 306: if (compiler->saveds >= 4)
307: size += compiler->saveds - 3;
1.1 misho 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
1.1.1.2 misho 322: if (compiler->saveds >= 1)
323: POP_REG(reg_map[SLJIT_SAVED_REG1]);
324: if (compiler->saveds >= 2) {
1.1 misho 325: #ifndef _WIN64
326: *buf++ = REX_B;
327: #endif
1.1.1.2 misho 328: POP_REG(reg_lmap[SLJIT_SAVED_REG2]);
1.1 misho 329: }
1.1.1.2 misho 330: if (compiler->saveds >= 3) {
1.1 misho 331: #ifndef _WIN64
332: *buf++ = REX_B;
333: #endif
1.1.1.2 misho 334: POP_REG(reg_lmap[SLJIT_SAVED_REG3]);
1.1 misho 335: }
1.1.1.2 misho 336: if (compiler->saveds >= 4) {
1.1 misho 337: *buf++ = REX_B;
1.1.1.2 misho 338: POP_REG(reg_lmap[SLJIT_SAVED_EREG1]);
1.1 misho 339: }
1.1.1.2 misho 340: if (compiler->saveds >= 5) {
1.1 misho 341: *buf++ = REX_B;
1.1.1.2 misho 342: POP_REG(reg_lmap[SLJIT_SAVED_EREG2]);
1.1 misho 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:
1.1.1.3 ! misho 442: if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0))
1.1 misho 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) {
1.1.1.2 misho 468: imma &= compiler->mode32 ? 0x1f : 0x3f;
1.1 misho 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:
1.1.1.3 ! misho 633: SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw)
1.1 misho 634: {
635: sljit_ub *buf;
636:
637: CHECK_ERROR();
1.1.1.3 ! misho 638: check_sljit_emit_fast_enter(compiler, dst, dstw);
! 639: ADJUST_LOCAL_OFFSET(dst, dstw);
1.1 misho 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);
1.1.1.3 ! misho 678: ADJUST_LOCAL_OFFSET(src, srcw);
1.1 misho 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) {
1.1.1.2 misho 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: }
1.1 misho 755: return emit_load_imm64(compiler, dst, srcw);
1.1.1.2 misho 756: }
1.1 misho 757: compiler->mode32 = 1;
1.1.1.2 misho 758: code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
1.1 misho 759: FAIL_IF(!code);
760: *code = 0xc7;
761: compiler->mode32 = 0;
762: return SLJIT_SUCCESS;
763: }
764:
1.1.1.2 misho 765: dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_SAVED_REG3) ? dst : TMP_REGISTER;
1.1 misho 766:
1.1.1.2 misho 767: if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_SAVED_REG3))
1.1 misho 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;
1.1.1.2 misho 774: } else {
775: compiler->mode32 = 1;
776: FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw));
777: compiler->mode32 = 0;
1.1 misho 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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>