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

トップ ページ
このメッセージを削除
著者: Subversion repository
日付:  
To: pcre-svn
題目: [Pcre-svn] [276] code/trunk/src/sljit: JIT compiler update
Revision: 276
          http://www.exim.org/viewvc/pcre2?view=rev&revision=276
Author:   zherczeg
Date:     2015-05-29 13:52:59 +0100 (Fri, 29 May 2015)
Log Message:
-----------
JIT compiler update


Modified Paths:
--------------
    code/trunk/src/sljit/sljitConfig.h
    code/trunk/src/sljit/sljitConfigInternal.h
    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_common.c
    code/trunk/src/sljit/sljitNativePPC_common.c
    code/trunk/src/sljit/sljitNativeSPARC_common.c
    code/trunk/src/sljit/sljitNativeX86_common.c


Modified: code/trunk/src/sljit/sljitConfig.h
===================================================================
--- code/trunk/src/sljit/sljitConfig.h    2015-05-28 16:48:42 UTC (rev 275)
+++ code/trunk/src/sljit/sljitConfig.h    2015-05-29 12:52:59 UTC (rev 276)
@@ -96,6 +96,15 @@
 #define SLJIT_EXECUTABLE_ALLOCATOR 1
 #endif


+/* Force cdecl calling convention even if a better calling
+ convention (e.g. fastcall) is supported by the C compiler.
+ If this option is enabled, C functions without
+ SLJIT_CALL can also be called from JIT code. */
+#ifndef SLJIT_USE_CDECL_CALLING_CONVENTION
+/* Disabled by default */
+#define SLJIT_USE_CDECL_CALLING_CONVENTION 0
+#endif
+
/* Return with error when an invalid argument is passed. */
#ifndef SLJIT_ARGUMENT_CHECKS
/* Disabled by default */

Modified: code/trunk/src/sljit/sljitConfigInternal.h
===================================================================
--- code/trunk/src/sljit/sljitConfigInternal.h    2015-05-28 16:48:42 UTC (rev 275)
+++ code/trunk/src/sljit/sljitConfigInternal.h    2015-05-29 12:52:59 UTC (rev 276)
@@ -468,8 +468,13 @@


#ifndef SLJIT_CALL

-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION)

+/* Force cdecl. */
+#define SLJIT_CALL
+
+#elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+
#if defined(__GNUC__) && !defined(__APPLE__)

#define SLJIT_CALL __attribute__ ((fastcall))

Modified: code/trunk/src/sljit/sljitLir.c
===================================================================
--- code/trunk/src/sljit/sljitLir.c    2015-05-28 16:48:42 UTC (rev 275)
+++ code/trunk/src/sljit/sljitLir.c    2015-05-29 12:52:59 UTC (rev 276)
@@ -845,8 +845,8 @@
     }


 static SLJIT_CONST char* op0_names[] = {
-    (char*)"breakpoint", (char*)"nop",
-    (char*)"lumul", (char*)"lsmul", (char*)"ludiv", (char*)"lsdiv",
+    (char*)"breakpoint", (char*)"nop", (char*)"lumul", (char*)"lsmul",
+    (char*)"udivmod", (char*)"sdivmod", (char*)"udivi", (char*)"sdivi"
 };


 static SLJIT_CONST char* op1_names[] = {
@@ -1036,7 +1036,7 @@
 {
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
     CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LSMUL)
-        || ((op & ~SLJIT_INT_OP) >= SLJIT_LUDIV && (op & ~SLJIT_INT_OP) <= SLJIT_LSDIV));
+        || ((op & ~SLJIT_INT_OP) >= SLJIT_UDIVMOD && (op & ~SLJIT_INT_OP) <= SLJIT_SDIVI));
     CHECK_ARGUMENT(op < SLJIT_LUMUL || compiler->scratches >= 2);
 #endif
 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
