JIT compiler update.
This commit is contained in:
parent
0d0ee67eb0
commit
c11b23e8cc
|
@ -144,6 +144,7 @@
|
|||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
# define PATCH_MD 0x10
|
||||
#endif
|
||||
# define TYPE_SHIFT 13
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||
|
@ -521,6 +522,12 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
|
|||
}
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label)
|
||||
{
|
||||
if (SLJIT_LIKELY(!!put_label))
|
||||
put_label->label = label;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
|
@ -620,6 +627,30 @@ static SLJIT_INLINE sljit_s32 get_arg_count(sljit_s32 arg_types)
|
|||
return arg_count;
|
||||
}
|
||||
|
||||
#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
|
||||
static SLJIT_INLINE sljit_uw compute_next_addr(struct sljit_label *label, struct sljit_jump *jump,
|
||||
struct sljit_const *const_, struct sljit_put_label *put_label)
|
||||
{
|
||||
sljit_uw result = ~(sljit_uw)0;
|
||||
|
||||
if (label)
|
||||
result = label->size;
|
||||
|
||||
if (jump && jump->addr < result)
|
||||
result = jump->addr;
|
||||
|
||||
if (const_ && const_->addr < result)
|
||||
result = const_->addr;
|
||||
|
||||
if (put_label && put_label->addr < result)
|
||||
result = put_label->addr;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* !SLJIT_CONFIG_X86 */
|
||||
|
||||
static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
|
@ -687,6 +718,18 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
|||
compiler->last_const = const_;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void set_put_label(struct sljit_put_label *put_label, struct sljit_compiler *compiler, sljit_uw offset)
|
||||
{
|
||||
put_label->next = NULL;
|
||||
put_label->addr = compiler->size - offset;
|
||||
put_label->flags = 0;
|
||||
if (compiler->last_put_label)
|
||||
compiler->last_put_label->next = put_label;
|
||||
else
|
||||
compiler->put_labels = put_label;
|
||||
compiler->last_put_label = put_label;
|
||||
}
|
||||
|
||||
#define ADDRESSING_DEPENDS_ON(exp, reg) \
|
||||
(((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg))
|
||||
|
||||
|
@ -1905,6 +1948,21 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compil
|
|||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
FUNCTION_CHECK_DST(dst, dstw, 0);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " put_label ");
|
||||
sljit_verbose_param(compiler, dst, dstw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */
|
||||
|
||||
#define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \
|
||||
|
@ -2581,6 +2639,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
return NULL;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(dst);
|
||||
SLJIT_UNUSED_ARG(dstw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(addr);
|
||||
|
@ -2597,4 +2663,4 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
|||
SLJIT_UNREACHABLE();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* !SLJIT_CONFIG_UNSUPPORTED */
|
||||
|
|
|
@ -348,13 +348,20 @@ struct sljit_label {
|
|||
struct sljit_jump {
|
||||
struct sljit_jump *next;
|
||||
sljit_uw addr;
|
||||
sljit_sw flags;
|
||||
sljit_uw flags;
|
||||
union {
|
||||
sljit_uw target;
|
||||
struct sljit_label *label;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct sljit_put_label {
|
||||
struct sljit_put_label *next;
|
||||
struct sljit_label *label;
|
||||
sljit_uw addr;
|
||||
sljit_uw flags;
|
||||
};
|
||||
|
||||
struct sljit_const {
|
||||
struct sljit_const *next;
|
||||
sljit_uw addr;
|
||||
|
@ -366,10 +373,12 @@ struct sljit_compiler {
|
|||
|
||||
struct sljit_label *labels;
|
||||
struct sljit_jump *jumps;
|
||||
struct sljit_put_label *put_labels;
|
||||
struct sljit_const *consts;
|
||||
struct sljit_label *last_label;
|
||||
struct sljit_jump *last_jump;
|
||||
struct sljit_const *last_const;
|
||||
struct sljit_put_label *last_put_label;
|
||||
|
||||
void *allocator_data;
|
||||
struct sljit_memory_fragment *buf;
|
||||
|
@ -1314,10 +1323,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
|
|||
Flags: - (may destroy flags) */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset);
|
||||
|
||||
/* The constant can be changed runtime (see: sljit_set_const)
|
||||
/* Store a value that can be changed runtime (see: sljit_get_const_addr / sljit_set_const)
|
||||
Flags: - (does not modify flags) */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value);
|
||||
|
||||
/* Store the value of a label (see: sljit_set_put_label)
|
||||
Flags: - (does not modify flags) */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw);
|
||||
|
||||
/* Set the value stored by put_label to this label. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label);
|
||||
|
||||
/* After the code generation the address for label, jump and const instructions
|
||||
are computed. Since these structures are freed by sljit_free_compiler, the
|
||||
addresses must be preserved by the user program elsewere. */
|
||||
|
|
|
@ -583,8 +583,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
sljit_uw *buf_end;
|
||||
sljit_uw size;
|
||||
sljit_uw word_count;
|
||||
sljit_uw next_addr;
|
||||
sljit_sw executable_offset;
|
||||
sljit_sw jump_addr;
|
||||
sljit_sw addr;
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
sljit_uw cpool_size;
|
||||
sljit_uw cpool_skip_alignment;
|
||||
|
@ -597,6 +598,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
struct sljit_label *label;
|
||||
struct sljit_jump *jump;
|
||||
struct sljit_const *const_;
|
||||
struct sljit_put_label *put_label;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_generate_code(compiler));
|
||||
|
@ -625,11 +627,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
code_ptr = code;
|
||||
word_count = 0;
|
||||
next_addr = 1;
|
||||
executable_offset = SLJIT_EXEC_OFFSET(code);
|
||||
|
||||
label = compiler->labels;
|
||||
jump = compiler->jumps;
|
||||
const_ = compiler->consts;
|
||||
put_label = compiler->put_labels;
|
||||
|
||||
if (label && label->size == 0) {
|
||||
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
|
||||
|
@ -669,10 +673,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
else if ((*buf_ptr & 0xff000000) != PUSH_POOL) {
|
||||
#endif
|
||||
*code_ptr = *buf_ptr++;
|
||||
/* These structures are ordered by their address. */
|
||||
if (next_addr == word_count) {
|
||||
SLJIT_ASSERT(!label || label->size >= word_count);
|
||||
SLJIT_ASSERT(!jump || jump->addr >= word_count);
|
||||
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
|
||||
SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
|
||||
|
||||
/* These structures are ordered by their address. */
|
||||
if (jump && jump->addr == word_count) {
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
if (detect_jump_type(jump, code_ptr, code, executable_offset))
|
||||
|
@ -699,6 +706,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
#endif
|
||||
const_ = const_->next;
|
||||
}
|
||||
if (put_label && put_label->addr == word_count) {
|
||||
SLJIT_ASSERT(put_label->label);
|
||||
put_label->addr = (sljit_uw)code_ptr;
|
||||
put_label = put_label->next;
|
||||
}
|
||||
next_addr = compute_next_addr(label, jump, const_, put_label);
|
||||
}
|
||||
code_ptr++;
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
}
|
||||
|
@ -725,6 +739,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
SLJIT_ASSERT(!label);
|
||||
SLJIT_ASSERT(!jump);
|
||||
SLJIT_ASSERT(!const_);
|
||||
SLJIT_ASSERT(!put_label);
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
SLJIT_ASSERT(cpool_size == 0);
|
||||
|
@ -755,15 +770,15 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
buf_ptr = (sljit_uw *)jump->addr;
|
||||
|
||||
if (jump->flags & PATCH_B) {
|
||||
jump_addr = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);
|
||||
addr = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);
|
||||
if (!(jump->flags & JUMP_ADDR)) {
|
||||
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
|
||||
SLJIT_ASSERT(((sljit_sw)jump->u.label->addr - jump_addr) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - jump_addr) >= -0x02000000);
|
||||
*buf_ptr |= (((sljit_sw)jump->u.label->addr - jump_addr) >> 2) & 0x00ffffff;
|
||||
SLJIT_ASSERT(((sljit_sw)jump->u.label->addr - addr) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - addr) >= -0x02000000);
|
||||
*buf_ptr |= (((sljit_sw)jump->u.label->addr - addr) >> 2) & 0x00ffffff;
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(((sljit_sw)jump->u.target - jump_addr) <= 0x01ffffff && ((sljit_sw)jump->u.target - jump_addr) >= -0x02000000);
|
||||
*buf_ptr |= (((sljit_sw)jump->u.target - jump_addr) >> 2) & 0x00ffffff;
|
||||
SLJIT_ASSERT(((sljit_sw)jump->u.target - addr) <= 0x01ffffff && ((sljit_sw)jump->u.target - addr) >= -0x02000000);
|
||||
*buf_ptr |= (((sljit_sw)jump->u.target - addr) >> 2) & 0x00ffffff;
|
||||
}
|
||||
}
|
||||
else if (jump->flags & SLJIT_REWRITABLE_JUMP) {
|
||||
|
@ -813,6 +828,22 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
}
|
||||
#endif
|
||||
|
||||
put_label = compiler->put_labels;
|
||||
while (put_label) {
|
||||
addr = put_label->label->addr;
|
||||
buf_ptr = (sljit_uw*)put_label->addr;
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
SLJIT_ASSERT((buf_ptr[0] & 0xffff0000) == 0xe59f0000);
|
||||
buf_ptr[((buf_ptr[0] & 0xfff) >> 2) + 2] = addr;
|
||||
#else
|
||||
SLJIT_ASSERT((buf_ptr[-1] & 0xfff00000) == MOVW && (buf_ptr[0] & 0xfff00000) == MOVT);
|
||||
buf_ptr[-1] |= ((addr << 4) & 0xf0000) | (addr & 0xfff);
|
||||
buf_ptr[0] |= ((addr >> 12) & 0xf0000) | ((addr >> 16) & 0xfff);
|
||||
#endif
|
||||
put_label = put_label->next;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(code_ptr - code <= (sljit_s32)size);
|
||||
|
||||
compiler->error = SLJIT_ERR_COMPILED;
|
||||
|
@ -2639,23 +2670,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
|
|||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||
{
|
||||
struct sljit_const *const_;
|
||||
sljit_s32 reg;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
|
||||
PTR_FAIL_IF(!const_);
|
||||
|
||||
reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
|
||||
dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), init_value));
|
||||
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), init_value));
|
||||
compiler->patches++;
|
||||
#else
|
||||
PTR_FAIL_IF(emit_imm(compiler, reg, init_value));
|
||||
PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value));
|
||||
#endif
|
||||
|
||||
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
|
||||
PTR_FAIL_IF(!const_);
|
||||
set_const(const_, compiler);
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
|
@ -2663,6 +2694,33 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
return const_;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
struct sljit_put_label *put_label;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), 0));
|
||||
compiler->patches++;
|
||||
#else
|
||||
PTR_FAIL_IF(emit_imm(compiler, dst_r, 0));
|
||||
#endif
|
||||
|
||||
put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
|
||||
PTR_FAIL_IF(!put_label);
|
||||
set_put_label(put_label, compiler, 0);
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
|
||||
return put_label;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
inline_set_jump_addr(addr, executable_offset, new_target, 1);
|
||||
|
|
|
@ -161,7 +161,7 @@ static SLJIT_INLINE void modify_imm64_const(sljit_ins* inst, sljit_uw new_imm)
|
|||
inst[3] = MOVK | dst | ((new_imm >> 48) << 5) | (3 << 21);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
|
||||
static SLJIT_INLINE sljit_sw detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_sw diff;
|
||||
sljit_uw target_addr;
|
||||
|
@ -196,14 +196,14 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
|
|||
return 4;
|
||||
}
|
||||
|
||||
if (target_addr <= 0xffffffffl) {
|
||||
if (target_addr < 0x100000000l) {
|
||||
if (jump->flags & IS_COND)
|
||||
code_ptr[-5] -= (2 << 5);
|
||||
code_ptr[-2] = code_ptr[0];
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (target_addr <= 0xffffffffffffl) {
|
||||
if (target_addr < 0x1000000000000l) {
|
||||
if (jump->flags & IS_COND)
|
||||
code_ptr[-5] -= (1 << 5);
|
||||
jump->flags |= PATCH_ABS48;
|
||||
|
@ -215,6 +215,22 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
|
|||
return 0;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
|
||||
{
|
||||
if (max_label < 0x100000000l) {
|
||||
put_label->flags = 0;
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (max_label < 0x1000000000000l) {
|
||||
put_label->flags = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
put_label->flags = 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
|
||||
{
|
||||
struct sljit_memory_fragment *buf;
|
||||
|
@ -223,6 +239,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
sljit_ins *buf_ptr;
|
||||
sljit_ins *buf_end;
|
||||
sljit_uw word_count;
|
||||
sljit_uw next_addr;
|
||||
sljit_sw executable_offset;
|
||||
sljit_uw addr;
|
||||
sljit_s32 dst;
|
||||
|
@ -230,6 +247,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
struct sljit_label *label;
|
||||
struct sljit_jump *jump;
|
||||
struct sljit_const *const_;
|
||||
struct sljit_put_label *put_label;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_generate_code(compiler));
|
||||
|
@ -241,21 +259,26 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
code_ptr = code;
|
||||
word_count = 0;
|
||||
next_addr = 0;
|
||||
executable_offset = SLJIT_EXEC_OFFSET(code);
|
||||
|
||||
label = compiler->labels;
|
||||
jump = compiler->jumps;
|
||||
const_ = compiler->consts;
|
||||
put_label = compiler->put_labels;
|
||||
|
||||
do {
|
||||
buf_ptr = (sljit_ins*)buf->memory;
|
||||
buf_end = buf_ptr + (buf->used_size >> 2);
|
||||
do {
|
||||
*code_ptr = *buf_ptr++;
|
||||
/* These structures are ordered by their address. */
|
||||
if (next_addr == word_count) {
|
||||
SLJIT_ASSERT(!label || label->size >= word_count);
|
||||
SLJIT_ASSERT(!jump || jump->addr >= word_count);
|
||||
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
|
||||
SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
|
||||
|
||||
/* These structures are ordered by their address. */
|
||||
if (label && label->size == word_count) {
|
||||
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
|
||||
label->size = code_ptr - code;
|
||||
|
@ -270,6 +293,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
const_->addr = (sljit_uw)code_ptr;
|
||||
const_ = const_->next;
|
||||
}
|
||||
if (put_label && put_label->addr == word_count) {
|
||||
SLJIT_ASSERT(put_label->label);
|
||||
put_label->addr = (sljit_uw)(code_ptr - 3);
|
||||
code_ptr -= put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
|
||||
put_label = put_label->next;
|
||||
}
|
||||
next_addr = compute_next_addr(label, jump, const_, put_label);
|
||||
}
|
||||
code_ptr ++;
|
||||
word_count ++;
|
||||
} while (buf_ptr < buf_end);
|
||||
|
@ -286,6 +317,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
SLJIT_ASSERT(!label);
|
||||
SLJIT_ASSERT(!jump);
|
||||
SLJIT_ASSERT(!const_);
|
||||
SLJIT_ASSERT(!put_label);
|
||||
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
|
||||
|
||||
jump = compiler->jumps;
|
||||
|
@ -323,6 +355,23 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
jump = jump->next;
|
||||
}
|
||||
|
||||
put_label = compiler->put_labels;
|
||||
while (put_label) {
|
||||
addr = put_label->label->addr;
|
||||
buf_ptr = (sljit_ins *)put_label->addr;
|
||||
|
||||
buf_ptr[0] |= (addr & 0xffff) << 5;
|
||||
buf_ptr[1] |= ((addr >> 16) & 0xffff) << 5;
|
||||
|
||||
if (put_label->flags >= 1)
|
||||
buf_ptr[2] |= ((addr >> 32) & 0xffff) << 5;
|
||||
|
||||
if (put_label->flags >= 2)
|
||||
buf_ptr[3] |= ((addr >> 48) & 0xffff) << 5;
|
||||
|
||||
put_label = put_label->next;
|
||||
}
|
||||
|
||||
compiler->error = SLJIT_ERR_COMPILED;
|
||||
compiler->executable_offset = executable_offset;
|
||||
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
|
||||
|
@ -1947,6 +1996,28 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
return const_;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
struct sljit_put_label *put_label;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
|
||||
PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, 0));
|
||||
|
||||
put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
|
||||
PTR_FAIL_IF(!put_label);
|
||||
set_put_label(put_label, compiler, 1);
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
|
||||
|
||||
return put_label;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins* inst = (sljit_ins*)addr;
|
||||
|
|
|
@ -365,11 +365,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
sljit_u16 *buf_ptr;
|
||||
sljit_u16 *buf_end;
|
||||
sljit_uw half_count;
|
||||
sljit_uw next_addr;
|
||||
sljit_sw executable_offset;
|
||||
|
||||
struct sljit_label *label;
|
||||
struct sljit_jump *jump;
|
||||
struct sljit_const *const_;
|
||||
struct sljit_put_label *put_label;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_generate_code(compiler));
|
||||
|
@ -381,21 +383,26 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
code_ptr = code;
|
||||
half_count = 0;
|
||||
next_addr = 0;
|
||||
executable_offset = SLJIT_EXEC_OFFSET(code);
|
||||
|
||||
label = compiler->labels;
|
||||
jump = compiler->jumps;
|
||||
const_ = compiler->consts;
|
||||
put_label = compiler->put_labels;
|
||||
|
||||
do {
|
||||
buf_ptr = (sljit_u16*)buf->memory;
|
||||
buf_end = buf_ptr + (buf->used_size >> 1);
|
||||
do {
|
||||
*code_ptr = *buf_ptr++;
|
||||
/* These structures are ordered by their address. */
|
||||
if (next_addr == half_count) {
|
||||
SLJIT_ASSERT(!label || label->size >= half_count);
|
||||
SLJIT_ASSERT(!jump || jump->addr >= half_count);
|
||||
SLJIT_ASSERT(!const_ || const_->addr >= half_count);
|
||||
SLJIT_ASSERT(!put_label || put_label->addr >= half_count);
|
||||
|
||||
/* These structures are ordered by their address. */
|
||||
if (label && label->size == half_count) {
|
||||
label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
|
||||
label->size = code_ptr - code;
|
||||
|
@ -410,6 +417,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
const_->addr = (sljit_uw)code_ptr;
|
||||
const_ = const_->next;
|
||||
}
|
||||
if (put_label && put_label->addr == half_count) {
|
||||
SLJIT_ASSERT(put_label->label);
|
||||
put_label->addr = (sljit_uw)code_ptr;
|
||||
put_label = put_label->next;
|
||||
}
|
||||
next_addr = compute_next_addr(label, jump, const_, put_label);
|
||||
}
|
||||
code_ptr ++;
|
||||
half_count ++;
|
||||
} while (buf_ptr < buf_end);
|
||||
|
@ -426,6 +440,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
SLJIT_ASSERT(!label);
|
||||
SLJIT_ASSERT(!jump);
|
||||
SLJIT_ASSERT(!const_);
|
||||
SLJIT_ASSERT(!put_label);
|
||||
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
|
||||
|
||||
jump = compiler->jumps;
|
||||
|
@ -434,6 +449,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
jump = jump->next;
|
||||
}
|
||||
|
||||
put_label = compiler->put_labels;
|
||||
while (put_label) {
|
||||
modify_imm32_const((sljit_u16 *)put_label->addr, put_label->label->addr);
|
||||
put_label = put_label->next;
|
||||
}
|
||||
|
||||
compiler->error = SLJIT_ERR_COMPILED;
|
||||
compiler->executable_offset = executable_offset;
|
||||
compiler->executable_size = (code_ptr - code) * sizeof(sljit_u16);
|
||||
|
@ -2311,6 +2332,27 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
return const_;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
struct sljit_put_label *put_label;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
|
||||
PTR_FAIL_IF(!put_label);
|
||||
set_put_label(put_label, compiler, 0);
|
||||
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
|
||||
PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, 0));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
|
||||
return put_label;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_u16 *inst = (sljit_u16*)addr;
|
||||
|
|
|
@ -425,6 +425,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
|
|||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
|
@ -435,6 +436,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
|||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
|
|
|
@ -449,6 +449,55 @@ static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_
|
|||
}
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
|
||||
static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
|
||||
{
|
||||
if (max_label < 0x80000000l) {
|
||||
put_label->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (max_label < 0x800000000000l) {
|
||||
put_label->flags = 1;
|
||||
return 3;
|
||||
}
|
||||
|
||||
put_label->flags = 2;
|
||||
return 5;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
|
||||
{
|
||||
sljit_uw addr = put_label->label->addr;
|
||||
sljit_ins *inst = (sljit_ins *)put_label->addr;
|
||||
sljit_s32 reg = *inst;
|
||||
|
||||
if (put_label->flags == 0) {
|
||||
SLJIT_ASSERT(addr < 0x80000000l);
|
||||
inst[0] = LUI | T(reg) | IMM(addr >> 16);
|
||||
}
|
||||
else if (put_label->flags == 1) {
|
||||
SLJIT_ASSERT(addr < 0x800000000000l);
|
||||
inst[0] = LUI | T(reg) | IMM(addr >> 32);
|
||||
inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
|
||||
inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
|
||||
inst += 2;
|
||||
}
|
||||
else {
|
||||
inst[0] = LUI | T(reg) | IMM(addr >> 48);
|
||||
inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);
|
||||
inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
|
||||
inst[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
|
||||
inst[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);
|
||||
inst += 4;
|
||||
}
|
||||
|
||||
inst[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
|
||||
{
|
||||
struct sljit_memory_fragment *buf;
|
||||
|
@ -457,12 +506,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
sljit_ins *buf_ptr;
|
||||
sljit_ins *buf_end;
|
||||
sljit_uw word_count;
|
||||
sljit_uw next_addr;
|
||||
sljit_sw executable_offset;
|
||||
sljit_uw addr;
|
||||
|
||||
struct sljit_label *label;
|
||||
struct sljit_jump *jump;
|
||||
struct sljit_const *const_;
|
||||
struct sljit_put_label *put_label;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_generate_code(compiler));
|
||||
|
@ -474,20 +525,25 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
code_ptr = code;
|
||||
word_count = 0;
|
||||
next_addr = 0;
|
||||
executable_offset = SLJIT_EXEC_OFFSET(code);
|
||||
|
||||
label = compiler->labels;
|
||||
jump = compiler->jumps;
|
||||
const_ = compiler->consts;
|
||||
put_label = compiler->put_labels;
|
||||
|
||||
do {
|
||||
buf_ptr = (sljit_ins*)buf->memory;
|
||||
buf_end = buf_ptr + (buf->used_size >> 2);
|
||||
do {
|
||||
*code_ptr = *buf_ptr++;
|
||||
if (next_addr == word_count) {
|
||||
SLJIT_ASSERT(!label || label->size >= word_count);
|
||||
SLJIT_ASSERT(!jump || jump->addr >= word_count);
|
||||
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
|
||||
SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
|
||||
|
||||
/* These structures are ordered by their address. */
|
||||
if (label && label->size == word_count) {
|
||||
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
|
||||
|
@ -504,10 +560,20 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
jump = jump->next;
|
||||
}
|
||||
if (const_ && const_->addr == word_count) {
|
||||
/* Just recording the address. */
|
||||
const_->addr = (sljit_uw)code_ptr;
|
||||
const_ = const_->next;
|
||||
}
|
||||
if (put_label && put_label->addr == word_count) {
|
||||
SLJIT_ASSERT(put_label->label);
|
||||
put_label->addr = (sljit_uw)code_ptr;
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
|
||||
word_count += 5;
|
||||
#endif
|
||||
put_label = put_label->next;
|
||||
}
|
||||
next_addr = compute_next_addr(label, jump, const_, put_label);
|
||||
}
|
||||
code_ptr ++;
|
||||
word_count ++;
|
||||
} while (buf_ptr < buf_end);
|
||||
|
@ -524,6 +590,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
SLJIT_ASSERT(!label);
|
||||
SLJIT_ASSERT(!jump);
|
||||
SLJIT_ASSERT(!const_);
|
||||
SLJIT_ASSERT(!put_label);
|
||||
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
|
||||
|
||||
jump = compiler->jumps;
|
||||
|
@ -571,6 +638,21 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
jump = jump->next;
|
||||
}
|
||||
|
||||
put_label = compiler->put_labels;
|
||||
while (put_label) {
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
addr = put_label->label->addr;
|
||||
buf_ptr = (sljit_ins *)put_label->addr;
|
||||
|
||||
SLJIT_ASSERT((buf_ptr[0] & 0xffe00000) == LUI && (buf_ptr[1] & 0xfc000000) == ORI);
|
||||
buf_ptr[0] |= (addr >> 16) & 0xffff;
|
||||
buf_ptr[1] |= addr & 0xffff;
|
||||
#else
|
||||
put_label_set(put_label);
|
||||
#endif
|
||||
put_label = put_label->next;
|
||||
}
|
||||
|
||||
compiler->error = SLJIT_ERR_COMPILED;
|
||||
compiler->executable_offset = executable_offset;
|
||||
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
|
||||
|
@ -2157,7 +2239,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||
{
|
||||
struct sljit_const *const_;
|
||||
sljit_s32 reg;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
|
||||
|
@ -2167,11 +2249,38 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
PTR_FAIL_IF(!const_);
|
||||
set_const(const_, compiler);
|
||||
|
||||
reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
|
||||
|
||||
return const_;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
struct sljit_put_label *put_label;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
|
||||
PTR_FAIL_IF(!put_label);
|
||||
set_put_label(put_label, compiler, 0);
|
||||
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
|
||||
#else
|
||||
PTR_FAIL_IF(push_inst(compiler, dst_r, UNMOVABLE_INS));
|
||||
compiler->size += 5;
|
||||
#endif
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
|
||||
|
||||
return put_label;
|
||||
}
|
||||
|
|
|
@ -259,6 +259,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
|
|||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
|
@ -269,6 +270,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
|||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
|
|
|
@ -35,9 +35,6 @@
|
|||
#error "Must implement count leading zeroes"
|
||||
#endif
|
||||
|
||||
#define RLDI(dst, src, sh, mb, type) \
|
||||
(HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20))
|
||||
|
||||
#define PUSH_RLDICR(reg, shift) \
|
||||
push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))
|
||||
|
||||
|
|
|
@ -231,6 +231,9 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
|
|||
#define SIMM_MIN (-0x8000)
|
||||
#define UIMM_MAX (0xffff)
|
||||
|
||||
#define RLDI(dst, src, sh, mb, type) \
|
||||
(HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20))
|
||||
|
||||
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func)
|
||||
{
|
||||
|
@ -324,6 +327,55 @@ keep_address:
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
|
||||
static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
|
||||
{
|
||||
if (max_label < 0x100000000l) {
|
||||
put_label->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (max_label < 0x1000000000000l) {
|
||||
put_label->flags = 1;
|
||||
return 3;
|
||||
}
|
||||
|
||||
put_label->flags = 2;
|
||||
return 4;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
|
||||
{
|
||||
sljit_uw addr = put_label->label->addr;
|
||||
sljit_ins *inst = (sljit_ins *)put_label->addr;
|
||||
sljit_s32 reg = *inst;
|
||||
|
||||
if (put_label->flags == 0) {
|
||||
SLJIT_ASSERT(addr < 0x100000000l);
|
||||
inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 16);
|
||||
}
|
||||
else {
|
||||
if (put_label->flags == 1) {
|
||||
SLJIT_ASSERT(addr < 0x1000000000000l);
|
||||
inst[0] = ORI | S(TMP_ZERO) | A(reg) | IMM(addr >> 32);
|
||||
}
|
||||
else {
|
||||
inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 48);
|
||||
inst[1] = ORI | S(reg) | A(reg) | IMM((addr >> 32) & 0xffff);
|
||||
inst ++;
|
||||
}
|
||||
|
||||
inst[1] = RLDI(reg, reg, 32, 31, 1);
|
||||
inst[2] = ORIS | S(reg) | A(reg) | IMM((addr >> 16) & 0xffff);
|
||||
inst += 2;
|
||||
}
|
||||
|
||||
inst[1] = ORI | S(reg) | A(reg) | IMM(addr & 0xffff);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
|
||||
{
|
||||
struct sljit_memory_fragment *buf;
|
||||
|
@ -332,12 +384,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
sljit_ins *buf_ptr;
|
||||
sljit_ins *buf_end;
|
||||
sljit_uw word_count;
|
||||
sljit_uw next_addr;
|
||||
sljit_sw executable_offset;
|
||||
sljit_uw addr;
|
||||
|
||||
struct sljit_label *label;
|
||||
struct sljit_jump *jump;
|
||||
struct sljit_const *const_;
|
||||
struct sljit_put_label *put_label;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_generate_code(compiler));
|
||||
|
@ -356,20 +410,25 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
code_ptr = code;
|
||||
word_count = 0;
|
||||
next_addr = 0;
|
||||
executable_offset = SLJIT_EXEC_OFFSET(code);
|
||||
|
||||
label = compiler->labels;
|
||||
jump = compiler->jumps;
|
||||
const_ = compiler->consts;
|
||||
put_label = compiler->put_labels;
|
||||
|
||||
do {
|
||||
buf_ptr = (sljit_ins*)buf->memory;
|
||||
buf_end = buf_ptr + (buf->used_size >> 2);
|
||||
do {
|
||||
*code_ptr = *buf_ptr++;
|
||||
if (next_addr == word_count) {
|
||||
SLJIT_ASSERT(!label || label->size >= word_count);
|
||||
SLJIT_ASSERT(!jump || jump->addr >= word_count);
|
||||
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
|
||||
SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
|
||||
|
||||
/* These structures are ordered by their address. */
|
||||
if (label && label->size == word_count) {
|
||||
/* Just recording the address. */
|
||||
|
@ -422,6 +481,17 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
const_->addr = (sljit_uw)code_ptr;
|
||||
const_ = const_->next;
|
||||
}
|
||||
if (put_label && put_label->addr == word_count) {
|
||||
SLJIT_ASSERT(put_label->label);
|
||||
put_label->addr = (sljit_uw)code_ptr;
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
|
||||
word_count += 4;
|
||||
#endif
|
||||
put_label = put_label->next;
|
||||
}
|
||||
next_addr = compute_next_addr(label, jump, const_, put_label);
|
||||
}
|
||||
code_ptr ++;
|
||||
word_count ++;
|
||||
} while (buf_ptr < buf_end);
|
||||
|
@ -438,6 +508,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
SLJIT_ASSERT(!label);
|
||||
SLJIT_ASSERT(!jump);
|
||||
SLJIT_ASSERT(!const_);
|
||||
SLJIT_ASSERT(!put_label);
|
||||
|
||||
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
|
||||
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins)));
|
||||
#else
|
||||
|
@ -503,6 +575,21 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
jump = jump->next;
|
||||
}
|
||||
|
||||
put_label = compiler->put_labels;
|
||||
while (put_label) {
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
addr = put_label->label->addr;
|
||||
buf_ptr = (sljit_ins *)put_label->addr;
|
||||
|
||||
SLJIT_ASSERT((buf_ptr[0] & 0xfc1f0000) == ADDIS && (buf_ptr[1] & 0xfc000000) == ORI);
|
||||
buf_ptr[0] |= (addr >> 16) & 0xffff;
|
||||
buf_ptr[1] |= addr & 0xffff;
|
||||
#else
|
||||
put_label_set(put_label);
|
||||
#endif
|
||||
put_label = put_label->next;
|
||||
}
|
||||
|
||||
compiler->error = SLJIT_ERR_COMPILED;
|
||||
compiler->executable_offset = executable_offset;
|
||||
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
|
||||
|
@ -2261,7 +2348,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
|
|||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||
{
|
||||
struct sljit_const *const_;
|
||||
sljit_s32 reg;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
|
||||
|
@ -2271,11 +2358,38 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
PTR_FAIL_IF(!const_);
|
||||
set_const(const_, compiler);
|
||||
|
||||
reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
|
||||
|
||||
return const_;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
struct sljit_put_label *put_label;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
|
||||
PTR_FAIL_IF(!put_label);
|
||||
set_put_label(put_label, compiler, 0);
|
||||
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
|
||||
#else
|
||||
PTR_FAIL_IF(push_inst(compiler, dst_r));
|
||||
compiler->size += 4;
|
||||
#endif
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
|
||||
|
||||
return put_label;
|
||||
}
|
||||
|
|
|
@ -267,6 +267,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
|
|||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
SLJIT_ASSERT(((inst[0] & 0xc1c00000) == 0x01000000) && ((inst[1] & 0xc1f82000) == 0x80102000));
|
||||
inst[0] = (inst[0] & 0xffc00000) | ((new_target >> 10) & 0x3fffff);
|
||||
inst[1] = (inst[1] & 0xfffffc00) | (new_target & 0x3ff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
|
@ -277,6 +278,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
|||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
|
||||
SLJIT_ASSERT(((inst[0] & 0xc1c00000) == 0x01000000) && ((inst[1] & 0xc1f82000) == 0x80102000));
|
||||
inst[0] = (inst[0] & 0xffc00000) | ((new_constant >> 10) & 0x3fffff);
|
||||
inst[1] = (inst[1] & 0xfffffc00) | (new_constant & 0x3ff);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
|
|
|
@ -298,12 +298,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
sljit_ins *buf_ptr;
|
||||
sljit_ins *buf_end;
|
||||
sljit_uw word_count;
|
||||
sljit_uw next_addr;
|
||||
sljit_sw executable_offset;
|
||||
sljit_uw addr;
|
||||
|
||||
struct sljit_label *label;
|
||||
struct sljit_jump *jump;
|
||||
struct sljit_const *const_;
|
||||
struct sljit_put_label *put_label;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_generate_code(compiler));
|
||||
|
@ -315,20 +317,25 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
code_ptr = code;
|
||||
word_count = 0;
|
||||
next_addr = 0;
|
||||
executable_offset = SLJIT_EXEC_OFFSET(code);
|
||||
|
||||
label = compiler->labels;
|
||||
jump = compiler->jumps;
|
||||
const_ = compiler->consts;
|
||||
put_label = compiler->put_labels;
|
||||
|
||||
do {
|
||||
buf_ptr = (sljit_ins*)buf->memory;
|
||||
buf_end = buf_ptr + (buf->used_size >> 2);
|
||||
do {
|
||||
*code_ptr = *buf_ptr++;
|
||||
if (next_addr == word_count) {
|
||||
SLJIT_ASSERT(!label || label->size >= word_count);
|
||||
SLJIT_ASSERT(!jump || jump->addr >= word_count);
|
||||
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
|
||||
SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
|
||||
|
||||
/* These structures are ordered by their address. */
|
||||
if (label && label->size == word_count) {
|
||||
/* Just recording the address. */
|
||||
|
@ -350,6 +357,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
const_->addr = (sljit_uw)code_ptr;
|
||||
const_ = const_->next;
|
||||
}
|
||||
if (put_label && put_label->addr == word_count) {
|
||||
SLJIT_ASSERT(put_label->label);
|
||||
put_label->addr = (sljit_uw)code_ptr;
|
||||
put_label = put_label->next;
|
||||
}
|
||||
next_addr = compute_next_addr(label, jump, const_, put_label);
|
||||
}
|
||||
code_ptr ++;
|
||||
word_count ++;
|
||||
} while (buf_ptr < buf_end);
|
||||
|
@ -366,6 +380,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
SLJIT_ASSERT(!label);
|
||||
SLJIT_ASSERT(!jump);
|
||||
SLJIT_ASSERT(!const_);
|
||||
SLJIT_ASSERT(!put_label);
|
||||
SLJIT_ASSERT(code_ptr - code <= (sljit_s32)compiler->size);
|
||||
|
||||
jump = compiler->jumps;
|
||||
|
@ -389,8 +404,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
|
||||
/* Set the fields of immediate loads. */
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
buf_ptr[0] = (buf_ptr[0] & 0xffc00000) | ((addr >> 10) & 0x3fffff);
|
||||
buf_ptr[1] = (buf_ptr[1] & 0xfffffc00) | (addr & 0x3ff);
|
||||
SLJIT_ASSERT(((buf_ptr[0] & 0xc1cfffff) == 0x01000000) && ((buf_ptr[1] & 0xc1f83fff) == 0x80102000));
|
||||
buf_ptr[0] |= (addr >> 10) & 0x3fffff;
|
||||
buf_ptr[1] |= addr & 0x3ff;
|
||||
#else
|
||||
#error "Implementation required"
|
||||
#endif
|
||||
|
@ -398,6 +414,20 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
jump = jump->next;
|
||||
}
|
||||
|
||||
put_label = compiler->put_labels;
|
||||
while (put_label) {
|
||||
addr = put_label->label->addr;
|
||||
buf_ptr = (sljit_ins *)put_label->addr;
|
||||
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
SLJIT_ASSERT(((buf_ptr[0] & 0xc1cfffff) == 0x01000000) && ((buf_ptr[1] & 0xc1f83fff) == 0x80102000));
|
||||
buf_ptr[0] |= (addr >> 10) & 0x3fffff;
|
||||
buf_ptr[1] |= addr & 0x3ff;
|
||||
#else
|
||||
#error "Implementation required"
|
||||
#endif
|
||||
put_label = put_label->next;
|
||||
}
|
||||
|
||||
compiler->error = SLJIT_ERR_COMPILED;
|
||||
compiler->executable_offset = executable_offset;
|
||||
|
@ -1465,8 +1495,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||
{
|
||||
sljit_s32 reg;
|
||||
struct sljit_const *const_;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
|
||||
|
@ -1476,11 +1506,31 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
PTR_FAIL_IF(!const_);
|
||||
set_const(const_, compiler);
|
||||
|
||||
reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
|
||||
return const_;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
struct sljit_put_label *put_label;
|
||||
sljit_s32 dst_r;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
|
||||
PTR_FAIL_IF(!put_label);
|
||||
set_put_label(put_label, compiler, 0);
|
||||
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
|
||||
return put_label;
|
||||
}
|
||||
|
|
|
@ -38,8 +38,10 @@ static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, s
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset)
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_s32 type = jump->flags >> TYPE_SHIFT;
|
||||
|
||||
if (type == SLJIT_JUMP) {
|
||||
*code_ptr++ = JMP_i32;
|
||||
jump->addr++;
|
||||
|
|
|
@ -39,8 +39,10 @@ static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg,
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type)
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr)
|
||||
{
|
||||
sljit_s32 type = jump->flags >> TYPE_SHIFT;
|
||||
|
||||
int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && !(jump->flags & JUMP_LABEL) && (jump->u.target <= 0xffffffff);
|
||||
|
||||
/* The relative jump below specialized for this case. */
|
||||
|
@ -72,6 +74,56 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_
|
|||
return code_ptr;
|
||||
}
|
||||
|
||||
static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, sljit_u8 *code_ptr, sljit_uw max_label)
|
||||
{
|
||||
if (max_label > HALFWORD_MAX) {
|
||||
put_label->addr -= put_label->flags;
|
||||
put_label->flags = PATCH_MD;
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
if (put_label->flags == 0) {
|
||||
/* Destination is register. */
|
||||
code_ptr = (sljit_u8*)put_label->addr - 2 - sizeof(sljit_uw);
|
||||
|
||||
SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);
|
||||
SLJIT_ASSERT((code_ptr[1] & 0xf8) == MOV_r_i32);
|
||||
|
||||
if ((code_ptr[0] & 0x07) != 0) {
|
||||
code_ptr[0] = (sljit_u8)(code_ptr[0] & ~0x08);
|
||||
code_ptr += 2 + sizeof(sljit_s32);
|
||||
}
|
||||
else {
|
||||
code_ptr[0] = code_ptr[1];
|
||||
code_ptr += 1 + sizeof(sljit_s32);
|
||||
}
|
||||
|
||||
put_label->addr = (sljit_uw)code_ptr;
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
code_ptr -= put_label->flags + (2 + sizeof(sljit_uw));
|
||||
SLJIT_MEMCPY(code_ptr, code_ptr + (2 + sizeof(sljit_uw)), put_label->flags);
|
||||
|
||||
SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);
|
||||
|
||||
if ((code_ptr[1] & 0xf8) == MOV_r_i32) {
|
||||
code_ptr += 2 + sizeof(sljit_uw);
|
||||
SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(code_ptr[1] == MOV_rm_r);
|
||||
|
||||
code_ptr[0] = (sljit_u8)(code_ptr[0] & ~0x4);
|
||||
code_ptr[1] = MOV_rm_i32;
|
||||
code_ptr[2] = (sljit_u8)(code_ptr[2] & ~(0x7 << 3));
|
||||
|
||||
code_ptr = (sljit_u8*)(put_label->addr - (2 + sizeof(sljit_uw)) + sizeof(sljit_s32));
|
||||
put_label->addr = (sljit_uw)code_ptr;
|
||||
put_label->flags = 0;
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
||||
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
||||
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
||||
|
|
|
@ -428,13 +428,15 @@ static sljit_u8 get_jump_code(sljit_s32 type)
|
|||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset);
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset);
|
||||
#else
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type);
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr);
|
||||
static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, sljit_u8 *code_ptr, sljit_uw max_label);
|
||||
#endif
|
||||
|
||||
static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_s32 type, sljit_sw executable_offset)
|
||||
static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_s32 type = jump->flags >> TYPE_SHIFT;
|
||||
sljit_s32 short_jump;
|
||||
sljit_uw label_addr;
|
||||
|
||||
|
@ -447,7 +449,7 @@ static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code
|
|||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if ((sljit_sw)(label_addr - (jump->addr + 1)) > HALFWORD_MAX || (sljit_sw)(label_addr - (jump->addr + 1)) < HALFWORD_MIN)
|
||||
return generate_far_jump_code(jump, code_ptr, type);
|
||||
return generate_far_jump_code(jump, code_ptr);
|
||||
#endif
|
||||
|
||||
if (type == SLJIT_JUMP) {
|
||||
|
@ -497,6 +499,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
struct sljit_label *label;
|
||||
struct sljit_jump *jump;
|
||||
struct sljit_const *const_;
|
||||
struct sljit_put_label *put_label;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_generate_code(compiler));
|
||||
|
@ -511,6 +514,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
label = compiler->labels;
|
||||
jump = compiler->jumps;
|
||||
const_ = compiler->consts;
|
||||
put_label = compiler->put_labels;
|
||||
executable_offset = SLJIT_EXEC_OFFSET(code);
|
||||
|
||||
do {
|
||||
|
@ -525,27 +529,38 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
buf_ptr += len;
|
||||
}
|
||||
else {
|
||||
if (*buf_ptr >= 2) {
|
||||
switch (*buf_ptr) {
|
||||
case 0:
|
||||
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
|
||||
label->size = code_ptr - code;
|
||||
label = label->next;
|
||||
break;
|
||||
case 1:
|
||||
jump->addr = (sljit_uw)code_ptr;
|
||||
if (!(jump->flags & SLJIT_REWRITABLE_JUMP))
|
||||
code_ptr = generate_near_jump_code(jump, code_ptr, code, *buf_ptr - 2, executable_offset);
|
||||
code_ptr = generate_near_jump_code(jump, code_ptr, code, executable_offset);
|
||||
else {
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 2, executable_offset);
|
||||
code_ptr = generate_far_jump_code(jump, code_ptr, executable_offset);
|
||||
#else
|
||||
code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 2);
|
||||
code_ptr = generate_far_jump_code(jump, code_ptr);
|
||||
#endif
|
||||
}
|
||||
jump = jump->next;
|
||||
}
|
||||
else if (*buf_ptr == 0) {
|
||||
label->addr = ((sljit_uw)code_ptr) + executable_offset;
|
||||
label->size = code_ptr - code;
|
||||
label = label->next;
|
||||
}
|
||||
else { /* *buf_ptr is 1 */
|
||||
break;
|
||||
case 2:
|
||||
const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw);
|
||||
const_ = const_->next;
|
||||
break;
|
||||
default:
|
||||
SLJIT_ASSERT(*buf_ptr == 3);
|
||||
SLJIT_ASSERT(put_label->label);
|
||||
put_label->addr = (sljit_uw)code_ptr;
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
code_ptr = generate_put_label_code(put_label, code_ptr, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
|
||||
#endif
|
||||
put_label = put_label->next;
|
||||
break;
|
||||
}
|
||||
buf_ptr++;
|
||||
}
|
||||
|
@ -557,6 +572,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
SLJIT_ASSERT(!label);
|
||||
SLJIT_ASSERT(!jump);
|
||||
SLJIT_ASSERT(!const_);
|
||||
SLJIT_ASSERT(!put_label);
|
||||
SLJIT_ASSERT(code_ptr <= code + compiler->size);
|
||||
|
||||
jump = compiler->jumps;
|
||||
while (jump) {
|
||||
|
@ -591,8 +608,24 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
jump = jump->next;
|
||||
}
|
||||
|
||||
/* Some space may be wasted because of short jumps. */
|
||||
SLJIT_ASSERT(code_ptr <= code + compiler->size);
|
||||
put_label = compiler->put_labels;
|
||||
while (put_label) {
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
sljit_unaligned_store_sw((void*)put_label->addr - sizeof(sljit_sw), (sljit_sw)put_label->label->addr);
|
||||
#else
|
||||
if (put_label->flags & PATCH_MD) {
|
||||
SLJIT_ASSERT(put_label->label->addr > HALFWORD_MAX);
|
||||
sljit_unaligned_store_sw((void*)put_label->addr - sizeof(sljit_sw), (sljit_sw)put_label->label->addr);
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(put_label->label->addr <= HALFWORD_MAX);
|
||||
sljit_unaligned_store_s32((void*)put_label->addr - sizeof(sljit_s32), (sljit_s32)put_label->label->addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
put_label = put_label->next;
|
||||
}
|
||||
|
||||
compiler->error = SLJIT_ERR_COMPILED;
|
||||
compiler->executable_offset = executable_offset;
|
||||
compiler->executable_size = code_ptr - code;
|
||||
|
@ -2481,8 +2514,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
PTR_FAIL_IF_NULL(jump);
|
||||
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
||||
type &= 0xff;
|
||||
set_jump(jump, compiler, (type & SLJIT_REWRITABLE_JUMP) | ((type & 0xff) << TYPE_SHIFT));
|
||||
|
||||
/* Worst case size. */
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
|
@ -2495,7 +2527,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
PTR_FAIL_IF_NULL(inst);
|
||||
|
||||
*inst++ = 0;
|
||||
*inst++ = type + 2;
|
||||
*inst++ = 1;
|
||||
return jump;
|
||||
}
|
||||
|
||||
|
@ -2513,7 +2545,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
|
|||
if (src == SLJIT_IMM) {
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
FAIL_IF_NULL(jump);
|
||||
set_jump(jump, compiler, JUMP_ADDR);
|
||||
set_jump(jump, compiler, JUMP_ADDR | (type << TYPE_SHIFT));
|
||||
jump->u.target = srcw;
|
||||
|
||||
/* Worst case size. */
|
||||
|
@ -2527,7 +2559,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
|
|||
FAIL_IF_NULL(inst);
|
||||
|
||||
*inst++ = 0;
|
||||
*inst++ = type + 2;
|
||||
*inst++ = 1;
|
||||
}
|
||||
else {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
|
@ -2831,7 +2863,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
PTR_FAIL_IF(!inst);
|
||||
|
||||
*inst++ = 0;
|
||||
*inst++ = 1;
|
||||
*inst++ = 2;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (dst & SLJIT_MEM)
|
||||
|
@ -2842,6 +2874,54 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
return const_;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
||||
{
|
||||
struct sljit_put_label *put_label;
|
||||
sljit_u8 *inst;
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
sljit_s32 reg;
|
||||
sljit_uw start_size;
|
||||
#endif
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
|
||||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
|
||||
CHECK_EXTRA_REGS(dst, dstw, (void)0);
|
||||
|
||||
put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
|
||||
PTR_FAIL_IF(!put_label);
|
||||
set_put_label(put_label, compiler, 0);
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
compiler->mode32 = 0;
|
||||
reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
|
||||
|
||||
if (emit_load_imm64(compiler, reg, 0))
|
||||
return NULL;
|
||||
#else
|
||||
if (emit_mov(compiler, dst, dstw, SLJIT_IMM, 0))
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
if (dst & SLJIT_MEM) {
|
||||
start_size = compiler->size;
|
||||
if (emit_mov(compiler, dst, dstw, TMP_REG1, 0))
|
||||
return NULL;
|
||||
put_label->flags = compiler->size - start_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 2);
|
||||
PTR_FAIL_IF(!inst);
|
||||
|
||||
*inst++ = 0;
|
||||
*inst++ = 3;
|
||||
|
||||
return put_label;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(executable_offset);
|
||||
|
|
Loading…
Reference in New Issue