[Pcre-svn] [1136] code/trunk/src/sljit: JIT compiler update.

Top Page
Delete this message
Author: Subversion repository
Date:  
To: pcre-svn
Subject: [Pcre-svn] [1136] code/trunk/src/sljit: JIT compiler update.
Revision: 1136
          http://www.exim.org/viewvc/pcre2?view=rev&revision=1136
Author:   zherczeg
Date:     2019-07-17 08:05:48 +0100 (Wed, 17 Jul 2019)
Log Message:
-----------
JIT compiler update.


Modified Paths:
--------------
    code/trunk/src/sljit/sljitLir.c
    code/trunk/src/sljit/sljitLir.h
    code/trunk/src/sljit/sljitNativeARM_32.c
    code/trunk/src/sljit/sljitNativeARM_64.c
    code/trunk/src/sljit/sljitNativeARM_T2_32.c
    code/trunk/src/sljit/sljitNativeMIPS_32.c
    code/trunk/src/sljit/sljitNativeMIPS_common.c
    code/trunk/src/sljit/sljitNativePPC_32.c
    code/trunk/src/sljit/sljitNativePPC_64.c
    code/trunk/src/sljit/sljitNativePPC_common.c
    code/trunk/src/sljit/sljitNativeSPARC_32.c
    code/trunk/src/sljit/sljitNativeSPARC_common.c
    code/trunk/src/sljit/sljitNativeX86_32.c
    code/trunk/src/sljit/sljitNativeX86_64.c
    code/trunk/src/sljit/sljitNativeX86_common.c


Modified: code/trunk/src/sljit/sljitLir.c
===================================================================
--- code/trunk/src/sljit/sljitLir.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitLir.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -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_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 @@
     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 @@
     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 @@
     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 @@
     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_UNREACHABLE();
 }


-#endif
+#endif /* !SLJIT_CONFIG_UNSUPPORTED */

Modified: code/trunk/src/sljit/sljitLir.h
===================================================================
--- code/trunk/src/sljit/sljitLir.h    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitLir.h    2019-07-17 07:05:48 UTC (rev 1136)
@@ -348,13 +348,20 @@
 struct sljit_jump {
     struct sljit_jump *next;
     sljit_uw addr;
-    sljit_sw flags;
+    sljit_uw flags;
     union {
         sljit_uw target;
-        struct sljit_label* label;
+        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_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 @@
    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. */


Modified: code/trunk/src/sljit/sljitNativeARM_32.c
===================================================================
--- code/trunk/src/sljit/sljitNativeARM_32.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitNativeARM_32.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -583,8 +583,9 @@
     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 @@
     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 @@


     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,35 +673,45 @@
             else if ((*buf_ptr & 0xff000000) != PUSH_POOL) {
 #endif
                 *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. */
-                SLJIT_ASSERT(!label || label->size >= word_count);
-                SLJIT_ASSERT(!jump || jump->addr >= word_count);
-                SLJIT_ASSERT(!const_ || const_->addr >= word_count);
-                if (jump && jump->addr == word_count) {
+                    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))
-                        code_ptr--;
-                    jump->addr = (sljit_uw)code_ptr;
+                        if (detect_jump_type(jump, code_ptr, code, executable_offset))
+                            code_ptr--;
+                        jump->addr = (sljit_uw)code_ptr;
 #else
-                    jump->addr = (sljit_uw)(code_ptr - 2);
-                    if (detect_jump_type(jump, code_ptr, code, executable_offset))
-                        code_ptr -= 2;
+                        jump->addr = (sljit_uw)(code_ptr - 2);
+                        if (detect_jump_type(jump, code_ptr, code, executable_offset))
+                            code_ptr -= 2;
 #endif
-                    jump = jump->next;
-                }
-                if (label && label->size == word_count) {
-                    /* code_ptr can be affected above. */
-                    label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset);
-                    label->size = (code_ptr + 1) - code;
-                    label = label->next;
-                }
-                if (const_ && const_->addr == word_count) {
+                        jump = jump->next;
+                    }
+                    if (label && label->size == word_count) {
+                        /* code_ptr can be affected above. */
+                        label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset);
+                        label->size = (code_ptr + 1) - code;
+                        label = label->next;
+                    }
+                    if (const_ && const_->addr == word_count) {
 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
-                    const_->addr = (sljit_uw)code_ptr;
+                        const_->addr = (sljit_uw)code_ptr;
 #else
-                    const_->addr = (sljit_uw)(code_ptr - 1);
+                        const_->addr = (sljit_uw)(code_ptr - 1);
 #endif
-                    const_ = const_->next;
+                        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_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 @@
         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 @@
     }
 #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,28 +2670,55 @@
 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);