@@ -1447,6 +1447,8 @@


 static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset)
 {
+    SLJIT_UNUSED_ARG(offset);
+
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
     FUNCTION_CHECK_DST(dst, dstw);
 #endif
@@ -1462,6 +1464,8 @@


 static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
 {
+    SLJIT_UNUSED_ARG(init_value);
+
 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
     FUNCTION_CHECK_DST(dst, dstw);
 #endif


Modified: code/trunk/src/sljit/sljitLir.h
===================================================================
--- code/trunk/src/sljit/sljitLir.h    2015-05-28 16:48:42 UTC (rev 275)
+++ code/trunk/src/sljit/sljitLir.h    2015-05-29 12:52:59 UTC (rev 276)
@@ -687,7 +687,7 @@
 #define SLJIT_OP0_BASE            0


 /* Flags: - (never set any flags)
-   Note: breakpoint instruction is not supported by all architectures (namely ppc)
+   Note: breakpoint instruction is not supported by all architectures (e.g. ppc)
          It falls back to SLJIT_NOP in those cases. */
 #define SLJIT_BREAKPOINT        (SLJIT_OP0_BASE + 0)
 /* Flags: - (never set any flags)
@@ -696,24 +696,42 @@
 #define SLJIT_NOP            (SLJIT_OP0_BASE + 1)
 /* Flags: - (may destroy flags)
    Unsigned multiplication of SLJIT_R0 and SLJIT_R1.
-   Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */
+   Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */
 #define SLJIT_LUMUL            (SLJIT_OP0_BASE + 2)
 /* Flags: - (may destroy flags)
    Signed multiplication of SLJIT_R0 and SLJIT_R1.
-   Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */
+   Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */
 #define SLJIT_LSMUL            (SLJIT_OP0_BASE + 3)
 /* Flags: I - (may destroy flags)
    Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
-   The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1.
-   Note: if SLJIT_R1 contains 0, the behaviour is undefined. */
-#define SLJIT_LUDIV            (SLJIT_OP0_BASE + 4)
-#define SLJIT_ILUDIV            (SLJIT_LUDIV | SLJIT_INT_OP)
+   The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.
+   Note: if SLJIT_R1 is 0, the behaviour is undefined. */
+#define SLJIT_UDIVMOD            (SLJIT_OP0_BASE + 4)
+#define SLJIT_IUDIVMOD            (SLJIT_UDIVMOD | SLJIT_INT_OP)
 /* Flags: I - (may destroy flags)
    Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
-   The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1.
-   Note: if SLJIT_R1 contains 0, the behaviour is undefined. */
-#define SLJIT_LSDIV            (SLJIT_OP0_BASE + 5)
-#define SLJIT_ILSDIV            (SLJIT_LSDIV | SLJIT_INT_OP)
+   The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.
+   Note: if SLJIT_R1 is 0, the behaviour is undefined.
+   Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00),
+         the behaviour is undefined. */
+#define SLJIT_SDIVMOD            (SLJIT_OP0_BASE + 5)
+#define SLJIT_ISDIVMOD            (SLJIT_SDIVMOD | SLJIT_INT_OP)
+/* Flags: I - (may destroy flags)
+   Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
+   The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.
+   Note: if SLJIT_R1 is 0, the behaviour is undefined.
+   Note: SLJIT_SDIV is single precision divide. */
+#define SLJIT_UDIVI            (SLJIT_OP0_BASE + 6)
+#define SLJIT_IUDIVI            (SLJIT_UDIVI | SLJIT_INT_OP)
+/* Flags: I - (may destroy flags)
+   Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
+   The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.
+   Note: if SLJIT_R1 is 0, the behaviour is undefined.
+   Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00),
+         the behaviour is undefined.
+   Note: SLJIT_SDIV is single precision divide. */
+#define SLJIT_SDIVI            (SLJIT_OP0_BASE + 7)
+#define SLJIT_ISDIVI            (SLJIT_SDIVI | SLJIT_INT_OP)


SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op);


Modified: code/trunk/src/sljit/sljitNativeARM_32.c
===================================================================
--- code/trunk/src/sljit/sljitNativeARM_32.c    2015-05-28 16:48:42 UTC (rev 275)
+++ code/trunk/src/sljit/sljitNativeARM_32.c    2015-05-29 12:52:59 UTC (rev 276)
@@ -1833,18 +1833,33 @@
             | (reg_map[SLJIT_R0] << 8)
             | reg_map[TMP_REG1]);
 #endif
