| 46 |
*code_ptr++ = 10 + 3; |
*code_ptr++ = 10 + 3; |
| 47 |
} |
} |
| 48 |
|
|
| 49 |
SLJIT_ASSERT(reg_map[TMP_REG3] == 9); |
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_first); |
| 50 |
*code_ptr++ = REX_W | REX_B; |
*code_ptr++ = REX_W | REX_B; |
| 51 |
*code_ptr++ = 0xb8 + 1; |
*code_ptr++ = 0xb8 + 1; |
| 52 |
jump->addr = (sljit_uw)code_ptr; |
jump->addr = (sljit_uw)code_ptr; |
| 73 |
*(sljit_w*)code_ptr = delta; |
*(sljit_w*)code_ptr = delta; |
| 74 |
} |
} |
| 75 |
else { |
else { |
| 76 |
SLJIT_ASSERT(reg_map[TMP_REG3] == 9); |
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second); |
| 77 |
*code_ptr++ = REX_W | REX_B; |
*code_ptr++ = REX_W | REX_B; |
| 78 |
*code_ptr++ = 0xb8 + 1; |
*code_ptr++ = 0xb8 + 1; |
| 79 |
*(sljit_w*)code_ptr = addr; |
*(sljit_w*)code_ptr = addr; |
| 86 |
return code_ptr; |
return code_ptr; |
| 87 |
} |
} |
| 88 |
|
|
| 89 |
int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) |
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; |
int size, pushed_size; |
| 92 |
sljit_ub *buf; |
sljit_ub *buf; |
| 93 |
|
|
| 94 |
CHECK_ERROR(); |
CHECK_ERROR(); |
| 99 |
compiler->flags_saved = 0; |
compiler->flags_saved = 0; |
| 100 |
|
|
| 101 |
size = generals; |
size = generals; |
| 102 |
|
/* Including the return address saved by the call instruction. */ |
| 103 |
|
pushed_size = (generals + 1) * sizeof(sljit_w); |
| 104 |
#ifndef _WIN64 |
#ifndef _WIN64 |
| 105 |
if (generals >= 2) |
if (generals >= 2) |
| 106 |
size += generals - 1; |
size += generals - 1; |
| 107 |
#else |
#else |
| 108 |
if (local_size > 0) |
/* Saving the virtual stack pointer. */ |
| 109 |
|
compiler->has_locals = local_size > 0; |
| 110 |
|
if (local_size > 0) { |
| 111 |
size += 2; |
size += 2; |
| 112 |
|
pushed_size += sizeof(sljit_w); |
| 113 |
|
} |
| 114 |
if (generals >= 4) |
if (generals >= 4) |
| 115 |
size += generals - 3; |
size += generals - 3; |
| 116 |
if (temporaries >= 5) |
if (temporaries >= 5) { |
| 117 |
size += (5 - 4) * 2; |
size += (5 - 4) * 2; |
| 118 |
|
pushed_size += sizeof(sljit_w); |
| 119 |
|
} |
| 120 |
#endif |
#endif |
| 121 |
size += args * 3; |
size += args * 3; |
| 122 |
if (size > 0) { |
if (size > 0) { |
| 125 |
|
|
| 126 |
INC_SIZE(size); |
INC_SIZE(size); |
| 127 |
if (generals >= 5) { |
if (generals >= 5) { |
| 128 |
SLJIT_ASSERT(reg_map[SLJIT_GENERAL_EREG2] >= 8); |
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_EREG2] >= 8, general_ereg2_is_hireg); |
| 129 |
*buf++ = REX_B; |
*buf++ = REX_B; |
| 130 |
PUSH_REG(reg_lmap[SLJIT_GENERAL_EREG2]); |
PUSH_REG(reg_lmap[SLJIT_GENERAL_EREG2]); |
| 131 |
} |
} |
| 132 |
if (generals >= 4) { |
if (generals >= 4) { |
| 133 |
SLJIT_ASSERT(reg_map[SLJIT_GENERAL_EREG1] >= 8); |
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_EREG1] >= 8, general_ereg1_is_hireg); |
| 134 |
*buf++ = REX_B; |
*buf++ = REX_B; |
| 135 |
PUSH_REG(reg_lmap[SLJIT_GENERAL_EREG1]); |
PUSH_REG(reg_lmap[SLJIT_GENERAL_EREG1]); |
| 136 |
} |
} |
| 137 |
if (generals >= 3) { |
if (generals >= 3) { |
| 138 |
#ifndef _WIN64 |
#ifndef _WIN64 |
| 139 |
SLJIT_ASSERT(reg_map[SLJIT_GENERAL_REG3] >= 8); |
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG3] >= 8, general_reg3_is_hireg); |
| 140 |
*buf++ = REX_B; |
*buf++ = REX_B; |
| 141 |
#else |
#else |
| 142 |
SLJIT_ASSERT(reg_map[SLJIT_GENERAL_REG3] < 8); |
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG3] < 8, general_reg3_is_loreg); |
| 143 |
#endif |
#endif |
| 144 |
PUSH_REG(reg_lmap[SLJIT_GENERAL_REG3]); |
PUSH_REG(reg_lmap[SLJIT_GENERAL_REG3]); |
| 145 |
} |
} |
| 146 |
if (generals >= 2) { |
if (generals >= 2) { |
| 147 |
#ifndef _WIN64 |
#ifndef _WIN64 |
| 148 |
SLJIT_ASSERT(reg_map[SLJIT_GENERAL_REG2] >= 8); |
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG2] >= 8, general_reg2_is_hireg); |
| 149 |
*buf++ = REX_B; |
*buf++ = REX_B; |
| 150 |
#else |
#else |
| 151 |
SLJIT_ASSERT(reg_map[SLJIT_GENERAL_REG2] < 8); |
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG2] < 8, general_reg2_is_loreg); |
| 152 |
#endif |
#endif |
| 153 |
PUSH_REG(reg_lmap[SLJIT_GENERAL_REG2]); |
PUSH_REG(reg_lmap[SLJIT_GENERAL_REG2]); |
| 154 |
} |
} |
| 155 |
if (generals >= 1) { |
if (generals >= 1) { |
| 156 |
SLJIT_ASSERT(reg_map[SLJIT_GENERAL_REG1] < 8); |
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_GENERAL_REG1] < 8, general_reg1_is_loreg); |
| 157 |
PUSH_REG(reg_lmap[SLJIT_GENERAL_REG1]); |
PUSH_REG(reg_lmap[SLJIT_GENERAL_REG1]); |
| 158 |
} |
} |
| 159 |
#ifdef _WIN64 |
#ifdef _WIN64 |
| 160 |
if (temporaries >= 5) { |
if (temporaries >= 5) { |
| 161 |
SLJIT_ASSERT(reg_map[SLJIT_TEMPORARY_EREG2] >= 8); |
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_EREG2] >= 8, temporary_ereg2_is_hireg); |
| 162 |
*buf++ = REX_B; |
*buf++ = REX_B; |
| 163 |
PUSH_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]); |
PUSH_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]); |
| 164 |
} |
} |
| 165 |
if (local_size > 0) { |
if (local_size > 0) { |
| 166 |
SLJIT_ASSERT(reg_map[SLJIT_LOCALS_REG] >= 8); |
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_LOCALS_REG] >= 8, locals_reg_is_hireg); |
| 167 |
*buf++ = REX_B; |
*buf++ = REX_B; |
| 168 |
PUSH_REG(reg_lmap[SLJIT_LOCALS_REG]); |
PUSH_REG(reg_lmap[SLJIT_LOCALS_REG]); |
| 169 |
} |
} |
| 204 |
#endif |
#endif |
| 205 |
} |
} |
| 206 |
|
|
| 207 |
local_size = (local_size + 16 - 1) & ~(16 - 1); |
local_size = ((local_size + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size; |
| 208 |
#ifdef _WIN64 |
#ifdef _WIN64 |
| 209 |
local_size += 4 * sizeof(sljit_w); |
local_size += 4 * sizeof(sljit_w); |
| 210 |
compiler->local_size = local_size; |
compiler->local_size = local_size; |
| 216 |
*buf++ = REX_W; |
*buf++ = REX_W; |
| 217 |
*buf++ = 0x83; |
*buf++ = 0x83; |
| 218 |
*buf++ = 0xc0 | (5 << 3) | 4; |
*buf++ = 0xc0 | (5 << 3) | 4; |
| 219 |
*buf++ = 4 * sizeof(sljit_w); |
/* Pushed size must be divisible by 8. */ |
| 220 |
local_size -= 4 * sizeof(sljit_w); |
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)); |
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))); |
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_touch_stack))); |
| 230 |
} |
} |
| 232 |
compiler->local_size = local_size; |
compiler->local_size = local_size; |
| 233 |
if (local_size > 0) { |
if (local_size > 0) { |
| 234 |
#endif |
#endif |
| 235 |
|
/* In case of Win64, local_size is always > 4 * sizeof(sljit_w) */ |
| 236 |
if (local_size <= 127) { |
if (local_size <= 127) { |
| 237 |
buf = (sljit_ub*)ensure_buf(compiler, 1 + 4); |
buf = (sljit_ub*)ensure_buf(compiler, 1 + 4); |
| 238 |
FAIL_IF(!buf); |
FAIL_IF(!buf); |
| 257 |
#endif |
#endif |
| 258 |
|
|
| 259 |
#ifdef _WIN64 |
#ifdef _WIN64 |
| 260 |
if (local_size > 4 * sizeof(sljit_w)) { |
if (compiler->has_locals) { |
| 261 |
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5); |
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5); |
| 262 |
FAIL_IF(!buf); |
FAIL_IF(!buf); |
| 263 |
INC_SIZE(5); |
INC_SIZE(5); |
| 273 |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
| 274 |
} |
} |
| 275 |
|
|
| 276 |
void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) |
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(); |
CHECK_ERROR_VOID(); |
| 281 |
check_sljit_fake_enter(compiler, args, temporaries, generals, local_size); |
check_sljit_fake_enter(compiler, args, temporaries, generals, local_size); |
| 282 |
|
|
| 283 |
compiler->temporaries = temporaries; |
compiler->temporaries = temporaries; |
| 284 |
compiler->generals = generals; |
compiler->generals = generals; |
| 285 |
compiler->local_size = (local_size + 16 - 1) & ~(16 - 1); |
/* 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 |
#ifdef _WIN64 |
| 296 |
compiler->local_size += 4 * sizeof(sljit_w); |
compiler->local_size += 4 * sizeof(sljit_w); |
| 297 |
#endif |
#endif |
| 298 |
} |
} |
| 299 |
|
|
| 300 |
int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw) |
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw) |
| 301 |
{ |
{ |
| 302 |
int size; |
int size; |
| 303 |
sljit_ub *buf; |
sljit_ub *buf; |
| 338 |
if (compiler->generals >= 2) |
if (compiler->generals >= 2) |
| 339 |
size += compiler->generals - 1; |
size += compiler->generals - 1; |
| 340 |
#else |
#else |
| 341 |
if (compiler->local_size > 4 * sizeof(sljit_w)) |
if (compiler->has_locals) |
| 342 |
size += 2; |
size += 2; |
| 343 |
if (compiler->generals >= 4) |
if (compiler->generals >= 4) |
| 344 |
size += compiler->generals - 3; |
size += compiler->generals - 3; |
| 351 |
INC_SIZE(size); |
INC_SIZE(size); |
| 352 |
|
|
| 353 |
#ifdef _WIN64 |
#ifdef _WIN64 |
| 354 |
if (compiler->local_size > 4 * sizeof(sljit_w)) { |
if (compiler->has_locals) { |
| 355 |
*buf++ = REX_B; |
*buf++ = REX_B; |
| 356 |
POP_REG(reg_lmap[SLJIT_LOCALS_REG]); |
POP_REG(reg_lmap[SLJIT_LOCALS_REG]); |
| 357 |
} |
} |
| 645 |
sljit_ub *buf; |
sljit_ub *buf; |
| 646 |
|
|
| 647 |
#ifndef _WIN64 |
#ifndef _WIN64 |
| 648 |
SLJIT_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 6 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8); |
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)); |
buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6)); |
| 651 |
FAIL_IF(!buf); |
FAIL_IF(!buf); |
| 659 |
*buf++ = 0x8b; |
*buf++ = 0x8b; |
| 660 |
*buf++ = 0xc0 | (0x7 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1]; |
*buf++ = 0xc0 | (0x7 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1]; |
| 661 |
#else |
#else |
| 662 |
SLJIT_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 2 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8); |
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)); |
buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6)); |
| 665 |
FAIL_IF(!buf); |
FAIL_IF(!buf); |
| 676 |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
| 677 |
} |
} |
| 678 |
|
|
| 679 |
int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int generals, int local_size) |
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; |
sljit_ub *buf; |
| 682 |
|
|
| 723 |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
| 724 |
} |
} |
| 725 |
|
|
| 726 |
int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw) |
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw) |
| 727 |
{ |
{ |
| 728 |
sljit_ub *buf; |
sljit_ub *buf; |
| 729 |
|
|