+    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), init_value));
+    compiler->patches++;
+#else
+    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);


-    reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+    if (dst & SLJIT_MEM)
+        PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
+    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, 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), 0));
     compiler->patches++;
 #else
-    PTR_FAIL_IF(emit_imm(compiler, reg, init_value));
+    PTR_FAIL_IF(emit_imm(compiler, dst_r, 0));
 #endif
-    set_const(const_, compiler);


+    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 const_;
+    return put_label;
 }


SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)

Modified: code/trunk/src/sljit/sljitNativeARM_64.c
===================================================================
--- code/trunk/src/sljit/sljitNativeARM_64.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitNativeARM_64.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -161,7 +161,7 @@
     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,7 +196,7 @@
         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];
@@ -203,7 +203,7 @@
         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 @@
     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_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 @@
     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,11 +259,13 @@


     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;
@@ -252,24 +272,35 @@
         buf_end = buf_ptr + (buf->used_size >> 2);
         do {
             *code_ptr = *buf_ptr++;
-            /* These structures are ordered by their address. */
-            SLJIT_ASSERT(!label || label->size >= word_count);
-            SLJIT_ASSERT(!jump || jump->addr >= word_count);
-            SLJIT_ASSERT(!const_ || const_->addr >= word_count);
-            if (label && label->size == word_count) {
-                label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
-                label->size = code_ptr - code;
-                label = label->next;
+            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;
+                    label = label->next;
+                }
+                if (jump && jump->addr == word_count) {
+                        jump->addr = (sljit_uw)(code_ptr - 4);
+                        code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
+                        jump = jump->next;
+                }
+                if (const_ && const_->addr == word_count) {
+                    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);
             }
-            if (jump && jump->addr == word_count) {
-                    jump->addr = (sljit_uw)(code_ptr - 4);
-                    code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
-                    jump = jump->next;
-            }
-            if (const_ && const_->addr == word_count) {
-                const_->addr = (sljit_uw)code_ptr;
-                const_ = const_->next;
-            }
             code_ptr ++;
             word_count ++;
         } while (buf_ptr < buf_end);
@@ -286,6 +317,7 @@
     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 @@
         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 @@
     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;


Modified: code/trunk/src/sljit/sljitNativeARM_T2_32.c
===================================================================
--- code/trunk/src/sljit/sljitNativeARM_T2_32.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitNativeARM_T2_32.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -365,11 +365,13 @@
     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,11 +383,13 @@


     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;
@@ -392,24 +396,34 @@
         buf_end = buf_ptr + (buf->used_size >> 1);
         do {
             *code_ptr = *buf_ptr++;
-            /* These structures are ordered by their address. */
-            SLJIT_ASSERT(!label || label->size >= half_count);
-            SLJIT_ASSERT(!jump || jump->addr >= half_count);
-            SLJIT_ASSERT(!const_ || const_->addr >= half_count);
-            if (label && label->size == half_count) {
-                label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
-                label->size = code_ptr - code;
-                label = label->next;
+            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;
+                    label = label->next;
+                }
+                if (jump && jump->addr == half_count) {
+                        jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8);
+                        code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
+                        jump = jump->next;
+                }
+                if (const_ && const_->addr == half_count) {
+                    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);
             }