-    case SLJIT_LUDIV:
-    case SLJIT_LSDIV:
-        if (compiler->scratches >= 3)
+    case SLJIT_UDIVMOD:
+    case SLJIT_SDIVMOD:
+    case SLJIT_UDIVI:
+    case SLJIT_SDIVI:
+        SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
+        SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2, bad_register_mapping);
+
+        if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) {
             FAIL_IF(push_inst(compiler, 0xe52d2008 /* str r2, [sp, #-8]! */));
+            FAIL_IF(push_inst(compiler, 0xe58d1004 /* str r1, [sp, #4] */));
+        }
+        else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3))
+            FAIL_IF(push_inst(compiler, 0xe52d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* str r1/r2, [sp, #-8]! */));
+
 #if defined(__GNUC__)
         FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
-            (op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
+            ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
 #else
 #error "Software divmod functions are needed"
 #endif
-        if (compiler->scratches >= 3)
-            return push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */);
+
+        if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) {
+            FAIL_IF(push_inst(compiler, 0xe59d1004 /* ldr r1, [sp, #4] */));
+            FAIL_IF(push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */));
+        }
+        else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3))
+            return push_inst(compiler, 0xe49d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* ldr r1/r2, [sp], #8 */);
         return SLJIT_SUCCESS;
     }



Modified: code/trunk/src/sljit/sljitNativeARM_64.c
===================================================================
--- code/trunk/src/sljit/sljitNativeARM_64.c    2015-05-28 16:48:42 UTC (rev 275)
+++ code/trunk/src/sljit/sljitNativeARM_64.c    2015-05-29 12:52:59 UTC (rev 276)
@@ -1087,7 +1087,8 @@
             saved_regs_size += sizeof(sljit_sw);
         }
         local_size -= saved_regs_size + SLJIT_LOCALS_OFFSET;
-        FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10)));
+        if (saved_regs_size > 0)
+            FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10)));
     }


     tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
@@ -1094,7 +1095,12 @@
     prev = -1;
     for (i = SLJIT_S0; i >= tmp; i--) {
         if (prev == -1) {
-            prev = i;
+            if (!(offs & (1 << 15))) {
+                prev = i;
+                continue;
+            }
+            FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
+            offs += 1 << 15;
             continue;
         }
         FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
@@ -1104,7 +1110,12 @@


     for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
         if (prev == -1) {
-            prev = i;
+            if (!(offs & (1 << 15))) {
+                prev = i;
+                continue;
+            }
+            FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
+            offs += 1 << 15;
             continue;
         }
         FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
@@ -1112,8 +1123,7 @@
         prev = -1;
     }


-    if (prev != -1)
-        FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(TMP_SP) | (offs >> 5)));
+    SLJIT_ASSERT(prev == -1);


     if (compiler->local_size > (63 * sizeof(sljit_sw))) {
         /* The local_size is already adjusted by the saved registers. */
@@ -1188,7 +1198,12 @@
     prev = -1;
     for (i = SLJIT_S0; i >= tmp; i--) {
         if (prev == -1) {
-            prev = i;
+            if (!(offs & (1 << 15))) {
+                prev = i;
+                continue;
+            }
+            FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
+            offs += 1 << 15;
             continue;
         }
         FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
@@ -1198,7 +1213,12 @@


     for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
         if (prev == -1) {
-            prev = i;
+            if (!(offs & (1 << 15))) {
+                prev = i;
+                continue;
+            }
+            FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
+            offs += 1 << 15;
             continue;
         }
         FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
@@ -1206,13 +1226,12 @@
         prev = -1;
     }


-    if (prev != -1)
-        FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(TMP_SP) | (offs >> 5)));
+    SLJIT_ASSERT(prev == -1);


     if (compiler->local_size <= (63 * sizeof(sljit_sw))) {
         FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR)
             | RN(TMP_SP) | (((local_size >> 3) & 0x7f) << 15)));
-    } else {
+    } else if (saved_regs_size > 0) {
         FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10)));
     }


@@ -1242,12 +1261,15 @@
         FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0)));
         FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO)));
         return push_inst(compiler, (op == SLJIT_LUMUL ? UMULH : SMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1));
-    case SLJIT_LUDIV:
-    case SLJIT_LSDIV:
+    case SLJIT_UDIVMOD:
+    case SLJIT_SDIVMOD:
         FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0)));
-        FAIL_IF(push_inst(compiler, ((op == SLJIT_LUDIV ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)));
+        FAIL_IF(push_inst(compiler, ((op == SLJIT_UDIVMOD ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)));
         FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_R1) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO)));
         return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1));
