| 1 |
/* |
/* |
| 2 |
* Stack-less Just-In-Time compiler |
* Stack-less Just-In-Time compiler |
| 3 |
* |
* |
| 4 |
* Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. |
* 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 |
* Redistribution and use in source and binary forms, with or without modification, are |
| 7 |
* permitted provided that the following conditions are met: |
* permitted provided that the following conditions are met: |
| 63 |
return code_ptr; |
return code_ptr; |
| 64 |
} |
} |
| 65 |
|
|
| 66 |
SLJIT_API_FUNC_ATTRIBUTE 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 saveds, int local_size) |
| 67 |
{ |
{ |
| 68 |
int size; |
int size; |
| 69 |
sljit_ub *buf; |
sljit_ub *buf; |
| 70 |
|
|
| 71 |
CHECK_ERROR(); |
CHECK_ERROR(); |
| 72 |
check_sljit_emit_enter(compiler, args, temporaries, generals, local_size); |
check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size); |
| 73 |
|
|
| 74 |
compiler->temporaries = temporaries; |
compiler->temporaries = temporaries; |
| 75 |
compiler->generals = generals; |
compiler->saveds = saveds; |
| 76 |
compiler->args = args; |
compiler->args = args; |
| 77 |
compiler->flags_saved = 0; |
compiler->flags_saved = 0; |
| 78 |
|
|
| 79 |
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) |
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) |
| 80 |
size = 1 + (generals <= 3 ? generals : 3) + (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0); |
size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0); |
| 81 |
#else |
#else |
| 82 |
size = 1 + (generals <= 3 ? generals : 3) + (args > 0 ? (2 + args * 3) : 0); |
size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (2 + args * 3) : 0); |
| 83 |
#endif |
#endif |
| 84 |
buf = (sljit_ub*)ensure_buf(compiler, 1 + size); |
buf = (sljit_ub*)ensure_buf(compiler, 1 + size); |
| 85 |
FAIL_IF(!buf); |
FAIL_IF(!buf); |
| 92 |
*buf++ = 0xc4 | (reg_map[TMP_REGISTER] << 3); |
*buf++ = 0xc4 | (reg_map[TMP_REGISTER] << 3); |
| 93 |
} |
} |
| 94 |
#endif |
#endif |
| 95 |
if (generals > 2) |
if (saveds > 2) |
| 96 |
PUSH_REG(reg_map[SLJIT_GENERAL_REG3]); |
PUSH_REG(reg_map[SLJIT_SAVED_REG3]); |
| 97 |
if (generals > 1) |
if (saveds > 1) |
| 98 |
PUSH_REG(reg_map[SLJIT_GENERAL_REG2]); |
PUSH_REG(reg_map[SLJIT_SAVED_REG2]); |
| 99 |
if (generals > 0) |
if (saveds > 0) |
| 100 |
PUSH_REG(reg_map[SLJIT_GENERAL_REG1]); |
PUSH_REG(reg_map[SLJIT_SAVED_REG1]); |
| 101 |
|
|
| 102 |
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) |
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) |
| 103 |
if (args > 0) { |
if (args > 0) { |
| 104 |
*buf++ = 0x8b; |
*buf++ = 0x8b; |
| 105 |
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG1] << 3) | reg_map[SLJIT_TEMPORARY_REG3]; |
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[SLJIT_TEMPORARY_REG3]; |
| 106 |
} |
} |
| 107 |
if (args > 1) { |
if (args > 1) { |
| 108 |
*buf++ = 0x8b; |
*buf++ = 0x8b; |
| 109 |
*buf++ = 0xc0 | (reg_map[SLJIT_GENERAL_REG2] << 3) | reg_map[SLJIT_TEMPORARY_REG2]; |
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[SLJIT_TEMPORARY_REG2]; |
| 110 |
} |
} |
| 111 |
if (args > 2) { |
if (args > 2) { |
| 112 |
*buf++ = 0x8b; |
*buf++ = 0x8b; |
| 113 |
*buf++ = 0x44 | (reg_map[SLJIT_GENERAL_REG3] << 3); |
*buf++ = 0x44 | (reg_map[SLJIT_SAVED_REG3] << 3); |
| 114 |
*buf++ = 0x24; |
*buf++ = 0x24; |
| 115 |
*buf++ = sizeof(sljit_w) * (3 + 2); /* generals >= 3 as well. */ |
*buf++ = sizeof(sljit_w) * (3 + 2); /* saveds >= 3 as well. */ |
| 116 |
} |
} |
| 117 |
#else |
#else |
| 118 |
if (args > 0) { |
if (args > 0) { |
| 119 |
*buf++ = 0x8b; |
*buf++ = 0x8b; |
| 120 |
*buf++ = 0x40 | (reg_map[SLJIT_GENERAL_REG1] << 3) | reg_map[TMP_REGISTER]; |
*buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REGISTER]; |
| 121 |
*buf++ = sizeof(sljit_w) * 2; |
*buf++ = sizeof(sljit_w) * 2; |
| 122 |
} |
} |
| 123 |
if (args > 1) { |
if (args > 1) { |
| 124 |
*buf++ = 0x8b; |
*buf++ = 0x8b; |
| 125 |
*buf++ = 0x40 | (reg_map[SLJIT_GENERAL_REG2] << 3) | reg_map[TMP_REGISTER]; |
*buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REGISTER]; |
| 126 |
*buf++ = sizeof(sljit_w) * 3; |
*buf++ = sizeof(sljit_w) * 3; |
| 127 |
} |
} |
| 128 |
if (args > 2) { |
if (args > 2) { |
| 129 |
*buf++ = 0x8b; |
*buf++ = 0x8b; |
| 130 |
*buf++ = 0x40 | (reg_map[SLJIT_GENERAL_REG3] << 3) | reg_map[TMP_REGISTER]; |
*buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REGISTER]; |
| 131 |
*buf++ = sizeof(sljit_w) * 4; |
*buf++ = sizeof(sljit_w) * 4; |
| 132 |
} |
} |
| 133 |
#endif |
#endif |
| 136 |
compiler->temporaries_start = local_size; |
compiler->temporaries_start = local_size; |
| 137 |
if (temporaries > 3) |
if (temporaries > 3) |
| 138 |
local_size += (temporaries - 3) * sizeof(sljit_uw); |
local_size += (temporaries - 3) * sizeof(sljit_uw); |
| 139 |
compiler->generals_start = local_size; |
compiler->saveds_start = local_size; |
| 140 |
if (generals > 3) |
if (saveds > 3) |
| 141 |
local_size += (generals - 3) * sizeof(sljit_uw); |
local_size += (saveds - 3) * sizeof(sljit_uw); |
| 142 |
|
|
| 143 |
#ifdef _WIN32 |
#ifdef _WIN32 |
| 144 |
if (local_size > 1024) { |
if (local_size > 1024) { |
| 152 |
return emit_non_cum_binary(compiler, 0x2b, 0x29, 0x5 << 3, 0x2d, |
return emit_non_cum_binary(compiler, 0x2b, 0x29, 0x5 << 3, 0x2d, |
| 153 |
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size); |
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size); |
| 154 |
|
|
|
/* Mov arguments to general registers. */ |
|
| 155 |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
| 156 |
} |
} |
| 157 |
|
|
| 158 |
SLJIT_API_FUNC_ATTRIBUTE void sljit_fake_enter(struct sljit_compiler *compiler, int args, int temporaries, int generals, int local_size) |
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) |
| 159 |
{ |
{ |
| 160 |
CHECK_ERROR_VOID(); |
CHECK_ERROR_VOID(); |
| 161 |
check_sljit_fake_enter(compiler, args, temporaries, generals, local_size); |
check_sljit_set_context(compiler, args, temporaries, saveds, local_size); |
| 162 |
|
|
| 163 |
compiler->temporaries = temporaries; |
compiler->temporaries = temporaries; |
| 164 |
compiler->generals = generals; |
compiler->saveds = saveds; |
| 165 |
compiler->args = args; |
compiler->args = args; |
| 166 |
compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1); |
compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1); |
| 167 |
compiler->temporaries_start = compiler->local_size; |
compiler->temporaries_start = compiler->local_size; |
| 168 |
if (temporaries > 3) |
if (temporaries > 3) |
| 169 |
compiler->local_size += (temporaries - 3) * sizeof(sljit_uw); |
compiler->local_size += (temporaries - 3) * sizeof(sljit_uw); |
| 170 |
compiler->generals_start = compiler->local_size; |
compiler->saveds_start = compiler->local_size; |
| 171 |
if (generals > 3) |
if (saveds > 3) |
| 172 |
compiler->local_size += (generals - 3) * sizeof(sljit_uw); |
compiler->local_size += (saveds - 3) * sizeof(sljit_uw); |
| 173 |
} |
} |
| 174 |
|
|
| 175 |
SLJIT_API_FUNC_ATTRIBUTE 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 op, int src, sljit_w srcw) |
| 176 |
{ |
{ |
| 177 |
int size; |
int size; |
| 178 |
sljit_ub *buf; |
sljit_ub *buf; |
| 179 |
|
|
| 180 |
CHECK_ERROR(); |
CHECK_ERROR(); |
| 181 |
check_sljit_emit_return(compiler, src, srcw); |
check_sljit_emit_return(compiler, op, src, srcw); |
| 182 |
SLJIT_ASSERT(compiler->args >= 0); |
SLJIT_ASSERT(compiler->args >= 0); |
| 183 |
|
|
| 184 |
compiler->flags_saved = 0; |
compiler->flags_saved = 0; |
| 185 |
CHECK_EXTRA_REGS(src, srcw, (void)0); |
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); |
|
|
|
|
if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG) |
|
|
FAIL_IF(emit_mov(compiler, SLJIT_RETURN_REG, 0, src, srcw)); |
|
| 186 |
|
|
| 187 |
if (compiler->local_size > 0) |
if (compiler->local_size > 0) |
| 188 |
FAIL_IF(emit_cum_binary(compiler, 0x03, 0x01, 0x0 << 3, 0x05, |
FAIL_IF(emit_cum_binary(compiler, 0x03, 0x01, 0x0 << 3, 0x05, |
| 189 |
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size)); |
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size)); |
| 190 |
|
|
| 191 |
size = 2 + (compiler->generals <= 3 ? compiler->generals : 3); |
size = 2 + (compiler->saveds <= 3 ? compiler->saveds : 3); |
| 192 |
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) |
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) |
| 193 |
if (compiler->args > 2) |
if (compiler->args > 2) |
| 194 |
size += 2; |
size += 2; |
| 201 |
|
|
| 202 |
INC_SIZE(size); |
INC_SIZE(size); |
| 203 |
|
|
| 204 |
if (compiler->generals > 0) |
if (compiler->saveds > 0) |
| 205 |
POP_REG(reg_map[SLJIT_GENERAL_REG1]); |
POP_REG(reg_map[SLJIT_SAVED_REG1]); |
| 206 |
if (compiler->generals > 1) |
if (compiler->saveds > 1) |
| 207 |
POP_REG(reg_map[SLJIT_GENERAL_REG2]); |
POP_REG(reg_map[SLJIT_SAVED_REG2]); |
| 208 |
if (compiler->generals > 2) |
if (compiler->saveds > 2) |
| 209 |
POP_REG(reg_map[SLJIT_GENERAL_REG3]); |
POP_REG(reg_map[SLJIT_SAVED_REG3]); |
| 210 |
POP_REG(reg_map[TMP_REGISTER]); |
POP_REG(reg_map[TMP_REGISTER]); |
| 211 |
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) |
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) |
| 212 |
if (compiler->args > 2) |
if (compiler->args > 2) |
| 431 |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
| 432 |
} |
} |
| 433 |
|
|
| 434 |
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) |
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size) |
| 435 |
{ |
{ |
| 436 |
sljit_ub *buf; |
sljit_ub *buf; |
| 437 |
|
|
| 438 |
CHECK_ERROR(); |
CHECK_ERROR(); |
| 439 |
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, generals, local_size); |
check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size); |
| 440 |
|
|
| 441 |
compiler->temporaries = temporaries; |
compiler->temporaries = temporaries; |
| 442 |
compiler->generals = generals; |
compiler->saveds = saveds; |
| 443 |
compiler->args = args; |
compiler->args = args; |
| 444 |
compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1); |
compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1); |
| 445 |
compiler->temporaries_start = compiler->local_size; |
compiler->temporaries_start = compiler->local_size; |
| 446 |
if (temporaries > 3) |
if (temporaries > 3) |
| 447 |
compiler->local_size += (temporaries - 3) * sizeof(sljit_uw); |
compiler->local_size += (temporaries - 3) * sizeof(sljit_uw); |
| 448 |
compiler->generals_start = compiler->local_size; |
compiler->saveds_start = compiler->local_size; |
| 449 |
if (generals > 3) |
if (saveds > 3) |
| 450 |
compiler->local_size += (generals - 3) * sizeof(sljit_uw); |
compiler->local_size += (saveds - 3) * sizeof(sljit_uw); |
| 451 |
|
|
| 452 |
CHECK_EXTRA_REGS(dst, dstw, (void)0); |
CHECK_EXTRA_REGS(dst, dstw, (void)0); |
| 453 |
|
|