-            if (jump && jump->addr == half_count) {
-                    jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8);
-                    code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
-                    jump = jump->next;
-            }
-            if (const_ && const_->addr == half_count) {
-                const_->addr = (sljit_uw)code_ptr;
-                const_ = const_->next;
-            }
             code_ptr ++;
             half_count ++;
         } while (buf_ptr < buf_end);
@@ -426,6 +440,7 @@
     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 @@
         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 @@
     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;


Modified: code/trunk/src/sljit/sljitNativeMIPS_32.c
===================================================================
--- code/trunk/src/sljit/sljitNativeMIPS_32.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitNativeMIPS_32.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -425,6 +425,7 @@
 {
     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_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);


Modified: code/trunk/src/sljit/sljitNativeMIPS_common.c
===================================================================
--- code/trunk/src/sljit/sljitNativeMIPS_common.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitNativeMIPS_common.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -449,6 +449,55 @@
 }
 #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,6 +506,7 @@
     sljit_ins *buf_ptr;
     sljit_ins *buf_end;
     sljit_uw word_count;
+    sljit_uw next_addr;
     sljit_sw executable_offset;
     sljit_uw addr;


@@ -463,6 +513,7 @@
     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,11 +525,13 @@


     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;
@@ -485,29 +538,42 @@
         buf_end = buf_ptr + (buf->used_size >> 2);
         do {
             *code_ptr = *buf_ptr++;
-            SLJIT_ASSERT(!label || label->size >= word_count);
-            SLJIT_ASSERT(!jump || jump->addr >= word_count);
-            SLJIT_ASSERT(!const_ || const_->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;
-                label = label->next;
-            }
-            if (jump && jump->addr == word_count) {
+            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;
+                    label = label->next;
+                }
+                if (jump && jump->addr == word_count) {
 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-                jump->addr = (sljit_uw)(code_ptr - 3);
+                    jump->addr = (sljit_uw)(code_ptr - 3);
 #else
-                jump->addr = (sljit_uw)(code_ptr - 7);
+                    jump->addr = (sljit_uw)(code_ptr - 7);
 #endif
-                code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
-                jump = jump->next;
+                    code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
+                    jump = jump->next;
+                }
+                if (const_ && const_->addr == word_count) {
+                    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);
             }
-            if (const_ && const_->addr == word_count) {
-                /* Just recording the address. */
-                const_->addr = (sljit_uw)code_ptr;
-                const_ = const_->next;
-            }
             code_ptr ++;
             word_count ++;
         } while (buf_ptr < buf_end);
@@ -524,6 +590,7 @@
     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 @@
         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 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 @@
     PTR_FAIL_IF(!const_);
     set_const(const_, compiler);


-    reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
+    dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+    PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));


-    PTR_FAIL_IF(emit_const(compiler, reg, 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;
+}


Modified: code/trunk/src/sljit/sljitNativePPC_32.c
===================================================================
--- code/trunk/src/sljit/sljitNativePPC_32.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitNativePPC_32.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -259,6 +259,7 @@
 {
     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_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);


Modified: code/trunk/src/sljit/sljitNativePPC_64.c
===================================================================
--- code/trunk/src/sljit/sljitNativePPC_64.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitNativePPC_64.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -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))



Modified: code/trunk/src/sljit/sljitNativePPC_common.c
===================================================================
--- code/trunk/src/sljit/sljitNativePPC_common.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitNativePPC_common.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -231,6 +231,9 @@
 #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 @@
     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,6 +384,7 @@
     sljit_ins *buf_ptr;
     sljit_ins *buf_end;
     sljit_uw word_count;
+    sljit_uw next_addr;
     sljit_sw executable_offset;
     sljit_uw addr;


@@ -338,6 +391,7 @@
     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,11 +410,13 @@


     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;