+    case SLJIT_UDIVI:
+    case SLJIT_SDIVI:
+        return push_inst(compiler, ((op == SLJIT_UDIVI ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1));
     }


     return SLJIT_SUCCESS;


Modified: code/trunk/src/sljit/sljitNativeARM_T2_32.c
===================================================================
--- code/trunk/src/sljit/sljitNativeARM_T2_32.c    2015-05-28 16:48:42 UTC (rev 275)
+++ code/trunk/src/sljit/sljitNativeARM_T2_32.c    2015-05-29 12:52:59 UTC (rev 276)
@@ -1239,6 +1239,9 @@


 SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
 {
+    sljit_sw saved_reg_list[3];
+    sljit_sw saved_reg_count;
+
     CHECK_ERROR();
     CHECK(check_sljit_emit_op0(compiler, op));


@@ -1255,24 +1258,53 @@
             | (reg_map[SLJIT_R0] << 12)
             | (reg_map[SLJIT_R0] << 16)
             | reg_map[SLJIT_R1]);
-    case SLJIT_LUDIV:
-    case SLJIT_LSDIV:
-        if (compiler->scratches >= 4) {
-            FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */));
-            FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */));
-        } else if (compiler->scratches >= 3)
-            FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */));
+    case SLJIT_UDIVMOD:
+    case SLJIT_SDIVMOD:
+    case SLJIT_UDIVI:
+    case SLJIT_SDIVI:
+        SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
+        SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 12, bad_register_mapping);
+
+        saved_reg_count = 0;
+        if (compiler->scratches >= 4)
+            saved_reg_list[saved_reg_count++] = 12;
+        if (compiler->scratches >= 3)
+            saved_reg_list[saved_reg_count++] = 2;
+        if (op >= SLJIT_UDIVI)
+            saved_reg_list[saved_reg_count++] = 1;
+
+        if (saved_reg_count > 0) {
+            FAIL_IF(push_inst32(compiler, 0xf84d0d00 | (saved_reg_count >= 3 ? 16 : 8)
+                        | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));
+            if (saved_reg_count >= 2) {
+                SLJIT_ASSERT(saved_reg_list[1] < 8);
+                FAIL_IF(push_inst16(compiler, 0x9001 | (saved_reg_list[1] << 8) /* str rX, [sp, #4] */));
+            }
+            if (saved_reg_count >= 3) {
+                SLJIT_ASSERT(saved_reg_list[2] < 8);
+                FAIL_IF(push_inst16(compiler, 0x9002 | (saved_reg_list[2] << 8) /* str rX, [sp, #8] */));
+            }
+        }
+
 #if defined(__GNUC__)
         FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
-            (op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
+            ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
 #else
 #error "Software divmod functions are needed"
 #endif
-        if (compiler->scratches >= 4) {
-            FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */));
-            return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */);
-        } else if (compiler->scratches >= 3)
-            return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */);
+
+        if (saved_reg_count > 0) {
+            if (saved_reg_count >= 3) {
+                SLJIT_ASSERT(saved_reg_list[2] < 8);
+                FAIL_IF(push_inst16(compiler, 0x9802 | (saved_reg_list[2] << 8) /* ldr rX, [sp, #8] */));
+            }
+            if (saved_reg_count >= 2) {
+                SLJIT_ASSERT(saved_reg_list[1] < 8);
+                FAIL_IF(push_inst16(compiler, 0x9801 | (saved_reg_list[1] << 8) /* ldr rX, [sp, #4] */));
+            }
+            return push_inst32(compiler, 0xf85d0b00 | (saved_reg_count >= 3 ? 16 : 8)
+                        | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
+        }
         return SLJIT_SUCCESS;
     }



Modified: code/trunk/src/sljit/sljitNativeMIPS_common.c
===================================================================
--- code/trunk/src/sljit/sljitNativeMIPS_common.c    2015-05-28 16:48:42 UTC (rev 275)
+++ code/trunk/src/sljit/sljitNativeMIPS_common.c    2015-05-29 12:52:59 UTC (rev 276)
@@ -1053,8 +1053,11 @@
 #endif
         FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
         return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
-    case SLJIT_LUDIV:
-    case SLJIT_LSDIV:
+    case SLJIT_UDIVMOD:
+    case SLJIT_SDIVMOD:
+    case SLJIT_UDIVI:
+    case SLJIT_SDIVI:
+        SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
 #if !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
         FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
         FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
@@ -1062,15 +1065,15 @@


 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
         if (int_op)
-            FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+            FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
         else
-            FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+            FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
 #else
-        FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+        FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
 #endif


         FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
-        return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
+        return (op >= SLJIT_UDIVI) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
     }


     return SLJIT_SUCCESS;


Modified: code/trunk/src/sljit/sljitNativePPC_common.c
===================================================================
--- code/trunk/src/sljit/sljitNativePPC_common.c    2015-05-28 16:48:42 UTC (rev 275)
+++ code/trunk/src/sljit/sljitNativePPC_common.c    2015-05-29 12:52:59 UTC (rev 276)
@@ -1267,22 +1267,23 @@
         FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
         return push_inst(compiler, (op == SLJIT_LUMUL ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
 #endif
-    case SLJIT_LUDIV:
-    case SLJIT_LSDIV:
+    case SLJIT_UDIVMOD:
+    case SLJIT_SDIVMOD:
         FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
-        if (int_op) {
-            FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
-            FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
-        } else {
-            FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVDU : DIVD) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
-            FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
-        }
-        return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
+        FAIL_IF(push_inst(compiler, (int_op ? (op == SLJIT_UDIVMOD ? DIVWU : DIVW) : (op == SLJIT_UDIVMOD ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
+        FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
 #else
-        FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
+        FAIL_IF(push_inst(compiler, (op == SLJIT_UDIVMOD ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
         FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
+#endif
         return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
+    case SLJIT_UDIVI:
+    case SLJIT_SDIVI:
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+        return push_inst(compiler, (int_op ? (op == SLJIT_UDIVI ? DIVWU : DIVW) : (op == SLJIT_UDIVI ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
+#else
+        return push_inst(compiler, (op == SLJIT_UDIVI ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
 #endif
     }



Modified: code/trunk/src/sljit/sljitNativeSPARC_common.c
===================================================================
--- code/trunk/src/sljit/sljitNativeSPARC_common.c    2015-05-28 16:48:42 UTC (rev 275)
+++ code/trunk/src/sljit/sljitNativeSPARC_common.c    2015-05-29 12:52:59 UTC (rev 276)
@@ -777,20 +777,25 @@
 #else
 #error "Implementation required"
 #endif
-    case SLJIT_LUDIV:
-    case SLJIT_LSDIV:
+    case SLJIT_UDIVMOD:
+    case SLJIT_SDIVMOD:
+    case SLJIT_UDIVI:
+    case SLJIT_SDIVI:
+        SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
 #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
-        if (op == SLJIT_LUDIV)
+        if ((op | 0x2) == SLJIT_UDIVI)
             FAIL_IF(push_inst(compiler, WRY | S1(0), MOVABLE_INS));
         else {
             FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(SLJIT_R0) | IMM(31), DR(TMP_REG1)));
             FAIL_IF(push_inst(compiler, WRY | S1(TMP_REG1), MOVABLE_INS));
         }
-        FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2)));
-        FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
+        if (op <= SLJIT_SDIVMOD)
+            FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2)));
+        FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
+        if (op >= SLJIT_UDIVI)
+            return SLJIT_SUCCESS;
         FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_R1) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R1)));
-        FAIL_IF(push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1)));
-        return SLJIT_SUCCESS;
+        return push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1));
 #else
 #error "Implementation required"
 #endif


Modified: code/trunk/src/sljit/sljitNativeX86_common.c
===================================================================
--- code/trunk/src/sljit/sljitNativeX86_common.c    2015-05-28 16:48:42 UTC (rev 275)
+++ code/trunk/src/sljit/sljitNativeX86_common.c    2015-05-29 12:52:59 UTC (rev 276)
@@ -742,8 +742,10 @@
         break;
     case SLJIT_LUMUL:
     case SLJIT_LSMUL:
-    case SLJIT_LUDIV:
-    case SLJIT_LSDIV:
+    case SLJIT_UDIVMOD:
+    case SLJIT_SDIVMOD:
+    case SLJIT_UDIVI:
+    case SLJIT_SDIVI:
         compiler->flags_saved = 0;
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
 #ifdef _WIN64
@@ -761,9 +763,10 @@
 #endif
         compiler->mode32 = op & SLJIT_INT_OP;
 #endif