@@ -367,61 +423,75 @@
         buf_end = buf_ptr + (buf->used_size >> 2);
         do {
             *code_ptr = *buf_ptr++;
-            SLJIT_ASSERT(!label || label->size >= word_count);
-            SLJIT_ASSERT(!jump || jump->addr >= word_count);
-            SLJIT_ASSERT(!const_ || const_->addr >= word_count);
-            /* These structures are ordered by their address. */
-            if (label && label->size == word_count) {
-                /* Just recording the address. */
-                label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
-                label->size = code_ptr - code;
-                label = label->next;
-            }
-            if (jump && jump->addr == word_count) {
+            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. */
+                    label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+                    label->size = code_ptr - code;
+                    label = label->next;
+                }
+                if (jump && jump->addr == word_count) {
 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
-                jump->addr = (sljit_uw)(code_ptr - 3);
+                    jump->addr = (sljit_uw)(code_ptr - 3);
 #else
-                jump->addr = (sljit_uw)(code_ptr - 6);
+                    jump->addr = (sljit_uw)(code_ptr - 6);
 #endif
-                if (detect_jump_type(jump, code_ptr, code, executable_offset)) {
+                    if (detect_jump_type(jump, code_ptr, code, executable_offset)) {
 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
-                    code_ptr[-3] = code_ptr[0];
-                    code_ptr -= 3;
+                        code_ptr[-3] = code_ptr[0];
+                        code_ptr -= 3;
 #else
-                    if (jump->flags & PATCH_ABS32) {
-                        code_ptr -= 3;
-                        code_ptr[-1] = code_ptr[2];
-                        code_ptr[0] = code_ptr[3];
-                    }
-                    else if (jump->flags & PATCH_ABS48) {
-                        code_ptr--;
-                        code_ptr[-1] = code_ptr[0];
-                        code_ptr[0] = code_ptr[1];
-                        /* rldicr rX,rX,32,31 -> rX,rX,16,47 */
-                        SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);
-                        code_ptr[-3] ^= 0x8422;
-                        /* oris -> ori */
-                        code_ptr[-2] ^= 0x4000000;
-                    }
-                    else {
-                        code_ptr[-6] = code_ptr[0];
-                        code_ptr -= 6;
-                    }
+                        if (jump->flags & PATCH_ABS32) {
+                            code_ptr -= 3;
+                            code_ptr[-1] = code_ptr[2];
+                            code_ptr[0] = code_ptr[3];
+                        }
+                        else if (jump->flags & PATCH_ABS48) {
+                            code_ptr--;
+                            code_ptr[-1] = code_ptr[0];
+                            code_ptr[0] = code_ptr[1];
+                            /* rldicr rX,rX,32,31 -> rX,rX,16,47 */
+                            SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);
+                            code_ptr[-3] ^= 0x8422;
+                            /* oris -> ori */
+                            code_ptr[-2] ^= 0x4000000;
+                        }
+                        else {
+                            code_ptr[-6] = code_ptr[0];
+                            code_ptr -= 6;
+                        }
 #endif
-                    if (jump->flags & REMOVE_COND) {
-                        code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
-                        code_ptr++;
-                        jump->addr += sizeof(sljit_ins);
-                        code_ptr[0] = Bx;
-                        jump->flags -= IS_COND;
+                        if (jump->flags & REMOVE_COND) {
+                            code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
+                            code_ptr++;
+                            jump->addr += sizeof(sljit_ins);
+                            code_ptr[0] = Bx;
+                            jump->flags -= IS_COND;
+                        }
                     }
+                    jump = jump->next;
                 }
-                jump = jump->next;
+                if (const_ && const_->addr == word_count) {
+                    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);
             }
-            if (const_ && const_->addr == word_count) {
-                const_->addr = (sljit_uw)code_ptr;
-                const_ = const_->next;
-            }
             code_ptr ++;
             word_count ++;
         } while (buf_ptr < buf_end);
@@ -438,6 +508,8 @@
     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 @@
         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 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 @@
     PTR_FAIL_IF(!const_);
     set_const(const_, compiler);


-    reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
+    dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+    PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));


-    PTR_FAIL_IF(emit_const(compiler, reg, 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;
+}


Modified: code/trunk/src/sljit/sljitNativeSPARC_32.c
===================================================================
--- code/trunk/src/sljit/sljitNativeSPARC_32.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitNativeSPARC_32.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -267,6 +267,7 @@
 {
     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_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);


Modified: code/trunk/src/sljit/sljitNativeSPARC_common.c
===================================================================
--- code/trunk/src/sljit/sljitNativeSPARC_common.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitNativeSPARC_common.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -298,6 +298,7 @@
     sljit_ins *buf_ptr;
     sljit_ins *buf_end;
     sljit_uw word_count;
+    sljit_uw next_addr;
     sljit_sw executable_offset;
     sljit_uw addr;


@@ -304,6 +305,7 @@
     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,11 +317,13 @@


     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;
@@ -326,30 +330,40 @@
         buf_end = buf_ptr + (buf->used_size >> 2);
         do {
             *code_ptr = *buf_ptr++;
-            SLJIT_ASSERT(!label || label->size >= word_count);
-            SLJIT_ASSERT(!jump || jump->addr >= word_count);
-            SLJIT_ASSERT(!const_ || const_->addr >= word_count);
-            /* These structures are ordered by their address. */
-            if (label && label->size == word_count) {
-                /* Just recording the address. */
-                label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
-                label->size = code_ptr - code;
-                label = label->next;
-            }
-            if (jump && jump->addr == word_count) {
+            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. */
+                    label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+                    label->size = code_ptr - code;
+                    label = label->next;
+                }
+                if (jump && jump->addr == word_count) {
 #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
-                jump->addr = (sljit_uw)(code_ptr - 3);
+                    jump->addr = (sljit_uw)(code_ptr - 3);
 #else
-                jump->addr = (sljit_uw)(code_ptr - 6);
+                    jump->addr = (sljit_uw)(code_ptr - 6);
 #endif
-                code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
-                jump = jump->next;
+                    code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
+                    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;
+                    put_label = put_label->next;
+                }
+                next_addr = compute_next_addr(label, jump, const_, put_label);
             }
-            if (const_ && const_->addr == word_count) {
-                /* Just recording the address. */
-                const_->addr = (sljit_uw)code_ptr;
-                const_ = const_->next;
-            }
             code_ptr ++;
             word_count ++;
         } while (buf_ptr < buf_end);
@@ -366,6 +380,7 @@
     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 @@


             /* 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,7 +414,21 @@
         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;
     compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
@@ -1465,8 +1495,8 @@


 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 @@
     PTR_FAIL_IF(!const_);
     set_const(const_, compiler);


-    reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
+    dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+    PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));


-    PTR_FAIL_IF(emit_const(compiler, reg, 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;
+}


Modified: code/trunk/src/sljit/sljitNativeX86_32.c
===================================================================
--- code/trunk/src/sljit/sljitNativeX86_32.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitNativeX86_32.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -38,8 +38,10 @@
     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++;


Modified: code/trunk/src/sljit/sljitNativeX86_64.c
===================================================================
--- code/trunk/src/sljit/sljitNativeX86_64.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitNativeX86_64.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -39,8 +39,10 @@
     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 @@
     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)


Modified: code/trunk/src/sljit/sljitNativeX86_common.c
===================================================================
--- code/trunk/src/sljit/sljitNativeX86_common.c    2019-07-16 16:16:45 UTC (rev 1135)
+++ code/trunk/src/sljit/sljitNativeX86_common.c    2019-07-17 07:05:48 UTC (rev 1136)
@@ -428,13 +428,15 @@
 }


#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 @@

 #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 @@
     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 @@
     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 @@
                 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_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 @@
         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 @@


     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 @@
     PTR_FAIL_IF_NULL(inst);


     *inst++ = 0;
-    *inst++ = type + 2;
+    *inst++ = 1;
     return jump;
 }


@@ -2513,7 +2545,7 @@
     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 @@
         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 @@
     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 @@
     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);