+        SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);


         op = GET_OPCODE(op);
-        if (op == SLJIT_LUDIV) {
+        if ((op | 0x2) == SLJIT_UDIVI) {
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
             EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0);
             inst = emit_x86_instruction(compiler, 1, SLJIT_R1, 0, SLJIT_R1, 0);
@@ -774,7 +777,7 @@
             *inst = XOR_r_rm;
         }


-        if (op == SLJIT_LSDIV) {
+        if ((op | 0x2) == SLJIT_SDIVI) {
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
             EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0);
 #endif
@@ -805,10 +808,10 @@
         FAIL_IF(!inst);
         INC_SIZE(2);
         *inst++ = GROUP_F7;
-        *inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]);
+        *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]);
 #else
 #ifdef _WIN64
-        size = (!compiler->mode32 || op >= SLJIT_LUDIV) ? 3 : 2;
+        size = (!compiler->mode32 || op >= SLJIT_UDIVMOD) ? 3 : 2;
 #else
         size = (!compiler->mode32) ? 3 : 2;
 #endif
@@ -817,11 +820,11 @@
         INC_SIZE(size);
 #ifdef _WIN64
         if (!compiler->mode32)
-            *inst++ = REX_W | ((op >= SLJIT_LUDIV) ? REX_B : 0);
-        else if (op >= SLJIT_LUDIV)
+            *inst++ = REX_W | ((op >= SLJIT_UDIVMOD) ? REX_B : 0);
+        else if (op >= SLJIT_UDIVMOD)
             *inst++ = REX_B;
         *inst++ = GROUP_F7;
-        *inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]);
+        *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]);
 #else
         if (!compiler->mode32)
             *inst++ = REX_W;
@@ -836,15 +839,21 @@
         case SLJIT_LSMUL:
             *inst |= IMUL;
             break;
-        case SLJIT_LUDIV:
+        case SLJIT_UDIVMOD:
+        case SLJIT_UDIVI:
             *inst |= DIV;
             break;
-        case SLJIT_LSDIV:
+        case SLJIT_SDIVMOD:
+        case SLJIT_SDIVI:
             *inst |= IDIV;
             break;
         }
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)
-        EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
+        if (op <= SLJIT_SDIVMOD)
+            EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
+#else
+        if (op >= SLJIT_UDIVI)
+            EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
 #endif
         break;
     }
@@ -1905,60 +1914,62 @@
         return SLJIT_SUCCESS;
     }


-    if (FAST_IS_REG(src1)) {
+    if (!(src1 & SLJIT_IMM)) {
         if (src2 & SLJIT_IMM) {
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
             if (IS_HALFWORD(src2w) || compiler->mode32) {
-                inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
+                inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);
                 FAIL_IF(!inst);
                 *inst = GROUP_F7;
             }
             else {
                 FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
-                inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, 0);
+                inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, src1w);
                 FAIL_IF(!inst);
                 *inst = TEST_rm_r;
             }
 #else
-            inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
+            inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);
             FAIL_IF(!inst);
             *inst = GROUP_F7;
 #endif
+            return SLJIT_SUCCESS;
         }
-        else {
+        else if (FAST_IS_REG(src1)) {
             inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);
             FAIL_IF(!inst);
             *inst = TEST_rm_r;
+            return SLJIT_SUCCESS;
         }
-        return SLJIT_SUCCESS;
     }


-    if (FAST_IS_REG(src2)) {
+    if (!(src2 & SLJIT_IMM)) {
         if (src1 & SLJIT_IMM) {
 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
             if (IS_HALFWORD(src1w) || compiler->mode32) {
-                inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, 0);
+                inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, src2w);
                 FAIL_IF(!inst);
                 *inst = GROUP_F7;
             }
             else {
                 FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w));
-                inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, 0);
+                inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, src2w);
                 FAIL_IF(!inst);
                 *inst = TEST_rm_r;
             }
 #else
-            inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, 0);
+            inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, src2w);
             FAIL_IF(!inst);
             *inst = GROUP_F7;
 #endif
+            return SLJIT_SUCCESS;
         }
-        else {
+        else if (FAST_IS_REG(src2)) {
             inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
             FAIL_IF(!inst);
             *inst = TEST_rm_r;
+            return SLJIT_SUCCESS;
         }
-        return SLJIT_SUCCESS;
     }


     EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);